芯片:esp32
开发环境:espidfv4.4
一、官网相关资料(又是英文—)
1)简介
SPI,没啥信息,跳过
2)esp32s3 SPI外设介绍
-
ESP32-S3集成了4个SPI外围设备。emm,实际能用的是两个
-
SPI0和SPI1在内部用于访问ESP32-S3的flash。两个控制器共享相同的SPI总线信号,并且有一个仲裁器来确定哪一个可以访问总线。
-
目前,SPI主驱动程序不支持SPI1总线。
-
SPI2和SPI3是通用SPI控制器。它们对用户开放。SPI2和SPI3具有各自名称相同的独立信号总线。SPI2有6条CS线路。SPI3有3条CS线路。每条CS线路可用于驱动一个SPI从设备。??cs线随便个IO不就可以
3)相关术语
Term | Definition |
---|---|
Host | 主机,ESP32-S3内部的SPI控制器外围设备,通过总线启动SPI传输,并充当SPI主设备。 |
Device | SPI从设备。SPI总线可以连接到一个或多个设备。每个设备共享MOSI、MISO和SCLK信号,但只有当主机断言设备的单个CS线路时,才在总线上激活。 |
Bus | 一种信号总线,后面不用看,对连接到一个主机的所有设备都是公用的。通常,总线包括以下线路:MISO、MOSI、SCLK、一条或多条CS线路,以及可选的QUADWP和QUADHD。因此,设备连接到相同的线路,除了每个设备都有自己的CS线路。如果以菊花链方式连接,多个设备也可以共享一条CS线路。 |
MOSI | Master Out, Slave In, |
MISO | Master In, Slave Out |
SCLK | 时钟 |
CS | 片选 |
QUADWP | 写入保护信号。用于4位(qio/qout)交易。也适用于八进制/OPI模式下的数据2信号。 |
QUADHD | 保持信号。用于4位(qio/qout)交易。同样适用于八进制/OPI模式下的数据3信号。 |
DATA4 | Data4 signal in Octal/OPI mode. |
DATA5 | Data5 signal in Octal/OPI mode. |
DATA6 | Data6 signal in Octal/OPI mode. |
DATA7 | Data7 signal in Octal/OPI mode. |
Assertion | 断言,激活线路的动作。 |
De-assertion | 取消断言,将线路返回非活动(返回空闲)状态的操作。 |
Transaction | 主机断言CS线路、向设备传输数据和从设备传输数据以及取消断言CS线路的一个实例。事务是原子的,这意味着它们永远不会被另一个事务中断。 |
Launch edge | 不懂 源寄存器*将信号发射到线路上的时钟边沿。 |
Latch edge | 亦不懂 目的寄存器*锁存在信号中的时钟的dge。 |
4)驱动特点
SPI主驱动程序控制主机与设备的通信。驱动程序支持以下功能:
-
多线程环境
-
读写数据时对DMA传输的透明处理
-
来自同一信号总线上不同设备的数据的自动时分复用,请参阅SPI总线锁定。嘛意思
-
SPI主驱动器具有连接到单个总线的多个设备的概念(共享单个ESP32-S3 SPI外围设备)。只要每个设备只被一个任务访问,驱动程序就是线程安全的。但是,如果多个任务试图访问同一个SPI设备,则驱动程序不是线程安全的。在这种情况下,建议: 重构应用程序,使每个SPI外围设备一次只能由单个任务访问。 使用xSemaphoreCreateMutex在共享设备周围添加互斥锁。
-
5)传输事务
SPI总线事务由五个阶段组成,可在下表中找到。这些阶段中的任何一个都可以跳过。
Phase | Description |
---|---|
Command | 主机向向从机写入0-16位数据 |
Address | 主机向从机写入0-32位地址数据 |
Write | 主机向设备发送数据。该数据遵循可选的命令和地址阶段,并且在电气级别上与它们无法区分。 |
Dummy | 此阶段是可配置的,用于满足时间要求。 |
Read | 读 |
事务的属性由总线配置结构spi_bus_config_t、设备配置结构spi_device_interface_config_ts和事务配置结构spi_transaction_t确定。
SPI主机可以发送全双工事务,在此期间读取和写入阶段同时发生。事务总长由以下成员的总和决定:
而成员spi_transaction_t::rxlength仅决定接收到缓冲区中的数据的长度。
在半双工事务中,读取和写入阶段不是同时进行的(一次一个方向)。写入和读取阶段的长度分别由结构spi_transaction_t的长度和rxlength成员决定。
命令和地址阶段是可选的,因为不是每个SPI设备都需要命令和/或地址。这反映在设备的配置中:如果command_bits和/或address_bits设置为零,则不会出现命令或地址阶段。
读取和写入阶段也可以是可选的,因为并非每个事务都需要写入和读取数据。如果rx_buffer为NULL并且未设置SPI_TRANS_USE_RXDATA,则跳过读取阶段。如果tx_buffer为NULL并且未设置SPI_TRANS_USE_TXDATA,则跳过写入阶段。
驱动程序支持两种类型的事务:中断事务和轮询事务。程序员可以选择每个设备使用不同的事务类型。如果您的设备需要两种事务类型,请参阅“向同一设备发送混合事务的说明”。
6)中断事务
中断事务将阻塞事务例程,直到事务完成,从而允许CPU运行其他任务。(怎末感觉折磨别扭)
一个应用程序任务可以对多个事务进行排队,驱动程序将在中断服务例程(ISR)中自动逐一处理这些事务。它允许任务切换到其他过程,直到所有事务完成。(索嘎)
7)轮询事务
轮询事务不使用中断。例程一直轮询SPI主机的状态位,直到事务完成。
所有使用中断事务的任务都可以被队列阻止。此时,他们将需要等待ISR运行两次,然后才能完成事务。轮询事务可以节省在队列处理和上下文切换上花费的时间,从而缩短事务持续时间。缺点是当这些事务正在进行时,CPU很忙。cpu很忙!!!
spi_device_polling_end()例程需要至少1us的开销,以便在事务完成时取消阻止其他任务。强烈建议使用函数spi_device_acquire_bus()和spi_device_release_bus(()包装一系列轮询事务,以避免开销。有关更多信息,请参阅总线获取。还没看api,8懂
8)事务线/行模式?
下面列出了ESP32-S3支持的行模式,要使用这些模式,请在结构体spi_transaction_t中设置成员标志,如transaction Flag列所示。如果要检查是否设置了相应的IO引脚,请在spi_bus_config_t中设置成员标志,如总线IO设置标志列所示。
乐鑫你网页没做好,表格超出了。不超出我也看不懂
9)命令地址阶段
在命令和地址阶段,结构spi_transaction_t中的成员cmd和addr被发送到总线,此时不读取任何内容。命令和地址阶段的默认长度是通过调用spi_bus_add_device()在spi_device_interface_config_t中设置的。如果未设置成员SPI_transaction_t::标志中的SPI_TRANS_VARIABLE_CMD和SPI_TRANS_VARIABLE_ADDR标志,则驱动程序会在设备初始化期间自动将这些阶段的长度设置为默认值。
(回头仔细看,可能有用)
如果命令和地址阶段的长度需要可变,则声明结构体spi_transaction_ext_t,在成员spi_transaction _ext_t::base中设置spi_TRANS_variable_CMD和/或spi_TRANS_variable_ADDR标志,并照常配置base的其余部分。然后,每个阶段的长度将等于结构spi_transaction_ext_t.v中设置的command_bits和address_bits
如果命令和地址阶段需要与数据阶段的行数相同,则需要将SPI_TRANS_MULTILINE_CMD和/或SPI_TRANS_MULTILINE_ADDR设置为结构SPI_transaction_t中的标志成员。另请参阅交易行模式。
10)读写
通常,需要传输到设备或从设备传输的数据将从结构spi_transaction_t的成员rx_buffer和tx_buffer指示的存储器块中读取或写入。如果为传输启用了DMA,则要求缓冲区为:
-
分配在具有DMA功能的内部内存中。如果启用了外部PSRAM,这意味着使用pvPortMallocCaps(大小,MALLOC_CAP_DMA)。
-
32位对齐(从32位边界开始,长度为4字节的倍数)。
-
如果不满足这些要求,则由于临时缓冲区的分配和复制,将影响事务效率。
如果使用多条数据线进行传输,请为结构体SPI_DEVICE_interface_config_t中的成员标志设置SPI_DEVICE_HALFDUPLEX标志。结构体spi_transaction_t中的成员标志应该按照事务行模式中的描述进行设置。
不支持同时具有读取和写入阶段的半双工事务。请使用全双工模式。
11)获取总线
有时,您可能希望以独占方式连续发送SPI事务,以便尽可能少地花费时间。为此,您可以使用总线获取,这有助于暂停到其他设备的事务(轮询或中断),直到总线释放。要获取和释放总线,请使用函数spi_device_acquire_bus()和spi_device_release_bus(。
12)驱动使用
-
通过调用函数SPI_bus_Initialize()初始化SPI总线。确保在结构spi_bus_config_t中设置了正确的I/O引脚。将不需要的信号设置为-1。
-
通过调用函数spi_bus_add_Device(),向驱动程序注册连接到总线的设备。请确保使用参数dev_config配置设备可能需要的任何定时要求。您现在应该已经获得了设备的句柄,该句柄将在向其发送事务时使用。
-
要与设备交互,请使用所需的任何事务参数填充一个或多个spi_transaction_t结构。然后使用轮询事务或中断事务发送结构:
-
中断
-
通过调用函数spi_device_queue_trans()对所有事务进行排队,稍后使用函数spi_device_get_trans_result()查询结果,或者通过将所有请求馈送到spi_device_transmit()中来同步处理所有请求。
-
-
轮询
-
调用函数spi_device_polling_transmit()发送轮询事务。或者,如果您想在两者之间插入一些东西,请使用spi_device_polling_start()和spi_device_polling_end()发送事务。
-
(可选)要使用设备执行背靠背事务,请在发送事务之前调用函数spi_Device_acquire_bus(),在发送事务之后调用函数spi_Device_release_bus(()。 (可选)要卸载某个设备的驱动程序,请调用spi_bus_remove_Device(),并将设备句柄作为参数。 (可选)要删除总线的驱动程序,请确保不再连接驱动程序,然后调用spi_bus_free()。
-
12)数据不超过32位的事务
当事务数据大小等于或小于32位时,为数据分配缓冲区将是次优的。数据可以直接存储在事务结构中。对于传输的数据,可以通过使用tx_data成员并在传输上设置SPI_TRANS_USE_TXDATA标志来实现。对于接收到的数据,使用rx_data并设置SPI_TRANS_use_RXDATA。在这两种情况下,都不要触摸tx_buffer或rx_buffer成员,因为它们使用与tx_data和rx_data相同的内存位置。
13)使用uint8_t以外的整数的事务
SPI主机逐字节地读取数据并将数据写入内存。默认情况下,发送数据时首先使用最高有效位(MSB),在极少数情况下首先使用LSB。如果需要发送小于8位的值,则应以MSB优先的方式将这些位写入存储器。
例如,如果需要发送0b00010,则应将其写入uint8_t变量,并且读取的长度应设置为5位。设备仍将接收8个比特和3个额外的“随机”比特,因此必须正确执行读取。
除此之外,ESP32-S3是一个小端序芯片,这意味着uint16_t和uint32_t变量的最低有效字节存储在最小地址。因此,如果uint16_t存储在存储器中,则首先发送比特[7:0],然后发送比特[15:8]。
对于要传输的数据具有不同于uint8_t阵列的大小的情况,可以使用以下宏将数据转换为SPI驱动程序可以直接发送的格式:
-
SPI_SWAP_DATA_TX for data to be transmitted
-
SPI_SWAP_DATA_RX for data received
14)混合事务传输注意事项,暂时用不到,先不看
15)传输速度注意事项
有三个因素限制了传输速度:
-
事务处理间隔
-
SPI时钟频率
-
SPI函数的缓存未命中,包括回调
决定大型事务传输速度的主要参数是时钟频率。对于多个小型事务,传输速度主要由事务间隔的长度决定。
16)传输持续时间
事务持续时间包括设置SPI外围寄存器、将数据复制到FIFO或设置DMA链路,以及SPI事务的时间。
中断事务允许附加额外的开销,以适应FreeRTOS队列的成本以及在任务和ISR之间切换所需的时间。
对于中断事务,CPU可以在事务进行时切换到其他任务。这节省了CPU时间,但增加了事务持续时间。请参阅中断事务。对于轮询事务,它不阻止任务,但允许在事务进行时进行轮询。有关详细信息,请参阅轮询事务。
如果启用了DMA,则设置链接列表需要每个事务大约2 us。当主机正在传输数据时,它会自动从链表中读取数据。如果未启用DMA,则CPU必须自己从FIFO中写入和读取每个字节。通常,这比2us快,但写入和读取的事务长度都限制为64字节。
一个字节数据的典型事务持续时间如下所示。(小字节不需要dma)
-
Interrupt Transaction via DMA: 26 µs.
-
Interrupt Transaction via CPU: 24 µs.
-
Polling Transaction via DMA: 11 µs.
-
Polling Transaction via CPU: 9 µs.
17)SPI时钟频率
传输每个字节需要八倍于8/fspi的时钟周期。别扭
18)缓存未命中(看不懂)
19)官方示例
可以在ESP-IDF示例的外围设备/SPI_master/hd_eprom目录中找到使用SPI主半双工模式来读取/写入AT93C46D EEPROM(8位模式)的代码示例。
下一篇分析下lcd历程