1 | /*************************************************************************
|
2 | *
|
3 | * Name : .init3
|
4 | *
|
5 | * Beschreibung : EBI und SysClock initialisieren
|
6 | *
|
7 | * Aufruf vor main durch den StartUp Code
|
8 | * Stack-Pointer ist hier schon initialisiert.
|
9 | * SDRam ab Adresse 0x4000 mit einer Länge von 8MB
|
10 | * einblenden.Der Speicher wird für globale Variablen
|
11 | * (static) und malloc()/free() verwendet. Für diese
|
12 | * Funktionen stehen 48K zur Verfügung, da gcc und die
|
13 | * libc von einem 16-Bit Adressraum ausgehen.
|
14 | *
|
15 | * Initialwerte werden im Anschluss durch den StartUp Code
|
16 | * aus dem Flash ins SDRam kopiert.
|
17 | * Die Linkeroptionen
|
18 | * "-Wl,-section-start=.data=0x804000" und
|
19 | * "-Wl,-defsym=__heap_end=0x80ffff"
|
20 | * sind Pflicht!
|
21 | * avr-size berücksichtigt den dazubekommenen Speicher
|
22 | * nicht!
|
23 | *
|
24 | * 32KHz/32MHz RC-OSC Starten
|
25 | * PLL mit 64MHz Starten
|
26 | * ClkCpu auf 32MHz; ClkPer2 auf 64MHz setzen
|
27 | *
|
28 | * Parameter : keine
|
29 | *
|
30 | * Rückgabe : keine
|
31 | *
|
32 | *************************************************************************/
|
33 | #define LED0_ON (PORTE_OUTCLR=PIN0_bm)
|
34 | #define LED1_ON (PORTE_OUTCLR=PIN1_bm)
|
35 | #define LED0_OFF (PORTE_OUTSET=PIN0_bm)
|
36 | #define LED1_OFF (PORTE_OUTSET=PIN1_bm)
|
37 |
|
38 | void __attribute__ ((naked, section(".init3"))) XplainMemAndClk(void)
|
39 | {
|
40 | uint8_t temp = (WDT.CTRL & ~WDT_ENABLE_bm) | WDT_CEN_bm;
|
41 | CCP = CCP_IOREG_gc;
|
42 | WDT.CTRL = temp; // Watchdog abschalten
|
43 |
|
44 | PORTE.DIR = 0xff; // LEDs auf Ausgang
|
45 | PORTE.OUT = 0xff; // LEDs aus
|
46 | LED0_ON; // Konfiguration beginnt...
|
47 |
|
48 | // EBI Initialisieren; stammt aus der Atmel AppNote AVR1312.PDF,
|
49 | // der TechNote AVR1312.ZIP und dem Micron MT48LC16M4A2TG DataSheed
|
50 |
|
51 | PORTH.OUT = 0x0F; // EBI PORTs richten
|
52 | PORTH.DIR = 0xFF;
|
53 | PORTK.DIR = 0xFF;
|
54 | PORTJ.DIR = 0xF0;
|
55 |
|
56 | EBI.CTRL = EBI_SDDATAW_4BIT_gc | EBI_IFMODE_3PORT_gc;
|
57 | EBI.SDRAMCTRLA = (EBI.SDRAMCTRLA & ~(EBI_SDCAS_bm | EBI_SDROW_bm | EBI_SDCOL_gm)) |
|
58 | EBI_SDCOL_10BIT_gc | EBI_SDROW_bm;
|
59 | EBI.SDRAMCTRLB = EBI_MRDLY_0CLK_gc | EBI_ROWCYCDLY_1CLK_gc | EBI_RPDLY_0CLK_gc;
|
60 | EBI.SDRAMCTRLC = EBI_WRDLY_0CLK_gc | EBI_ESRDLY_0CLK_gc | EBI_ROWCOLDLY_0CLK_gc;
|
61 | EBI.REFRESH = 0xff00;
|
62 | EBI.INITDLY = 0x0100;
|
63 | EBI.CS3.CTRLB = (EBI.CS3.CTRLB & ~(EBI_CS_SDSREN_bm | EBI_CS_SDMODE_gm)) |
|
64 | EBI_CS_SDMODE_NORMAL_gc;
|
65 | EBI.CS3.BASEADDR = (((uint32_t) SDRAM_ADDR)>>8) & (0xFFFF<<(EBI_CS_ASPACE_8MB_gc>>2));
|
66 | EBI.CS3.CTRLA = (EBI.CS3.CTRLA & ~(EBI_CS_ASPACE_gm | EBI_CS_MODE_gm)) |
|
67 | EBI_CS_ASPACE_8MB_gc | EBI_CS_MODE_SDRAM_gc;
|
68 |
|
69 | while(!(EBI.CS3.CTRLB & EBI_CS_SDINITDONE_bm)); // warten bis fertig
|
70 |
|
71 | // System Clock initialisieren
|
72 | OSC.PLLCTRL = OSC_PLLSRC_RC32M_gc | OSC_PLLFAC3_bm;// 32MHz/4 * 8 = 64MHz
|
73 | OSC.DFLLCTRL = OSC_RC32MCREF_bm; // 32MHz Rc kalibrieren
|
74 | DFLLRC32M.CTRL = DFLL_ENABLE_bm; // Kalibrierung ein
|
75 |
|
76 | OSC.CTRL |= OSC_RC32MEN_bm | OSC_RC32KEN_bm; // 32M+32K OSC einschalten
|
77 | while(!(OSC.STATUS & OSC_RC32KRDY_bm)); // warten bis stabil
|
78 | while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // warten bis stabil
|
79 |
|
80 | OSC.CTRL |= OSC_PLLEN_bm ; // PLL mit 64Mhz ein
|
81 | uint8_t CTRLn = (CLK.PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm))) |
|
82 | CLK_PSADIV_1_gc | CLK_PSBCDIV_1_2_gc;
|
83 | CCP = CCP_IOREG_gc; // ClkCPU = 32Mhz; ClkPer2 = 64 MHz
|
84 | CLK.PSCTRL = CTRLn; // Prescaler setzen
|
85 | while(!(OSC.STATUS & OSC_PLLRDY_bm)); // warten bis PLL stabil
|
86 | CCP = CCP_IOREG_gc;
|
87 | CLK.CTRL = CLK_SCLKSEL_PLL_gc; // Sysclock über PLL
|
88 |
|
89 | // SDRAM testen
|
90 | uint16_t Crc1 = 0xDEAD;
|
91 | uint16_t Crc2 = 0xDEAD;
|
92 | uint16_t i;
|
93 | uint8_t Val = 0;
|
94 |
|
95 | for(i=SDRAM_ADDR; i < 0xffff - SDRAM_ADDR; i++)
|
96 | {
|
97 | *(uint8_t*) i = Val; // Speicher beschreiben
|
98 | Crc1 = _crc_ccitt_update(Crc1 ,Val++);// CRC bilden
|
99 | }
|
100 |
|
101 | // *(uint16_t*) 0x7654 = 0xBEAF; // Fehler erzwingen
|
102 |
|
103 | for(i=SDRAM_ADDR; i < 0xffff - SDRAM_ADDR; i++)
|
104 | {
|
105 | Val = *(uint8_t*) i; // Speicher lesen
|
106 | Crc2 = _crc_ccitt_update(Crc2 ,Val); // CRC bilden
|
107 | }
|
108 |
|
109 | if(Crc1 == Crc2) // passt?
|
110 | LED0_OFF; // Speicherfehler!
|
111 |
|
112 | LED1_ON; // ... geschafft
|
113 | }
|