AnsweredAssumed Answered

STM32F7 Heap on External SDRAM

Question asked by Keaven on May 4, 2016
Latest reply on Aug 10, 2017 by Willem La Grange
Hello everyone,

I have managed to configure the FMC to read/write on my external SDRAM.  Now, I am trying to put the heap on it.  Unfortunately, I am unsuccessful.   I look up on the forum and I have did change the startup file to use the same size and use a scatter file for place the heap on it.  In the map file , the heap seems well placed.

The problem occurs when I am trying to do a malloc().  I get a hard fault.
Here is the code I am using...

int main(void)
{
    char* p;
    static char AddressString[16] = {0};
     
    //Compatibility call currently not required in version 4.75
    //Initialize CMSIS-RTOS
    osKernelInitialize();
 
    //Enable I-Cache
    SCB_EnableICache();
 
    //Enable D-Cache
    SCB_EnableDCache();
 
    //Configure the system clock to 216 MHz
    SystemClock_Config();
 
    //Reset of all peripherals, initialize the flash interface and the systick
    HAL_Init();
 
    //Compatibility call currently not required in version 4.75
    //Start CMSIS-RTOS thread execution
    osKernelStart();
 
    p = (char*) malloc(0x2000);
     
    sprintf(AddressString, "%08x", (uint32_t) p);
     
    free(p);
     
}
 
void InitFMC (void)
{
    FMC_SDRAM_TimingTypeDef SdramTiming;
    FMC_SDRAM_CommandTypeDef Command;
    volatile uint32_t timeout = SDRAM_TIMEOUT;
 
    /** Perform the SDRAM2 memory initialization sequence
    */
    hsdram2.Instance = FMC_SDRAM_DEVICE;
    /* hsdram2.Init */
    hsdram2.Init.SDBank = FMC_SDRAM_BANK1;
    hsdram2.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
    hsdram2.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
    hsdram2.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
    hsdram2.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
    hsdram2.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
    hsdram2.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
    hsdram2.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
    hsdram2.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
    hsdram2.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_2;
 
    /* SdramTiming */
//  Timing for 143 Mhz so ok for 108MHz(9.25ns)
    SdramTiming.LoadToActiveDelay = 2;
    SdramTiming.ExitSelfRefreshDelay = 10;
    SdramTiming.SelfRefreshTime = 6;
    SdramTiming.RowCycleDelay = 9;
    SdramTiming.WriteRecoveryTime = 3;
    SdramTiming.RPDelay = 3;
    SdramTiming.RCDDelay = 3;
 
    HAL_SDRAM_Init(&hsdram2, &SdramTiming);
 
    /* SDRAM Init sequence */
 
    /* Configure a clock configuration enable command */
    Command.CommandMode             = FMC_SDRAM_CMD_CLK_ENABLE;
    Command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber       = 1;
    Command.ModeRegisterDefinition  = 0;
 
    /* Send command */
    HAL_SDRAM_SendCommand(&hsdram2, &Command, SDRAM_TIMEOUT);
 
    //NOP
    Command.CommandMode             = FMC_SDRAM_CMD_NORMAL_MODE;
    Command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber       = 1;
    Command.ModeRegisterDefinition  = 0;
 
    /* Send command */
    HAL_SDRAM_SendCommand(&hsdram2, &Command, SDRAM_TIMEOUT);
 
    /* Little delay */
    timeout = SDRAM_TIMEOUT * 0xF;
    while (timeout--);
 
    /* Configure a PALL (precharge all) command */
    Command.CommandMode             = FMC_SDRAM_CMD_PALL;
    Command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber       = 2;
    Command.ModeRegisterDefinition  = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(&hsdram2, &Command, SDRAM_TIMEOUT);
 
    /* Configure a Auto-Refresh command */
    Command.CommandMode             = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
    Command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber       = 8;
    Command.ModeRegisterDefinition  = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(&hsdram2, &Command, SDRAM_TIMEOUT);
 
    /* Configure a load Mode register command */
    Command.CommandMode             = FMC_SDRAM_CMD_LOAD_MODE;
    Command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber       = 2;
    Command.ModeRegisterDefinition  = (uint32_t)0x230;
 
    /* Wait until the SDRAM controller is ready */
    /* Send the command */
    HAL_SDRAM_SendCommand(&hsdram2, &Command, SDRAM_TIMEOUT);
 
    /* Step 6: Set the refresh rate counter */
    /* Set the device refresh rate */
    //64ms for 8192 rows = 7.8125 us.
    //(7.8125us * 108 MHz ) - 20 = 823.75
    HAL_SDRAM_ProgramRefreshRate(&hsdram2, 0x337);
     
    //SYSCFG->MEMRMP |= 0x00000400;
}
 
void HAL_MspInit(void)
{
    //Initialize Peripherals
    InitFMC();
}
 
void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram)
{
    GPIO_InitTypeDef GPIO_InitStruct;
 
    __HAL_RCC_FMC_CLK_ENABLE();
 
    /* GPIOC */
    __HAL_RCC_GPIOC_CLK_ENABLE();
     
    //PC0:nWE
    //PC2:nCS
    //PC3:CKE
    GPIO_InitStruct.Pin =       GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3;
    GPIO_InitStruct.Mode =      GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull =      GPIO_NOPULL;
    GPIO_InitStruct.Speed =     GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
    /* GPIOD */
    __HAL_RCC_GPIOD_CLK_ENABLE();
 
    //PD0:DQ2
    //PD1:DQ3
    //PD8:DQ13
    //PD9:DQ14
    //PD10:DQ15
    //PD14:DQ0
    //PD15:DQ1
    GPIO_InitStruct.Pin =       GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |
                                GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStruct.Mode =      GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull =      GPIO_NOPULL;
    GPIO_InitStruct.Speed =     GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);   
 
    /* GPIOE */
    __HAL_RCC_GPIOE_CLK_ENABLE();
     
    //PE0:DQML
    //PE1:DQMH
    //PE7:DQ4
    //PE8:DQ5
    //PE9:DQ6
    //PE10:DQ7
    //PE11:DQ8
    //PE12:DQ9
    //PE13:DQ10
    //PE14:DQ11
    //PE15:DQ12
    GPIO_InitStruct.Pin =       GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |
                                GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                                GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStruct.Mode =      GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull =      GPIO_NOPULL;
    GPIO_InitStruct.Speed =     GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
    /* GPIOF */
    __HAL_RCC_GPIOF_CLK_ENABLE();
 
    //PF0:A0
    //PF1:A1
    //PF2:A2
    //PF3:A3
    //PF4:A4
    //PF5:A5
    //PF11:nRAS
    //PF12:A6
    //PF13:A7
    //PF14:A8
    //PF15:A9
    GPIO_InitStruct.Pin =       GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                                GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 |
                                GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStruct.Mode =      GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull =      GPIO_NOPULL;
    GPIO_InitStruct.Speed =     GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
    /* GPIOG */
    __HAL_RCC_GPIOG_CLK_ENABLE();
 
    //  PG0:A10
    //  PG1:A11
    //  PG2:A12
    //  PG4:BA0
    //  PG5:BA1
    //  PG8:CLK
    //  PG15:nCAS
    GPIO_InitStruct.Pin =       GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 |
                                GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15;
    GPIO_InitStruct.Mode =      GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull =      GPIO_NOPULL;
    GPIO_InitStruct.Speed =     GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
 
}
 
//In startup.s
; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
 
Heap_Size       EQU     0x02000000
 
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit
 
//Scatter file
 
LR_IROM1 0x08040000 0x000C0000  {    ; load region size_region
  ER_IROM1 0x08040000 0x000C0000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20010000 0x00040000  {  ; RW data
   .ANY (+RW +ZI)
  }
  RW_IRAM2 0x20000000 0x00010000  {
    CSCH_DTCM_Buffers.o (+ZI +RW)
  }
  RW_RAM1 0xC0000000 0x02000000  {
    *(HEAP)
  }
}

Thank you!

Outcomes