cancel
Showing results for 
Search instead for 
Did you mean: 

DMA between external SRAM and LCD on FSMC

linas2
Associate II
Posted on October 16, 2012 at 22:58

hello,

i am trying to learn how to use DMA for frame buffer. Idea is to manualy fill SRAM with data (10k points each 16b) and send to LCD by using DMA. FSMC_Bank1_NORSRAM2 and adress: #define Bank1_SRAM2_ADDR ((uint32_t)0x64000000) LCD is on #define LCD_REG (*((volatile unsigned short *) 0x60000000)) // RS = 0 #define LCD_RAM (*((volatile unsigned short *) 0x60020000)) // RS = 1 is this DMA Config is right ?

NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* Reset DMA Stream registers (for debug purpose) */
DMA_DeInit(DMA_STREAM);
while (DMA_GetCmdStatus(DMA_STREAM) != DISABLE)
{
}
DMA_InitStructure.DMA_Channel = DMA_Channel_0; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) 0x64000000;
DMA_InitStructure.DMA_Memory0BaseAddr = ((uint32_t)(0x60000000 | 0x60020000));
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
DMA_InitStructure.DMA_BufferSize = (uint32_t) 10000;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
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_PeripheralBurst_Single; 
DMA_Init(DMA_STREAM, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA_STREAM, DMA_IT_TC, ENABLE);
/* DMA Stream enable */
DMA_Cmd(DMA_STREAM, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA_STREAM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

Before i start 10k points transfer, i need prepare LCD, does any one know how DMA Transfer start interrupt is called ? since now i just have

DMA Stream Transfer Complete interrupt

Code is half working, i get some right data on screen, but with lot of errors
7 REPLIES 7
linas2
Associate II
Posted on October 16, 2012 at 23:20

OK, i used internal SRAM and it worked (more or less)

i made array: uint16_t masyvas[10000]={0};

DMA_InitStructure.DMA_Channel = DMA_Channel_0; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) masyvas;;
DMA_InitStructure.DMA_Memory0BaseAddr = ((uint32_t)(0x60000000 | 0x60020000));
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
DMA_InitStructure.DMA_BufferSize = (uint32_t)sizeof(masyvas);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
DMA_Init(DMA_STREAM, &DMA_InitStructure);

now question is: i am constantly refiling array with data, and i what constant update to screen, how do that ? (also, is this DMA config is right for my application ? ) before full 10k points DMA transfer, i need to prepare LCD to take data, how to do that ?
Posted on October 17, 2012 at 03:14

Surely just
 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0x60020000;

There isn't a start DMA interrupt, what you'd want is non-circular, catching the TC for the LAST transfer, send what you need to the LCD control, and then light off the NEXT transfer.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
linas2
Associate II
Posted on October 17, 2012 at 08:24

one more question:

i want to speed up LCD refresh rate, so i need constantly read data from array (in theory)

but is it possible at the same time transfer array with DMA , and fill it with processor ? or i have to wait until DMA finish transfer, refill array, and then enable DMA transfer again ?

in that case i will not win any second in LCD refresh.

Posted on October 17, 2012 at 16:08

Well you could use two buffers, and switch frames once you finish painting.

You can use a single buffer, the CPU/DMA will contend for the memory, both should work, but your painting may be apparent to the viewer, and memory accesses will appear slower than normal.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jj2
Associate II
Posted on October 17, 2012 at 20:26

Believe that Clive has done a wonderful job in advising.  Have worked many years in the display field - sense that I may, ''fill in some needed blanks'' here...

You are aware (or should be) that what you're attempting has been long solved - and the solution most always involves dedicated hardware.  Such design is not the best use of the MCU - the MCU's strengths are of little consequence - while the MCU's weaknesses are impacting.  Put simply - Square Peg - Round Hole. 

Solomon-Systech (I receive no benefit) produces a wide ranging TFT/LCD Control IC - SSD1963 - far better suited for your application.  This IC includes a large storage buffer and dedicated, internal hardware precisely manages items and aspects which you've likely not yet even considered.  This Controller supports to 800x480 pixel TFTs - thus it covers the full display spectrum from 3.5 - 8.x'' TFTs.

The ability of the STM32 family to output 16 bit data will enhance your use of this IC.  Suggest this as a better use of your time/effort.  Yes there is a ''cost'' involved (~10 USD in some volume) but far better to introduce a well-working product - which just may Sell - than a ''band-aid'' flickering one - which compromises all other functions due to the ''wish'' for, ''Do everything with the MCU!''  (resulting in most everything done poorly...)

One final point - use of an external TFT Control IC enables you to employ smaller, less costly STM32 MCU.  This further erodes any ''cost penalty'' for the Control IC.  And - if I read our electronic tea leaves correctly - push is far stronger for faster/better serial memories and commo devices - not the wide, parallel bus of the past.  And - have you considered the EMI/RFI implications - produced by 40+ parallel, ''radiators?'' 

Perhaps worthy of some consideration - simply ''DNF'' the Control IC when a simpler (or no) display is your target.  By eliminating the cost, size, complexity of multiple external, parallel bus devices - you may find a nice niche for your product.  We did...

linas2
Associate II
Posted on October 17, 2012 at 22:29

I am already using SSD1963 to drive LCD, all i need is to unload time processor send data to LCD via FSMC, so i need to have buffer so i can fill it, but at the same time read that to LCD, it will give few % for overall speed (it's more for learning purpose)

well, right now i get 300FPS from SSD1963, and SSD1963 can do max 65FPS.

But that is when you have all data ready to lcd, like picture in ram.

But if i am trying to produce content via complex math, i need DMA for speed.

STM32F4 can do 130MHz gpio toggle with little mod.

jj2
Associate II
Posted on October 17, 2012 at 22:45

Completely missed your #define Lcd Reg and #define Lcd Ram (should have been Lcd Data) - my bad. 

Have you developed a fast mechanism to update a programmably sized, rectangular region, w/in your MCU addressed SRAM?  You must weigh the time costs of simple, full buffer updates versus more complex, partial buffer updates. 

Much depends upon how frequently your image is changing - and whether you really must perform, ''each/every'' small update.  (you may wish to ''retain'' certain small image updates - until they ''qualify'' for transfer to the display controller.) 

You may wish to explore how the newer ARM MCUs - in consumer devices - manage their high res. screens.  (extremely well)  May be several things you can ''adapt'' for your application...