OpenHarmony中AT模塊的代碼理解之三
現在開啟第三篇,核心內容是AT命令的注冊。
1、AT命令結構體
typedef struct {
hi_char *at_cmd_name;
hi_s8 at_cmd_len;
at_call_back_func at_test_cmd;
at_call_back_func at_query_cmd;
at_call_back_func at_setup_cmd;
at_call_back_func at_exe_cmd;
} at_cmd_func;
hi_char *at_cmd_name;為命令字符串,不包含“AT”字符。
hi_s8 at_cmd_len;為字符串長度。
后面的四個回調函數,分別對應AT命令的四種類似:測試命令,查詢命令,設置命令和執行命令。
如:{“+RST”, 4, HI_NULL, HI_NULL, (at_call_back_func)at_setup_reset_cmd, (at_call_back_func)at_exe_reset_cmd}。
2、注冊函數
hi_at_sys_cmd_register()這個函數中包含了很多注冊的函數。每個函數又包含了一類的AT命令。
hi_void hi_at_sys_cmd_register(hi_void)
{
hi_at_general_cmd_register();
#ifndef CONFIG_FACTORY_TEST_MODE
hi_at_sta_cmd_register();
hi_at_softap_cmd_register();
#endif
hi_at_hipriv_cmd_register();
#ifndef CONFIG_FACTORY_TEST_MODE
#ifdef LOSCFG_APP_MESH
hi_at_mesh_cmd_register();
#endif
hi_at_lowpower_cmd_register();
#endif
hi_at_general_factory_test_cmd_register();
hi_at_sta_factory_test_cmd_register();
hi_at_hipriv_factory_test_cmd_register();
hi_at_io_cmd_register();
}
只取其中的一個,進行進一步的說明,拿這個函數hi_at_general_cmd_register()舉例。函數中引用了AT命令的注冊函數。
hi_at_register_cmd(g_at_general_func_tbl, AT_GENERAL_FUNC_NUM);
函數的參數有兩個:結構體數組和結構體數組的長度。結構體數組就是第一部分中介紹的AT命令結構體。
const at_cmd_func g_at_general_func_tbl[] = {
{"", 0, HI_NULL, HI_NULL, HI_NULL, (at_call_back_func)at_exe_at_cmd},
{"+RST", 4, HI_NULL, HI_NULL, (at_call_back_func)at_setup_reset_cmd, (at_call_back_func)at_exe_reset_cmd},
{"+MAC", 4, HI_NULL, (at_call_back_func)cmd_get_macaddr, (at_call_back_func)cmd_set_macaddr, HI_NULL},
{"+HELP", 5, HI_NULL, HI_NULL, HI_NULL, (at_call_back_func)at_exe_help_cmd},
};
下面對注冊函數的實現進行說明。
hi_u32 hi_at_register_cmd(HI_CONST at_cmd_func *cmd_tbl, hi_u16 cmd_num)
{
hi_u32 ret = HI_ERR_FAILURE;
hi_u8 i;
if (cmd_tbl == HI_NULL || cmd_num == 0) {
return HI_ERR_FAILURE;
}
ret = check_cmd_tbl(cmd_tbl, cmd_num);
if (ret != HI_ERR_SUCCESS) {
return ret;
}
at_cmd_func_list *cmd_list = at_get_list();
for (i = 0; i < AT_CMD_LIST_NUM; i++) {
if ((cmd_list->at_cmd_list[i] == HI_NULL) || (cmd_list->at_cmd_num[i] == 0)) {
cmd_list->at_cmd_list[i] = cmd_tbl;
cmd_list->at_cmd_num[i] = cmd_num;
ret = HI_ERR_SUCCESS;
break;
}
ret = check_name_and_callback(cmd_list, i, cmd_tbl, cmd_num);
if (ret != HI_ERR_SUCCESS) {
break;
}
}
return ret;
}
其中幾個核心函數的說明:
(1)check_cmd_tbl(cmd_tbl, cmd_num)。
確認需要注冊的AT命令結構體中沒有重復的指令。
(2)at_get_list()。
獲取全局變量HI_PRV at_cmd_func_list g_at_cmd_list = { 0 }的指針。這個結構體數據中存儲著已經注冊的AT命令。
(3)check_name_and_callback(cmd_list, i, cmd_tbl, cmd_num)。
為檢查要注冊的AT命令是否有重復,避免重復注冊。
(4)for (i = 0; i < AT_CMD_LIST_NUM; i++) {}去遍歷g_at_cmd_list中已經存儲到了第幾個位置。如果遍歷到空位置,則將要注冊的AT命令結構體的指針進行存儲。
cmd_list->at_cmd_list[i] = cmd_tbl;
cmd_list->at_cmd_num[i] = cmd_num;
3、總結
注冊部分功能,就是將AT命令的添加到g_at_cmd_list的數組中。等到通過串口接收到的指令進行解析的時候,還會遍歷存儲在g_at_cmd_list中的指令的。所有這個結構體數組,后續還會用到。
如果想要自己添加AT命令。可以仿照給出的通用規則,自己添加即可。這里不展開說明。
這篇文章,就先介紹到這里。