IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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 模块与接口

1.2 非DMA传输

?1.3 DMA传输

1.3.1 DMA寄存器

1.3.3 DMA水线设置

2.调试问题

2.1 uboot

2.1.1 Read Flash ID失败

?2.1.2 一次只能读出27B有效内容

?2.2 kernel

2.2.1 spi访问读取内容无效

2.2.2 dma传输rx超时

3.?内核SPI驱动

3.1 SPI框架

3.2 spi-dw驱动

4.调试命令

4.1 uboot

4.2 kernel

4.2.1 mtd_debug

4.2.2 debugfs

4.2.3 module parameter


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 uboot

2.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 kernel

2.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配置项:

spi0: spi@f0da0000 {
    compatible = "snps,dw-apb-ssi";
    pinctrl-names = "default";
    pinctrl-0 = <&PA26_pinctrl>;
    cs-gpios = <&porta 26 GPIO_ACTIVE_LOW>;
};

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数据。

? ? ? tx方向,传输一个data item意味着从DDR取8bit数据,填入ssi fifo 32bits entry(DR寄存器)的低8位,一次burst传4个data item,也就是4B;

? ? ? rx方向,传输一个data item意味着ssi fifo 32bits entry(DR寄存器)读入32位数据,取低8位填入DDR,一次burst传4个data item,也就是4B。

? ? ? DMA的DST和SRC虽然数据宽度不同,但是一次传输的有效数据都是4B,所以dma_tx_req和dma_rx_req最终的次数也是一致的。

下面分析软件从FLASH offset = 0处读取48B数据的dma流程。

有问题的配置对应的DMA处理流程。

发送方向:

? ? ? (1) ssi tx fifo空,ssi发起dma_tx_req,dmac响应请求,发起一次tx burst,注入DEST_MSIZE个数据(4个),一共写入4*8bits = 4B。

? ? ? (2)此时仍然tx fifo有效数据仍低于DMATDLR水线,于是ssi再次发起若干次dma_tx_req,dmac响应请求,每次都注入DEST_MSIZE个数据,直到tx fifo中数据个数高于DMATDLR水线。

? ? ? (3) 随着ssi发送数据,当tx fifo中数据个数下降到DMATDLR水线,ssi再次发起dma_tx_req,dmac响应请求,发起一次tx burst,再注入DEST_MSIZE个数据。

? ? ? 下面重复步骤(3)直到所有数据均写入tx fifo,等待ssi陆续发完。

接收方向:

? ? ? (1) 由于tx方向持续发送数据,在接收方向上也会持续接收数据。

? ? ? ?当ssi rx fifo中数据上涨到达(DMARDLR + 1)水线,ssi发起dma_rx_req,dmac响应请求,发起一次rx burst,读出SRC_MSIZE个数据(4个),一共读出4*8bits = 4B。

? ? ? (2) 如果此时ssi rx fifo中数据个数仍高于(DMARDLR + 1)水线,那么ssi仍会持续发起dma_rx_req,dmac也会持续读出数据,直到ssi rx fifo中数据个数低于(DMARDLR + 1)水线。

? ? ? (3)?这里DMARDLR + 1 = 16,而SRC_MSIZE = 4,这就使得ssi rx fifo中会残留12B数据,因为达不到水线,无法通知dmac取走,于是导致rx方向最终超时失败。

?正确的配置对应的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 相关的驱动分为了几部分:

? ? ?(1)?SPI 主机以及主机驱动:SoC 的 SPI Controller 部分的驱动

? ? ?(2)?SPI 外设驱动描述:比如 SPI Flash 驱动

? ? ?(3)?SPI 从设备描述:比如 SPI Flash 设备

? ? ?(4)?SPI 传输层描述:spi_transfer 和 spi_message 组成

? ? ? 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申请通道资源。

  1. spi框架中先map buf,再传输message,提交dma描述符,挂接回调,传输发起后阻塞等待completion;
  2. dma传输,dma中断处理确认通道传输完成,调度vchan tasklet;
  3. vchan tasklet调用dma描述符的callback回调,complete传输;
  4. spi框架从阻塞处继续执行,unmap buf,message传输完成。

函数返回0。

4.调试命令

4.1 uboot

(1) sf 相关命令

(2) sspi [<bus>:]<cs>[.<mode>][@<freq>] <bit_len> <dout>

4.2 kernel

4.2.1 mtd_debug

SPI 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例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:46:32  更:2022-02-26 11:48:43 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码