做网站费用可以看为广告费用吗wordpress注册字段
目录
- 1.uart设备基类
 - 2.uart设备基类的子类
 - 3.初始化/构造流程
 - 3.1设备驱动层
 - 3.2 设备驱动框架层
 - 3.3 设备io管理层
 
- 4.总结
 - 5.使用
 
1.uart设备基类
此层处于设备驱动框架层。也是抽象类。
在/ components / drivers / include / drivers 下的serial.h定义了如下uart设备基类
 struct rt_serial_device
 {
 struct rt_device parent;
 const struct rt_uart_ops *ops;
 struct serial_configure config;
 void *serial_rx;
 void *serial_tx;
 struct rt_spinlock spinlock;
 struct rt_device_notify rx_notify;
 };
 uart设备基类继承自设备基类,剩下都是私有属性和私有方法。
uart设备基类的方法定义如下
 struct rt_uart_ops
 {
 rt_err_t (*configure)(struct rt_serial_device *serial, struct serial_configure *cfg);
 rt_err_t (*control)(struct rt_serial_device *serial, int cmd, void *arg);
 int (*putc)(struct rt_serial_device *serial, char c);
 int (*getc)(struct rt_serial_device *serial);
 rt_ssize_t (*dma_transmit)(struct
 rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
 };
抽象出了串口的共性配置、发送、接受、dma传输成为uart设备基类的方法。
2.uart设备基类的子类
此层是设备驱动层,此类是实现类。各个uart设备基类的子类在各个bsp来实现,例如
 / bsp / stm32 / libraries / HAL_Drivers / drivers 下的drv_usart.h定义的stm32_uart 类,这是可以实例化的实现类。其他芯片厂家如此这般一样。
3.初始化/构造流程
以stm32为例,从设备驱动层、设备驱动框架层到设备io管理层从下到上的构造/初始化流程如下
3.1设备驱动层
此层是bsp层,可以实例化的终类地。
c文件:
 / bsp / stm32 / libraries / HAL_Drivers / drivers 下的drv_usart.h。
定义了stm32的uart类
 struct stm32_uart
 {
 UART_HandleTypeDef handle;
 struct stm32_uart_config *config;
 rt_uint32_t DR_mask;
#ifdef RT_SERIAL_USING_DMA
 struct
 {
 DMA_HandleTypeDef handle;
 rt_size_t remaining_cnt;
 } dma_rx;
 struct
 {
 DMA_HandleTypeDef handle;
 } dma_tx;
 #endif
rt_uint16_t uart_dma_flag;
 struct rt_serial_device serial;
 };
 stm32的uart设备类继承自uart设备基类serial,但是这样定义的类把父类写到最后——和rtt设备io框架不一致,改成这样多好:
 struct stm32_uart
 {
 struct rt_serial_device serial;
 UART_HandleTypeDef handle;
 struct stm32_uart_config *config;
 rt_uint32_t DR_mask;
#ifdef RT_SERIAL_USING_DMA
 struct
 {
 DMA_HandleTypeDef handle;
 rt_size_t remaining_cnt;
 } dma_rx;
 struct
 {
 DMA_HandleTypeDef handle;
 } dma_tx;
 #endif
rt_uint16_t uart_dma_flag;
 };
 这样舒服多了。
在/ bsp/stm32/libraries /HAL_Drivers/drivers/drv_usart.c中:
实例化了stm32的uart设备:
 static struct stm32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
stm32支持多个串口,所以可以实例化多个stm32串口设备对象。
重写了uart设备基类的方法:
 static const struct rt_uart_ops stm32_uart_ops =
 {
 .configure = stm32_configure,
 .control = stm32_control,
 .putc = stm32_putc,
 .getc = stm32_getc,
 .dma_transmit = stm32_dma_transmit
 };
int rt_hw_usart_init中开启stm32的uart设备的初始化:
 重写uart设备基类的方法与属性
 uart_obj[i].config = &uart_config[i];
 uart_obj[i].serial.ops = &stm32_uart_ops; uart_obj[i].serial.config = config;
最后调用/ components / drivers /serial /serial.c的rt_device_pwm_register函数来初始化uart设备基类对象:
 rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | uart_obj[i].uart_dma_flag , NULL);
3.2 设备驱动框架层
/ components / drivers /serial 下的serial.c实现了设备驱动框架层接口rt_hw_serial_register,是uart设备驱动框架层的入口,开启uart设备基类的构造/初始化流程。
该层重写了uart设备基类的父类——设备基类——的方法:
 #ifdef RT_USING_DEVICE_OPS
 device->ops = &serial_ops;
 #else
 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;
 #endif
并最终调用设备基类的构造函rt_device_register。
3.3 设备io管理层
在/ components / drivers / core 下的device.c中实现了rt_device_register,它是io管理层的入口。
 它将stm32 uart设备对象放到对象容器里管理。
4.总结
整个设备对象的构造/初始化流程其实是对具体设备对象也就是结构体进行初始化赋值——它这个结构体是包含一个个的结构体——模拟的是面向对象的继承机制。跟套娃似的,层层进行初始化。这样的好处是什么?每层有每层的初始化(构造)函数,就模拟了面向对象的构造函数——按照先调用子类构造/初始化函数,再调用父类的构造/初始化函数方式——其实也是子类构造/初始化函数调用父类构造/初始化函数的流程,来完成设备对象的初始化/构造。最终放到对象容器里来管理。
 这样的好处是可扩展,如搭积木似的,也是对内封闭,对外开放,扩展性好,模拟的是面向对象的继承多态机制。
其实每个类的注册函数模拟的是面向对象的构造函数。
5.使用
文档
