DMA between external SRAM and LCD on FSMC
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-16 1:58 PM
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-16 2:20 PM
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 ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-16 6:14 PM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-16 11:24 PM
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-17 7:08 AM
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.Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-17 11:26 AM
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...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-17 1:29 PM
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2012-10-17 1:45 PM
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...