cancel
Showing results for 
Search instead for 
Did you mean: 

Is there an example to use external RAM for the STM32F429I-DISCO?

lhofstaetter9
Associate II

The evaluation board STM32F429I-DISCO has a Synchronous Dynamic RAM: ISSI IS42S16400J

I must use this external RAM instead of the internal RAM so I had a look to the example from "FMC/FMC_SDRAM_DataMemory"

The example looks quiete easy. Nevertheless I wonder if the example really fits to my hardware because the example implements one SystemInit_ExtMemCtl for "SRAM mounted on STM324xG_EVAL/STM324x7I" and an other SystemInit_ExtMemCtl for "SDRAM mounted on STM324x9I_EVAL board".

Do I need to adapt the SystemInit_ExtMemCtl for my evaluation board?

3 REPLIES 3
lhofstaetter9
Associate II

Okay, I had a look to the example code of the STM32F429I-DISCO and to the example code of the FMC_SDRAM_DataMemory.

What I did so far:

I adapted _estack added the RAM region in the linker file:

/* Highest address of the user mode stack */
_estack = 0x60030000;
 
/* Specify the memory areas */
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 2048K
  RAM (xrw)       : ORIGIN = 0x60000000, LENGTH = 192K
  CCM (rw)        : ORIGIN = 0x10000000, LENGTH = 64K
}

I edited the startup file. At the beginning of the Reset_Handler the stack pointer is set to internal RAM. After the Call of SystemInit the stack pointer is being set to the original value pointing to the external RAM.

/* stack used for SystemInit & SystemInit_ExtMemCtl*/
.equ __initial_spTop, 0x20000400
    .section  .text.Reset_Handler
  .weak  Reset_Handler
  .type  Reset_Handler, %function
Reset_Handler:
 ldr   sp, =__initial_spTop     /* set stack pointer */
 
...
 
/* Call the clock system intitialization function.*/
  bl  SystemInit
/* Call static constructors */
  bl __libc_init_array
 
    /* Restore original stack pointer. */
  ldr     r0, =_estack
  msr     MSP, r0
/* Call the application's entry point.*/
  bl  main

In the sytem_stm32f4xx.c the define `DATA_IN_ExtSDRAM` is set to enable the call to `SystemInit_ExtMemCtl` which I took from the example code of the STM32F429I-DISCO.

void SystemInit_ExtMemCtl(void)
{
  register uint32_t tmpreg = 0, timeout = 0xFFFF;
  register uint32_t index;
 
  /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface 
      clock */
  RCC->AHB1ENR |= 0x000001FC;
  
  /* Connect PCx pins to FMC Alternate function */
  GPIOC->AFR[0]  = 0x0000000c;
  GPIOC->AFR[1]  = 0x00007700;
  /* Configure PCx pins in Alternate function mode */  
  GPIOC->MODER   = 0x00a00002;
  /* Configure PCx pins speed to 50 MHz */  
  GPIOC->OSPEEDR = 0x00a00002;
  /* Configure PCx pins Output type to push-pull */  
  GPIOC->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PCx pins */ 
  GPIOC->PUPDR   = 0x00500000;
  
  /* Connect PDx pins to FMC Alternate function */
  GPIOD->AFR[0]  = 0x000000CC;
  GPIOD->AFR[1]  = 0xCC000CCC;
  /* Configure PDx pins in Alternate function mode */  
  GPIOD->MODER   = 0xA02A000A;
  /* Configure PDx pins speed to 50 MHz */  
  GPIOD->OSPEEDR = 0xA02A000A;
  /* Configure PDx pins Output type to push-pull */  
  GPIOD->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PDx pins */ 
  GPIOD->PUPDR   = 0x00000000;
 
  /* Connect PEx pins to FMC Alternate function */
  GPIOE->AFR[0]  = 0xC00000CC;
  GPIOE->AFR[1]  = 0xCCCCCCCC;
  /* Configure PEx pins in Alternate function mode */ 
  GPIOE->MODER   = 0xAAAA800A;
  /* Configure PEx pins speed to 50 MHz */ 
  GPIOE->OSPEEDR = 0xAAAA800A;
  /* Configure PEx pins Output type to push-pull */  
  GPIOE->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PEx pins */ 
  GPIOE->PUPDR   = 0x00000000;
 
  /* Connect PFx pins to FMC Alternate function */
  GPIOF->AFR[0]  = 0xcccccccc;
  GPIOF->AFR[1]  = 0xcccccccc;
  /* Configure PFx pins in Alternate function mode */   
  GPIOF->MODER   = 0xAA800AAA;
  /* Configure PFx pins speed to 50 MHz */ 
  GPIOF->OSPEEDR = 0xAA800AAA;
  /* Configure PFx pins Output type to push-pull */  
  GPIOF->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PFx pins */ 
  GPIOF->PUPDR   = 0x00000000;
 
  /* Connect PGx pins to FMC Alternate function */
  GPIOG->AFR[0]  = 0xcccccccc;
  GPIOG->AFR[1]  = 0xcccccccc;
  /* Configure PGx pins in Alternate function mode */ 
  GPIOG->MODER   = 0xaaaaaaaa;
  /* Configure PGx pins speed to 50 MHz */ 
  GPIOG->OSPEEDR = 0xaaaaaaaa;
  /* Configure PGx pins Output type to push-pull */  
  GPIOG->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PGx pins */ 
  GPIOG->PUPDR   = 0x00000000;
  
  /* Connect PHx pins to FMC Alternate function */
  GPIOH->AFR[0]  = 0x00C0CC00;
  GPIOH->AFR[1]  = 0xCCCCCCCC;
  /* Configure PHx pins in Alternate function mode */ 
  GPIOH->MODER   = 0xAAAA08A0;
  /* Configure PHx pins speed to 50 MHz */ 
  GPIOH->OSPEEDR = 0xAAAA08A0;
  /* Configure PHx pins Output type to push-pull */  
  GPIOH->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PHx pins */ 
  GPIOH->PUPDR   = 0x00000000;
  
  /* Connect PIx pins to FMC Alternate function */
  GPIOI->AFR[0]  = 0xCCCCCCCC;
  GPIOI->AFR[1]  = 0x00000CC0;
  /* Configure PIx pins in Alternate function mode */ 
  GPIOI->MODER   = 0x0028AAAA;
  /* Configure PIx pins speed to 50 MHz */ 
  GPIOI->OSPEEDR = 0x0028AAAA;
  /* Configure PIx pins Output type to push-pull */  
  GPIOI->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PIx pins */ 
  GPIOI->PUPDR   = 0x00000000;
  
/*-- FMC Configuration ------------------------------------------------------*/
  /* Enable the FMC interface clock */
  RCC->AHB3ENR |= 0x00000001;
  
  /* Configure and enable SDRAM bank1 */
  FMC_Bank5_6->SDCR[0] = 0x000029D0;
  FMC_Bank5_6->SDTR[0] = 0x01115351;      
  
  /* SDRAM initialization sequence */
  /* Clock enable command */
  FMC_Bank5_6->SDCMR = 0x00000011; 
  tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }
 
  /* Delay */
  for (index = 0; index<1000; index++);
  
  /* PALL command */
  FMC_Bank5_6->SDCMR = 0x00000012;           
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }
  
  /* Auto refresh command */
  FMC_Bank5_6->SDCMR = 0x00000073;
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }
 
  /* MRD register program */
  FMC_Bank5_6->SDCMR = 0x00046014;
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  } 
  
  /* Set refresh count */
  tmpreg = FMC_Bank5_6->SDRTR;
  FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
  
  /* Disable write protection */
  tmpreg = FMC_Bank5_6->SDCR[0]; 
  FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
 
/*
  Bank1_SDRAM is configured as follow:
 
  FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;      
  FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 6;  
  FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;        
  FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 6;         
  FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;      
  FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;                
  FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;               
 
  FMC_SDRAMInitStructure.FMC_Bank = SDRAM_BANK;
  FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
  FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_11b;
  FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b;
  FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
  FMC_SDRAMInitStructure.FMC_CASLatency = FMC_CAS_Latency_3; 
  FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
  FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_2;
  FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_disable;
  FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1;
  FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
*/
}

In the main routine I added something like this:

int test = 42;
  int *ref = &test;
  *ref = *ref + 42;

So far so good. After compiling and flashing the stm32 runs very well into the main routine. I used the debugger to verify that stack pointer is set right in the startup assember code. The test statements I added in the main does not work. Take a look to the debugger view:

0690X0000087mEgQAI.png

 It looks like the value stored by`str    r3, [r7, #12]` in the RAM canote be loaded by `ldr    r3, [r7, #12]`.

So the processor "thinks" the register R3 had been stored to RAM. But the Value of R3 has never been written to extern RAM or cannot be read back.

  

Does anybody know how to go on from here?

As I recall the SDRAM on the STM32F429I-DISCO is situated at 0xD0000000

I would avoid using it for the stack, it will make everything run slower.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
lhofstaetter9
Associate II

Hi Clive,

Thank's for the hints. It will be no problem if the execution will be slower because this project is just about On-Chip Unit Tests which need amounts of RAM for Coverage Data.

I had a look to schematics and your're nearly right. The SDRAM is not located to 0x60000000. It is located to 0xC0000000 which is the SDRAM bank 1.

Using the Debugger to write manually to the SDRAM showed that writing to 0x60000000 or 0xD0000000 is not possible. Writing to 0xC000000 works partially. After writing 0x12345678 the value which I read back is 0x56785678.

I thought the Examples of ST would run out of the box. But it really looks like I need to read and understand the whole FMC documentation and the SRAM Wiring...