2012-10-16 01: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
2012-10-16 02: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 ?
2012-10-16 06: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.
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.2012-10-17 07: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.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...2012-10-17 01: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.2012-10-17 01: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...