esp-idf icon indicating copy to clipboard operation
esp-idf copied to clipboard

spi_device_polling_transmit(...) in DMA mode muzz support 5-, 9-, etc-bytes I/O sessions with 1-byte Tx and Rx (IDFGH-13038)

Open powerbroker opened this issue 1 year ago • 8 comments

Answers checklist.

  • [X] I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • [X] I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • [X] I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

ESP-IDF v5.2.1-dirty

Espressif SoC revision.

ESP32 chip revision: v3.1

Operating System used.

Windows

How did you build your project?

Eclipse IDE

If you are using Windows, please specify command line type.

None

Development Kit.

ESP32 WROOM

Power Supply used.

USB

What is the expected behavior?

spi_device_polling_transmit(handle, &t) populates ALL t.length (== 72) bits of t.rx_buffer with received data, not only first 64 bits.

What is the actual behavior?

t.length = 8 * 9;
t.tx_buffer = (unsigned char*){ 0xF7 };
t.rxLength = 8 * 8;
t.rx_buffer = (unsigned char*){ 1, 2, 3, 4, 5, 6, 7, 8, 9 };

spi_device_polling_transmit(spiDevice, &t);

SPI I/O flows successfully and results in following activity on CLK / MISO lines:

dso_01_01_13_55_47

note 72 total CLK pulses and '00 0x80 00 00 0x80 00 00 0x80 00' stream on MISO line. so, exactly MISO data is expected in t.rx_buffer after all. but it has '00 0x80 00 00 0x80 00 00 0x80 9' instead - last byte is dropped.

bus activity indicates: all 9 bytes processed by SPI hardware.

Steps to reproduce.

Implement described SPI IO with multiple of 32-bits(of 4-bytes) + 1 byte total I/O length: 1-byte Tx and 4, 8, 12, ... Rx. enjoy only multiple-of-32 bits(multiple-of-4 bytes) of received data is transferred into t.rx_buffer and last byte is dropped.

powerbroker avatar Jun 15 '24 09:06 powerbroker

@powerbroker Hello, As you see, it not a bug, it driver design as this,,,

  • If you only set t.length = 8 * 9;, tx and rx will be same length
  • If you set t.length = 8 * 9; and t.rxLength = 8 * 8;, it will trans 8 * 9 in hardware but write only 8 * 8 of rx buffer
  • t.rxLength > t.length is not allowed

wanckl avatar Jun 17 '24 03:06 wanckl

@powerbroker A bit different,

You can understand as rx buffer is align to start, so if rx length one smaller then tx length, it still not you want.

you can consider configure devices as devcfg.command_bits = 8 then using spi_transaction_t::cmd to send you command, this length don't belong to t.length, then simply using t.length as your rx length.

wanckl avatar Jun 18 '24 02:06 wanckl

@powerbroker

devcfg.command_bits is originally the feature for this condition, it not any kind of workaround,,

In idf there is devcfg.command_bits support 0-16 bits, and devcfg.address_bits support 0-64 bits, which handle many kind of devices not only 1+6

and btw, actually your case is ony half-duplex transaction, any other chips if you using full-duplex mode you need also handle tail-align by yourselves. anyway, there is many way to archive this with little difference, you can freely select one as your workaround.

wanckl avatar Jun 24 '24 04:06 wanckl

@powerbroker Hello, If no problem, please close this issue, thanks

wanckl avatar Jul 08 '24 03:07 wanckl

You can manual control CS or use flags==SPI_TRANS_CS_KEEP_ACTIVE and do multiple SPI transactions to form one with exactly what you need.

Maksons avatar Jul 31 '24 11:07 Maksons