裸机/FreeRTOS 环境下使用面向对象的方式实现 UART 的通用接口功能

重要的事情说在前边

  1. 编写程序时,特别是C程序,应该也只有C程序。一定要 仔细 仔细 仔细 调用宏函数时传递的实参类型是否是被定义函数实际的参数类型。
    比如传递指针,up 因为调用 API 时自以为是的传入指针导致程序跑不通,关键是既然可以成功编译,这就很无语。。。
    这要 “得益于” 宏函数在预处理阶段只是简单的文本替换,并没有类型检查,这种问题连编译期都不会被检查到。
    虽然不是像常规函数一样进行调用,无函数调用开销(如入栈、出栈等操作)。这使得宏函数在某些性能要求较高的情况下比普通函数更有效率。
    但是这会导致调试时无法像常规函数一样查看调用栈、参数等信息。如果传递错误参数。。。并且是上万行的代码量。。。
    或者在调用宏函数中有参数操作行为(比如计算同一个表达式 A(a++)),在预处理阶段就会执行,运行时再次执行,导致意外的结果,这种问题根本没法调试。。。
    所以不建议使用宏函数,建议使用内联函数(inline)来代替宏函数,因为内联函数还可以进行类型检查、调试。

  2. 编译器要比你仔细,一定要注意 warning 并不是只有 error 才会导致错误,就是因为无视了 warning 也可以编译通过,才会在某些问题上止步不前。

  3. 少用全局变量,这会增加程序的可维护性和降低程序的可读性,全局变量可以被程序中的任何函数访问和修改,这使得代码的跟踪和调试变得非常困难。
    很难确定某个特定函数是否会修改全局变量,从而可能引入错误或意外结果。并且对于弱需求的全局变量,会浪费内存资源。在多线程环境下还要考虑并发的问题。
    最重要的是增加了程序的耦合性,当你发现一个全局变量并不符合现在的设计需求时,会浪费很多时间在修改不同程序中的同一个全局变量上。
    同时多个函数依赖同一个全局变量(依赖同一个值)这本来就增加了函数的耦合性,不符合函数的单一最小化原则,和高内聚低耦合的要求,同时导致其他负面影响。

interface_uart.h

#ifndef __INTERFACE_UART_H__
#define __INTERFACE_UART_H__

/******************/
#define stm32_hal                                      1
#define stm32f4xx                                      0
#define stm32h5xx                                      1

#define CIRCLE_BUF_LEN                                 1000
#define BAREMETAL                                      0
#define FREERTOS                                       1
/******************/

#include "stdint.h"

#if BAREMETAL
    #include "circle_buffer.h"
#elif FREERTOS
    #include "FreeRTOS.h"
    #include "task.h"
    #include "queue.h"
    #include "semphr.h"
#endif

#if stm32f4xx
    #include "stm32f4xx_hal.h"
    #include "usart.h"
#elif stm32h5xx
    #include "stm32h5xx_hal.h"
    #include "usart.h"
#endif

#ifdef __cplusplus
extern "C"{
#endif

/**
 * @brief 
 */
typedef struct uart_init_s
{
    uint32_t baud_rate;
    uint8_t data_bits;
    uint32_t stop_bits;
    int32_t parity_bits;
    uint32_t mode;
    uint32_t flow_control;
    /*
        ...
    */
} *p_uart_init, uart_init_t;

/**
 * @brief 
 */
typedef struct uart_device_s 
{
    int8_t *device_name;

    #if stm32_hal
        UART_HandleTypeDef *uart_handle;
    #elif /* others */
        /* others */
    #else
        struct uart_init_t *uart_init;
    #endif

    #if BAREMETAL
        circle_buf_t *uart_buf_circle;
        uint8_t *uart_buf_temp;
        uint8_t *uart_buf_byte;
        uint8_t uart_cplt_tx;
        uint8_t uart_cplt_rx;
    #elif FREERTOS
        SemaphoreHandle_t *uart_semaphore_tx;
        QueueHandle_t *uart_queue_rx;
        uint8_t *uart_buf_rx;
    #endif

} *p_uart_device, uart_device_t;


typedef struct uart_handle_s 
{
    // uart_device_t uart_dev;

    uint8_t (*uart_init)(uart_device_t *pDev);
    uint8_t (*uart_deinit)(uart_device_t *pDev);
    uint8_t (*uart_receive)(uart_device_t *pDev);
    uint8_t (*uart_transmit)(uart_device_t *pDev, uint8_t *buf, uint16_t len, uint16_t timeout);
    uint8_t (*uart_get_byte)(uart_device_t *pDev, uint8_t *data, uint16_t timeout);

} *p_uart_handle, uart_handle_t;


#if FREERTOS
    uint8_t uart_init_rtos(uart_device_t *pDev);
    uint8_t uart_receive_rtos(uart_device_t *pDev);
    uint8_t uart_transmit_rtos(uart_device_t *pDev, uint8_t *data, uint16_t len, uint16_t timeout);
    uint8_t uart_get_byte_rtos(uart_device_t *pDev, uint8_t *data, uint16_t timeout);
#endif

#if BAREMETAL
    uint8_t uart_init_baremetal(uart_device_t *pDev);
    uint8_t uart_deinit_baremetal(uart_device_t *pDev);
    uint8_t uart_receive_baremetal(uart_device_t *pDev);
    uint8_t uart_transmit_baremetal(uart_device_t *pDev, uint8_t *buf, uint16_t len, uint16_t timeout);
    uint8_t uart_transmit_by_it(uart_device_t *pDev , uint8_t *buf, uint16_t len, uint16_t timeout);
#endif


uint16_t uart_print(const int8_t *const fmt, ...);

uint8_t uart_test(void);

#ifdef __cplusplus
}
#endif

#endif


interface_uart.c

#include "interface_uart.h"
#include "stdio.h"
#include "string.h"
#include "stdarg.h"

/******************************************** freertos ***********************************************/

#if FREERTOS

uart_device_t *g_uart4_dev;
uart_handle_t *g_uart4_handle;

uart_device_t *g_uart2_dev;
uart_handle_t *g_uart2_handle;

uint8_t uart_init_rtos(uart_device_t *pDev)
{
	// *(pDev->uart_semaphore_tx) = xSemaphoreCreateBinary();
    // *(pDev->uart_queue_rx) = xQueueCreate(200, 1);

    if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_rx, 100) != HAL_OK)
    {
        return 1;
    }

	return 0;
}

uint8_t uart_receive_rtos(uart_device_t *pDev)
{
    if (pDev == NULL)
    {
        return 2;
    }

    /* Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs. */
    if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_rx, 100) != HAL_OK)
    {
        return 1;
    }
    
    return 0;
}

uint8_t uart_transmit_rtos(uart_device_t *pDev, uint8_t *data, uint16_t len, uint16_t timeout)
{
    if (HAL_UART_Transmit_DMA(pDev->uart_handle, data, len) != HAL_OK)
    {
        return 1;
    }
    
	if (pdTRUE == xSemaphoreTake(*(pDev->uart_semaphore_tx), (uint32_t)timeout))
    {
        return 0;
    }
	else
    {
		return 2;
    }
}

uint8_t uart_get_byte_rtos(uart_device_t *pDev, uint8_t *data, uint16_t timeout)
{
	if (pdPASS == xQueueReceive(*(pDev->uart_queue_rx), (uint8_t*)data, (uint32_t)timeout))
    {
	    return 0;
    }
	else
    {
		return 1;
    }
}

#endif

/************************************ bare matel *************************************/

#if BAREMETAL

circle_buf_t g_uart2_buf_circle = {0};
uint8_t g_uart2_buf_rcv[CIRCLE_BUF_LEN] = {0};
uint8_t g_uart2_buf_temp[100] = {0};
uint8_t g_uart2_buf_byte = 0;
uart_device_t g_uart2_dev = {"uart2", &huart2, &g_uart2_buf_circle, &g_uart2_buf_temp, &g_uart2_buf_byte, 0, 0};
uart_handle_t g_uart2_handle = {0};

circle_buf_t g_uart4_buf_circle = {0};
uint8_t g_uart4_buf_rcv[CIRCLE_BUF_LEN] = {0};
uint8_t g_uart4_buf_temp[100] = {0};
uint8_t g_uart4_buf_byte = 0;
uart_device_t g_uart4_dev = {"uart4", &huart4, &g_uart4_buf_circle, &g_uart4_buf_temp, &g_uart4_buf_byte, 0, 0};
uart_handle_t g_uart4_handle = {0};

#endif


#if BAREMETAL

uint8_t uart_init_baremetal(uart_device_t *pDev)
{
    if (pDev == NULL)
    {
        return 2;
    }

    /* 这里可以学习模仿 HAL 库在初始化 UART 时使用的 MX_UARTx_Init() 函数的实现 */
    /*
        huart4.Instance = UART4;
        huart4.Init.BaudRate = 115200;
        huart4.Init.WordLength = UART_WORDLENGTH_8B;
        huart4.Init.StopBits = UART_STOPBITS_1;
        huart4.Init.Parity = UART_PARITY_NONE;
        huart4.Init.Mode = UART_MODE_TX_RX;
        ...
    */

    /* 也可以学习 HAL 库将初始化参数都封装到 UART_InitTypeDef Init 这个结构体中,并提供一个 UART_HandleTypeDef 的句柄 */
    /* 其中包括所要使用的 UART 设备的所有寄存器地址映射 USART_TypeDef, 初始化参数 UART_InitTypeDef, 进一步初始化的参数 UART_AdvFeatureInitTypeDef ... */

    /* 初始化时创建 uart_handle_t uart4_handle 实例后 uart4.uart_init = interface_uart_init(&g_uart4_dev) 只需要调用通用的接口 uart4.uart_init 就可以实现 uart4 的初始化 */

    /* 初始化后开启串口接收 */
    // if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_temp, 100) != HAL_OK)
    // {
    //     return 1;
    // }
    
    return 0;
}

uint8_t uart_deinit_baremetal(uart_device_t *pDev)
{
    if (HAL_UART_DeInit(pDev->uart_handle) != HAL_OK)
    {
        return 1;
    }
    
    return 0;
}

uint8_t uart_receive_baremetal(uart_device_t *pDev)
{
    if (pDev == NULL)
    {
        return 2;
    }

    pDev->uart_cplt_rx = 0;

    /* Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs. */
    if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_temp, 100) != HAL_OK)
    {
        return 1;
    }
    
    return 0;
}

uint8_t uart_transmit_baremetal(uart_device_t *pDev, uint8_t *buf, uint16_t len, uint16_t timeout)
{
    if (pDev == NULL || buf == NULL)
    {
        /* NULL pointer */
        return 2;
    }

    if (timeout <= 0)
    {
        timeout = 65535;
    }

    /* clear transmission completion flag */
    pDev->uart_cplt_tx = 0;
    
    /* transmit using DMA */
    if (HAL_UART_Transmit_DMA(pDev->uart_handle, (uint8_t*)buf, len) != HAL_OK)
    {
        /* HAL transmit failed */
        return 1;
    }

    /* 可以用定时器创建自定义延时函数 */
    uint32_t start_time = HAL_GetTick();

    /* waiting for DMA transmission completion */
    /* 注意:pDev->uart_tx_done 应在 HAL_UART_TxCpltCallback 回调中置为 1 */
    while ((pDev->uart_cplt_tx == 0) && ((HAL_GetTick() - start_time) < timeout))
    {
        /* 空循环等待 */
        __NOP();
    }

    if (pDev->uart_cplt_tx)
    {
        return 0;
    }
    else
    {
        /* timeout */
        return 3;
    }
}

uint8_t uart_transmit_by_it(uart_device_t *pDev , uint8_t *buf, uint16_t len, uint16_t timeout)
{
    if (pDev == NULL || buf == NULL)
    {
        /* NULL pointer */
        return 2;
    }

    timeout = 1000;
    
    /* clear transmission completion interrupt flag */
    pDev->uart_cplt_tx = 0;

    /* transmit */
    if (HAL_UART_Transmit_IT(pDev->uart_handle, (uint8_t*)buf, len) != HAL_OK)
    {
        /* HAL transmit failed */
        return 1;
    }

    /* waiting for events */
    /* 注意:pDev->uart_tx_done 应在 HAL_UART_TxCpltCallback 回调中置为 1 */
    /* 方式一 */
    // while((pDev->uart_tx_done == 0) && (timeout != 0))
    // {
    //     HAL_Delay(1);
    //     timeout--;
    // }

    // /* check the timeout */
    // if (timeout != 0)
    // {   
    //     /* return success */
    //     return 0;
    // }
    // else
    // {
    //     /* timeout return failed */
    //     return 1;
    // }

    /* 方式二 减少 CPU 消耗 */
    uint32_t start_time = HAL_GetTick();
    while ((pDev->uart_cplt_tx == 0) && ((HAL_GetTick() - start_time) < timeout))
    {
        /* 空循环等待 */
        __NOP();
    }

    if (pDev->uart_cplt_tx)
    {
        return 0;
    }
    else
    {
        /* timeout */
        return 3;
    }
}

#endif


/******************************************** Custom Implement ************************************************/

static inline void uart4_cplt_tx(void)
{
    #if BAREMETAL
        g_uart4_dev.uart_cplt_tx = 1;
    #elif FREERTOS
        xSemaphoreGiveFromISR(g_uart4_dev->uart_semaphore_tx, NULL);    
    #endif
}

static inline void uart2_cplt_tx(void)
{
    #if BAREMETAL
        g_uart2_dev.uart_cplt_tx = 1;
    #elif FREERTOS
        xSemaphoreGiveFromISR(g_uart2_dev->uart_semaphore_tx, NULL);    
    #endif
}

static inline void uart2_cplt_rx(void)
{
    #if BAREMETAL
        for (int i = 0; i < 100; i++)
        {
            circle_buf_write(g_uart2_dev.uart_buf_circle, g_uart2_dev.uart_buf_temp[i]);
        }
        
        g_uart2_dev.uart_cplt_rx = 1;

        /* re-start DMA+IDLE rx */
        HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev.uart_handle, g_uart2_dev.uart_buf_temp, 100);    
    #elif FREERTOS
        for (int i = 0; i < 100; i++)
		{
			xQueueSendFromISR(*(g_uart2_dev->uart_queue_rx), &(g_uart2_dev->uart_buf_rx[i]), NULL);
		}
		
		/* re-start DMA+IDLE rx */
		HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev->uart_handle, g_uart2_dev->uart_buf_rx, 100);
	#endif
}

static inline void uart4_cplt_rx(void)
{
    #if BAREMETAL
        for (int i = 0; i < 100; i++)
        {
            circle_buf_write(g_uart4_dev.uart_buf_circle, g_uart4_dev.uart_buf_temp[i]);
        }
        
        g_uart4_dev.uart_cplt_rx = 1;

        /* re-start DMA+IDLE rx */
        HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev.uart_handle, g_uart4_dev.uart_buf_temp, 100);
	#elif FREERTOS
		for (int i = 0; i < 100; i++)
		{
			xQueueSendFromISR(*(g_uart4_dev->uart_queue_rx), &(g_uart4_dev->uart_buf_rx[i]), NULL);
		}
		
		/* re-start DMA+IDLE rx */
		HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev->uart_handle, g_uart4_dev->uart_buf_rx, 100);
    #endif
}


uint16_t uart_print(const int8_t *const fmt, ...)
{
    int8_t str[512];
    uint16_t len = 0;
    va_list args;

    memset(str, 0, sizeof(str));
    va_start(args, fmt);
    vsnprintf(str, sizeof(str) - 1, fmt, args);
    va_end(args);
    
    len = strlen(str);
    if(interface_uart_transmit(&g_uart4_dev, str, len, 0) != 0)
    {
        return 0;
    }
    else
    {
        return len;
    }
}


/************************************************ Uart Tset ************************************************/

uint8_t uart_test(void)
{

    return 0;
}


/*************************************** IRQ Handler Callback Implement ***************************************/

/**
 * @brief 发送完成中断回调函数
 * @param huart 
 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart == &huart4)
  {
    /* set transmission completion flag */
    uart4_cplt_tx();
  }
  if (huart == &huart2)
  {
    /* set transmission completion flag */
    uart2_cplt_tx();
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart == &huart2)
	{
		uart2_cplt_rx();
	}	
	
	if (huart == &huart4)
	{
        uart4_cplt_rx();
    }	
}


/**
 * @brief 接收事件中断回调函数(包括 IDLE Event 或 Rx the specified number of bytes)
 * @param huart 
 * @param Size  rx transfer size, number of bytes actually received
 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart == &huart4)
    {
        #if BAREMETAL
            for (uint16_t i = 0; i < Size; i++)
            {
                circle_buf_write(g_uart4_dev.uart_buf_circle, g_uart4_dev.uart_buf_temp[i]);
            }
    
            HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev.uart_handle, g_uart4_dev.uart_buf_temp, 100);
        #elif FREERTOS
            for (uint16_t i = 0; i < Size; i++)
            {
                xQueueSendFromISR(*(g_uart4_dev->uart_queue_rx), &(g_uart4_dev->uart_buf_rx[i]), NULL);
            }

            HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev->uart_handle, g_uart4_dev->uart_buf_rx, 100);
        #endif
    }

    if (huart == &huart2)
    {
        #if BAREMETAL
            for (uint16_t i = 0; i < Size; i++)
            {
                circle_buf_write(g_uart2_dev.uart_buf_circle, g_uart2_dev.uart_buf_temp[i]);
            }
    
            HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev.uart_handle, g_uart2_dev.uart_buf_temp, 100);
        #elif FREERTOS
            for (uint16_t i = 0; i < Size; i++)
            {
                xQueueSendFromISR(*(g_uart2_dev->uart_queue_rx), &(g_uart2_dev->uart_buf_rx[i]), NULL);
            }

            HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev->uart_handle, g_uart2_dev->uart_buf_rx, 100);
        #endif
    }
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
	if (huart == &huart2)
	{
        #if BAERMETAL
		    HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev.uart_handle, g_uart2_dev.uart_buf_temp, 100);
        #elif FREERTOS
            HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev->uart_handle, g_uart2_dev->uart_buf_rx, 100);
        #endif
	}	
	if (huart == &huart4)
	{
		#if BAERMETAL
		    HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev.uart_handle, g_uart4_dev.uart_buf_temp, 100);
        #elif FREERTOS
            HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev->uart_handle, g_uart4_dev->uart_buf_rx, 100);
        #endif
	}
}

circle_buffer.h

#ifndef __CIRCLE_BUF_H__
#define __CIRCLE_BUF_H__

#include <stdint.h>

#ifdef __cplusplus
extern "C"
{
#endif

typedef struct circle_buf_s
{
	uint32_t r; /* 循环buf 的队头 */
	uint32_t w; /* 循环buf 的队尾 */
	uint8_t *buf;
	uint32_t len;
} *p_circle_buf_t, circle_buf_t;

void circle_buf_init(p_circle_buf_t pCircleBuf, uint8_t *buf, uint32_t len);
int circle_buf_read(p_circle_buf_t pCircleBuf, uint8_t *pVal);
int circle_buf_write(p_circle_buf_t pCircleBuf, uint8_t val);

#ifdef __cplusplus
}
#endif

#endif /* __CIRCLE_BUF_H__ */


circle_buffer.c

#include "circle_buffer.h"

/**
 * @brief 初始化循环队列 buffer
 * @param pCircleBuf
 * @param len
 * @param buf
 */
void circle_buf_init(p_circle_buf_t pCircleBuf, uint8_t *buf, uint32_t len)
{
	pCircleBuf->r = pCircleBuf->w = 0;
	pCircleBuf->len = len;
	pCircleBuf->buf = buf;
}

/**
 * @brief 判断循环队列 buffer 是否为空
 * @param pCircleBuf
 * @return
 */
int circle_buf_is_empty(p_circle_buf_t pCircleBuf)
{
	return (pCircleBuf->r == pCircleBuf->w);
}

/**
 * @brief 判断循环队列 buffer 是否满
 * @param pCircleBuf
 * @return
 */
int circle_buf_is_full(p_circle_buf_t pCircleBuf)
{
	return (pCircleBuf->w + 1) % pCircleBuf->len == pCircleBuf->r;
}

/**
 * @brief 循环队列 buf 出队操作
 * @param pCircleBuf
 * @param pVal
 * @return
 */
int circle_buf_read(p_circle_buf_t pCircleBuf, uint8_t *pVal)
{
	if (circle_buf_is_empty(pCircleBuf)) /* 如果循环buf 为空 */
	{
		return -1; /* buf为空,读取失败 */
	}

	*pVal = pCircleBuf->buf[pCircleBuf->r];

	pCircleBuf->r = (pCircleBuf->r + 1) % pCircleBuf->len;

	return 0;
}

/**
 * @brief 循环队列 buf 入队操作
 * @param pCircleBuf
 * @param val
 * @return
 */
int circle_buf_write(p_circle_buf_t pCircleBuf, uint8_t val)
{
	if (circle_buf_is_full(pCircleBuf)) /* 如果循环buf 已满 */
	{
		return -1; /* buf已满,写入失败 */
	}
	pCircleBuf->buf[pCircleBuf->w] = val;

	pCircleBuf->w = (pCircleBuf->w + 1) % pCircleBuf->len;

	return 0;
}

main.c


extern uart_device_t *g_uart4_dev;
extern uart_handle_t *g_uart4_handle;

extern uart_device_t *g_uart2_dev;
extern uart_handle_t *g_uart2_handle;


/************** 测串 uart *************** */
  QueueHandle_t uart4_queue_rx;
  SemaphoreHandle_t uart4_semaphore_tx;
  
  g_uart4_dev = (uart_device_t*)malloc(sizeof(uart_device_t));
  g_uart4_dev->device_name = (int8_t*)"uart4";
  g_uart4_dev->uart_handle = &huart4;
  g_uart4_dev->uart_buf_rx = (uint8_t*)malloc(sizeof(uint8_t)*100);
  uart4_queue_rx = xQueueCreate(200, 1);
  g_uart4_dev->uart_queue_rx = &uart4_queue_rx ;
  uart4_semaphore_tx = xSemaphoreCreateBinary();
  g_uart4_dev->uart_semaphore_tx = &uart4_semaphore_tx;

  g_uart4_handle = (uart_handle_t*)malloc(sizeof(uart_handle_t));
  g_uart4_handle->uart_init = uart_init_rtos;
  g_uart4_handle->uart_receive = uart_receive_rtos;
  g_uart4_handle->uart_transmit = uart_transmit_rtos;
  g_uart4_handle->uart_get_byte = uart_get_byte_rtos;
  

  QueueHandle_t uart2_queue_rx;
  SemaphoreHandle_t uart2_semaphore_tx;

  g_uart2_dev = (uart_device_t*)malloc(sizeof(uart_device_t));
  g_uart2_dev->device_name = (int8_t*)"uart2";
  g_uart2_dev->uart_handle = &huart2;
  g_uart2_dev->uart_buf_rx = (uint8_t*)malloc(sizeof(uint8_t)*100);
  uart2_queue_rx = xQueueCreate(200, 1);
  g_uart2_dev->uart_queue_rx = &uart2_queue_rx ;
  uart2_semaphore_tx = xSemaphoreCreateBinary();
  g_uart2_dev->uart_semaphore_tx = &uart2_semaphore_tx;

  g_uart2_handle = (uart_handle_t*)malloc(sizeof(uart_handle_t));
  g_uart2_handle->uart_init = uart_init_rtos;
  g_uart2_handle->uart_receive = uart_receive_rtos;
  g_uart2_handle->uart_transmit = uart_transmit_rtos;
  g_uart2_handle->uart_get_byte = uart_get_byte_rtos;

rtostask

static void CH1_UART2_TxTaskFunction(void *pvParameters)	
{
	uint8_t c = 0;


  g_uart2_handle->uart_init(g_uart2_dev);

	while (1)
	{
		/* send data */
    g_uart2_handle->uart_transmit(g_uart2_dev, &c, 1, 100);
		vTaskDelay(100);
		c++;
	}
}


static void CH2_UART4_RxTaskFunction(void *pvParameters)	
{
	uint8_t c = 0;
	int cnt = 0;
	char buf[100];
	
  g_uart4_handle->uart_init(g_uart4_dev);

	/* 接收数据 */
  g_uart4_handle->uart_receive(g_uart4_dev);

	while (1)
	{	
    g_uart4_handle->uart_get_byte(g_uart4_dev, &c, 200);

		sprintf(buf, "Recv Data : 0x%02x, Cnt : %d", c, cnt++);
		Draw_String(0, 0, buf, 0x0000ff00, 0);
	}
}