| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> dw ssi(spi)驱动调试 -> 正文阅读 |
|
[嵌入式]dw ssi(spi)驱动调试 |
目录 1.芯片简介1.1 模块与接口? ? ? dw_apb_ssi支持全双工的master和slave模式,支持dma传输,支持SPI(Motorola Serial Peripheral Interface),SSP(Texas Instruments Serial Protocol),National Semiconductor Microwire三种接口类型。支持Transmit and Receive,Transmit Only,Receive Only,EEPROM Read四种传输模式。 APB Interface用于寄存器访问和数据收发。 DMA Interface用于跟DMA控制器通信,进行握手/传输请求/传输应答等控制信号的交互。 1.2 非DMA传输master模式数据传输流程流程如下: ? ? ? (1)?软件配置控制寄存器设置传输模式,分频系数,FIFO收发门限,中断使能,选择device片选,然后使能控制器,发起传输。 ? ? ? (2)?软件写Tx FIFO,SPI传输的特点决定了有发送才有接收,发送多少数据,接收多少数据。如果传输数据较长,那么要考虑根据FIFO的长度将数据分片。如果只是发送数据,那么直接发送有效的数据内容即可。接收数据时一般配置为Transmit and Receive模式,此时为了接收数据,需要持续在发送方向发送dummy数据。 ? ? ? (3)?软件持续从Rx FIFO中读出数据。 非DMA传输可以采取轮询或者中断方式,uboot下采用轮询模式,内核驱动两种方式都支持。 ?1.3 DMA传输1.3.1 DMA寄存器DMA传输方式需要通用DMA控制器驱动配合。dw ssi引出一组dma控制信号与DMAC交互。 dma_tx_req/dma_rx_req/dma_tx_single/dma_rx_single 是ssi发给dmac的请求信号。 dma_tx_ack/dma_rx_ack 是dmac发给ssi的应答信号。 此外,dw ssi还提供了3个DMA相关的寄存器用于使能DMA收发和设置DMA水线。 ? ? ? DMACR用于使能DMA传输,DMATDLR配置tx fifo水线,DMARDLR配置rx fifo水线。 ? ? ? 当tx fifo中的待发数据个数向下减少到水线值时,ssi向dmac发起dma_tx_req,此时dmac应该往tx fifo中注入数据,使得待发数据个数重新达到水线之上。 ? ? ? 然后随着ssi逐步发出数据,待发数据个数又开始减少到达水线,于是再次发起dma_tx_req,提示dmac再次注入数据,如此循环。 ? ? ? 水线设置低,一次burst发送的数据个数较多,ssi向dmac发起dma_tx_req的频率相对较低;水线设置高,一次burst发送的数据个数较少,ssi向dmac发起dma_tx_req的频率相对较高。 ? ? ? dmac应该及时注入数据,如果水线设置较低,tx fifo很快就会将fifo中剩余的数据发完,而dmac还没来得及注入足够的数据,就会发生下溢(ssi无数据可发)。 ? ? ? 当rx fifo中的待收数据个数向上增长到水线值时,发起dma_rx_req,此时dmac应该从rx fifo中取走数据,使得待收数据个数降到水线之下。 ? ? ? 然后随着ssi逐步接收数据,待收数据个数又开始增长到达水线,于是再次发起dma_rx_req,提示dmac再次取走数据,如此循环。 ? ? ? 水线设置低,一次burst接收的数据个数较少,ssi向dmac发起dma_rx_req的频率相对较高;水线设置高,一次burst接收的数据个数较多,ssi向dmac发起dma_rx_req的频率相对较低。 ? ? ? dmac应该及时取走数据,如果水线设置较高,rx fifo空闲空间很快将被耗尽,而dmac还没来得及取走数据,就会发生上溢(ssi无空间保存新接收的数据)。 ?1.3.2 DMA传输分片 一次block传输12个data item,分为3次burst,每次burst传输4个data item。 ? ? ? ?一次block传输15个data item,分为3次burst和3次single,每次burst传输4个data item,每次single传输1个data item。 1.3.3 DMA水线设置dw_ssi通常用于MEM <-> DEVICE 这种对接场景,发送方向DST device侧发送速率较低,接收方向SRC device侧接收速率较低。以下是手册建议的水线配置: DMA.CTLx.DEST_MSIZE = FIFO_DEPTH - SSI.DMATDLR DMA.CTLx.SRC_MSIZE = SSI.DMARDLR + 1 2.调试问题2.1 uboot2.1.1 Read Flash ID失败【问题现象】 uboot命令行视图执行sf probe命令,未读到有效数据。 ? ? ? 先确认SPI相关引脚的复用配置,确认为SPI模式。 ? ? ? 然后对比A53验证代码,可以读到ID,说明硬件没问题。不同在于收发数据流程:A53中将opcode和dummy data合并在一起,在一个transfer里发送到device,但uboot没有这样的处理。 【问题原因】 ? ? ? 使用dw ssi控制device片选信号时,包括READ ID在内的read reg/read data流程要求 ? ? ? opcode/addr/dummy一起发给device,如果是读取数据,tx方向需要继续发送dummy数据,接收方向在接收数据后需要过滤掉无效数据(对应opcode/addr/dummy收到的内容)。 ?2.1.2 一次只能读出27B有效内容【问题现象】 从offset=0开始连续读取37B,只有前面27B有效,后面10B内容为0xff。 从offset=0开始读0x25(37B)数据,因为fifo为32B,所以软件中读操作拆分成2段: 第一段:tx opcode=0bh, addr=0x000000, dummy=0xff, tx padding 27B, 同时rx 27B data 第二段:tx opcode=0bh, addr=0x00001b, dummy=0xff, tx padding 10B, 同时rx 10B data 但从实际结果看,第一段读到的内容是正确的,从0x00 - 0x1a; 第二段读到的内容是全FF,正确的数据应该是0x1b - 0x24。 【问题原因】 ? ? ? Read data使用的address必须以小端方式发送给device,offset=0x00时,大小端都一样,所以可以读到正确的内容,offset=0x1b时,实际发送的addr是0x1b0000,该地址实际上未被写入内容,读到的就是0xff。正确的做法是将地址转成小端。 ? ?2.2 kernel2.2.1 spi访问读取内容无效【问题现象】 ? ? ? 内核spi框架传输opcode/addr/dummy与后面的data传输,分成2次transfer完成,这样无法得到正确的数据。像uboot那样将2次transfer拼接成一个,可以得到正确的结果。但是这样一来在spi访问前后增加了2次内存拷贝,开销很大。 ? ? ? 抓波形可以看到,分2次传输时,cs中间自动拉高了,接下来opcode=0x9f对应的接收内容是0x00。 ? ? ? 而合并成1次transfer时,只出一次片选,opcode=0x9f读到的内容确实是FLASH的JEDEC ID。 ?【问题原因】 ? ? ? 控制器驱动cs时,2次transfer中间cs自动拉高,相当于中断了完整的SPI访问流程,导致得不到正确的数据。将cs引脚配置为gpio模式,由软件控制,2次tranfer过程全程使能cs不拉高,可以得到正确的数据内容。 ?对应的dts新增cs-gpios配置项:
2.2.2 dma传输rx超时【问题现象】 dma方式从flash读48 byte内容,dma tx结束,dma rx超时。 【问题原因】 ? ? ? dw DMAC控制器的硬件实现限制最大发送/接收的Burst Len为4,而dw ssi DMARDLR配置接收水线为16,大于DMA通道的Burst Len,使得传输过程最后rx fifo存有数据,但是因为达不到水线,无法触发dma_rx_req,导致数据残留在rx fifo中未被软件接收,dma rx超时。 ? ? ? 修改dts中DMAC的burst能力,限制为4,这样相应的dw ssi rx fifo接收水线DMARDLR也配置为4,可以保证rx fifo中数据被完整接收。 ? 注意:虽然ssi DR的宽度为32bits,但一次只能收发8bit数据。
下面分析软件从FLASH offset = 0处读取48B数据的dma流程。 有问题的配置对应的DMA处理流程。 发送方向:
接收方向:
?正确的配置对应的DMA处理流程。 发送方向:跟之前相同 接收方向:DMARDLR + 1 = SRC_MSIZE = 4,保证了一次rx burst读走rx fifo中所有的数据,没有残留,所以rx 方向可以顺利结束。 ? ? ? 残留数据的验证:dma超时后读取RXFLR,确认此时rx fifo中是否有数据,有的话直接dump DR寄存器内容,确认正好就是最后12B数据内容。??? 3.?内核SPI驱动3.1 SPI框架Linux SPI 驱动结构中,将 SPI 相关的驱动分为了几部分:
? ? ? SPI 主机控制器部分是整个 SPI 系统的核心存在,它并不属于 SPI 下的 bus、device、drvier 这一组结构,因为他并不是挂接到 bus 上的 device,更不是对应挂接在 bus 上 device 的 driver,而是相对独立的一个存在,所以 SPI 控制器部分,是连接到 platform 下的,并执行 platform 的 probe。? ? ? ? ?在数据发送的结构部分,内核将其抽象如下,一次传输封装为message,一个message包含一个或多个transfer。 3.2 spi-dw驱动? ? ? spi读写流程,device驱动封装读写接口,调用spi框架的传输API spi_sync(),执行device所属的控制器驱动挂接的transfer_one()接口,实现总线层面的数据访问,传输完成后,spi_sync()返回阻塞的读写进程,得到spi访问的结果。 以SPI FLASH驱动m25p80为例: read流程 (1) mtd_debug 或者其它应用程序 -> m25p80_read_reg() -> spi_sync(spi, &message) -> spi_transfer_one_message() -> dw_spi_transfer_one() -> wait_for_completion_timeout() 阻塞 (2) dw ssi控制器spi传输 dw_spi_irq() -> dw_reader() -> complete() 通知阻塞流程继续往下执行 (3) mtd_debug 或者其它应用程序得到spi访问数据。 其中dw ssi控制器的传输接口dw_spi_transfer_one()支持三种传输方式:轮询,中断,dma。 (1)轮询 调用dw_spi_poll_transfer(dws, transfer)完成传输,边发边收。 函数返回0。 (2)中断 调用dw_spi_irq_setup(dws)设置中断,后续数据收发在ssi中断处理中完成。 函数返回1。 (3)dma 调用dw_spi_dma_transfer()触发dma传输,后续传输由dma完成,dma中断确认完成状态。spi-dw驱动在初始化时需要事先从通用dma申请通道资源。
函数返回0。 4.调试命令4.1 uboot(1) sf 相关命令 (2) sspi [<bus>:]<cs>[.<mode>][@<freq>] <bit_len> <dout> 4.2 kernel4.2.1 mtd_debugSPI FLASH读/擦/写。 #?mtd_debug????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? usage:?mtd_debug info <device>?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????mtd_debug read <device> <offset> <len> <dest-filename>??????????????????????????????????????????????????????????????????????? ???????mtd_debug write <device> <offset> <len> <source-filename>???????????????????????????????????????????????????????????????????? ???????mtd_debug erase <device> <offset> <len> 4.2.2 debugfs查看ssi寄存器内容。 #?mount -t debugfs none /sys/kernel/debug??????????????????????????????????????????????????????????????????????????????????????????? #?cat /sys/kernel/debug/dw_spi0/registers??????????????????????????????????????????????????????????????????????????????????????????? CTRLR0 ???????= 0x00070000 ?????? .........................? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 4.2.3 module parameter使能/去使能dma传输。 #?echo 1 > /sys/module/spi_dw/parameters/dma_enable #?echo 0 > /sys/module/spi_dw/parameters/dma_enable |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 9:51:49- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |