国产嵌入式操作系统——RT-Thread的串口接收解析

RT-Thread的串口接收解析

RT-Thread的串口接收非常方便,只需要设置好接收回调函数,在回调函数中释放信号量,然后在读数线程中等待信号量,调用设备框架读取设备缓存即可,那底层到底怎么实现的呢,让我们来看看

1.设置回调函数

rt_device_set_rx_indicate(dev->serial,uart_input);//通过这个设置接收中断时要进行的工作,使用回调函数

2.函数调用路径

中断触发->USARTx_IRQHandler()【位于drv_usart】->uart_isr()【位于drv_usart】->rt_hw_serial_isr()【位于serial】->serial->parent.rx_indicate

3.Serial结构体的继承关系

rt_serial_device可以说是stm32_uart的父结构体,rt_device是rt_serial_device的父结构体,rt_object是rt_device的父结构体,这里类似C++的类的概念,但实际是结构体,不同点是结构体的成员需要赋值语句进行初始化,没有构造函数。
整理了以上结构体的定义,可以看到一层一层的包含关系。

/**
 * Base structure of Kernel object
 */
struct rt_object
{
    char       name[RT_NAME_MAX];                       /**< name of kernel object */
    rt_uint8_t type;                                    /**< type of kernel object */
    rt_uint8_t flag;                                    /**< flag of kernel object */

#ifdef RT_USING_MODULE
    void      *module_id;                               /**< id of application module */
#endif
    rt_list_t  list;                                    /**< list node of kernel object */
};
/**
 * Device structure
 */
struct rt_device
{
    struct rt_object          parent;                   /**< inherit from rt_object */

    enum rt_device_class_type type;                     /**< device type */
    rt_uint16_t               flag;                     /**< device flag */
    rt_uint16_t               open_flag;                /**< device open flag */

    rt_uint8_t                ref_count;                /**< reference count */
    rt_uint8_t                device_id;                /**< 0 - 255 */

    /* device call back */
    rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);
    rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);

#ifdef RT_USING_DEVICE_OPS
    const struct rt_device_ops *ops;
#else
    /* common device interface */
    rt_err_t  (*init)   (rt_device_t dev);
    rt_err_t  (*open)   (rt_device_t dev, rt_uint16_t oflag);
    rt_err_t  (*close)  (rt_device_t dev);
    rt_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
    rt_size_t (*write)  (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
    rt_err_t  (*control)(rt_device_t dev, int cmd, void *args);
#endif

#if defined(RT_USING_POSIX)
    const struct dfs_file_ops *fops;
    struct rt_wqueue wait_queue;
#endif

    void                     *user_data;                /**< device private data */
};

struct rt_serial_device
{
    struct rt_device          parent;

    const struct rt_uart_ops *ops;
    struct serial_configure   config;

    void *serial_rx;
    void *serial_tx;
};
/* stm32 uart dirver class */
struct stm32_uart
{
    UART_HandleTypeDef handle;
    struct stm32_uart_config *config;

#ifdef RT_SERIAL_USING_DMA
    struct
    {
        DMA_HandleTypeDef handle;
        rt_size_t last_index;
    } dma_rx;
    struct
    {
        DMA_HandleTypeDef handle;
    } dma_tx;
#endif
    rt_uint16_t uart_dma_flag;
    struct rt_serial_device serial;
};

串口收到数据后会通过rt_dma_recv_update_put_index放入rt_serial_rx_fifo,rt_serial_rx_fifo就是rt_serial_device类中的serial_rx成员(类型是rt_serial_rx_fifo类的指针)

/*
 * Serial FIFO mode 
 */
struct rt_serial_rx_fifo
{
    /* software fifo */
    rt_uint8_t *buffer;

    rt_uint16_t put_index, get_index;

    rt_bool_t is_full;
};

这里放一下别人的图,做的比较好我就直接拿来用了原文链接RT-Thread的串口V1接收
在这里插入图片描述
图1 中断接收
在这里插入图片描述
图2 DMA接收

rt_serial_rx_fifo在内存的位置分析

rt_serial_rx_fifo到底在内存什么位置呢,我找V1版本没有找到,有人在V2上似乎找到了RT-Thread-RT-Thread 串口驱动问题-缓存一致性RT-Thread问答社区
在这里插入图片描述
图3 SerialV2

V2版本是malloc申请的,不过提问者遇到了申请结果在DMA不能访问的DTCM的问题,好在他自己写了一个malloc解决了,话说回来V1怎么搞的呢,哈哈也找到了,也是malloc出来的。
在这里插入图片描述
图4 serialV1初始化
在这里插入图片描述
图5 serialV1申请fifo内存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值