59 views
in Getting started by

Hi.

I want to take the example provided by the Embedded Wizard and place resource data on a QSPI NOR-FLASH(MT25QL128ABA - 16MB) on my custom board(using STM32H753).

 

/**
  * @brief QUADSPI Initialization Function
  * @param None
  * @retval None
  */
static void MX_QUADSPI_Init(void) {

    /* USER CODE BEGIN QUADSPI_Init 0 */

    /* USER CODE END QUADSPI_Init 0 */

    /* USER CODE BEGIN QUADSPI_Init 1 */

    /* USER CODE END QUADSPI_Init 1 */
    /* QUADSPI parameter configuration*/
    hqspi.Instance = QUADSPI;
    hqspi.Init.ClockPrescaler = 1;
    hqspi.Init.FifoThreshold = 4;
    hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
    hqspi.Init.FlashSize = 24-1;
    hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_5_CYCLE;
    hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
    hqspi.Init.FlashID = QSPI_FLASH_ID_1;
    hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
    if (HAL_QSPI_Init(&hqspi) != HAL_OK) {
        Error_Handler();
    }
    /* USER CODE BEGIN QUADSPI_Init 2 */

    /* USER CODE END QUADSPI_Init 2 */

}
/**
 * @brief                   set NOR-FLASH memory mapped mode
 * @return                  result
 */
uint8_t set_memory_mapped(void) {

    QSPI_CommandTypeDef cmd;
    QSPI_MemoryMappedTypeDef memory;
    // set read command
    cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    cmd.Instruction = MEMORY_FAST_READ;
    cmd.AddressMode = QSPI_ADDRESS_4_LINES;
    cmd.AddressSize = QSPI_ADDRESS_24_BITS;
    cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    cmd.DummyCycles = 0x0A;
    cmd.DataMode = QSPI_DATA_4_LINES;
    cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
    cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
    cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
    // set memory command
    memory.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
    memory.TimeOutPeriod = 0;
    // set command
    if (HAL_QSPI_MemoryMapped(&hqspi, &cmd, &memory) != HAL_OK)
        return 0;
    // result
    return 1;
}

 

main.c

// initialize QSPI device
MX_QUADSPI_Init();

...

// set memory mapped mode
if (set_memory_mapped_mode() == 0)
   // set error
   Error_Handler();

...


// initialize embedded wizard
if (EwInit() == 0)
   // set error
   Error_Handler();


/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
   // process embedded wizard
   EwProcess();
}

 

STM32H7753XIHX_FLASH.ld

/*
 ******************************************************************************
 **
 **  File        : LinkerScript.ld
 **
 **  Author      : STM32CubeIDE
 **
 **  Abstract    : Linker script for STM32H7 series
 **                2048Kbytes FLASH and 1056Kbytes RAM
 **
 **                Set heap size, stack size and stack location according
 **                to application requirements.
 **
 **                Set memory bank area and size if external memory is used.
 **
 **  Target      : STMicroelectronics STM32
 **
 **  Distribution: The file is distributed as is, without any warranty
 **                of any kind.
 **
 *****************************************************************************
 ** @attention
 **
 ** Copyright (c) 2024 STMicroelectronics.
 ** All rights reserved.
 **
 ** This software is licensed under terms that can be found in the LICENSE file
 ** in the root directory of this software component.
 ** If no LICENSE file comes with this software, it is provided AS-IS.
 **
 ****************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1);    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x2000;      /* required amount of heap  */
_Min_Stack_Size = 0x2000; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
    FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 2048K
    QSPI (xrw)      : ORIGIN = 0x90000000, LENGTH = 16M
    RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH = 512K
}

/* Define output sections */
SECTIONS
{
    /* The startup code goes first into FLASH */
    .isr_vector :
    {
        . = ALIGN(4);
        KEEP(*(.isr_vector)) /* Startup code */
        . = ALIGN(4);
    } >FLASH
    
    /* The Embedded Wizard resource rodata goes into external FLASH */
    .SectionEwResource (NOLOAD) :
    {
        . = ALIGN(4);
        *(.SectionEwResource)
        . = ALIGN(4);
    } >QSPI
    
    /* The program code and other data goes into FLASH */
    .text :
    {
        . = ALIGN(4);
        *(.text)           /* .text sections (code) */
        *(.text*)          /* .text* sections (code) */
        *(.glue_7)         /* glue arm to thumb code */
        *(.glue_7t)        /* glue thumb to arm code */
        *(.eh_frame)
        
        KEEP (*(.init))
        KEEP (*(.fini))
        
        . = ALIGN(4);
        _etext = .;        /* define a global symbols at end of code */
    } >FLASH

    /* Constant data goes into FLASH */
    .rodata :
    {
        . = ALIGN(4);
        *(.rodata)         /* .rodata sections (constants, strings, etc.) */
        *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
        . = ALIGN(4);
    } >FLASH
    
    .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } >FLASH
    .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
    {
        __exidx_start = .;
        *(.ARM.exidx*)
        __exidx_end = .;
    } >FLASH
    
    .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
    {
        PROVIDE_HIDDEN (__preinit_array_start = .);
        KEEP (*(.preinit_array*))
        PROVIDE_HIDDEN (__preinit_array_end = .);
    } >FLASH
    
    .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
    {
        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array*))
        PROVIDE_HIDDEN (__init_array_end = .);
    } >FLASH
    
    .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
    {
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP (*(SORT(.fini_array.*)))
        KEEP (*(.fini_array*))
        PROVIDE_HIDDEN (__fini_array_end = .);
    } >FLASH
    
    /* used by the startup to initialize data */
    _sidata = LOADADDR(.data);
    
    /* Initialized data sections goes into RAM, load LMA copy after code */
    .data :
    {
        . = ALIGN(4);
        _sdata = .;        /* create a global symbol at data start */
        *(.data)           /* .data sections */
        *(.data*)          /* .data* sections */
        
        . = ALIGN(4);
        _edata = .;        /* define a global symbol at data end */
    } >RAM_D1 AT> FLASH
    
    /* Uninitialized data section */
    . = ALIGN(4);
    .bss :
    {
        /* This is used by the startup in order to initialize the .bss section */
        _sbss = .;         /* define a global symbol at bss start */
        __bss_start__ = _sbss;
        *(.bss)
        *(.bss*)
        *(COMMON)
        
        . = ALIGN(4);
        _ebss = .;         /* define a global symbol at bss end */
        __bss_end__ = _ebss;
    } >RAM_D1
    
    /* User_heap_stack section, used to check that there is enough RAM left */
    ._user_heap_stack :
    {
        . = ALIGN(8);
        PROVIDE ( end = . );
        PROVIDE ( _end = . );
        . = . + _Min_Heap_Size;
        . = . + _Min_Stack_Size;
        . = ALIGN(8);
    } >RAM_D1
        
    /* Remove information from the standard libraries */
    /DISCARD/ :
    {
        libc.a ( * )
        libm.a ( * )
        libgcc.a ( * )
    }
    
    .ARM.attributes 0 : { *(.ARM.attributes) }
}

 

 

The QSPI has an input clock of 120 MHz.

The build works fine and when debugging, the system freezes on the EwNewObjectIndirect() function call inside the EwInit() function.

I'm trying to use memory mapped mode of QSPI for the first time to reduce the usage of internal FLASH and I'm not sure what the problem is.

 

1 Answer

0 votes
by
Hello,

maybe you can try first to make a simple read routine to ensure that the QSPI flash is working and that the expected data are received. Does this work?

Have you enhanced your MPU settings to allow the CPU to access the region located within the QSPI flash?

Best regards,

Manfred.
by

1. We tested the read/write functionality for all sectors.
   When you say read test, do you mean to do it in memory mapped mode?
   

2. MPU settings are set.

/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER4;
MPU_InitStruct.BaseAddress = 0x90000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

 

by

1. Yes, the data should be read directly by CPU by using the mapped address area. Does this work?

2. Let me recommend the MPU settings:

  MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
  MPU_InitStruct.Number           = MPU_REGION_NUMBER4;
  MPU_InitStruct.BaseAddress      = 0x90000000;
  MPU_InitStruct.Size             = MPU_REGION_SIZE_16MB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
  MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
  HAL_MPU_ConfigRegion(&MPU_InitStruct);

 

by

1. When tested with the following code, it crashes when accessing the QSPI during debugging.

volatile uint32_t *flash = (uint32_t *) 0x90000000;
volatile uint32_t res = 0;
// check size
for (int i = 0; i < 1000; ++i) {
    res += flash[i];
}

 

by
What means "crashes"?

I assume there is an hardfault or memfault with some additional information that could help.

Maybe you can find some help in ST forum concerning the access of QSPI flash. Due to the fact that you cannot read it with a simple loop, the topic is not related to Embedded Wizard and GUI development...
by
Debugging no longer works - pausing, restarting, etc. doesn't work at all.

Thank you for your response. I will contact ST about the QSPI memory mapped mode.
by
Thanks. It would be great if you can share the result.

Embedded Wizard Website | Privacy Policy | Imprint

...