Forum: Mikrocontroller und Digitale Elektronik LPC1788 + SDRAM als "System Memory"


von Raff (Gast)


Lesenswert?

Hi,

Ist es möglich, ähnlich wie bei einem STM32, bei einem LPC1778/1788 den 
externen SDRAM als Daten/System-Memory (sprich anstelle des internen 
SRAM) zu benutzen?

Ein Blick ins Reference Manual und eine suche bei Google brachte keine 
schlüssige Antwort :(

Besten Dank
Raff

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Sollte schon gehen, musst eben nur dem Linkerscript sagen, dass das 
Programm jetz auf ner anderen Adresse anfängt.

von Raff (Gast)


Lesenswert?

Hallo Martin

Dies habe ich bereits probiert. Funktioniert aber nicht wirklich :-(
Vorneweg, der SDRAM ansich funktioniert problemlos.

Was ich nun versucht habe:
- RAM wird gleich nach dem Clock/PLL initialisiert (direkt die 
entsprechenden Werte in die Kontrollregister)
- Linker-Script auf die entsprechende Adresse umgebogen (0xA0000000)

Die Initialisierung u.s.w. klappt soweit. Allerdings hauts ihn dann im 
startup auf den Sack (bin jetzt grad nicht mehr sicher ob beim 
CopyDataInit oder LoopCopyDataInit).

Gruss
Raff

von gerhard (Gast)


Lesenswert?

hallo raff,
welche tool chain verwendet du den?
wird der sdram controller initialisiert bevor der startup-code versucht 
auf das SDRAM zuzugreifen?

gruss
gerhard

von Raff (Gast)


Lesenswert?

Hi gerhard

Ich verwende codesourcery lite in der aktuellen Version.

der RAM wird in der SystemInit funktion gleich nach dem PLL 
initialisiert.

Kann heute Abend gerne mal den Code posten.

Gruss
Raff

von Raff (Gast)


Lesenswert?

Hi,

Ich habe noch ein bisschen experimentiert.
Das RAM-Init funktioniert erst nach dem SystemInit (PLL & Co).
Wird er vorher ausgeführt läuft der RAM nicht.
Das ist jetzt natürlich insofern ein Problem als im Startup als erstes 
mal die .data und .bss section kopiert/initialisiert werden.
Wenn das Linkerscript dann auf den SDRAM-Bereich zeigt knallts 
natürlich.

Hat jemand eine Idee?
der STM32 löst dies offenbar so das während dem System und RAM-Init der 
Stack auf dem internen RAM liegt und dieser danach umgebogen wird.
Ich werde mal versuchen dies auf beim LPC auch so zu machen

Gruss & Danke
Raff

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Also auf den ARM Kisten in der Uni auf dem wir grade nen Betriebssystem 
schreiben ist das mit nem Bootloader gelöst.

Der macht das init der grundlegenden Hardware und läd dann das Programm 
in den RAM.

von Raff (Gast)


Lesenswert?

Hallo Martin

Danke für den Tipp, dies ist natürlich auch ne Idee.
Denke aber der "Trick" mit MSP umbiegen scheint auch zu funktionieren - 
muss es aber noch genau testen.

Damit dies erstmal für die Nachwelt erhalten bleibt:

Hier das original LPC Startup File (Auszug)
1
Reset_Handler:
2
  ldr   sp, =_estack    /* set stack pointer */
3
4
  /* 1. copy .data section (Copy from ROM to RAM) */
5
  movs r1, #0
6
  b LoopCopyDataInit

Und hier das geänderte:
1
/* temporary stack address for startup */
2
.equ _temp_stack, 0x10010000
3
4
(...)
5
6
Reset_Handler:
7
  ldr   sp, = _temp_stack    /* set stack pointer */
8
9
  bl SystemInit
10
11
  bl ram_init
12
13
/* Restore original stack pointer. */
14
  ldr     r0, =_estack
15
  msr     MSP, r0
16
17
  /* 1. copy .data section (Copy from ROM to RAM) */
18
  movs r1, #0
19
  b LoopCopyDataInit


und der guten Ordnung halber noch die ram_init funktion:
1
void ram_init()
2
{
3
    volatile uint32_t i;
4
    
5
    PINSEL_ConfigPin(2,16,1);  //CAS
6
    PINSEL_ConfigPin(2,17,1);  //RAS
7
    PINSEL_ConfigPin(2,18,1);  //CLK
8
    PINSEL_ConfigPin(2,20,1);  //CS
9
    PINSEL_ConfigPin(2,24,1);  //CKE
10
    PINSEL_ConfigPin(2,28,1);  //DQM0
11
    PINSEL_ConfigPin(2,29,1);  //DQM1
12
    PINSEL_ConfigPin(4,25,1);  //WE
13
14
    //A0-14
15
    PINSEL_ConfigPin(4,0,1);
16
    PINSEL_ConfigPin(4,1,1);
17
    PINSEL_ConfigPin(4,2,1);
18
    PINSEL_ConfigPin(4,3,1);
19
    PINSEL_ConfigPin(4,4,1);
20
    PINSEL_ConfigPin(4,5,1);
21
    PINSEL_ConfigPin(4,6,1);
22
    PINSEL_ConfigPin(4,7,1);
23
    PINSEL_ConfigPin(4,8,1);
24
    PINSEL_ConfigPin(4,9,1);
25
    PINSEL_ConfigPin(4,10,1);
26
    PINSEL_ConfigPin(4,11,1);
27
    PINSEL_ConfigPin(4,12,1);
28
    PINSEL_ConfigPin(4,13,1);
29
    PINSEL_ConfigPin(4,14,1);
30
31
    //D0-15
32
    PINSEL_ConfigPin(3,0,1);
33
    PINSEL_ConfigPin(3,1,1);
34
    PINSEL_ConfigPin(3,2,1);
35
    PINSEL_ConfigPin(3,3,1);
36
    PINSEL_ConfigPin(3,4,1);
37
    PINSEL_ConfigPin(3,5,1);
38
    PINSEL_ConfigPin(3,6,1);
39
    PINSEL_ConfigPin(3,7,1);
40
    PINSEL_ConfigPin(3,8,1);
41
    PINSEL_ConfigPin(3,9,1);
42
    PINSEL_ConfigPin(3,10,1);
43
    PINSEL_ConfigPin(3,11,1);
44
    PINSEL_ConfigPin(3,12,1);
45
    PINSEL_ConfigPin(3,13,1);
46
    PINSEL_ConfigPin(3,14,1);
47
    PINSEL_ConfigPin(3,15,1);
48
49
    volatile unsigned long Dummy;
50
51
  LPC_SC->PCONP     |= 0x00000800;
52
  /*Init SDRAM controller*/
53
  LPC_SC->EMCDLYCTL |= (8<<0);
54
  /*Set data read delay*/
55
  LPC_SC->EMCDLYCTL |=(8<<8);
56
  LPC_SC->EMCDLYCTL |= (0x08 <<16);
57
58
  LPC_EMC->Control = 1;
59
  LPC_EMC->DynamicReadConfig = 1;
60
  LPC_EMC->DynamicRasCas0 = 0;
61
  LPC_EMC->DynamicRasCas0 |=(3<<8);
62
  LPC_EMC->DynamicRasCas0 |= (3<<0);
63
  LPC_EMC->DynamicRP = P2C(SDRAM_TRP);
64
  LPC_EMC->DynamicRAS = P2C(SDRAM_TRAS);
65
  LPC_EMC->DynamicSREX = P2C(SDRAM_TXSR);
66
  LPC_EMC->DynamicAPR = SDRAM_TAPR;
67
  LPC_EMC->DynamicDAL = SDRAM_TDAL+P2C(SDRAM_TRP);
68
  LPC_EMC->DynamicWR = SDRAM_TWR;
69
  LPC_EMC->DynamicRC = P2C(SDRAM_TRC);
70
  LPC_EMC->DynamicRFC = P2C(SDRAM_TRFC);
71
  LPC_EMC->DynamicXSR = P2C(SDRAM_TXSR);
72
  LPC_EMC->DynamicRRD = P2C(SDRAM_TRRD);
73
  LPC_EMC->DynamicMRD = SDRAM_TMRD;
74
75
  // 13 row, 9 - col, SDRAM
76
  LPC_EMC->DynamicConfig0 = 0x0000680;
77
  // JEDEC General SDRAM Initialization Sequence
78
  // DELAY to allow power and clocks to stabilize ~100 us
79
  // NOP
80
  LPC_EMC->DynamicControl = 0x0183;
81
  for(i= 200*30; i;i--);
82
  // PALL
83
  LPC_EMC->DynamicControl = 0x0103;
84
  LPC_EMC->DynamicRefresh = 1;
85
  for(i= 256; i; --i); // > 128 clk
86
  LPC_EMC->DynamicRefresh = P2C(SDRAM_REFRESH) >> 4;
87
  // COMM
88
89
    LPC_EMC->DynamicControl    = 0x00000083; /* Issue MODE command */
90
  Dummy = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x33<<12)));
91
  // NORM
92
  LPC_EMC->DynamicControl = 0x0000;
93
  LPC_EMC->DynamicConfig0 |=(1<<19);
94
  for(i = 100000; i;i--);
95
}

Und hier noch das Linker Script im Original:
1
/* Highest address of the user mode stack */
2
_estack = 0x10010000;    /* end of 64K RAM */
3
4
(...)
5
6
/* Specify the memory areas */
7
MEMORY
8
{
9
  FLASH (rx)      : ORIGIN = 0x00000000, LENGTH = 512K
10
  RAM (xrw)       : ORIGIN = 0x10000000, LENGTH = 64K
11
  RAM1 (xrw)      : ORIGIN = 0x2007C000, LENGTH = 16K
12
  RAM2 (xrw)      : ORIGIN = 0x20080000, LENGTH = 0K
13
  MEMORY_B1 (rx)  : ORIGIN = 0x80000000, LENGTH = 0K
14
}

Und das geänderte:
1
/* Highest address of the user mode stack */
2
_estack = 0xA2000000;    /* end of 32M RAM */
3
4
(...)
5
6
/* Specify the memory areas */
7
MEMORY
8
{
9
  FLASH (rx)      : ORIGIN = 0x00000000, LENGTH = 512K
10
  RAM (xrw)       : ORIGIN = 0xA0000000, LENGTH = 0x02000000
11
  RAM1 (xrw)      : ORIGIN = 0x2007C000, LENGTH = 16K
12
  RAM2 (xrw)      : ORIGIN = 0x20080000, LENGTH = 0K
13
  MEMORY_B1 (rx)  : ORIGIN = 0x80000000, LENGTH = 0K
14
}

Und raus kommt danach das hier:
1
CPU/Periph/EMC/USB              120/60/60/48 MHz
2
Ram-Config
3
DynamicRP=3
4
DynamicRAS=6
5
DynamicSREX=9
6
DynamicDAL=6
7
DynamicRC=8
8
DynamicRFC=8
9
DynamicXSR=9
10
DynamicRRD=2
11
DynamicRefresh=58
12
EMCDLYCTL=526872
13
PCONP=86552542
14
DynamicRasCas0=771
15
MSP=0xa1ffff98 <--

Der Stackpointer zeit jetzt ganz ordentlich auf den externen SDRAM.


Gruss Raff

von Harper (Gast)


Lesenswert?

Raff schrieb:
> LPC_SC->PCONP     |= 0x00000800;

Damit wird das Bit 12 "PCADC" gesetzt. Sollte das nicht das Bit 11 
"PCEMC" sein?

von Harper (Gast)


Lesenswert?

Ich hab mich verzählt. Bitte ignorieren.

von Harper B. (harper)


Lesenswert?

Raff schrieb:
>
> und der guten Ordnung halber noch die ram_init funktion:
>
> [c]
> void ram_init()
> {
>     volatile uint32_t i;
>
...
>   /*Init SDRAM controller*/
>   LPC_SC->EMCDLYCTL |= (8<<0);
>   /*Set data read delay*/
>   LPC_SC->EMCDLYCTL |=(8<<8);
>   LPC_SC->EMCDLYCTL |= (0x08 <<16);
Hier werde nur Bits gesetzt. Von welcher Anfangsbelegung gehst Du hier 
aus?

>   LPC_EMC->DynamicRP = P2C(SDRAM_TRP);
...
Hier wird die Funktion (oder das Makro) P2C verwendet. Kannst Du dieses 
posten?
Wie hast Du die SDRAM_XXX -Werte gefunden?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.