| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*
- * Change Logs:
- * Date Author Notes
- * 2024-05-24 Slyant the first version
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <uart_framework.h>
- enum work_model
- {
- WORK_NORMAL = 0, WORK_TAKE, WORK_RELEASE, WORK_TAKE_RELEASE
- };
- static rt_err_t rx_ind(rt_device_t dev, rt_size_t size)
- {
- uart_framework_t uf = dev->user_data;
- rt_sem_release(uf->rx_sem);
- return RT_EOK;
- }
- /**
- * @brief 创建 UART 框架
- *
- * 根据给定的 UART 框架配置,创建并初始化 UART 框架。
- *
- * @param cfg UART 框架配置指针
- *
- * @return UART 框架指针,如果创建失败则返回 RT_NULL
- */
- uart_framework_t uart_framework_create(struct uart_framework_cfg *cfg)
- {
- rt_err_t open_result;
- static int rx_sem_count = 0;
- static int rx_mut_count = 0;
- char ufsem_name[RT_NAME_MAX] = { 0 };
- char ufmut_name[RT_NAME_MAX] = { 0 };
- uart_framework_t uf = rt_calloc(1, sizeof(struct uart_framework));
- if (uf == RT_NULL)
- return RT_NULL;
- uf->uart_device = rt_device_find(cfg->uart_name);
- if (uf->uart_device == RT_NULL || uf->uart_device->type != RT_Device_Class_Char)
- {
- rt_free(uf);
- return RT_NULL;
- }
- rt_snprintf(ufsem_name, RT_NAME_MAX, "ufsem%d", rx_sem_count++);
- uf->rx_sem = rt_sem_create(ufsem_name, 0, RT_IPC_FLAG_FIFO);
- if (uf->rx_sem == RT_NULL)
- {
- rt_free(uf);
- return RT_NULL;
- }
- rt_snprintf(ufmut_name, RT_NAME_MAX, "ufmut%d", rx_mut_count++);
- uf->dev_lock = rt_mutex_create(ufmut_name, RT_IPC_FLAG_FIFO);
- if (uf->dev_lock == RT_NULL)
- {
- rt_sem_delete(uf->rx_sem);
- rt_free(uf);
- return RT_NULL;
- }
- uf->rx_buf = rt_calloc(1, cfg->max_frame_size);
- if (uf->rx_buf == RT_NULL)
- {
- rt_sem_delete(uf->rx_sem);
- rt_mutex_delete(uf->dev_lock);
- rt_free(uf);
- return RT_NULL;
- }
- rt_memcpy(&uf->cfg, cfg, sizeof(struct uart_framework_cfg));
- #ifdef RT_USING_SERIAL_V2
- open_result = rt_device_open(uf->uart_device, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
- #else
- #ifdef RT_SERIAL_USING_DMA
- /* using DMA mode first */
- open_result = rt_device_open(uf->uart_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
- /* using interrupt mode when DMA mode not supported */
- if (open_result == RT_EOK)
- {
- }
- else if (open_result == -RT_EIO)
- #endif
- {
- open_result = rt_device_open(uf->uart_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
- }
- #endif
- RT_ASSERT(open_result == RT_EOK);
- if (uf->cfg.rx_ind)
- {
- rt_device_set_rx_indicate(uf->uart_device, uf->cfg.rx_ind);
- }
- else
- {
- if (uf->uart_device->user_data == RT_NULL)
- {
- uf->uart_device->user_data = uf;
- rt_device_set_rx_indicate(uf->uart_device, rx_ind);
- }
- }
- uf->is_waiting_response = RT_FALSE;
- return uf;
- }
- /**
- * @brief 发送数据
- *
- * 根据给定的工作模式和 UART 框架,发送数据到 UART 设备,并进入等待响应状态。
- *
- * @param model 工作模式
- * @param uf UART 框架结构体指针
- * @param data 数据指针
- * @param size 数据大小
- *
- * @return 实际发送的字节数
- */
- static rt_size_t _send(enum work_model model, uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
- {
- while (rt_tick_get() - uf->send_tick < rt_tick_from_millisecond(uf->cfg.send_interval_ms))
- {
- rt_thread_mdelay(10);
- }
- if (model == WORK_TAKE || model == WORK_TAKE_RELEASE)
- {
- rt_mutex_take(uf->dev_lock, RT_WAITING_FOREVER);
- rt_sem_control(uf->rx_sem, RT_IPC_CMD_RESET, 0);
- while (rt_device_read(uf->uart_device, 0, &uf->rx_ch, 1))
- ;
- }
- if (uf->cfg.rs485_txd)
- uf->cfg.rs485_txd();
- rt_size_t wsize = rt_device_write(uf->uart_device, 0, data, size);
- if (uf->cfg.rs485_rxd)
- uf->cfg.rs485_rxd();
- uf->send_tick = rt_tick_get(); // 重置定时器
- if (model == WORK_TAKE_RELEASE)
- {
- rt_mutex_release(uf->dev_lock);
- }
- uf->is_waiting_response = RT_TRUE;
- return wsize;
- }
- /**
- * @brief 接收串口数据
- *
- * 根据指定的工作模型,从串口框架中接收数据后,退出等待响应状态。
- *
- * @param model 工作模型
- * @param uf 串口框架对象
- * @param timeout_ms 超时时间(毫秒)
- * @param frame_handler 数据帧处理函数
- * @param out 存储处理结果的缓冲区
- * @param out_size 处理结果的实际长度
- * @param out_max_size 缓冲区最大容量
- *
- * @return 错误码,RT_EOK 表示成功,其他值表示错误
- */
- static rt_err_t _receive(enum work_model model, uart_framework_t uf, rt_uint32_t timeout_ms, rt_uint8_t *out,
- rt_size_t *out_size, rt_size_t out_max_size)
- {
- // rt_memset(uf->rx_buf, 0, uf->cfg.max_frame_size);
- uf->rx_size = 0;
- uf->last_tick = rt_tick_get();
- while (1)
- {
- if (rt_sem_take(uf->rx_sem, rt_tick_from_millisecond(timeout_ms)) == RT_EOK)
- {
- if (model == WORK_TAKE_RELEASE)
- {
- rt_mutex_take(uf->dev_lock, RT_WAITING_FOREVER);
- }
- while (1)
- {
- while (rt_device_read(uf->uart_device, 0, &uf->rx_ch, 1))
- {
- uf->last_tick = rt_tick_get(); // 重置定时器
- if (uf->rx_size < uf->cfg.max_frame_size)
- {
- uf->rx_buf[uf->rx_size++] = uf->rx_ch;
- }
- }
- if (rt_tick_get() - uf->last_tick > rt_tick_from_millisecond(uf->cfg.frame_interval_ms))
- {
- if (uf->rx_size > 0)
- {
- if (out)
- {
- rt_memcpy(out, uf->rx_buf, uf->rx_size > out_max_size ? out_max_size : uf->rx_size);
- }
- if (out_size)
- {
- *out_size = uf->rx_size;
- }
- if (model == WORK_RELEASE || model == WORK_TAKE_RELEASE)
- {
- rt_mutex_release(uf->dev_lock);
- }
- uf->is_waiting_response = RT_FALSE;
- return RT_EOK;
- }
- else
- {
- break;
- }
- }
- rt_thread_mdelay(10);
- }
- if (model == WORK_RELEASE || model == WORK_TAKE_RELEASE)
- {
- rt_mutex_release(uf->dev_lock);
- }
- }
- else
- {
- if (model == WORK_RELEASE)
- {
- rt_mutex_release(uf->dev_lock);
- }
- uf->is_waiting_response = RT_FALSE;
- return -RT_ETIMEOUT;
- }
- }
- }
- /**
- * @brief 发送数据到UART框架
- *
- * 通过UART框架发送指定大小的数据。
- *
- * @param uf UART框架对象指针
- * @param data 要发送的数据指针
- * @param size 数据大小
- *
- * @return 发送的字节数
- */
- rt_size_t uart_framework_send(uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
- {
- return _send(WORK_NORMAL, uf, data, size);
- }
- /**
- * @brief UART框架发送数据(独占)
- *
- * 通过UART框架发送指定大小的数据。
- *
- * @param uf UART框架对象
- * @param data 要发送的数据指针
- * @param size 要发送的数据大小
- *
- * @return 实际发送的数据大小
- */
- rt_size_t uart_framework_send_take(uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
- {
- return _send(WORK_TAKE, uf, data, size);
- }
- /**
- * @brief UART框架发送数据(独占发送后释放)
- *
- * 通过UART框架发送指定大小的数据。
- *
- * @param uf UART框架对象指针
- * @param data 要发送的数据指针
- * @param size 要发送的数据大小
- *
- * @return 实际发送的字节数
- */
- rt_size_t uart_framework_send_take_release(uart_framework_t uf, rt_uint8_t *data, rt_size_t size)
- {
- return _send(WORK_TAKE_RELEASE, uf, data, size);
- }
- /**
- * @brief 接收UART框架数据
- *
- * 在给定的超时时间内,从UART框架中接收数据,并调用帧处理器处理接收到的数据。
- *
- * @param uf UART框架对象
- * @param timeout_ms 超时时间(毫秒)
- * @param out 存储处理结果的缓冲区
- * @param out_size 处理结果的实际长度
- * @param out_max_size 缓冲区最大容量
- *
- * @return 返回错误码,表示操作是否成功
- */
- rt_err_t uart_framework_receive(uart_framework_t uf, rt_uint32_t timeout_ms, rt_uint8_t *out, rt_size_t *out_size,
- rt_size_t out_max_size)
- {
- return _receive(WORK_NORMAL, uf, timeout_ms, out, out_size, out_max_size);
- }
- /**
- * @brief UART 框架接收数据(接收后释放独占)
- *
- * 从 UART 框架收数据,通过回调函数处理接收到的数据帧。
- *
- * @param uf UART框架对象
- * @param timeout_ms 超时时间(毫秒)
- * @param out 存储处理结果的缓冲区
- * @param out_size 处理结果的实际长度
- * @param out_max_size 缓冲区最大容量
- *
- * @return 返回错误码,表示操作是否成功
- */
- rt_err_t uart_framework_receive_release(uart_framework_t uf, rt_uint32_t timeout_ms, rt_uint8_t *out,
- rt_size_t *out_size, rt_size_t out_max_size)
- {
- return _receive(WORK_RELEASE, uf, timeout_ms, out, out_size, out_max_size);
- }
- /**
- * @brief UART框架接收数据(独占接收后释放)
- *
- * 从UART框架中接收数据,并在处理完成后释放相关资源。
- *
- * @param uf UART框架对象
- * @param timeout_ms 超时时间(毫秒)
- * @param out 存储处理结果的缓冲区
- * @param out_size 处理结果的实际长度
- * @param out_max_size 缓冲区最大容量
- *
- * @return 返回错误码,表示操作是否成功
- */
- rt_err_t uart_framework_receive_take_release(uart_framework_t uf, rt_uint32_t timeout_ms, rt_uint8_t *out,
- rt_size_t *out_size, rt_size_t out_max_size)
- {
- return _receive(WORK_TAKE_RELEASE, uf, timeout_ms, out, out_size, out_max_size);
- }
- /**
- * @brief 在非等待响应状态,接收串口数据
- *
- * 在非等待响应状态,从串口框架中接收数据,并在用户回调函数中处理接收到的数据帧。
- *
- * @param uf 串口框架对象
- * @param frame_handler_callback 数据帧处理回调函数
- * @param out 存储处理结果的缓冲区
- * @param out_size 处理结果的实际长度
- * @param out_max_size 缓冲区最大容量
- *
- * @return 返回错误码,表示操作是否成功
- */
- rt_err_t uart_framework_receive_without_waiting_response(uart_framework_t uf,
- void (*frame_handler_callback)(rt_uint8_t *data, rt_size_t size), rt_uint8_t *out, rt_size_t *out_size,
- rt_size_t out_max_size)
- {
- if (uf->is_waiting_response == RT_FALSE)
- {
- if (rt_sem_trytake(uf->rx_sem) == RT_EOK)
- {
- rt_mutex_take(uf->dev_lock, RT_WAITING_FOREVER);
- uf->rx_size = 0;
- uf->last_tick = rt_tick_get();
- while (1)
- {
- while (rt_device_read(uf->uart_device, 0, &uf->rx_ch, 1))
- {
- uf->last_tick = rt_tick_get(); // 重置定时器
- if (uf->rx_size < uf->cfg.max_frame_size)
- {
- uf->rx_buf[uf->rx_size++] = uf->rx_ch;
- }
- }
- if (rt_tick_get() - uf->last_tick > rt_tick_from_millisecond(uf->cfg.frame_interval_ms))
- {
- if (uf->rx_size > 0)
- {
- if (out)
- {
- rt_memcpy(out, uf->rx_buf, uf->rx_size > out_max_size ? out_max_size : uf->rx_size);
- }
- if (out_size)
- {
- *out_size = uf->rx_size;
- }
- if (frame_handler_callback)
- {
- frame_handler_callback(uf->rx_buf, uf->rx_size);
- }
- rt_mutex_release(uf->dev_lock);
- return RT_EOK;
- }
- else
- {
- break;
- }
- }
- rt_thread_mdelay(10);
- }
- rt_mutex_release(uf->dev_lock);
- }
- }
- return -RT_ERROR;
- }
|