4G_module/custom/custom_main/src/app_uart.c

222 lines
6.9 KiB
C
Raw Normal View History


/****************************************************************************
* 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);
}