dw ssi(spi)驱动调试

2023-10-27 18:50
文章标签 驱动 调试 dw spi ssi

本文主要是介绍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

这篇关于dw ssi(spi)驱动调试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/287664

相关文章

Java服务实现开启Debug远程调试

《Java服务实现开启Debug远程调试》文章介绍如何通过JVM参数开启Java服务远程调试,便于在线上排查问题,在IDEA中配置客户端连接,实现无需频繁部署的调试,提升效率... 目录一、背景二、相关图示说明三、具体操作步骤1、服务端配置2、客户端配置总结一、背景日常项目中,通常我们的代码都是部署到远程

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

在IntelliJ IDEA中高效运行与调试Spring Boot项目的实战步骤

《在IntelliJIDEA中高效运行与调试SpringBoot项目的实战步骤》本章详解SpringBoot项目导入IntelliJIDEA的流程,教授运行与调试技巧,包括断点设置与变量查看,奠定... 目录引言:为良驹配上好鞍一、为何选择IntelliJ IDEA?二、实战:导入并运行你的第一个项目步骤1

Linux之platform平台设备驱动详解

《Linux之platform平台设备驱动详解》Linux设备驱动模型中,Platform总线作为虚拟总线统一管理无物理总线依赖的嵌入式设备,通过platform_driver和platform_de... 目录platform驱动注册platform设备注册设备树Platform驱动和设备的关系总结在 l

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

IDEA如何实现远程断点调试jar包

《IDEA如何实现远程断点调试jar包》:本文主要介绍IDEA如何实现远程断点调试jar包的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录问题步骤总结问题以jar包的形式运行Spring Boot项目时报错,但是在IDEA开发环境javascript下编译

一文彻底搞懂Java 中的 SPI 是什么

《一文彻底搞懂Java中的SPI是什么》:本文主要介绍Java中的SPI是什么,本篇文章将通过经典题目、实战解析和面试官视角,帮助你从容应对“SPI”相关问题,赢得技术面试的加分项,需要的朋... 目录一、面试主题概述二、高频面试题汇总三、重点题目详解✅ 面试题1:Java 的 SPI 是什么?如何实现一个

Dubbo之SPI机制的实现原理和优势分析

《Dubbo之SPI机制的实现原理和优势分析》:本文主要介绍Dubbo之SPI机制的实现原理和优势,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Dubbo中SPI机制的实现原理和优势JDK 中的 SPI 机制解析Dubbo 中的 SPI 机制解析总结Dubbo中