《李阳阳-SPI驱动框架精妙设计.pptx》由会员分享,可在线阅读,更多相关《李阳阳-SPI驱动框架精妙设计.pptx(14页珍藏版)》请在三个皮匠报告上搜索。
1、SPI驱动框架精妙设计李阳阳(https:/ IO设备如何管理rt_err_t rt_device_register(rt_device_t dev,const char*name,rt_uint16_t flags);rt_device_t rt_device_find(const char*name);rt_err_t rt_spidev_device_init(struct rt_spi_device*dev,const char*name)struct rt_device*device;RT_ASSERT(dev!=RT_NULL);device=&(dev-parent);/*set
2、 device type*/device-type =RT_Device_Class_SPIDevice;#ifdef RT_USING_DEVICE_OPS device-ops =&spi_device_ops;#else device-init =RT_NULL;device-open =RT_NULL;device-close =RT_NULL;device-read =_spidev_device_read;device-write =_spidev_device_write;device-control=_spidev_device_control;#endif /*registe
3、r to device manager*/return rt_device_register(device,name,RT_DEVICE_FLAG_RDWR);rt_err_t rt_spi_bus_device_init(struct rt_spi_bus*bus,const char*name)struct rt_device*device;RT_ASSERT(bus!=RT_NULL);device=&bus-parent;/*set device type*/device-type =RT_Device_Class_SPIBUS;/*initialize device interfac
4、e*/#ifdef RT_USING_DEVICE_OPS device-ops =&spi_bus_ops;#else device-init =RT_NULL;device-open =RT_NULL;device-close =RT_NULL;device-read =_spi_bus_device_read;device-write =_spi_bus_device_write;device-control=RT_NULL;#endif /*register to device manager*/return rt_device_register(device,name,RT_DEVI
5、CE_FLAG_RDWR);1、添加到内核相关链表进行管理。2、对接相关接口统一应用程序接口。SPI硬件模型抽象之SPI控制器根据RT-Thread面向对象的思维方式,对SPI控制器进行模型抽象:属性:SPI控制器是QSPI控制器还是普通SPI控制器。当前正在使用SPI控制器传输数据的SPI设备。为了方便管理设备,使用IO设备的注册机制,继承IO设备rt_device。行为:传输数据。配置SPI控制器。SPI硬件模型抽象之SPI设备根据RT-Thread面向对象的思维方式,对SPI设备进行模型抽象:属性:SPI设备挂载在哪个SPI控制器上面。SPI设备的一些配置信息,包括工作模式和速率等。SP
6、I设备使用到的cs片选引脚。为了方便管理设备,使用IO设备的注册机制,继承IO设备rt_device。行为:无。为什么每个设备需要单独记录自己的配置信息?SPI控制器的注册和调用流程/注册rt_err_t rt_spi_bus_register(struct rt_spi_bus*bus,const char*name,const struct rt_spi_ops*ops);/调用rt_ssize_t rt_device_write(rt_device_t dev,rt_off_t pos,const void*buffer,rt_size_t size);SPI设备的注册和调用流程/注册r
7、t_err_t rt_spi_bus_attach_device_cspin(struct rt_spi_device*device,const char*name,const char*bus_name,rt_base_t cs_pin,void*user_data);/调用rt_ssize_t rt_device_write(rt_device_t dev,rt_off_t pos,const void*buffer,rt_size_t size);rt_ssize_t rt_spi_transfer(struct rt_spi_device*device,const void*send_
8、buf,void*recv_buf,rt_size_t length);SPI驱动框架传输数据接口rt_ssize_t rt_spi_transfer(struct rt_spi_device*device,const void *send_buf,void *recv_buf,rt_size_t length)spi_device_1spi_device_1spi_device_2spi_device_2spi_device_3spi_device_3spi_bus_1spi_bus_1spi_bus_2spi_bus_2rt_ssize_t rt_spi_transfer(struct r
9、t_spi_device*device,const void *send_buf,void *recv_buf,rt_size_t length)rt_ssize_t result;struct rt_spi_message message;if(device-bus-owner!=device)device-bus-ops-configure(device,&device-config);device-bus-owner=device;/*initial message*/.device-bus-ops-xfer(device,&message);return result;SPI硬件模型抽
10、象之SPI消息对SPI消息进行模型抽象:属性:发送数据和接收数据的缓存区。传输数据的长度。是否连续发送消息。消息发送前后cs片选引脚的状态。行为:无。massagemassage如何控制SPI控制器的发送和接收?SPI消息之CS片选引脚管理static rt_ssize_t mcu_spi_xfer(struct rt_spi_device*device,struct rt_spi_message*message)if(message-cs_take&!(device-config.mode&RT_SPI_NO_CS)&(device-cs_pin!=PIN_NONE)if(device-co
11、nfig.mode&RT_SPI_CS_HIGH)rt_pin_write(device-cs_pin,PIN_HIGH);else rt_pin_write(device-cs_pin,PIN_LOW);/真正的控制硬件进行数据传输的代码 if(message-cs_release&!(device-config.mode&RT_SPI_NO_CS)&(device-cs_pin!=PIN_NONE)if(device-config.mode&RT_SPI_CS_HIGH)rt_pin_write(device-cs_pin,PIN_LOW);else rt_pin_write(device
12、-cs_pin,PIN_HIGH);软件SPI的设计思路梳理一下硬件SPI传输数据的流程:根据SPI设备的工作特性来配置硬件SPI控制器。配置SPI控制器的数据寄存器用于发送数据。SPI控制器将会根据配置的工作模式和发送的数据来控制GPIO控制器发出相应波形。观察上述流程,重点是什么?控制GPIO控制器发出相应的波形。硬件SPI:通过操作SPI相关寄存器来间接间接控制GPIO引脚发出工作时序波形。软件SPI:通过操作GPIO相关寄存器来直接直接控制GPIO引脚发出工作时序波形。rt_ssize_t spi_hard_xfer(struct rt_spi_device*device,struct
13、 rt_spi_message*message)/配置一些跟数据传输相关的寄存器rt_err_t spi_hard_configure(struct rt_spi_device*device,struct rt_spi_configuration*configuration)/配置一些跟波形配置相关的寄存器static const struct rt_spi_ops spi_hard_ops=.configure=spi_hard_configure,.xfer =spi_hard_xfer,;rt_ssize_t spi_soft_xfer(struct rt_spi_device*devi
14、ce,struct rt_spi_message*message)/直接操作使用到的传输引脚发出高低电平或者读取高低电平rt_err_t spi_soft_configure(struct rt_spi_device*device,struct rt_spi_configuration*configuration)/配置电平反转延时之类的(控制传输速率)static const struct rt_spi_ops spi_soft_ops=.configure=spi_soft_configure,.xfer =spi_soft_xfer,;对于任何MCU,如果配置相同,发出的波形即相同,而不一样的是对引脚的控制。对此可以对SPI波形的控制再做一层封装,而对引脚的控制留出接口。软件SPI的框架以及注册流程软件SPI的调用流程Thank you!