OpenHarmony中AT模块的代码理解(4) 原创 精华
之前已经写了三篇
https://ost.51cto.com/posts/10773
https://ost.51cto.com/posts/10756
https://ost.51cto.com/posts/10744
这是本系列的第四篇文章。
今天从AT接收任务hi_void at_proc_task_body(hi_void param)说起。
hi_void *at_proc_task_body(hi_void* param)
{
hi_unref_param(param);
hi_u32 ret;
hi_u32 event_bit;
hi_char *buf = NULL;
for (;;) {
if (g_at_ctrl.at_state != AT_DATA_RECVING) {
hi_at_printf("\r\n");
}
event_bit = 0;
ret = hi_event_wait(g_at_event, 0xFFF, &event_bit, HI_SYS_WAIT_FOREVER,
HI_EVENT_WAITMODE_OR | HI_EVENT_WAITMODE_CLR);
if (ret == HI_ERR_EVENT_WAIT_TIME_OUT) {
hi_at_printf("get event timeout\r\n");
continue;
}
if (event_bit == 0x111) {
buf = at_get_buf();
if (buf == NULL) {
g_at_ctrl.at_state = AT_IDLE;
continue;
}
if (g_at_ctrl.at_state == AT_CMD_PROCESS) {
at_cmd_execute(buf);
} else if (g_at_ctrl.at_state == AT_DATA_SENDING) {
#ifndef CONFIG_FACTORY_TEST_MODE
at_send_serial_data(buf);
g_at_ctrl.at_state = AT_IDLE;
g_at_ctrl.is_first_over_data = HI_TRUE;
#endif
}
hi_free(HI_MOD_ID_APP_AT, buf);
}
}
}
该函数主要包括①等待Event事件数据,②读取数据,③根据模式g_at_ctrl.at_state,确定是执行AT命令的数据处理,或者是数据的转发。
1)读取数据at_get_buf()
hi_char* at_get_buf(hi_void)
{
hi_char *buf = NULL;
hi_u32 buf_len;
if (g_at_ctrl.at_state == AT_CMD_PROCESS) {
buf_len = strlen(g_at_buf) + 1;
buf = hi_malloc(HI_MOD_ID_APP_AT, buf_len);
if (buf != NULL) {
memset_s(buf, buf_len, 0, buf_len);
if (memcpy_s(buf, buf_len, g_at_buf, strlen(g_at_buf)) != EOK) {
hi_at_printf("buf copy fail in %s[%d]", __FUNCTION__, __LINE__);
hi_free(HI_MOD_ID_APP_AT, buf);
buf = NULL;
}
}
} else if (g_at_ctrl.at_state == AT_DATA_SENDING) {
buf_len = g_at_ctrl.send_len + 1;
buf = hi_malloc(HI_MOD_ID_APP_AT, buf_len);
if (buf != NULL) {
memset_s(buf, buf_len, 0, buf_len);
if (memcpy_s(buf, buf_len, g_at_data, g_at_ctrl.send_len) != EOK) {
hi_at_printf("buf copy fail in %s[%d]", __FUNCTION__, __LINE__);
hi_free(HI_MOD_ID_APP_AT, buf);
buf = NULL;
}
}
}
hi_event_send(g_at_event, 0x1000);
return buf;
}
该函数根据g_at_ctrl.at_state的不同状态,从相对应的缓冲区中取数据,复制到新开辟的内存空间中。然后发送hi_event_send(g_at_event, 0x1000)让数据接收任务可以继续接收串口数据。
2)at_cmd_execute->at_cmd_process
接受到整行的数据,开始处理。复制到out_cmd_line数组,并且将行的\r\n去掉。
然后通过函数hi_u32 at_func_process(hi_char *out_cmd_line, at_cmd_attr *cmd_parsed)进行处理。
3)at_func_process
该函数是AT命令数据处理的核心函数了。
hi_u32 at_func_process(hi_char *out_cmd_line, at_cmd_attr *cmd_parsed)
{
hi_u32 ret;
at_cmd_func *cmd_func = HI_NULL;
at_get_cmd_name(out_cmd_line, cmd_parsed);
if (cmd_parsed->at_cmd_len != (-1)) {
cmd_func = at_find_proc_func(cmd_parsed);
}
if (cmd_func != HI_NULL) {
ret = at_cmd_parse(out_cmd_line, cmd_parsed);
if (ret != HI_ERR_SUCCESS) {
at_printf("%s line: %d PARSE CMD FAIL!\r\n", __FUNCTION__, __LINE__);
return ret;
}
ret = at_cmd_excute(cmd_func, cmd_parsed);
} else {
ret = HI_ERR_FAILURE;
at_printf("%s line: %d COMMAND NOT SUPPORT!\r\n", __FUNCTION__, __LINE__);
}
return ret;
}
at_get_cmd_name(out_cmd_line, cmd_parsed);为通过对比,找到对应AT命令的名称。有就是=号或者?等之前的命令。
at_find_proc_func,找到对应的at_cmd_func结构体中匹配的对象。也就是我们注册的AT命令。并将该注册的命令返回。
at_cmd_parse,为确认是哪种类型的命令:test_cmd;query_cmd;setup_cmd;exe_cmd。
at_cmd_excute,执行该命令。
AT命令的相关内容,今天就说到这里。很粗略的做了一个说明,希望对你有用。下面会对该部分代码进行移植和简化。