OpenHarmony中AT模塊的代碼理解之一
1、背景
最早接觸AT命令是在使用通信模塊的時候,那時的AT命令的打包和解析都是自己寫的函數實現,代碼邏輯和框架也都不成熟,通用性也不強。現在的RTOS操作系統中也都包含了這部分的內容,比如RTT等,通用性更強,代碼的邏輯性也值得我們去分析和學習。接觸openharmony,發現系統代碼中也包含了AT相關的業務。今天,嘗試整理一下這部分代碼的思路。
2、提要
(1)代碼路徑
device\hisilicon\hispark_pegasus\sdk_liteos\components\at\src\
(2)關閉AT服務
有時候自己需要使用串口做一些私有業務,不想使用原生的AT命令,比如,移植micropython,就需要關閉AT服務。關閉的方法如下:
打開device\hisilicon\hispark_pegasus\sdk_liteos\build\config\usr_config.mk。
將其中的#CONFIG_AT_SUPPORT=y刪除。或者使用menuconfig操作該文件關閉。
關閉宏之后,config.mk中,會判斷該宏的值。
ifeq ($(CONFIG_AT_SUPPORT), y)
DEFINES += -DCONFIG_AT_COMMAND
endif
會使得AT的初始化,注冊相關函數無效。
3、框架
簡單的描述一下程序框架,核心內容分為接收任務和處理任務,兩個任務之間通過Event事件同步。cmd_register函數用來注冊我們需要解析的AT命令。
4、代碼
(1) 數據的接收
在hi_u32 hi_at_init(hi_void)中創建了數據接收的任務。
attr.stack_size = g_at_uart_task_size;
attr.task_prio = AT_UART_TASK_PRIO;
attr.task_name = (hi_char*)"at_uart";
ret = hi_task_create(&at_uart_task, &attr, at_uart_task_body, 0);
if (ret != HI_ERR_SUCCESS) {
hi_at_printf("AT_UART_TSK init fail\r\n");
return ret;
}
(2) 數據的處理
attr.stack_size = 1024*6;
attr.task_prio = AT_PROC_TASK_PRIO;
attr.task_name = (hi_char*)"at_proc";
ret = hi_task_create(&at_proc_task, &attr, at_proc_task_body, 0);
if (ret != HI_ERR_SUCCESS) {
hi_at_printf("AT_PROC_TSK init fail\r\n");
return ret;
}
兩個任務之間通過g_at_event傳遞數據。buf = at_get_buf();獲取數據之后,進行解析和處理。處理函數如下。
hi_void at_cmd_execute(hi_char *buf)
{
hi_u32 ret;
if (memcmp(buf, AT_CMD_HEADER, strlen(AT_CMD_HEADER)) == EOK) {
hi_char *at_buf = buf + strlen(AT_CMD_HEADER);
ret = at_cmd_process(at_buf);
if ((ret != HI_ERR_SUCCESS) && (ret != HI_ERR_RECVING)) {
g_at_ctrl.at_state = AT_IDLE;
}
} else {
AT_ENTER;
AT_RESPONSE_ERROR;
g_at_ctrl.at_state = AT_IDLE;
}
}
處理函數會從注冊的AT命令中對比關鍵詞,然后解析,處理,執行。
5、總結
這篇文章先整理到這里,后續會有更詳細的對AT命令邏輯的分析。
后續的計劃:
(1)繼續分析openharmony的AT命令的代碼思路和關鍵函數的使用。
(2)對比RT-Thread等其他RTOS的AT部分實現。
(3)精簡openharmony部分代碼,移植出一套可以在其他平臺使用的AT框架。