通过看TencentOs tiny github附带的API源码学习课程,竟然还有视频终于都AT框架的实现有更彻底的认识,如果要明白SAL层和AT框架如何与模组进行同步异步通信的必须学习两个知识,信号量和互斥锁。
信号量和互斥锁的原理百度千篇一律,我从视频和博客针对TencentOS tiny源码的分析,对信号量和互斥锁才是彻底掌握。
我以以下tencentOs里AT框架源码解释一下互斥锁,我们最关心的就是AT框架如何利用AT指令与模组进行通信,这里AT框架提供两个发指令API:
1) tos_at_cmd_exec 发送一条指令,取得串口所有权后,发送完即返回
2)tos_at_cmd_exec_until 发送一条指令,直到捡到期望值echo对象后才返回
先从tos_at_cmd_exec解释起,这个API只用到了互斥锁,就是在获取uart口这个临界资源时,tos_mutex_pend获取锁,当获取不到时任务则被挂起等待其他任务释放互斥uart锁,当代码能继续往下运行代码已经获取到uart锁了,当数据发送出去后,任务at_parser及时处理模组串口指令回复,赋值给echo对象,达到同步效果,通过互斥锁的挂起,实现代码看似顺序执行,无需等待即拿到模组串口指令回复。
附带tos_at_cmd_exec接口源码:
__API__ int tos_at_cmd_exec(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
{int ret = 0;va_list args;if (echo) {at_echo_attach(echo);}va_start(args, cmd);ret = at_cmd_do_exec(cmd, args);va_end(args);if (ret != 0) {AT_AGENT->echo = K_NULL;return -1;}tos_task_delay(tos_millisec2tick(timeout));AT_AGENT->echo = K_NULL;return 0;
}
tos_at_cmd_exec_until这个API较为不同的是它必须收到模组串口回复的值与事先创建的echo对象,echo对象相关知识可以看腾讯云大学有一个视频是介绍TencentOs tiny的,里有介绍AT框架特别是echo对象含义。
比如发送一串网络数据出去,我们期望得到send ok才认为数据发送出去(实际移远模组send ok只是代表模组收到了需要发送的数据还不代表服务器收到),TencentOS tiny源码是先创建一个信号量tos_sem_create(&echo->__expect_notify, 0)创建一个初始值为0的信号量,也就是说必须有地方post释放一个信号量才能被获取,创建信号量后,跟tos_at_cmd_execAPI一致等拿到uart口资源后发送数据,然后不同之处来了,会去获取刚才创建的的信号量tos_sem_pend(&echo->__expect_notify, tos_millisec2tick(timeout)),这是任务被挂起,直到任务at_parser解析数据然后释放,这时才获取到期待返回的值,TencentIOS TINY这种处理使用了系统的资源互斥锁和信号量,针对这个我之前是用队列去解决这一问题,队列来控制串口的所有权,当然TencentOS tiny更是大众的写法也更好,后续打算替换到已经在开发的项目,实现代码编程技术提升。
以下tos_at_cmd_exec_until源码:
__API__ int tos_at_cmd_exec_until(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
{int ret = 0;va_list args;if (!echo || !echo->echo_expect) {return -1;}if (tos_sem_create(&echo->__expect_notify, 0) != K_ERR_NONE) {return -1;}echo->__is_expecting = K_TRUE;at_echo_attach(echo);va_start(args, cmd);ret = at_cmd_do_exec(cmd, args);va_end(args);if (ret != 0) {AT_AGENT->echo = K_NULL;return -1;}if (tos_sem_pend(&echo->__expect_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {ret = -1;}tos_sem_destroy(&echo->__expect_notify);AT_AGENT->echo = K_NULL;return ret;
}
分享杰杰大神的的博客https://blog.csdn.net/jiejiemcu/article/details/100056641。