cancel
Showing results for 
Search instead for 
Did you mean: 

Why would DMA behave differently on two NUCLEO devices (F446RE/L432KC) ?

Vex1
Associate III

Hey,

I have both a NUCLEO-L432KC and a NUCLEO-F446RE. I'm using them to interface with an ili9163c based display.

When I hook up the display to the L432KC it works great and I get a single image that fills the whole display. However, I'm trying to transfer the project over to a F446RE but when I run the program on the F446RE it only draws on the top half of the display and repeats the image i.e. if you were to divide the display into 4 quarters it is only drawing in the top two quarters and each of the top quarters are a repeat of the image I want to fill the whole display. I've tried using the same clock speeds on the F446RE as the L432KC just to see if it was something to do with timing but it doesn't appear to be the case.

I suspect this has something to do with DMA because when I hook it up to a logic analyzer I can see the DMA signal (MOSI) has two repeating versions of the image. Any ideas why the DMA on one device would be behaving differently from the DMA on another?

I am using DMA in circular mode with a HAL_SPI_TxCpltCallback function.

Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions

Difference between 'F446 and 'L432 which caught you here is data packing in SPI.

SPI is set to 8-bit frames.

DMA in 'L432 picks a halfword from memory, stores it into SPI which splits it to two 8-bit frames and transmits both.

DMA in 'F446 picks a halfword from memory, stores it into SPI, which ignores the upper 8-bit and transmits one 8-bit frame.

In 'L4 Cube, this is accounted for, that's why half of the Size parameter of HAL_SPI_Transmit_DMA() appears in CNDTR. So, the Size parameter means "number of transmitted SPI frames, whatever size of SPI frames you used. Cube's documentation might've said so as it's surprising and different from what other functions involving DMA do, but that's Cube for you. (Btw. this "automation" would fail would you use 32-bit transfers in DMA).

In 'F4 you need either to change SPI's frames to 16 bits (which would potentially mess with other functions using SPI, so you would need to switch the frame size between 8 and 16 bits dynamically, something I really won't recommend to a novice), or change DMA transfers to 8-bits.

JW

View solution in original post

14 REPLIES 14

The DMA units in 'F446 is different from that in 'L432, but the problem is not likely to be related directly to this fact.

> I am using DMA in circular mode

Why?

> with a HAL_SPI_TxCpltCallback function.

How? Describe this in detail.

 JW

  • Why? (Circular mode)
    • I'm not really sure. I'm using a library I got off GitHub (https://github.com/Spirit532/ILI9163C_STM32_HAL_DMA). I suspect it's because if you want to really get the frame rates advertised then it becomes important but I'm not really using it to get insane frame rates.
    • When I run it in normal mode everything seems to work fine on the L432KC so again not sure what the point of it is. My understanding is that it's useful when you want to constantly send something over and over but that isn't really how it's implemented.
    • When I run the program in normal mode on the F446RE I still get the same issue.
  • How? Describe this in detail
    • You draw everything to a frame buffer. There is then a function that renders the frame buffer to the display. Within the render function there is a call to HAL_SPI_Transmit_DMA(&hspi1, frameBuffer, numberPixels (128*160) * 2). After this call, SPI_DMA_FL is set to 0 (custom flag not register flag i.e. a variable). There is then a function in main that is called HAL_SPI_TxCpltCallback().
// SPI transmit complete callback
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
	SPI_DMA_CNT--;
	if(SPI_DMA_CNT == 0) {
		HAL_SPI_DMAStop(&hspi1);
		SPI_DMA_CNT = 1;
		SPI_DMA_FL = 1;
	}
}
  • I'm really sure why you would put it into circular mode and then call HAL_SPI_DMAStop on every transmit complete event. Again, my understanding of the point of circular mode is that it doesn't stop after every transmit complete event it just starts transmitting again.
    • SPI_DMA_FL is initialized to 0 and SPI_DMA_CNT is initialized to 1.

The DMA settings screen for the 446RE has a FIFO setting which the L432KC doesn't have. I've just left it unchecked. Could this be what is causing the issue?

I should also mention I've had a look at the frame buffer during debug on both the F446RE and the L432KC and they are identical i.e. the buffer is good it's not the buffer that is getting corrupted.

How large is the buffer, how wide is the transfer?

DMA is typically limited to 65535 transactions.

SPI on L4​ likely better, with wider buffering/FIFO and width funnelling/management.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
  • How large is the buffer
    • I only have a single frame buffer at the moment. It's a 160 x 128 display - 16 bit colour - (160 x 128 x 2) = 40960 bytes.
  • How wide is the transfer
    • I'm not sure what this means. Could you please explain this more? Is this a function of the hardware or the software. Both the F446RE and the L432KC are on SPI1; which from the datasheet I understand to be the largest capacity SPI.

>>How wide is the transfer. I'm not sure what this means.

Byte, Half-Word or Word, the width of the IO operation on the SPI register address (peripheral) you're selected for the DMA

The Transfer Count on the DMA units is 16-bit wide, the total transactions limited to 65535 (give or take)

Count != Bytes for different widths.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Vex1
Associate III

The DMA data width is set to half-word. Would that make it 160 x 128 (20480) units since it's 40960 bytes and a half word is 16 bits?

Yes, you should check if Count length is reflective of expectations, or has been scale too much.

The callback (IRQ) tends to trigger at DMA HT and TC events (Half Transfer, Transfer Complete)

In Circular mode you'd expect a continuous stream of HT, TC, HT, TC, .. interrupts, if enabled.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Vex1
Associate III
  • check if Count length is reflective of expectations
    • Okay so I added a watchpoint to S3NDTR (indicates the remaining data items to be transmitted). Turns out it is being initialized to 40960 (160 x 128 x 2). I added a HAL_SPI_TxHalfCpltCallback function with nothing in it and put a breakpoint in. When the breakpoint triggers it isn't at exactly 40960/2 but I suspect that is because of how the debugger is implemented.
    • I also added a HAL_SPI_ErrorCallback and put a breakpoint in. It isn't triggering the breakpoint so I'm going to assume there aren't any errors being thrown with the DMA transfer.

I'm still perplexed by the fact that it works fine on the L432KC but then I put it on the F446RE and it freaks out. It has to be something like the clock rate or something right. Why would it work on one and not the other. They are setup identically as far as I can tell.

>>Why would it work on one and not the other.

a) The F4 is a significantly older design, it might be a rougher implementation with more warts.

b) The library code you're using is buggy and poorly tested, and designed to mask differences between STM32 families as they evolved.

A more critical review of the F4 Errata and Reference Manuals, and then the library code built on those, would perhaps be enlightening.

Top half image repeating speaks to a mismatch in widths (peripheral,memory,etc) or transfer count

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..