rt-thread从头解析串口设备初始化及使用

一、怎么使用

例子:

#define        RT_DEVICE_UART           "uart1" 

static rt_device_t uart;                                   // 静态创建一个串口设备

const char *str ="Hello World!\n";

uart = rt_device_find(RT_DEVICE_UART);  // 查找串口设备,函数会在设备链表中找出与RT_DEVICE_UART宏指定的设备名一致的设备

rt_device_open(uart, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);  // 打开该串口设备
rt_device_write(uart, 0, str, rt_strlen(str));     // 发送str指向的数据

rt_device_close(uart);                                    // 关闭串口设备

二、从头开始解析

$Super$$main函数调用rtthread_startup(),
components.c
int $Super$$main(void)
{
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}

rtthread_startup()->rt_hw_board_init()
components.c
int rtthread_startup(void)
{
……
/* board level initalization
* NOTE: please initialize heap inside board initialization.
*/
rt_hw_board_init();
……
}

rt_hw_board_init()->rt_components_board_init()
board.c
void rt_hw_board_init(void)
{
……
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
……
}

在rt_components_board_init()函数里会依次调用INIT_BOARD_EXPORT()这个宏存放在特定位置的函数,自然而然的调用了rt_hw_usart_init()这个函数
drv_usart.c
INIT_BOARD_EXPORT(rt_hw_usart_init);
components.c
void rt_components_board_init(void)
{
……
for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
{
(*fn_ptr)();
}
……
}

/***********************************************************************************************************/

drv_usart.c

int rt_hw_usart_init(void)
{
    struct stm32_uart *uart;
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#if defined(RT_USING_UART1)
    uart = &uart1;
    config.baud_rate = BAUD_RATE_115200;
    serial1.ops    = &stm32_uart_ops; // 底层操作函数
    serial1.config = config;
    MX_USART_UART_Init(&uart->huart); // 硬件层的初始化
    /* register UART1 device */
    rt_hw_serial_register(&serial1, "uart1",
                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                          uart);
#endif /* RT_USING_UART1 */
    ……
}

说明:rt_hw_usart_init()函数进行了默认的一系列初始化工作,serial1.ops 存放收发和配置函数。

并把serial1以uart1为名放入设备链表中,查找可以用rt_device_find(“uart1”)函数实现。

serial.c

rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
                               const char              *name,
                               rt_uint32_t              flag,
                               void                    *data)
{
    rt_err_t ret;
    struct rt_device *device;
    RT_ASSERT(serial != RT_NULL);

    device = &(serial->parent);

    device->type        = RT_Device_Class_Char;
    device->rx_indicate = RT_NULL;
    device->tx_complete = RT_NULL;

    device->init        = rt_serial_init;
    device->open        = rt_serial_open;
    device->close       = rt_serial_close;
    device->read        = rt_serial_read;
    device->write       = rt_serial_write;
    device->control     = rt_serial_control;
    device->user_data   = data;

    /* register a character device */
    ret = rt_device_register(device, name, flag);

    return ret;
}

说明:应用层面的rt_device_open()、rt_device_write()和rt_device_read()函数就是调用对应的

rt_serial_open()、rt_serial_write()、 rt_serial_read()函数,最终调用rt_hw_usart_init()函数里

stm32_uart_ops结构体里存放的的函数。

比如rt_serial_read()函数,调用关系rt_serial_read()->_serial_poll_rx()->serial->ops->getc()

serial.c

static rt_size_t rt_serial_read(struct rt_device *dev,
                                rt_off_t          pos,
                                void             *buffer,
                                rt_size_t         size)
{
    struct rt_serial_device *serial;

    RT_ASSERT(dev != RT_NULL);
    if (size == 0) return 0;

    serial = (struct rt_serial_device *)dev;

    if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
    {
        return _serial_int_rx(serial, buffer, size);
    }

    return _serial_poll_rx(serial, buffer, size);
}

 serial.c

rt_inline int _serial_poll_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
{
    int ch;
    int size;

    RT_ASSERT(serial != RT_NULL);
    size = length;

    while (length)
    {
        ch = serial->ops->getc(serial);
        if (ch == -1) break;

        *data = ch;
        data ++; length --;

        if (ch == '\n') break;
    }

    return size - length;
}

这样初始化之后应用层函数就可以操作rt_device_write()和rt_device_read()等函数。

总结:

        1、首先创建一个struct rt_serial_device serial1;设备;

        2、对串口设备serial1进行初始化,挂接底层处理函数,注册等工作;

        3、应用层使用相应接口函数使用串口设备;

  • 21
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值