cancel
Showing results for 
Search instead for 
Did you mean: 

F334 SPI DMA and endian issues

Manu Abraham
Senior
Posted on March 10, 2017 at 14:46

Hi,

Continuing my saga on SPI DMA, which works now.

The idea is to use it to drive a SPI LCD, an ILI9341 with DMA.

I see that I can communicate with the LCD, but all 16 bit writes are messed up due to SPI write with 16 bits and DMA.

The F334 runs in little endian mode which I verified.

The LCD needs big endian mode. Little endian mode on the LCD is not available in SPI mode. The LCD datasheet makes it quite clear.

'ENDIAN: Select Little Endian Interface bit. At Little Endian mode, the host sends LSB data first.

Note: Little Endian is valid on only 65K 8-bit and 9-bit MCU interface mode.'

I started looking for a bitrev in the peripheral, rather than the available rbit instruction, to avoid CPU intervention on the large chunks of GRAM data, which would defeat the whole point of using DMA. In this context: Is it possible to do some bit reversing for the LCD, without CPU intervention, while still using DMA ?

But given this context, I was lost how a lot of other STM32 controllers are using the LCD. Looking at other controllers, I do see that they have a DFF bit to select between 8bit and 16bit modes, which is not available on the F334. Am I right to think that the DFF bit does bit reversing. Eventually to assume that 16 bit DMA to LCD seems impossible with the F334 ?

Can someone clarify, please ?

Any suggestions ?

Thanks!

12 REPLIES 12
Chris1
Senior III
Posted on March 10, 2017 at 21:13

Well, the STM32F334xx reference manual says, 'The SPI shift register can be set up to shift out MSB-first or LSB-first, depending on the value of the LSBFIRST bit. The data frame size is chosen by using the DS bits. It can be set

from 4-bit up to 16-bit length and the setting applies for both transmission and reception.'
T J
Lead
Posted on March 10, 2017 at 22:39

I found that if you use an 8 bit SPI transfers results in the bytes in order

but using 16 bit SPI transfers, the bytes are reversed.

I had to use the 8bit SPI transfers to make my stuff work.

the DMAs still work just as good in 8 bit mode.

Posted on March 11, 2017 at 12:14

A MSB first, or a LSB first with Data size alone does not address the endian issue in anyway.

A 32 bit register in memory which holds actually 0x1234567, looks thus

67 45 23 01

Eventually, there is still one flip ..

Posted on March 11, 2017 at 12:27

True, the bytes are still flipped with the 16bit mode in all the possible situations.

Tried a simple polling method, to isolate any DMA issues and to keep it simple while debugging the transfers.

Verified the SPI output on a scope and documented the way it works.

Attached the outputs, in case any one would like to have a look.

But in the case where you transfer the GRAM contents which look 16 bits, needs to be carefully converted to 8 bits, if 8 bit transactions are used.

Need to figure out how to get the 8 bit transfer to the LCD working with the least overhead.

________________

Attachments :

SPI 8Bit Debugging with the STM32F334.pdf : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HynJ&d=%2Fa%2F0X0000000bCg%2FXpkM9Vs2RGgoqkIDyUxPnA37sVEfnZ_Uy8jyvyX5Cq4&asPdf=false

SPI 16Bit Debugging with the STM32F334.pdf : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyoL&d=%2Fa%2F0X0000000bCh%2FNl60VZndq_4Sz1VvjgltdT8puz3samBpLCFrQW2Wt7M&asPdf=false
S.Ma
Principal
Posted on March 11, 2017 at 13:50

Are the 16 bit pixels generated by mcu sw? If yes, declare and compute pixels and store them in ram already pre swapped as 5:6:5 will need sw bit shifting anyway... 

Posted on March 11, 2017 at 15:34

Another thought occurred to me, on the LCD controller there is a 6 bit mode, ie a RGB 6:6:6 mode, which requires exactly 3 transfers

Page 193, '6- bit RGB interface (3 transfer/pixel)' ie RIM=1, COLMOD[6:4]=110 (262K color). I think that would simplify the CPU intervention slightly, with regards to the DMA transfers. What do you think ?

Posted on March 11, 2017 at 18:04

Use the 4 wire interface mode with 16 bit quantities for easy DMA push.

Usually, 8 bit parallel interface are more common as they can achieve higher frame rate.

You'll also have to use TE to push the transfer at the right time to avoid motion artifacts (tearing).

My point: Pre-MSB/LSB swap when preparing the frame buffer you want to send by SPI.

When you prepare your pixels to send to the Ilitek, today each 16 bit quantity is like:

R43210 G543210 B43210

Change the way to create the pixels in the MCU RAM to 

G210 B43210 R43210 G543

Otherwise, with additional RAM, Memory to Memory DMA transfer scheme should be able to effectively reorder MSB/LSB.

T J
Lead
Posted on March 11, 2017 at 22:25

<edited>

have you considered a hardware solution ?

this chip should be able to adjust your pixel positions 'on the fly'

datasheet attached

http://www.digikey.com/product-detail/en/lattice-semiconductor-corporation/LCMXO256C-3TN100C/220-1189-ND/2731490

but for SPI, you don't need so many pins

this one has enough pins for an SPI solution:

http://www.digikey.com/product-detail/en/lattice-semiconductor-corporation/ICE40UL640-SWG16ITR50/220-1961-2-ND/5130905

search harder, you may find a similar package with a hardened SPI port.

0690X00000603ldQAA.jpg

________________

Attachments :

Lattice 78IO MachXO.pdf : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyO9&d=%2Fa%2F0X0000000bCd%2FcQ5Kvrg.ITLtBdM7JS2IKRVQ2khWncCA7vS25MFzTEs&asPdf=false
Posted on March 12, 2017 at 15:34

I think you misunderstood part of my question. I wasn't referring to the 8 bit parallel operation, but instead using the SPI 8bit mode with the lcd configured for RGB666. I wasn't sure whether that the RGB666 format was meant for the SPI mode or for the parallel mode, which caused yet another confusion. My question on that topic was whether the RGB666 format is possible over SPI 8bit mode, thus avoiding SPI 16 bit mode altogether.

I did some more tests, with the palette in the G210 B43210 R43210 G543 format.

Did a flood fill on the LCD, it did work partially; ie

If i do a lcd_fill(0, 0, 320, 240, GREEN); this does work fine, similarly for the other colors as well.

But if I do:

void lcd_fill(uint16_t x_start,

          uint16_t y_start,

          uint16_t width,

          uint16_t height,

          uint16_t color)

{

    uint32_t pixels = width * height;

    

    sprintf((char *)dbgstr,

        '%s: 0x%.4x (Palette Order: G210 B43210 R43210 G543)\r',

        __func__,

        color);

    putstr(USART1, dbgstr);

    __LCD_CSx(0);

    lcd_set_window(x_start, y_start, (u16) (x_start + width - 1), (u16) (y_start + height - 1));

//    lcd_cmd(LCD_GRAM);

    spi_dma_cmd(LCD_GRAM);

    spi_set_size(SPI_DataSize_16b);

    spi_dma_cmd(LCD_GRAM);

    dmaFill16(color, pixels);

    spi_set_size(SPI_DataSize_8b);

    __LCD_CSx(1);

}

    while (1) {

        lcd_fill(0, 0, 320, 240, GREEN);

        delay(2000);

        lcd_fill(0, 0, 320, 240, BLUE);

        delay(2000);

        lcd_fill(0, 0, 320, 240, RED);

        __LED_TOGGLE();

        delay(2000);

    }

All I get is the first color in the loop and white after that. It stays white forever ..

Wonder whether it is supposed to behave that way  ?