This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G3107: Hard Fault exception when zeroing structs.

Part Number: MSPM0G3107

Tool/software:

Hi

I'm porting some software to this MCU and I have issues with the MCU throwing Hard Fault exceptions when I'm zeroing structs.

I am a bit lost after trying to figure out what causes the issue. But I suspect the problem might lie in the linker file.

I am using IAR 9.50 and Ozone as  debugger, and here's the exception

Hard fault

Link script below:

/************** MEMORY MAP ******************************************/
/* _________________________________________________________________*/
/*| Non Main BSL                       |0x41C0 017F           (128B)*/
/*|____________________________________|0x41C0 0100_________________*/
/*:                                    :                            */
/*| Non Main BCR                       |0x41C0 007F                 */
/*|____________________________________|0x41C0 0000_________________*/
/*:                                    :                            */
/*:____________________________________:           _________________*/
/*| Stack, Heap, Static data           |0x2020 7FFF  RAM (32K)      */
/*|                                    |                            */
/*|____________________________________|0x2020 1650_________________*/
/*| Class B (size 0xe00)               |                            */
/*|____________________________________|0x2020 0850_________________*/
/*| RUNTIME_CHK_BUF (0x20)             |                            */
/*|____________________________________|0x2020 0830_________________*/
/*| CSTACK (0x800 + 0x10)              |                            */
/*|____________________________________|0x2020 0020_________________*/
/*| Common RAM (0x20)                  |                            */
/*|____________________________________|0x2020 0000_________________*/
/*:                                    :                            */
/*:____________________________________:           _________________*/
/*| HwInfo                             |0x0001 FFFF           (1K)  */
/*|____________________________________|0x0001 FC00_________________*/
/*| Settings                           |0x0001 FBFF           (2K)  */
/*|                                    |                            */
/*|____________________________________|0x0001 F400_________________*/
/*| Boot Config                        |0x0001 F3FF           (85K) */
/*| (256B)                             |                    :       */
/*|____________________________________|0x0001 F300         :       */
/*| Application code                   |                    :       */
/*|____________________________________|                    :       */
/*| Common const for Applic            |                    :       */
/*| (version info) (568B)              |                    :       */
/*|____________________________________|0x0000 A300         :       */
/*| Int vectors for Applic             |                            */
/*|____________________________________|0x0000 A000_________________*/
/*| Boot code                          |0x0000 9FFF           (40K) */
/*|____________________________________|                            */
/*| Common const for Boot              |                            */
/*| (version info) (568B)              |                            */
/*|____________________________________|0x0000 0300                 */
/*| Int vectors for Boot               |                            */
/*|____________________________________|0x0000 0000_________________*/

/*--- Specials ---*/
/* Offset to start of code for application */
define symbol __application_displacement__      = 0x0a000;

/* Offset to start of const data area for application (available also from boot) */
define symbol __common_const_displacement__     = 0x00300;

/* Size of common Ram area for boot and application */
define symbol __size_common_ram__               = 0x00020;

/* size_classBdata_ram */
define symbol __size_classBdata_ram__           = 0x00e00;

/* Absolute address for start of interrupt vector table */
define symbol __intvec_start__                  = 0x0a000;

/* Absolute address to area with constants for boot for access from both appl and boot */
define symbol __common_const_appl_start__       = 0x0a300;

/* Size of boot configuration area located at end of a App address space */
define symbol __size_bootconfig__               = 0x00100;

/*-Sizes-*/
define symbol __size_proc_stack__               = 0x0000;
define symbol __size_cstack__                   = 0x400;
define symbol __size_heap__                     = 0x800;
define symbol __size_stack_bottom__             = 0x10;

/*-Memory Regions-*/
define symbol __region_ROM_start__              = 0x00000000;
define symbol __region_ROM_end__                = 0x0001FFFF;
define symbol __region_RAM_start__              = 0x20200000;
define symbol __region_RAM_end__                = 0x20207FFF;
define symbol __region_RAM_stack_start__        = __region_RAM_start__ + __size_common_ram__;
define symbol __region_RAM_stack_end__          = __region_RAM_stack_start__ + __size_cstack__ + __size_stack_bottom__ - 1;
define symbol __region_RUN_TIME_CHK_BUF_start__ = __region_RAM_stack_end__ + 1;
define symbol __region_RUN_TIME_CHK_BUF_end__   = __region_RUN_TIME_CHK_BUF_start__ + 32 - 1;   // Size (6+2)*4 bytes
define symbol __region_CLASSB_start__           = __region_RUN_TIME_CHK_BUF_end__ + 4 + 1;      // 4 bytes because RAM check operates 4 bytes before CLASSB RAM area.
define symbol __region_CLASSB_end__             = __region_CLASSB_start__ + __size_classBdata_ram__ - 1;


define symbol __region_NON_MAIN_BCR_start__     = 0x41C00000;
define symbol __region_NON_MAIN_BCR_end__       = 0x41C0007F;
define symbol __region_NON_MAIN_BSL_start__     = 0x41C00100;
define symbol __region_NON_MAIN_BSL_end__       = 0x41C0017F;




define symbol __region_application_end__        = __region_ROM_end__ - __size_bootconfig__;
define symbol __region_BootConf_start__         = __region_application_end__ + 1; // Start on the first address after application end

/* Reserved space in iar.dynexit for calls at exit */
define symbol __iar_maximum_atexit_calls        = 3;

export symbol __region_ROM_start__;
export symbol __region_ROM_end__;
export symbol __region_RAM_start__;
export symbol __region_RAM_end__;
export symbol __region_CLASSB_start__;
export symbol __region_CLASSB_end__;
export symbol __region_BootConf_start__;

define memory mem with size = 4G;

define region ROM_region                = mem:[from __region_ROM_start__ to __region_ROM_end__];
define region BOOT_CONFIG_region        = mem:[from __region_BootConf_start__ to __region_ROM_end__ ];   // Boot config region/area
define region RAM_stack_region          = mem:[from __region_RAM_stack_start__ to __region_RAM_stack_end__];
define region RUN_TIME_CHK_BUF_region   = mem:[from __region_RUN_TIME_CHK_BUF_start__ to __region_RUN_TIME_CHK_BUF_end__];
define region CLASS_B_RAM_region        = mem:[from __region_CLASSB_start__ to __region_CLASSB_end__];
define region RAM_region                = mem:[from __region_RAM_start__ to __region_RAM_end__];

define region NON_MAIN_BCR_region       = mem:[from __region_NON_MAIN_BCR_start__ to __region_NON_MAIN_BCR_end__];
define region NON_MAIN_BSL_region       = mem:[from __region_NON_MAIN_BSL_start__ to __region_NON_MAIN_BSL_end__];

initialize by copy { readwrite };
do not initialize  { section .noinit, section STACK_BOTTOM, section RUN_TIME_RAM_BUF, section CLASS_B_RAM};

// placements #############################
place at address mem:__intvec_start__ { readonly section .intvec };
place at address mem:__common_const_appl_start__ { readonly section .CommonConst };

// Create an 8-byte end-aligned block and put all read-only sections in it
define block ALIGNED_ROM with end alignment = 8 { readonly };
place in ROM_region  { block ALIGNED_ROM };

define block CSTACK     with alignment = 8, size = __size_cstack__     { };
define block PROC_STACK with alignment = 8, size = __size_proc_stack__ { };
define block HEAP       with alignment = 8, size = __size_heap__       { };
place in RAM_region  { readwrite, block PROC_STACK, block HEAP };

define block STACK_BOTTOM_B  with alignment = 8, size = __size_stack_bottom__  { section STACK_BOTTOM };
define block stack_order with fixed order { block STACK_BOTTOM_B, block CSTACK };
place in RAM_stack_region { block stack_order };

place in CLASS_B_RAM_region { readwrite data section CLASS_B_RAM, section CLASS_B_RAM_REV  };
place in RUN_TIME_CHK_BUF_region { readwrite data section RUN_TIME_RAM_BUF  };

place in NON_MAIN_BCR_region  { section .BCRConfig };
place in NON_MAIN_BSL_region  { section .BSLConfig };

  • The first place I'd look is the .map file, to see what's at 0x108A0. That should at least give you a function name to work with.

    If you think you're in the midst of zeroing bunches of memory, my first guess is that the size is being computed incorrectly. (Maybe it worked-by-accident before?)

  • This code is ported from an STM32 platform, so I think something went haywire in the porting process since the code that causes this is unchanged.

    After checking the map file I can confirm that the memory address is where the memset happens.

  • Do you know which (memset) call is doing this? Stepping through the calling function should tell you something. You can also find the spot by tracking back through the stack, though that takes some patience.

    The Usual Suspects in porting structs are are bitfields and packing.

    The Cortex-M0 is incapable of unaligned memory references, while the Cortex-M4/M7 allow them. (Though memset is supposed to be immune to alignment hazards.)

  • That was my suspicion too.
    But it was apparently a red herring. For some reason my debugger acted up and hardfaulted at the wrong place.

    Because after zeroing the array the code proceeds to check some flash areas, one byte at a time, and after a few reads it hardfaults.

  • Do you know which code line (even better: which instruction) is failing? The stack layout (at *SP) is the same as in the Related Thread.

    If it's not in memset(), that (re-)introduces the possibility of an alignment thing. Which STM32 are you porting from?

  • Hi Isac,

    Is your device hard faulting on the exact same memory read? and is this a hard fault or are you hitting an NMI?

    Looking at the memory map comment you have in the beginning, you're in ECC region of memory. You will want to make sure you're also setting the ECC bits and waiting properly. This is all if your struct is in Flash, with SRAM I would be more interested if you're getting a memory access fault due to the bounds of your array and where the array is getting placed.

    Regards,
    Luke

  • It reads from flash yes and it faults on the same memory read, at least it changes depending if I e.g. change the optimization, make bigger changes to the code base etc, but it's in the same general area. But if I don't change anything it fails on the exact same spot.

    And as far as I can see it hard faults. No Flash DED seems to be detected when I check the NMIs.
    But I found that DEDERRADDR contains an address. Does this mean that the address in DEDERRADDR has a problem?

    EDIT: Ok, I'm beginning to suspect it's a combination of issues. Both Flash access and zeroing/populating structs that are in SRAM causes crashes. But it seems like simple writes to RAM might cause crashes too.

  • Hi Isac,

    The Flash read would be what detects/triggers the FLASHDED error.

    • Are you writing a flash word at a time or are you doing smaller sets?
      • Smaller writes will require you to handle the ECC section in a particular manner. Section 6.3.3.2 in the TRM provides details. 
    • The DEDERRADDR does contain the address for what caused the ECC error. What I would recommend is to handle the FLASHDED NMI and use that address to reprogram the sector. You shouldn't regularly get ECC errors unless you're handling the writes incorrectly which could be 
    • Are you able to check what SRAM address is getting accessed when you hit this fault?
      • I wouldn't expect an SRAM access to have any hard faults unless your bounds are going passed the SRAM region. (Potentially caused by pointer access then an addition on the address)

    Also, you're not trying to use memset on flash, right? Memset shouldn't be used on the flash region.

    Regards,
    Luke 

  • I only use memset for objects in RAM.

    But I think I found the problem. It was an implementation in one of the drivers where it did an out of bounds read on flash, combined with some objects filling up the RAM.
    It was a tricky one since the flash read failed very early and not when it was out of bounds.

    So my solution was to adjust the boundaries and fix the bug in the driver (not the DL driver), and adjust some struct sizes and it now works.

    Thank you for helping out!