OpenHarmony中AT模块的代码理解(4) 原创 精华

再见南丫岛
发布于 2022-4-5 16:15
浏览
1收藏

之前已经写了三篇
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命令的相关内容,今天就说到这里。很粗略的做了一个说明,希望对你有用。下面会对该部分代码进行移植和简化。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-4-5 16:15:14修改
2
收藏 1
回复
举报
回复
    相关推荐