cancel
Showing results for 
Search instead for 
Did you mean: 

Frustrating LCD + DMA

warcatz
Associate II
Posted on September 04, 2013 at 18:36

Hi 🙂

I'm faced to a DMA who don't want work ...

I have look all around (this forum , internet , crystal ball .. ) but i don't know why my screen stay blank :(

I use a 320 x 480 (ILI9481) tft screen , it work perfect when i use it in standard mode (fsmc) but why not use my external sram with DMA if it can help the CPU (stm32f407).

Here is the code i use :

#define LCD_REG (*((volatile unsigned short *) 0x68000000)) /* RS = 0 */

#define LCD_RAM (*((volatile unsigned short *) 0x68000002)) /* RS = 1 */

uint16_t *VideoSRAM = (uint16_t *)Bank1_SRAM4_ADDR;

uint16_t *DMA_Buffnum1 = (uint16_t *)LCD_Screen_Memory_Start;

uint16_t *DMA_Buffnum2 = (uint16_t *)LCD_Screen_Memory_Start + 61440;

uint16_t *DMA_Buffnum3 = (uint16_t *)LCD_Screen_Memory_Start + 122880;

uint16_t *DMA_Buffnum4 = (uint16_t *)LCD_Screen_Memory_Start + 184320;

uint16_t *DMA_Buffnum5 = (uint16_t *)LCD_Screen_Memory_Start + 245760;

uint16_t DMA_Buff_Len = 61440;

uint8_t DMA_BuffNum = 1;

void LCD_VideoBuff_Init(void)

{

uint32_t cnt = 0;

for(cnt = 0;cnt <

LCD_Buffer_Length

; cnt++)

VideoSRAM[cnt]=Black;

}

// DMA Interrup init

void LCD_DMA_Int_Init(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

//---------------------------------------------

// init for DMA Interrupt

// For TransferComplete Interrupt

// DMA2, Stream5, Channel6

//---------------------------------------------

DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);

// NVIC konfig

NVIC_InitStructure.NVIC_IRQChannel

=

DMA2_Stream5_IRQn

;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority

=

0

;

NVIC_InitStructure.NVIC_IRQChannelSubPriority

=

0

;

NVIC_InitStructure.NVIC_IRQChannelCmd

=

ENABLE

;

NVIC_Init(&NVIC_InitStructure);

}

//--------------------------------------------------------------

// DMA Init

//--------------------------------------------------------------

void LCD_InitDMA(void)

{

DMA_InitTypeDef DMA_InitStructure;

//---------------------------------------------

//

DMA

=

2

,

Channel

=

6

,

Stream

=

5

//---------------------------------------------

// Clock Enable (DMA)

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

DMA_DeInit(DMA2_Stream5);

// DMA init (DMA2, Channel6, Stream5)

DMA_Cmd(DMA2_Stream5, DISABLE);

DMA_DeInit(DMA2_Stream5);

DMA_InitStructure.DMA_Channel

=

DMA_Channel_6

;

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)VideoSRAM;

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)LCD_RAM;

DMA_InitStructure.DMA_DIR

=

DMA_DIR_MemoryToMemory

;

DMA_InitStructure.DMA_BufferSize = (uint16_t)(DMA_Buff_Len);

DMA_InitStructure.DMA_PeripheralInc

=

DMA_PeripheralInc_Disable

;

DMA_InitStructure.DMA_MemoryInc

=

DMA_MemoryInc_Enable

;

DMA_InitStructure.DMA_PeripheralDataSize

=

DMA_PeripheralDataSize_HalfWord

;

DMA_InitStructure.DMA_MemoryDataSize

=

DMA_PeripheralDataSize_HalfWord

;

DMA_InitStructure.DMA_Mode

=

DMA_Mode_Normal

;

DMA_InitStructure.DMA_Priority

=

DMA_Priority_High

;

DMA_InitStructure.DMA_FIFOMode

=

DMA_FIFOMode_Disable

;

DMA_InitStructure.DMA_FIFOThreshold

=

DMA_FIFOThreshold_Full

;

DMA_InitStructure.DMA_MemoryBurst

=

DMA_MemoryBurst_Single

;

DMA_InitStructure.DMA_PeripheralBurst

=

DMA_MemoryBurst_Single

;

DMA_Init(DMA2_Stream5, &DMA_InitStructure);

// DMA interrupt

DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);

// DMA Enable

DMA_Cmd(DMA2_Stream5, ENABLE);

}

//--------------------------------------------------------------

// Interrupt

// will be start at DMA Interrupt

// For TransferCompleteInterrupt -> stop the DMA

//

void DMA2_Stream5_IRQHandler(void)

{

if(DMA_GetITStatus(DMA2_Stream5, DMA_IT_TCIF5))

{

// TransferInterruptComplete Interrupt from DMA2 is active

DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5);

// when all Pixel from one of the video buffer are sent => DMA Transfer stop

// DMA2 disable

DMA2_Stream5->CR=0;

// Increment the video buffer number for DMA

DMA_BuffNum++;

if(DMA_BuffNum == 6)

{

// we restart from 0,0 coordinate on the screen

SetArea(0,0,LCD_MAX_X,LCD_MAX_Y);

//Set the first video buffer

DMA_BuffNum = 1;

}

// Set the memory adress to use with the video DMA

switch(DMA_BuffNum)

{

case 1:

DMA2_Stream5->M0AR = (uint32_t)DMA_Buffnum1;

break;

case 2:

DMA2_Stream5->M0AR = (uint32_t)DMA_Buffnum2;

break;

case 3:

DMA2_Stream5->M0AR = (uint32_t)DMA_Buffnum3;

break;

case 4:

DMA2_Stream5->M0AR = (uint32_t)DMA_Buffnum4;

break;

case 5:

DMA2_Stream5->M0AR = (uint32_t)DMA_Buffnum5;

break;

}

// DMA2 enable

DMA2_Stream5->CR|=DMA_SxCR_EN;

}

}

void LCD_Clear(uint16_t color , uint8_t BuffNum)

{

uint32_t index=0;

for( index = 0; index < LCD_Buffer_Length; index++ )

{

// Write color in external SRAM

VideoSRAM[index] = color;

}

}

As you will see i cut the screen in 5 equal part of

61440

bytes.

320 x 480 in 16bits colors can't be managed from the stm32f4 , it's why i fill a external ram buffer and want use it with DMA continuously (in less than 64k limit from DMA).

In the code i change the buffer number each time the Transfer complete from DMA show up but something goes wrong because nothing appear on screen.

It will be good if someone can tell me what i do wrong , because in debug , they are no error , everything is running !! 🙂

Cheer.

Darth.

#stm32f4-dma-fsmc-lcd-tft #fsmc-dma

4 REPLIES 4
jj2
Associate II
Posted on September 04, 2013 at 20:25

Know displays - not so much your MCU's uDMA & hookup.

If you'll accept a general info harvest/test procedure - one follows:

You report success via FSMC - have you properly ''duplicated'' the key control & strobe signals - generated under that mode of operation?  For the screen to appear ''blank'' - as you state - seems reasonable that key clocks/strobes are now improper or absent.

Scoping those key control & strobe signals - when working properly under FSMC - seems a worthwhile beginning.  Provides a sound means for you to compare your new usage against.

KISS always helps - are you able to ''temporarily'' relax the 16 bpp?  (perhaps 8 or just 3?)  Of course color depth/variety is lost - but you may confirm that clocks/strobes are present/proper - at this relaxed condition.

A link to your display would assist - that size/pixel array is straight from cell-phone - demands > 10MHz pixel clock - iirc. 

Suggest that you forego all advanced ''test images'' - simple color stripes should confirm many of your design intents - and their proper execution.

Suspect that critical pixel clock or key gating signals are absent or beyond spec...

Good luck...

warcatz
Associate II
Posted on September 04, 2013 at 20:56

Hi ,

The IO etc are configured as before with fsmc , all i do is just to try to send the pixels with DMA 🙂

In my code i just fill the screen with one color , it work with the ''normal'' clear screen routine under ''normal fsmc'' mode.

I don't have know that the timing will be different with DMA because the io are configured under fsmc timing ... hmmm ... i think i have to look deeper on how DMA work on the

stm32 😉

Thank you for the advice 😉

Darth.

jpeacock2399
Associate II
Posted on September 05, 2013 at 00:47

Sending data by DMA does make a timing difference.  Check the Ilitek datasheet for the command cycle time (good luck if it's on the sheet, Ilitek usually has only a bare minimum of information).  The cycle time is the minimum time between writes...the time the LCD controller needs to process the command you send it.  DMA can substantially compress the time between commands, overrunning the LCD controller.

With memory to memory DMA there's no bus throttle to limit how fast data is transferred, unlike the onboard peripherals that sync DMA with a status register.  You are writing at the speed of the RAM interface, likely far beyond what the LCD controller can handle.

  Jack Peacock
warcatz
Associate II
Posted on September 05, 2013 at 06:48

Ho my ....

Yea , i understand now 🙂

I have all timing on the data sheet .. address setup 10nS , Chip select 20nS and Write cycle 100nS.

I have to use interrupt here 😉 , and set it that i have time for read from the SRAM (25nS) and write to the LCD !! (155nS) i think i will start with 200nS 🙂

Thanks for this info bud 😉

Darth.