《李陽陽-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!