uart_framework.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * Change Logs:
  3. * Date Author Notes
  4. * 2024-05-24 Slyant the first version
  5. */
  6. #include <rtthread.h>
  7. #include <rtdevice.h>
  8. #include <uart_framework.h>
  9. enum work_model
  10. {
  11. WORK_NORMAL = 0,
  12. WORK_TAKE,
  13. WORK_RELEASE,
  14. WORK_TAKE_RELEASE
  15. };
  16. /**
  17. * @brief 创建 UART 框架
  18. *
  19. * 根据给定的 UART 框架配置,创建并初始化 UART 框架。
  20. *
  21. * @param cfg UART 框架配置指针
  22. *
  23. * @return UART 框架指针,如果创建失败则返回 RT_NULL
  24. */
  25. uart_framework_t uart_framework_create(struct uart_framework_cfg *cfg)
  26. {
  27. rt_err_t open_result;
  28. static int rx_sem_count = 0;
  29. static int rx_mut_count = 0;
  30. char ufsem_name[RT_NAME_MAX] = {0};
  31. char ufmut_name[RT_NAME_MAX] = {0};
  32. uart_framework_t uf = rt_calloc(1, sizeof(struct uart_framework));
  33. if (uf == RT_NULL)
  34. return RT_NULL;
  35. uf->uart_device = rt_device_find(cfg->uart_name);
  36. if (uf->uart_device == RT_NULL || uf->uart_device->type != RT_Device_Class_Char)
  37. {
  38. rt_free(uf);
  39. return RT_NULL;
  40. }
  41. rt_snprintf(ufsem_name, RT_NAME_MAX, "ufsem%d", rx_sem_count++);
  42. uf->rx_sem = rt_sem_create(ufsem_name, 0, RT_IPC_FLAG_FIFO);
  43. if (uf->rx_sem == RT_NULL)
  44. {
  45. rt_free(uf);
  46. return RT_NULL;
  47. }
  48. rt_snprintf(ufmut_name, RT_NAME_MAX, "ufmut%d", rx_mut_count++);
  49. uf->dev_lock = rt_mutex_create(ufmut_name, RT_IPC_FLAG_FIFO);
  50. if (uf->dev_lock == RT_NULL)
  51. {
  52. rt_sem_delete(uf->rx_sem);
  53. rt_free(uf);
  54. return RT_NULL;
  55. }
  56. uf->rx_buf = rt_calloc(1, cfg->max_frame_size);
  57. if (uf->rx_buf == RT_NULL)
  58. {
  59. rt_sem_delete(uf->rx_sem);
  60. rt_mutex_delete(uf->dev_lock);
  61. rt_free(uf);
  62. return RT_NULL;
  63. }
  64. rt_memcpy(&uf->cfg, cfg, sizeof(struct uart_framework_cfg));
  65. #ifdef RT_USING_SERIAL_V2
  66. open_result = rt_device_open(uf->uart_device, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
  67. #else
  68. #ifdef RT_SERIAL_USING_DMA
  69. /* using DMA mode first */
  70. open_result = rt_device_open(uf->uart_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
  71. /* using interrupt mode when DMA mode not supported */
  72. if (open_result == RT_EOK)
  73. {
  74. }
  75. else if (open_result == -RT_EIO)
  76. #endif
  77. {
  78. open_result = rt_device_open(uf->uart_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
  79. }
  80. #endif
  81. RT_ASSERT(open_result == RT_EOK);
  82. rt_device_set_rx_indicate(uf->uart_device, uf->cfg.rx_ind);
  83. return uf;
  84. }
  85. /**
  86. * @brief 发送数据
  87. *
  88. * 根据给定的工作模式和 UART 框架,发送数据到 UART 设备。
  89. *
  90. * @param model 工作模式
  91. * @param uf UART 框架结构体指针
  92. * @param data 数据指针
  93. * @param size 数据大小
  94. *
  95. * @return 实际发送的字节数
  96. */
  97. static rt_size_t _send(enum work_model model, uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
  98. {
  99. while (rt_tick_get() - uf->send_tick < rt_tick_from_millisecond(uf->cfg.send_interval_ms))
  100. {
  101. rt_thread_mdelay(10);
  102. }
  103. if (model == WORK_TAKE || model == WORK_TAKE_RELEASE)
  104. {
  105. rt_mutex_take(uf->dev_lock, RT_WAITING_FOREVER);
  106. rt_sem_control(uf->rx_sem, RT_IPC_CMD_RESET, 0);
  107. while (rt_device_read(uf->uart_device, 0, &uf->rx_ch, 1))
  108. ;
  109. }
  110. if (uf->cfg.rs485_txd)
  111. uf->cfg.rs485_txd();
  112. rt_size_t wsize = rt_device_write(uf->uart_device, 0, data, size);
  113. if (uf->cfg.rs485_rxd)
  114. uf->cfg.rs485_rxd();
  115. uf->send_tick = rt_tick_get(); // 重置定时器
  116. if (model == WORK_TAKE_RELEASE)
  117. {
  118. rt_mutex_release(uf->dev_lock);
  119. }
  120. return wsize;
  121. }
  122. /**
  123. * @brief 接收串口数据
  124. *
  125. * 根据指定的工作模型,从串口框架中接收数据,并处理接收到的数据帧。
  126. *
  127. * @param model 工作模型
  128. * @param uf 串口框架对象
  129. * @param timeout_ms 超时时间(毫秒)
  130. * @param frame_handler 数据帧处理函数
  131. * @param out 输出缓冲区
  132. * @param out_max_size 输出缓冲区最大大小
  133. *
  134. * @return 错误码,RT_EOK 表示成功,其他值表示错误
  135. */
  136. static rt_err_t _receive(enum work_model model, uart_framework_t uf, rt_uint32_t timeout_ms,
  137. rt_err_t (*frame_handler)(rt_uint8_t *data, rt_size_t size), rt_uint8_t *out, rt_size_t out_max_size)
  138. {
  139. // rt_memset(uf->rx_buf, 0, uf->cfg.max_frame_size);
  140. uf->rx_size = 0;
  141. uf->last_tick = rt_tick_get();
  142. while (1)
  143. {
  144. if (rt_sem_take(uf->rx_sem, rt_tick_from_millisecond(timeout_ms)) == RT_EOK)
  145. {
  146. if (model == WORK_TAKE_RELEASE)
  147. {
  148. rt_mutex_take(uf->dev_lock, RT_WAITING_FOREVER);
  149. }
  150. while (1)
  151. {
  152. while (rt_device_read(uf->uart_device, 0, &uf->rx_ch, 1))
  153. {
  154. uf->last_tick = rt_tick_get(); // 重置定时器
  155. if (uf->rx_size < uf->cfg.max_frame_size)
  156. {
  157. uf->rx_buf[uf->rx_size++] = uf->rx_ch;
  158. }
  159. }
  160. if (rt_tick_get() - uf->last_tick > rt_tick_from_millisecond(uf->cfg.frame_interval_ms))
  161. {
  162. if (uf->rx_size > 0)
  163. {
  164. if (out && out_max_size > 0)
  165. {
  166. rt_memcpy(out, uf->rx_buf, uf->rx_size > out_max_size ? out_max_size : uf->rx_size);
  167. }
  168. if (frame_handler)
  169. {
  170. rt_err_t err = frame_handler(uf->rx_buf, uf->rx_size);
  171. if (model == WORK_RELEASE || model == WORK_TAKE_RELEASE)
  172. {
  173. rt_mutex_release(uf->dev_lock);
  174. }
  175. return err;
  176. }
  177. else
  178. {
  179. if (model == WORK_RELEASE || model == WORK_TAKE_RELEASE)
  180. {
  181. rt_mutex_release(uf->dev_lock);
  182. }
  183. return RT_EOK;
  184. }
  185. }
  186. else
  187. {
  188. break;
  189. }
  190. }
  191. rt_thread_mdelay(10);
  192. }
  193. if (model == WORK_RELEASE || model == WORK_TAKE_RELEASE)
  194. {
  195. rt_mutex_release(uf->dev_lock);
  196. }
  197. }
  198. else
  199. {
  200. if (model == WORK_RELEASE)
  201. {
  202. rt_mutex_release(uf->dev_lock);
  203. }
  204. return -RT_ETIMEOUT;
  205. }
  206. }
  207. }
  208. /**
  209. * @brief 发送数据到UART框架
  210. *
  211. * 通过UART框架发送指定大小的数据。
  212. *
  213. * @param uf UART框架对象指针
  214. * @param data 要发送的数据指针
  215. * @param size 数据大小
  216. *
  217. * @return 发送的字节数
  218. */
  219. rt_size_t uart_framework_send(uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
  220. {
  221. return _send(WORK_NORMAL, uf, data, size);
  222. }
  223. /**
  224. * @brief UART框架发送数据(独占)
  225. *
  226. * 通过UART框架发送指定大小的数据。
  227. *
  228. * @param uf UART框架对象
  229. * @param data 要发送的数据指针
  230. * @param size 要发送的数据大小
  231. *
  232. * @return 实际发送的数据大小
  233. */
  234. rt_size_t uart_framework_send_take(uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
  235. {
  236. return _send(WORK_TAKE, uf, data, size);
  237. }
  238. /**
  239. * @brief UART框架发送数据(独占发送后释放)
  240. *
  241. * 通过UART框架发送指定大小的数据。
  242. *
  243. * @param uf UART框架对象指针
  244. * @param data 要发送的数据指针
  245. * @param size 要发送的数据大小
  246. *
  247. * @return 实际发送的字节数
  248. */
  249. rt_size_t uart_framework_send_take_release(uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
  250. {
  251. return _send(WORK_TAKE_RELEASE, uf, data, size);
  252. }
  253. /**
  254. * @brief 接收UART框架数据
  255. *
  256. * 在给定的超时时间内,从UART框架中接收数据,并调用帧处理器处理接收到的数据。
  257. *
  258. * @param uf UART框架对象
  259. * @param timeout_ms 超时时间(毫秒)
  260. * @param frame_handler 帧处理器函数指针,用于处理接收到的数据
  261. * @param out 存储处理结果的缓冲区
  262. * @param out_max_size 缓冲区最大容量
  263. *
  264. * @return 返回错误码,表示操作是否成功
  265. */
  266. rt_err_t uart_framework_receive(uart_framework_t uf, rt_uint32_t timeout_ms,
  267. rt_err_t (*frame_handler)(rt_uint8_t *data, rt_size_t size), rt_uint8_t *out, rt_size_t out_max_size)
  268. {
  269. return _receive(WORK_NORMAL, uf, timeout_ms, frame_handler, out, out_max_size);
  270. }
  271. /**
  272. * @brief UART 框架接收数据(接收后释放独占)
  273. *
  274. * 从 UART 框架收数据,通过回调函数处理接收到的数据帧。
  275. *
  276. * @param uf UART 框架对象
  277. * @param timeout_ms 超时时间(毫秒)
  278. * @param frame_handler 数据帧处理回调函数
  279. * @param out 存储处理结果的缓冲区
  280. * @param out_max_size 缓冲区最大大小
  281. *
  282. * @return 返回错误码,表示操作结果
  283. */
  284. rt_err_t uart_framework_receive_release(uart_framework_t uf, rt_uint32_t timeout_ms,
  285. rt_err_t (*frame_handler)(rt_uint8_t *data, rt_size_t size), rt_uint8_t *out, rt_size_t out_max_size)
  286. {
  287. return _receive(WORK_RELEASE, uf, timeout_ms, frame_handler, out, out_max_size);
  288. }
  289. /**
  290. * @brief UART框架接收数据(独占接收后释放)
  291. *
  292. * 从UART框架中接收数据,并在处理完成后释放相关资源。
  293. *
  294. * @param uf UART框架指针
  295. * @param timeout_ms 超时时间(单位:毫秒)
  296. * @param frame_handler 帧处理函数指针
  297. * @param out 输出缓冲区指针
  298. * @param out_max_size 输出缓冲区最大大小
  299. *
  300. * @return 返回错误码,表示操作是否成功
  301. */
  302. rt_err_t uart_framework_receive_take_release(uart_framework_t uf, rt_uint32_t timeout_ms,
  303. rt_err_t (*frame_handler)(rt_uint8_t *data, rt_size_t size), rt_uint8_t *out, rt_size_t out_max_size)
  304. {
  305. return _receive(WORK_TAKE_RELEASE, uf, timeout_ms, frame_handler, out, out_max_size);
  306. }