GPDMA from SPIFI to SDRAM

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

GPDMA from SPIFI to SDRAM

407 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by scout_3pm on Fri Sep 27 07:39:51 MST 2013
Hello,

I'm new to the LPC43xx series and more especially LPC4357.
I have the LPC4357-K43WQA which is LPC4357-EVB + 4.3' TFT K430WQA-V4F.

I want to use SPIFI for storage of images, which then to be shown on the LCD.
LCD's framebuffer is in SDRAM. So I need to make DMA transfer from SPIFI to SDRAM.

I read the User Manual, but it doesn't became very clear how exactly i have to configure the GPDMA.
I was hoping looking at the Standard Peripheral Library from NXP to find the needed settings, but there nowhere is mentioned SPIFI as SRC or DST for the GPDMA. And this looks odd because in the User Manual I see that for Source Peripheral can be used SPIFI. So then I figure that maybe SPIFI as mapped onto the Memory Map it can be just configured as a Memory 2 Memory transfer, but i get strange result. Only part of the screen is filled and the pixels are corrupt.

I also in the STD Peripheral library didn't find where or how to configure if I want the address to be incremented after every chunk of data transfered.

Thank You for Your Time.

Here is my current code generating the described behavior above:
void DMA_SPIFItoFB_Init(const unsigned char image[])
{
GPDMA_Channel_CFG_Type myDMA0;

GPDMA_ChannelCmd(0, DISABLE);

/* Disable GPDMA interrupt */
NVIC_DisableIRQ(DMA_IRQn);
/* preemption = 1, sub-priority = 1 */
NVIC_SetPriority(DMA_IRQn, ((0x01<<3)|0x01));

GPDMA_Init();

myDMA0.ChannelNum = 0; //highest priority DMA channel
myDMA0.TransferSize = (480*272*3)/4; //word size transfer 4 bytes = 32bit WORD
myDMA0.TransferType = GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA;
myDMA0.TransferWidth = GPDMA_WIDTH_WORD; //used only for M2M operation
myDMA0.SrcMemAddr = (uint32_t) image; //used only for M2M and M2P operation
myDMA0.DstMemAddr = (uint32_t) 0x28000000;
myDMA0.DMALLI = 0; //no linked list
GPDMA_Setup(&myDMA0);

/* Enable GPDMA interrupt */
NVIC_EnableIRQ(DMA_IRQn);

// Enable GPDMA channel 0
GPDMA_ChannelCmd(0, ENABLE);
}
Labels (1)
0 Kudos
1 Reply

262 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by scout_3pm on Mon Sep 30 11:23:31 MST 2013
OK. For everybody that wants to use DMA from SPIFI to any point of other DMA location should read the last page of the SPIFI chapter in the User Manual. Very important information there.

A SPIFI to SDRAM can be done with M2M transfer.

EDITED
I also used Linked List so i can transfer the whole image at once.

I'm transferring 480*272*4 bytes of data from SPIFI which is configured at 102Mhz (51MB/s theoretical) to SDRAM which also runs at 102Mhz. Also LCD peripheral is configured at 34Mhz and its DMA from SDRAM to LCD is working too.

Here is the code: (I'm using MDK-ARM)
This is the right code that transfers 32*4080 32bit WORDS of data or 480x272 WORDS of single image

#include "lpc43xx.h"
#include "lpc43xx_gpdma.h"
#include "dma.h"

GPDMA_LLI_Type myLLI[31] __attribute__((at(0x10007000)));;

void DMA_SPIFItoFB_Init(const unsigned char * image)
{
GPDMA_Channel_CFG_Type myDMA1;
uint32_t i, *p, *fb;

p = (uint32_t *) image;
fb = (uint32_t *) 0x28000000;
/* Disable DMA */
GPDMA_ChannelCmd(1, DISABLE);
/* Disable GPDMA interrupt */
NVIC_DisableIRQ(DMA_IRQn);
/* preemption = 1, sub-priority = 1 */
NVIC_SetPriority(DMA_IRQn, ((0x01<<3)|0x01));

GPDMA_Init();

myDMA1.ChannelNum = 1; //DMA channel
myDMA1.TransferSize = 4080; //word size transfer 4 bytes = 32bit WORD
myDMA1.TransferType = GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA;
myDMA1.TransferWidth = GPDMA_WIDTH_WORD; //used only for M2M operation
myDMA1.SrcMemAddr = (uint32_t) p; //used only for M2M and M2P operation
myDMA1.DstMemAddr = (uint32_t) fb;
myDMA1.DMALLI = (uint32_t) 0x10007000; //linked list
GPDMA_Setup(&myDMA1);

for(i=0; i < 31; i++)
{
p += 4080;
fb += 4080;
myLLI.SrcAddr = (uint32_t) p;
myLLI.DstAddr = (uint32_t) fb;
myLLI.Control = (uint32_t) (GPDMA_DMACCxControl_TransferSize(4080) |
 GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD) | 
 GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD) |
 GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_1) |
 GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_1)|
 GPDMA_DMACCxControl_SI | 
 GPDMA_DMACCxControl_DI |
 GPDMA_DMACCxControl_I);
if(i == 30) myLLI.NextLLI = (uint32_t) 0;
else myLLI.NextLLI = (uint32_t) &(myLLI[(i+1)]);
}

/* Enable GPDMA interrupt */
NVIC_EnableIRQ(DMA_IRQn);

// Enable GPDMA channel 1
GPDMA_ChannelCmd(1, ENABLE);
}


DMA IRQ Handler:
void DMA_IRQHandler (void)
{
// check GPDMA interrupt on channel 1
if (GPDMA_IntGetStatus(GPDMA_STAT_INT, 1)){ //check interrupt status on channel 7
// Check counter terminal status
if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 1)){
// Clear terminate counter Interrupt pending
GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 1);
//DMA_StartTransfer();
imgn++; //count complete transfers
}
if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 1)){
// Clear error counter Interrupt pending
GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 1);
imgn--; //count error transfers
}
}
}
0 Kudos