/* LPC4088, 208 pins */ /*----------- externer SDRAM -------------------------- IC = Micron MT48LC4M32B2-7 1 Mega x 32 Bit x 4 Bänke Refreshcount = 4 K ROW Adressing = 4 K (A0..A11) row length = 12 COL Adressing = 256 (A0..A7) col length = 8 Bank Adressing = 4 (BA0, BA1) max Clockfrequenz = 143 MHz Accesstime = 5.5 ns (CL=3 ; CAS read latency) konkret angeschlossen ist der SDRAM so: RAM A0..A11 an LPC A0..A11 RAM Pin69 (A12) an LPC A12 RAM BA0 an LPC A13 RAM BA1 an LPC A14 RAM CKE an LPC CKE_0 RAM CLK an LPC CLK_0 RAM CS an LPC DYCS0 RAM WE an LPC WE RAM CAS an LPC CAS RAM RAS an LPC RAS RAM DQM0 an LPC DQM_0 RAM DQM1 an LPC DQM_1 RAM DQM2 an LPC DQM_2 RAM DQM3 an LPC DQM_3 RAM DQ0..31 an LPC DQ0..31 EMC läuft mit CCLK (also EMCCLK=CCLK), macht 120 MHz, also 8.33 ns pro Clocktakt Mapping laut NXP: (B=Busbreite, L=LoPower, M=Mapping Bits) 32 bit external bus high-performance address mapping (Row, Bank, Column) (MB = MegaBits) ======================================================================== B L MMM MM 1 0 010 10 = 128 MB (4Mx32), 4 banks, row length = 12, column length = 8 <--? 1 1 010 10 = 128 MB (4Mx32), 4 banks, row length = 12, column length = 8 <--loPower also Mapping = 0x01010 */ #define Mapping (0x0A) // bin = 01010; /*--- EMC_DYN_CFG0 = Konfiguration -----*/ #define MD (01 << 3) // LoPower SDRAM #define AM (Mapping << 7) // je nach SDRAM-Typ #define B12 (1 << 12) // 1 = LoPower, 0 = sonst #define B14 (1 << 14) // Busbreite #define BufferEnable (1 << 19) // erst nach Init einschalten #define ValFor_EMC_DYN_CFG0 (MD | AM | B12 | B14) /*-------- Kommandos zum EMC -----------*/ #define NORMAL_CMD (0<<7) // NORMAL Command #define MODE_CMD (1<<7) // MODE Command #define PALL_CMD (2<<7) // Precharge All Command #define NOP_CMD (3<<7) // NOP Command /*-------- Mode-Register im SDRAM ------*/ /* Bit 2..0: Burst length 0 = 1er burst 1 = 2er burst 2 = 4er burst <--- das benutzen, weil 32 Bit 3 = 8er burst 4..6 = verboten 7 = full page bei M3=0 Bit 3: M3 0=sequential, 1=interleaved ( 0 benutzen ) Bit 6..4: CAS latency erlaubt: 1, 2 oder 3 ( 2 benutzen ) Bit 9: Write Burst Mode: 0=programmierte Burstlänge, <--- das benutzen 1=single location access Der Zugriff ist gemein!! nämlich ohne Daten. Stattdessen Lesezugriff über SDRAM-Startadresse+Wert für Moderegister also read [0xA0000000 + (WertFürModereg shl 10)] */ #define MD_BurstLen (2 << 0) // 4er Burst #define MD_Interleaved (0 << 3) // 1 = ein, 0 = aus = sequenziell #define MD_CAS_Latenz (3 << 4) // soll zu DYNAMICRASCAS0 passen #define MD_word (MD_BurstLen | MD_Interleaved | MD_CAS_Latenz) #define modesetadr (0xA0000000 | (MD_word << 10)) // 2 Bit wegen Datenbreite, 8 Bit CAS ------------- Auszug -------------- /*----------- externer SDRAM -----------------------------------------*/ /* F_Platform = 120 MHz, also 1 Takt = 8.33 ns */ PCONP |= PCEMC; // Power für EMC einschalten EMC_CONTROL = 1; // EMC enable, Adressmirror aus, normal mode EMC_CONFIG = 0; //(0) Little Endian mode DYNAMICCONTROL = 2; // DYNAMICRP = 2; //(1) tRP (mind. 20ns) auf (n+1) = 3 Takte = 25 ns DYNAMICRAS = 5; //(3) tRAS (mind. 42ns) auf (n+1) = 6 Takte = 50 ns DYNAMICSREX = 8; // tSREX=tXSR (mind. 70ns) auf (n+1) = 9 Takte = 75 ns DYNAMICAPR = 1; //(1) tAPR in Clocks (nicht gefunden) DYNAMICDAL = 5; // tDAL (CL=3) --> 5 Takte DYNAMICWR = 1; //(1) tWR (1 CLK+7ns) also (n+1) = 2 Takte DYNAMICRC = 8; // tRC (mind. 70ns) auf (n+1) = 9 Takte = 75 ns DYNAMICRFC = 8; // tRFC (mind. 70ns) auf (n+1) = 9 Takte = 75 ns DYNAMICXSR = 8; // tXSR (mind. 70ns) auf (n+1) = 9 Takte = 75 ns DYNAMICRRD = 1; // tRRD (mind. 14ns) auf (n+1) = 2 Takte = 16 ns DYNAMICMRD = 1; // tMRD = (n+1) = 2 Takte DYNAMICREADCONFIG = 1; // "Command delayed strategie" --> benutzt EMCCLKDELAY DYNAMICRASCAS0 = 0x0303; // je 3 Takte DYNAMICCONFIG0 = ValFor_EMC_DYN_CFG0; delay(1000); L = 2000; while (--L) { delay(1); DYNAMICCONTROL = NOP_CMD | 3; // zuerst NOP Command + alle Takte ein } delay(10000); DYNAMICCONTROL = PALL_CMD | 3; // Precharge Command + alle Takte ein DYNAMICREFRESH = 2; // erstmal 2*16 = alle 32 CCLK's Refresh ..? delay(10000); // und das lange... DYNAMICREFRESH = 14; // jetzt alle 14*16 CCLK's nen Refresh DYNAMICCONTROL = MODE_CMD | 3; // jetzt kommt's zum Moderegister setzen PDW = (dword*)modesetadr; D = *PDW; // dummy read von berechneter Adresse delay(2000); DYNAMICCONTROL = NORMAL_CMD; // endlich zum Normalmode kommen DYNAMICCONFIG0 = ValFor_EMC_DYN_CFG0 | BufferEnable; // Puffer einschalten -------------- Auszug Ende ------------------