2025-01-17 01:06 PM - edited 2025-01-17 01:13 PM
uint8_t my_buffer[ 1B_LEN_PREFIX + 24B_LEN_DATA + nB_LEN_SUFFIX ] = {0};
(void) HAL_SPI_TRANSMIT_DMA(&hspi2, &my_buffer[0], sizeof(my_buffer));
I'm using the SPI TX line only to drive an addressable LED, making a custom waveform from SPI bits to LED bits. Not using the SPI CLK line, although it does have to be defined in AF Mode for SPI to work at all.
Scenario:
* Using GPDMA in a non-linked list mode
* I am always ending on a low bit.
* After transfer complete, the MOSI goes high
* It usually floats down softly
* When I start a new transmission, there is a 40ns spike before my prefix (1B 0x00) data on subsequent transfers. This is because the SPI was disabled after ending high, re-enabled, and immediately goes high for a moment before DMA data loads.
* If I ended on a high bit, I would expect MOSI to be and stay high at the end of the transfer
* If we pad the DMA buffer with 15 bytes of 0x00 data or less, the line stays high, and floats back low
* If we pad the DMA buffer with 16 bytes or more of 0x00, the MOSI terminates low as expected
First scope picture, less than 15 bytes of data on the suffix. Notice the 40ns spike before the data, the dwell after when DMA finishes it raises high and weakly drops off (when debugger running, this stays high, IDK!). The spike is when starting a new transfer and immediately trying to go high again but DMA loading prefix data in.
Second scope picture, 16+ bytes of data on the suffix. No spike up front, because there is no raise at the end before disabling/completing DMA.
I'm using HAL to remove any possibility of my code causing the issue.
My working theory is that the DMA is loading an additional byte into the TXDR at the end of the transfer, that this byte starts high, this causes the SPI to end high but it's out of data so it stops. By padding it with enough data I'm shifting the "bad DMA" data out too. The SPI FIFO is 4B, this is GPDMA1 CH4 which is an 8 word / 32B block, but the numbers don't add up, my prefix + data is 25 bytes, so it would only need +7 to get to 32B. Something else is happening, and I feel it's behind the scenes.
I have no idea what is going on, and I'm not entirely confident in my solution.
2025-01-17 02:34 PM
That's know for ages, nasty but not really a big problem. Just add the proper number of all-zero frames for reset before WS data. Long one after the useful data does not spoil anything for WS2812.
2025-01-17 03:00 PM
It's not an issue of leading. I'm ok with that padding, and it's fine. The issue is the number of bytes held low, doesn't matter until it does.
It's not the value I'm ending on. It's not an amount of time I'm holding for the LED data line low. It's a number of bytes loaded into DMA that allows MOSI to interpret that it's last held or next ready data is a zero, not a one to pre-set as high.