S32K118 optimizing code makes SDK FLASH_DRV_EraseSector() return STATUS_ERROR

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

S32K118 optimizing code makes SDK FLASH_DRV_EraseSector() return STATUS_ERROR

Jump to solution
641 Views
melvinw
Contributor II

Hello Community,

I'm working on a bootloader for a custom PCB with the S32K118 processor. Here i communicate al the data of the hexfile through the CAN communication and write each flash sector to the following address and upwards: 0x20000.This bootloader successfully flashes the communicated data to the flash of the MCU. And if i jump to the application that is flashed it seems to work fine.

But when i change the optimization level of my bootloader code from none to for example -O3 like below in my build settings:

melvinw_0-1678719505598.png

Something strange happens in on of my methods:

status_t abs_Flash_Write_Sector(uint32_t address, uint32_t size, uint8_t* sourceBuffer, uint32_t bufferSize)
{
status_t ret = STATUS_SUCCESS;
uint32_t failAddress = 0;

INT_SYS_DisableIRQGlobal();

/* Set callback function before a long time consuming flash operation
* (ex: erasing) to let the application code do other tasks while flash
* in operation. In this case we use it to enable interrupt for
* Flash Command Complete event */
flash_callback_t pCallBack = (flash_callback_t)CCIF_Callback;
flashSSDConfig.CallBack = pCallBack;

/* Erase the specific PFlash sector */
/* Configure address, size to erase sector function. For example on S32K144 */
size = FEATURE_FLS_PF_BLOCK_SECTOR_SIZE;
ret = FLASH_DRV_EraseSector(&flashSSDConfig, address, size);             <----------- HERE MY CODE CRASHES (more info below)
DEV_ASSERT(STATUS_SUCCESS == ret);

/* Disable Callback */
flashSSDConfig.CallBack = NULL_CALLBACK;

/* Verify the erase operation at margin level value of 1, user read */
ret = FLASH_DRV_VerifySection(&flashSSDConfig, address, size / FTFx_DPHRASE_SIZE, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);

/* Write some data to the erased PFlash sector */
ret = FLASH_DRV_Program(&flashSSDConfig, address, bufferSize, sourceBuffer);
DEV_ASSERT(STATUS_SUCCESS == ret);

/* Verify the program operation at margin level value of 1, user margin */
ret = FLASH_DRV_ProgramCheck(&flashSSDConfig, address, bufferSize, sourceBuffer, &failAddress, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);

INT_SYS_EnableIRQGlobal();

return ret;
}

When this method is called the and i run the debug with my Universal Multilink Debug probe its shows that is crashes and goes to the default ISR. And when i place a breakpoint the FLASH_DRV_EraseSector() returns a STATUS_ERROR.

melvinw_1-1678720082930.png

When i unplug the debug probe restart the pcb and run my code without debug. The same fault seems to happen when i start to flash my hexfile to the device. Because is can see it stops working on the same spot.

I'm not sure why this is happening. I've read that uninitialized variables can cause this behavior, but i made sure that everything i could think of is initialized.

Does anybody have a clou what can be the cause of this? Any help is greatly appriciated.

 

Below my linker file of the bootloader:

/* Entry Point */
ENTRY(Reset_Handler)

HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x00000200;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000200;

/* If symbol __flash_vector_table__=1 is defined at link time
* the interrupt vector will not be copied to RAM.
* Warning: Using the interrupt vector from Flash will not allow
* INT_SYS_InstallHandler because the section is Read Only.
*/
M_VECTOR_RAM_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : 0x00C0;

/* Specify the memory areas */
MEMORY
{
/* Flash */
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000C0
m_flash_config (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x0001FFFF - 0x00000410 /* 16KB - 0x10*/

/* SRAM_L */
m_custom (RW) : ORIGIN = 0x1FFFFC00, LENGTH = 0x00000400

/* SRAM_U */
m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x000030C0
m_data_2 (RW) : ORIGIN = 0x200030C0, LENGTH = 0x00002740

m_exchange_info (RW) : ORIGIN = 0x20005800, LENGTH = 0x00000010
}

/* Define output sections */
SECTIONS
{
/* The startup code goes first into internal flash */
.interrupts :
{
__VECTOR_TABLE = .;
__interrupts_start__ = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
__interrupts_end__ = .;
. = ALIGN(4);
} > m_interrupts

.flash_config :
{
. = ALIGN(4);
KEEP(*(.FlashConfig)) /* Flash Configuration Field (FCF) */
. = ALIGN(4);
} > m_flash_config


/* The program code and other data goes into internal flash */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.init) /* section used in crti.o files */
*(.fini) /* section used in crti.o files */
*(.eh_frame) /* section used in crtbegin.o files */
. = ALIGN(4);
} > m_text


/* Section used by the libgcc.a library for fvp4 */
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text

__etext = .; /* Define a global symbol at end of code. */
__DATA_ROM = .; /* Symbol is used by startup for data initialization. */

.interrupts_ram :
{
. = ALIGN(4);
__VECTOR_RAM__ = .;
__RAM_START = .;
__interrupts_ram_start__ = .; /* Create a global symbol at data start. */
*(.m_interrupts_ram) /* This is a user defined section. */
. += M_VECTOR_RAM_SIZE;
. = ALIGN(4);
__interrupts_ram_end__ = .; /* Define a global symbol at data end. */
} > m_data

__VECTOR_RAM = DEFINED(__flash_vector_table__) ? ORIGIN(m_interrupts) : __VECTOR_RAM__ ;
__RAM_VECTOR_TABLE_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : (__interrupts_ram_end__ - __interrupts_ram_start__) ;

.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* Create a global symbol at data start. */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
__data_end__ = .; /* Define a global symbol at data end. */
} > m_data

__DATA_END = __DATA_ROM + (__data_end__ - __data_start__);
__CODE_ROM = __DATA_END; /* Symbol is used by code initialization. */

.code : AT(__CODE_ROM)
{
. = ALIGN(4);
__CODE_RAM = .;
__code_start__ = .; /* Create a global symbol at code start. */
__code_ram_start__ = .;
*(.code_ram) /* Custom section for storing code in RAM */
. = ALIGN(4);
__code_end__ = .; /* Define a global symbol at code end. */
__code_ram_end__ = .;
} > m_data

__CODE_END = __CODE_ROM + (__code_end__ - __code_start__);
__CUSTOM_ROM = __CODE_END;

/* Custom Section Block that can be used to place data at absolute address. */
/* Use __attribute__((section (".customSection"))) to place data here. */
/* Use this section only when MTB (Micro Trace Buffer) is not used, because MTB uses the same RAM area, as described in S32K Reference Manual. */
.customSectionBlock ORIGIN(m_custom) : AT(__CUSTOM_ROM)
{
__customSectionStart = .;
__customSection_start__ = .;
KEEP(*(.customSection)) /* Keep section even if not referenced. */
__customSection_end__ = .;
} > m_custom
__CUSTOM_END = __CUSTOM_ROM + (__customSection_end__ - __customSection_start__);
__rom_end = __CUSTOM_END;

/* Uninitialized data section. */
.bss :
{
/* This is used by the startup in order to initialize the .bss section. */
. = ALIGN(4);
__BSS_START = .;
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__BSS_END = .;
} > m_data_2

/* Put heap section after the program data */
.heap :
{
. = ALIGN(8);
__end__ = .;
__heap_start__ = .;
PROVIDE(end = .);
PROVIDE(_end = .);
PROVIDE(__end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .;
__heap_end__ = .;
} > m_data_2

/* Initializes stack on the end of block */
__StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
__RAM_END = __StackTop;

.stack __StackLimit :
{
. = ALIGN(8);
__stack_start__ = .;
. += STACK_SIZE;
__stack_end__ = .;
} > m_data_2

.ARM.attributes 0 : { *(.ARM.attributes) }

/* Memory validation */
ASSERT(__rom_end <= (ORIGIN(m_text) + LENGTH(m_text)), "Region m_text overflowed!")

ASSERT(__StackLimit >= __HeapLimit, "region m_data_2 overflowed with stack and heap")
}

 

0 Kudos
1 Solution
614 Views
VaneB
NXP TechSupport
NXP TechSupport
0 Kudos
3 Replies
615 Views
VaneB
NXP TechSupport
NXP TechSupport

Hi @melvinw 

Please refer to this community post:

 

B.R.

VaneB

 

0 Kudos
602 Views
melvinw
Contributor II

Thx i will have a long look at it! Until now i haven't found a flag that is causing this problem. Are there other compiler unrelated options that i might want to take into consideration that could cause this kind of behaviour?

Best Regard,

MelvinW

0 Kudos
586 Views
VaneB
NXP TechSupport
NXP TechSupport

Hi @melvinw 

As it is said in the post shared before: "when your application becomes complex, and the optimizations start harming the overall functionality of your application. This is related to the optimizations that are being done, meaning the code was written to work as one thing, but the optimization changes the overall logic (due to the changes creating a better performance, changing memory accesses and implementing optimized loops), and this new logic can happen to be not compliant with what the original idea was, hence harming functionality.

As for performance, each level will create a different kind of optimization related to loop-unrolling, memory access pipelining, and so. Given that -Os is related to size and -O3 is related to more optimizations, we can assume that -O3 should have a better performance than the -Os one.

Still, the optimization level is to be taken with care, given that a -Os optimized application can be running as expected. However, once you up the optimization to -O3, the application can fail due to non-compliant behavior.

Again, this is more related to the compiler itself, rather than the NXP products. We might recommend talking a look into the different optimization flags and see if any of them can be non-compliant with your application."