cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7A3x stack overwriting issue at f_read (SDMMC + DMA + FATFS)

Emilmart
Senior

Hi,

I am currently developping a custom bootloader to flash my app with STM32H7A3ZIx / SDMMC / FATFS with DMA template

It fetch a binary (*.bin) from an SD card, read maximum BUFFER_SIZE (=8192) and stores it in a uint8_t RAM_Buf[BUFFER_SIZE] array (8KB).

The reading with FATFS function f_read(&SDFile, RAM_Buf, BUFFER_SIZE, (uint_t *)&bytesread fills the RAM_Buf with the correct datas from my binary.

The problem is that the f_read erase my stack, so the locals variables like readflag are overwritted. (1 at init, but 0 after the f_read). Here's the code (from X-CUBE-IAP-SD) :

#define BUFFER_SIZE ((uint16_t)1 * 8192)
static uint32_t RamAddress = 0x00;
static uint8_t RAM_Buf[BUFFER_SIZE] = {0x00};
#define TRUE    1
#define FALSE   0
 
/**
  * @brief  Programs the internal Flash memory.
  * @param  None
  * @retval None
  */
static void COMMAND_ProgramFlashMemory(void)
{
	uint16_t bytesread = 0;
	uint8_t readflag = TRUE;
 
	/* RAM Address Initialization */
	RamAddress = (uint32_t)&RAM_Buf;
 
	/* Erase address init */
	LastPGAddress = FLASH_USER_START_ADDR;
 
	/* While file still contain data */
	while ((readflag == TRUE))
	{
		/* Read maximum "BUFFER_SIZE" Kbyte from the selected file  */
		if (f_read(&SDFile, RAM_Buf, BUFFER_SIZE, (uint_t *)&bytesread) != FR_OK)    // after the first execution of the f_read, readflag is overwritten to 0
		{
			Error_Handler();
		}
 
		/* The read data < "BUFFER_SIZE" Kbyte */
		if (bytesread < BUFFER_SIZE)
		{
			readflag = FALSE;
		}
 
        if (FLASH_If_Write(LastPGAddress, (uint32_t *)RamAddress, bytesread / 4) != 0x00)
        {
            /* Flash programming error */
            Error_Handler();
        }
 
		/* Update last programmed address value */
		LastPGAddress = LastPGAddress + bytesread;
	}
}

I cannot pinpoint why the stack is overwritted. I have tried to increase my stack, use a ram section dedicated to the RAM_Buf, but it does not fix the problem.

CPU ICache/DCache is disabled.

Here's my linker file :

/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);	/* end of "RAM" Ram type memory */
 
_Min_Heap_Size = 0x3000 ;	/* required amount of heap  */
_Min_Stack_Size = 0x2000 ;	/* required amount of stack */
 
/* Memories definition */
MEMORY
{
  DTCMRAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
  ITCMRAM    (xrw)    : ORIGIN = 0x00000000,   LENGTH = 64K
  RAM    (xrw)    : ORIGIN = 0x24000000,   LENGTH = 1024K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 128K
}
 
/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH
    
  /* The program code and other data into "FLASH" Rom type memory */
  .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 into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH
 
  .ARM.extab   : {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH
 
  .ARM : {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH
 
  .preinit_array     :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH
 
  .init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH
 
  .fini_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH
 
  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);
 
  /* Initialized data sections into "RAM" Ram type memory */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */
    
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
 
  } >RAM AT> FLASH
 
  /* Uninitialized data section into "RAM" Ram type memory */
  . = 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
 
  /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM
 
  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
 
  .ARM.attributes 0 : { *(.ARM.attributes) }
}

Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
SStor
Senior

Your variable bytesread has to be 32bit and not 16bit.

Therefore the following local variable readflag will be corrupted on stack.

View solution in original post

2 REPLIES 2
SStor
Senior

Your variable bytesread has to be 32bit and not 16bit.

Therefore the following local variable readflag will be corrupted on stack.

Emilmart
Senior

that's it ! guess I'll buy new glasses. thanks 👍