AnsweredAssumed Answered

Frustrating LCD + DMA

Question asked by vader.darth on Sep 4, 2013
Latest reply on Sep 5, 2013 by vader.darth
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.

Outcomes