Запуск SDRAM:
Код
SCS|=0x00000002; // Reset EMC.
EMCCONTROL=0x00000001; // Enable EMC and Disable Address mirror.
PCONP|=0x00000800; // Turn on EMC PCLK.
PINSEL5=0x05050555; // CAS,RAS,CLKOUT0_1,DYCS0_1,CKEOUT0_1,DQMOUT0_1.
PINSEL6=0x55555555; // D0-D15.
PINSEL8=0x55555555; // A0-A15.
PINSEL9=0x10555555; // A16-A23,OE,WE,BLS0_1,CS_0_.
EMCDYNAMICRP =2; // Command period: 3(n+1) clock cycles.
EMCDYNAMICRAS =3; // RAS command period: 4(n+1) clock cycles.
EMCDYNAMICSREX=7; // Self-refresh period: 8(n+1) clock cycles.
EMCDYNAMICAPR =2; // Data out to active: 3(n+1) clock cycles.
EMCDYNAMICDAL =5; // Data in to active: 5(n+1) clock cycles.
EMCDYNAMICWR =1; // Write recovery: 2(n+1) clock cycles.
EMCDYNAMICRC =5; // Active to Active cmd: 6(n+1) clock cycles.
EMCDYNAMICRFC =5; // Auto-refresh: 6(n+1) clock cycles.
EMCDYNAMICXSR =7; // Exit self-refresh: 8(n+1) clock cycles.
EMCDYNAMICRRD =1; // Active bank A->B: 2(n+1) clock cycles.
EMCDYNAMICMRD =2; // Load Mode to Active cmd: 3(n+1) clock cycles.
EMCDINAMICRDCFG=1; // Command delayed strategy.
EMCDYNAMICRASCAS0=0x00000303; // Default setting, RAS latency 3 CCLKs, CAS latenty 3 CCLKs.
EMCDYNAMICCFG0=0x00000680; // 256MB, 16Mx16, 4 banks, row=13, column=9.
delayMs(100); // 100 ms.
EMCDINAMICCTRL=0x00000183; // Mem clock enable, CLKOUT runs, send command: NOP.
delayMs(200); // 200 ms.
EMCDINAMICCTRL=0x00000103; // Send command: PRECHARGE-ALL, shortest possible refresh period.
EMCDINAMICRFR=2; // Set 32 CCLKs between SDRAM refresh cycles.
for (int i=0; i<0x40; i++) asm("nop"); // Wait 128 AHB clock cycles.
EMCDINAMICRFR=28; // Set 28 x 16CCLKs=448CCLK=7us between SDRAM refresh cycles.
//To set mode register in SDRAM, enter mode by issue
//MODE command, after finishing, bailout and back to NORMAL mode.
EMCDINAMICCTRL=0x00000083; // Mem clock enable, CLKOUT runs, send command: MODE.
dummy=*((volatile unsigned int*)(SDRAM_BASE|(0x33<<12))); // Set mode register in SDRAM.
EMCDINAMICCTRL=0x00000000; // Send command: NORMAL.
EMCDYNAMICCFG0|=0x00080000; // Enable buffer.
delayMs(1); // 1 ms.
EMCSTATICWAITWEN0 =0x2; // Selects the delay from chip select 0 to write enable.
EMCSTATICWAITOEN0 =0x2; // Selects the delay from chip select 0 or address change, whichever is later, to output enable.
EMCSTATICWAITRD0 =0x1f; // Selects the delay from chip select 0 to a read access.
EMCSTATICWAITPG0 =0x1f; // Selects the delay for asynchronous page mode sequential accesses for chip select 0.
EMCSTATICWAITWR0 =0x1f; // Selects the delay from chip select 0 to a write access.
EMCSTATICWAITTURN0=0xf; // Selects the number of bus turnaround cycles for chip select 0.
EMCSTATICCNFG0 =0x00000081; // Selects the memory configuration for static chip select 0.
EMCCONTROL=0x00000001; // Enable EMC and Disable Address mirror.
PCONP|=0x00000800; // Turn on EMC PCLK.
PINSEL5=0x05050555; // CAS,RAS,CLKOUT0_1,DYCS0_1,CKEOUT0_1,DQMOUT0_1.
PINSEL6=0x55555555; // D0-D15.
PINSEL8=0x55555555; // A0-A15.
PINSEL9=0x10555555; // A16-A23,OE,WE,BLS0_1,CS_0_.
EMCDYNAMICRP =2; // Command period: 3(n+1) clock cycles.
EMCDYNAMICRAS =3; // RAS command period: 4(n+1) clock cycles.
EMCDYNAMICSREX=7; // Self-refresh period: 8(n+1) clock cycles.
EMCDYNAMICAPR =2; // Data out to active: 3(n+1) clock cycles.
EMCDYNAMICDAL =5; // Data in to active: 5(n+1) clock cycles.
EMCDYNAMICWR =1; // Write recovery: 2(n+1) clock cycles.
EMCDYNAMICRC =5; // Active to Active cmd: 6(n+1) clock cycles.
EMCDYNAMICRFC =5; // Auto-refresh: 6(n+1) clock cycles.
EMCDYNAMICXSR =7; // Exit self-refresh: 8(n+1) clock cycles.
EMCDYNAMICRRD =1; // Active bank A->B: 2(n+1) clock cycles.
EMCDYNAMICMRD =2; // Load Mode to Active cmd: 3(n+1) clock cycles.
EMCDINAMICRDCFG=1; // Command delayed strategy.
EMCDYNAMICRASCAS0=0x00000303; // Default setting, RAS latency 3 CCLKs, CAS latenty 3 CCLKs.
EMCDYNAMICCFG0=0x00000680; // 256MB, 16Mx16, 4 banks, row=13, column=9.
delayMs(100); // 100 ms.
EMCDINAMICCTRL=0x00000183; // Mem clock enable, CLKOUT runs, send command: NOP.
delayMs(200); // 200 ms.
EMCDINAMICCTRL=0x00000103; // Send command: PRECHARGE-ALL, shortest possible refresh period.
EMCDINAMICRFR=2; // Set 32 CCLKs between SDRAM refresh cycles.
for (int i=0; i<0x40; i++) asm("nop"); // Wait 128 AHB clock cycles.
EMCDINAMICRFR=28; // Set 28 x 16CCLKs=448CCLK=7us between SDRAM refresh cycles.
//To set mode register in SDRAM, enter mode by issue
//MODE command, after finishing, bailout and back to NORMAL mode.
EMCDINAMICCTRL=0x00000083; // Mem clock enable, CLKOUT runs, send command: MODE.
dummy=*((volatile unsigned int*)(SDRAM_BASE|(0x33<<12))); // Set mode register in SDRAM.
EMCDINAMICCTRL=0x00000000; // Send command: NORMAL.
EMCDYNAMICCFG0|=0x00080000; // Enable buffer.
delayMs(1); // 1 ms.
EMCSTATICWAITWEN0 =0x2; // Selects the delay from chip select 0 to write enable.
EMCSTATICWAITOEN0 =0x2; // Selects the delay from chip select 0 or address change, whichever is later, to output enable.
EMCSTATICWAITRD0 =0x1f; // Selects the delay from chip select 0 to a read access.
EMCSTATICWAITPG0 =0x1f; // Selects the delay for asynchronous page mode sequential accesses for chip select 0.
EMCSTATICWAITWR0 =0x1f; // Selects the delay from chip select 0 to a write access.
EMCSTATICWAITTURN0=0xf; // Selects the number of bus turnaround cycles for chip select 0.
EMCSTATICCNFG0 =0x00000081; // Selects the memory configuration for static chip select 0.
LCD:
Код
PCONP|=0x00100000; // Power Control for CLCDC.
// Assign pin:
PINSEL0&=BIN32(11111111,11111111,11111111,11111111);
PINSEL0|=BIN32(00000000,00000101,01010101,00000000); // P0.4(LCD0), P0.5(LCD1), P0.6(LCD8), P0.7(LCD9), P0.8(LCD16), P0.9(LCD17).
PINMODE0&= BIN32(00000000,00000000,00000000,00000000);
PINSEL3&=BIN32(11111111,11111111,11111111,11111111);
PINSEL3|=BIN32(00000101,01010101,01010101,00000000); // P1.20(LCD10), P1.21(LCD11), P1.22(LCD12), P1.23(LCD13), P1.24(LCD14), P1.25(LCD15), P1.26(LCD20), P1.27(LCD21), P1.28(LCD22), P1.29(LCD23).
PINMODE3&=BIN32(00000000,00000000,00000000,00000000);
PINSEL4&=BIN32(11111111,11111111,11111111,11111111);
PINSEL4|=BIN32(00000101,01001111,11111111,11111111); // P2.0(LCDPWR), P2.1(LCDLE), P2.2(LCDDCP), P2.3(LCDFP), P2.4(LCDENAB), P2.5(LCDLP), P2.6(LCD4), P2.7(LCD5), P2.8(LCD6), P2.9(LCD7), P2.12(LCD18), P2.13(LCD19).
PINMODE4&=BIN32(00000000,00000000,00000000,00000000);
PINSEL9&=BIN32(11111111,11111111,11111111,11111111);
PINSEL9|=BIN32(00001010,00000000,00000000,00000000); // P4.28(LCD2), P4.29(LCD3).
PINMODE9&=BIN32(00000000,00000000,00000000,00000000);
PINSEL11&=BIN32(11111111,11111111,11111111,11111111);
PINSEL11|=BIN32(00000000,00000000,00000000,00001101); // bit0=1 - LCD port is enabled. bit1...3 = 110 TFT 16-bit. (1:5:5:5 mode)
// ADJ_PH.
PINSEL7_bit.P3_24=0x00;
FIO3DIR_bit.P3_24=1;
FIO3SET_bit.P3_24=1;
// Pixel serializer.
/* This block reads the 32-bit wide LCD data from the output port of the DMA FIFO and
extracts 24, 16, 8, 4, 2, or 1 bpp data, depending on the current mode of operation. The
LCD controller supports big-endian, little-endian, and Windows CE data formats. */
// For HV Mode, DV Mode 16-bit
LCD_CFG=2;
LCD_TIMH=((131<<24)|(17<<16)|(11<<8)|(((640/16)-1)<<2));
LCD_TIMV=((11<<24)|(32<<16)|(2<<10)|480);
LCD_POL=((0<<27)|(1<<26)|(((640/1)-1)<<16)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(0<<6)|(0<<5)|(2<<0));
LCD_CTRL=((0<<10)|(0<<9)|(0<<8)|(1<<5)|(4<<1)|(0<<0)); // 100 = 16 bpp, 1:5:5:5 mode. 101 = 24 bpp (TFT panel only). 110 = 16 bpp, 5:6:5 mode.
LCD_UPBASE=SDRAM_BASE;
LCD_LPBASE=SDRAM_BASE;
for (int i=0;i<50000;i++);
LCD_CTRL|=1;
for (int i=0;i<50000;i++);
LCD_CTRL|=1<<11;
// Assign pin:
PINSEL0&=BIN32(11111111,11111111,11111111,11111111);
PINSEL0|=BIN32(00000000,00000101,01010101,00000000); // P0.4(LCD0), P0.5(LCD1), P0.6(LCD8), P0.7(LCD9), P0.8(LCD16), P0.9(LCD17).
PINMODE0&= BIN32(00000000,00000000,00000000,00000000);
PINSEL3&=BIN32(11111111,11111111,11111111,11111111);
PINSEL3|=BIN32(00000101,01010101,01010101,00000000); // P1.20(LCD10), P1.21(LCD11), P1.22(LCD12), P1.23(LCD13), P1.24(LCD14), P1.25(LCD15), P1.26(LCD20), P1.27(LCD21), P1.28(LCD22), P1.29(LCD23).
PINMODE3&=BIN32(00000000,00000000,00000000,00000000);
PINSEL4&=BIN32(11111111,11111111,11111111,11111111);
PINSEL4|=BIN32(00000101,01001111,11111111,11111111); // P2.0(LCDPWR), P2.1(LCDLE), P2.2(LCDDCP), P2.3(LCDFP), P2.4(LCDENAB), P2.5(LCDLP), P2.6(LCD4), P2.7(LCD5), P2.8(LCD6), P2.9(LCD7), P2.12(LCD18), P2.13(LCD19).
PINMODE4&=BIN32(00000000,00000000,00000000,00000000);
PINSEL9&=BIN32(11111111,11111111,11111111,11111111);
PINSEL9|=BIN32(00001010,00000000,00000000,00000000); // P4.28(LCD2), P4.29(LCD3).
PINMODE9&=BIN32(00000000,00000000,00000000,00000000);
PINSEL11&=BIN32(11111111,11111111,11111111,11111111);
PINSEL11|=BIN32(00000000,00000000,00000000,00001101); // bit0=1 - LCD port is enabled. bit1...3 = 110 TFT 16-bit. (1:5:5:5 mode)
// ADJ_PH.
PINSEL7_bit.P3_24=0x00;
FIO3DIR_bit.P3_24=1;
FIO3SET_bit.P3_24=1;
// Pixel serializer.
/* This block reads the 32-bit wide LCD data from the output port of the DMA FIFO and
extracts 24, 16, 8, 4, 2, or 1 bpp data, depending on the current mode of operation. The
LCD controller supports big-endian, little-endian, and Windows CE data formats. */
// For HV Mode, DV Mode 16-bit
LCD_CFG=2;
LCD_TIMH=((131<<24)|(17<<16)|(11<<8)|(((640/16)-1)<<2));
LCD_TIMV=((11<<24)|(32<<16)|(2<<10)|480);
LCD_POL=((0<<27)|(1<<26)|(((640/1)-1)<<16)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(0<<6)|(0<<5)|(2<<0));
LCD_CTRL=((0<<10)|(0<<9)|(0<<8)|(1<<5)|(4<<1)|(0<<0)); // 100 = 16 bpp, 1:5:5:5 mode. 101 = 24 bpp (TFT panel only). 110 = 16 bpp, 5:6:5 mode.
LCD_UPBASE=SDRAM_BASE;
LCD_LPBASE=SDRAM_BASE;
for (int i=0;i<50000;i++);
LCD_CTRL|=1;
for (int i=0;i<50000;i++);
LCD_CTRL|=1<<11;
Код почищен, есть только запуск. Затем тупо записываем муар в видеопамять - чередование черный цвет/серый 50%. Видим: изображение дрожит, будто низкая частота кадров. При этом проц крутится в пустом цикле, ничего не делая.
Если вставляем в пустой цикл запись любого значения в любой адрес SDRAM, картинка разваливается - выглядит, как помехи на телевизоре при отсутствии сигнала. При этом память значения держит, ничего не изменяется и не теряется. То есть очевидно, что контроллер дисплея тупит.
Поэтому вопросы:
1. Кто знает, что не так запущено? Как убрать мерцание муара?
2. Какие могут быть особенности, чтобы контроллер LCD не обваливался при записи в SDRAM?
3. Не к железу вопрос, а к софту. Как IARу объяснить, что SDRAM можно использовать под HEAP например? Ручками назначать указатели и писать свой менеджер памяти неохота...
4. Хотел приделать работу с масштабируемыми шрифтами, но задача переделки freetype linux'ового под МК мне показалсь слишком сложной. Есть ли что попроще готовое?
Буду крайне благодарен за любые советы.