/**************************************************************************** * Included Files ****************************************************************************/ #include "cm_iomux.h" #include "cm_gpio.h" #include "stdio.h" #include "stdlib.h" #include "stdarg.h" #include "cm_os.h" #include "cm_mem.h" #include "cm_sys.h" #include "cm_uart.h" #include "app_uart.h" #include "app_common.h" #define APP_UART_TASK_PRIORITY osPriorityNormal #define APP_URAT 0 //uart0 #if (APP_URAT == 0) #define APP_UARTTX_IOMUX CM_IOMUX_PIN_18, CM_IOMUX_FUNC_FUNCTION1 #define APP_UARTRX_IOMUX CM_IOMUX_PIN_17, CM_IOMUX_FUNC_FUNCTION1 #endif //uart1 #if (APP_URAT == 1) #define APP_UARTRX_IOMUX CM_IOMUX_PIN_28, CM_IOMUX_FUNC_FUNCTION1 #define APP_UARTTX_IOMUX CM_IOMUX_PIN_29, CM_IOMUX_FUNC_FUNCTION1 #endif #if (APP_URAT == 2) #define APP_UARTTX_IOMUX CM_IOMUX_PIN_50, CM_IOMUX_FUNC_FUNCTION3 #define APP_UARTRX_IOMUX CM_IOMUX_PIN_51, CM_IOMUX_FUNC_FUNCTION3 #endif typedef struct{ int msg_type; } uart_event_msg_t; #define UART_BUF_LEN 1024 static int rx_rev_len = 0; static char rx_rev_data[UART_BUF_LEN] = {0}; static osThreadId_t os_UART_ThreadId = NULL; //串口数据接收、解析任务Handle static osThreadId_t uart_event_thread = NULL; static void* g_uart_sem = NULL; static osMessageQueueId_t uart_event_queue = NULL; // 用于测试串口事件,用户可参考 static void uart_event_task(void *arg){ uart_event_msg_t msg = {0}; while (1) { if (osMessageQueueGet(uart_event_queue, &msg, NULL, osWaitForever) == osOK) { //cm_log_printf(0, "uart event msg type = %d\n", msg.msg_type); if (CM_UART_EVENT_TYPE_RX_OVERFLOW & msg.msg_type){ app_printf("CM_UART_EVENT_TYPE_RX_OVERFLOW... ...\r\n"); cm_uart_read(APP_URAT, (void*)&rx_rev_data[0], UART_BUF_LEN, 1000); cm_uart_read(APP_URAT, (void*)&rx_rev_data[0], UART_BUF_LEN, 1000); cm_uart_read(APP_URAT, (void*)&rx_rev_data[0], UART_BUF_LEN, 1000); cm_uart_read(APP_URAT, (void*)&rx_rev_data[0], UART_BUF_LEN, 1000); } } } } // 用于测试串口事件,用户可参考 static int uart_event_task_create(void){ if (uart_event_queue == NULL){ uart_event_queue = osMessageQueueNew(10, sizeof(uart_event_msg_t), NULL); } if (uart_event_thread == NULL) { osThreadAttr_t attr1 = { .name = "uart_event", .priority = APP_UART_TASK_PRIORITY, .stack_size = 1024, }; uart_event_thread = osThreadNew(uart_event_task, NULL, (const osThreadAttr_t*)&attr1); } return 0; } /* 串口接收示例,平时使用信号量挂起,当收到接收事件后,释放信号量以触发读取任务 */ static void Uart_TaskHandle(void *param){ int temp_len = 0; while (1){ if (g_uart_sem != NULL){ osSemaphoreAcquire(g_uart_sem, osWaitForever);//阻塞 } if (rx_rev_len < UART_BUF_LEN){ temp_len = cm_uart_read(APP_URAT, (void*)&rx_rev_data[rx_rev_len], UART_BUF_LEN - rx_rev_len, 1000); rx_rev_len += temp_len; } app_printf("uart rev data len = %d\n", rx_rev_len); /* 后续用于SDK测试,用户可酌情参考*/ if (g_uart_sem != NULL && (strstr(rx_rev_data, "\r\n"))){ //处理收到数据事件 cm_uart_write(APP_URAT, rx_rev_data, rx_rev_len, 1000); memset((void*)rx_rev_data, 0, sizeof(rx_rev_data)); rx_rev_len = 0; } } } // 串口事件回调函数// 回调函数中不可输出LOG、串口打印、执行复杂任务或消耗过多资源,建议以信号量或消息队列形式控制其他线程执行任务 static void app_uart_event_callback(void *param, uint32_t type){ uart_event_msg_t msg = {0}; if (CM_UART_EVENT_TYPE_RX_ARRIVED & type){ /* 收到接收事件,触发其他线程执行读取数据 */ osSemaphoreRelease(g_uart_sem); } if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type){ /* 收到溢出事件,触发其他线程处理溢出事件 */ msg.msg_type = type; if (uart_event_queue != NULL){//向队列发送数据 osMessageQueuePut(uart_event_queue, &msg, 0, 0); } } } void app_uart_init(void){ int32_t ret = -1; // 配置引脚复用 cm_iomux_set_pin_func(APP_UARTTX_IOMUX); cm_iomux_set_pin_func(APP_UARTRX_IOMUX); cm_iomux_set_pin_cmd(CM_IOMUX_PIN_17, CM_IOMUX_PINCMD3_PULL, CM_IOMUX_PINCMD3_FUNC2_PULL_HIGH); // cm_iomux_set_pin_cmd(CM_IOMUX_PIN_18, CM_IOMUX_PINCMD3_PULL, CM_IOMUX_PINCMD3_FUNC2_PULL_HIGH); // 事件参数 cm_uart_event_t uart_event = { CM_UART_EVENT_TYPE_RX_ARRIVED | CM_UART_EVENT_TYPE_RX_OVERFLOW, //注册需要上报的事件类型 "uart0", //用户参数 app_uart_event_callback //上报事件的回调函数 }; // 注册事件和回调函数 ret = cm_uart_register_event(APP_URAT, &uart_event); if(ret != RET_SUCCESS){ cm_log_printf(0, "uart register event err,ret=%d\n", ret); return; } // 配置参数 cm_uart_cfg_t uart_cfg = { CM_UART_BYTE_SIZE_8, CM_UART_PARITY_NONE, CM_UART_STOP_BIT_ONE, CM_UART_FLOW_CTRL_NONE, CM_UART_BAUDRATE_9600, 0 //配置为普通串口模式,若要配置为低功耗模式可改为1 }; // 开启串口 ret = cm_uart_open(APP_URAT, &uart_cfg); if (ret != RET_SUCCESS){ cm_log_printf(0, "uart init err,ret=%d\n", ret); return; } // // 配置uart唤醒功能,使能边沿检测才具备唤醒功能,仅主串口具有唤醒功能,用于唤醒的数据并不能被uart接收,请在唤醒后再进行uart数传 // cm_iomux_set_pin_cmd(APP_UARTRX_IOMUX , CM_IOMUX_PINCMD1_LPMEDEG, CM_IOMUX_PINCMD1_FUNC1_LPM_EDGE_RISE); // 串口接收处理任务 osThreadAttr_t uart_task_attr = {0}; uart_task_attr.name = "uart_task"; uart_task_attr.stack_size = 2048; uart_task_attr.priority= APP_UART_TASK_PRIORITY; os_UART_ThreadId= osThreadNew(Uart_TaskHandle, 0, &uart_task_attr); if (g_uart_sem == NULL) { g_uart_sem = osSemaphoreNew(1, 0, NULL); } uart_event_task_create(); } /* 关闭串口 */ void app_uart_close(void){ cm_uart_dev_e dev = CM_UART_DEV_0; if (0 == cm_uart_close(dev)){ app_printf("uart%d close is ok\n", dev); }else{ app_printf("uart%d close is error\n", dev); } } void app_printf(char *str, ...){ static char s[600]; //This needs to be large enough to store the string TODO Change magic number va_list args; int len; if ((str == NULL) || (strlen(str) == 0)) { return; } va_start(args, str); len = vsnprintf((char*)s, 600, str, args); va_end(args); cm_uart_write(APP_URAT, s, len, 1000); }