Hard fault exception: To fill up unused RAM

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

Hard fault exception: To fill up unused RAM

4,466 Views
sardalkar
Contributor I

We are filling up RAM with predefined value (0xDF) after RAM initialization in startup.  But as we enable the SVC interrupt for illegal opcode, it gives hard fault interrupt and even if we do not fill up RAM with 0xDF, it gives exception.

Is there any way/sequence to initialize RAM for illegal opcode?  How do we debug this issue?

Labels (1)
0 Kudos
Reply
14 Replies

3,899 Views
sardalkar
Contributor I

Target MCU - S32K142
S32DS Version - 2.0
SDK version - 0.8.4

0 Kudos
Reply

3,899 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello Sandip,

Sorry for the late response. If I understood correctly, the hard fault occurs once you install and initialize the SVC interrupt, correct? Where are you calling the function INT_SYS_InstallHandler? Please keep in mind that before calling this function, the RAM memory should be initialized, did you considered this?

I recommend you to take a look at the following community document where one of my coworkers explains how to fill the unused memory.

Hope it helps!

Victor

0 Kudos
Reply

3,899 Views
sardalkar
Contributor I

Hi Victor,

The function INT_SYS_InstallHandler is called in main function after startup.

How do we ensure that RAM memory initialized properly? 

I am unable to access community document.

Best Regards,

Sandip

0 Kudos
Reply

3,899 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello Sandip, 

This is a quick post about an interesting thread shared on Kinetis community, this is also applicable for S32DS + S32K1xx, following the below steps, we can fill up the unused memory with any command/data we want. On the other hand, ARM devices have the opcode feature to generate an SVC_Handler (0xDFDF ). So, if R13 goes to an unexpected address and this random address has 0xDFDF there, the CPU will jump to this SVC function. When using this feature we could avoid errors in case the CPU goes to blank memory space.  

2.1 . No fill() command involed.

Define segment in MEMORY section:

my_section    (rx) : ORIGIN = 0X00000800, LENGTH = 0x20

 

define output  SECTION:

.myData :

{

    . = ALIGN(4); 

         KEEP(*(.myData))

    . = ALIGN(4);

}> my_section

In C code, define const variable “my_const” (0xCCCCDDDD)

const int my_const __attribute__((section(".myData"))) = 0xCCCCDDDD;

 

After the build, we will see only 0xCCCCDDDD in this area in the generated s19 file:

S1070800DDDDCCCC9E

 

2.2 Use FILL(0xaa)  command to fill unused area of my_section with 0xAA.

Here is the modified code in ld file, I highlight the code I add:

.myData :

{

       . = ALIGN(4); 

                 KEEP(*(.myData))

    . = ALIGN(4);

    FILL(0xaa)

    . = ORIGIN(my_section) + LENGTH(my_section) ;

  }> my_section

Rebuild the project. we will see the rest of the field of my_section is filled with 0xAA in  S19 file:

S1130800DDDDCCCCAAAAAAAAAAAAAAAAAAAAAAAA9A

S1130810AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA34

I hope it helps!

Victor 

0 Kudos
Reply

3,899 Views
sardalkar
Contributor I
Hi Victor,

Thank you for your quick reply.

We have issue with SVC interrupt for illegal opcode. As we enable the SVC interrupt for illegal opcode, it gives a hard fault interrupt (Microcontroller S32K142).

Earlier you replied " Where are you calling the function INT_SYS_InstallHandler? Please keep in mind that before calling this function, the RAM memory should be initialized"

How do we verify that RAM is initialized properly. 

Regards,

Sandip
0 Kudos
Reply

3,899 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello Sandip, 

Sorry for the misunderstood, I didn't notice that you are using the function: INT_SYS_EnableIRQ(SVCall_IRQn); This is what is causing the problem. This function should be called only for the device-specific interrupts, not for the core interrupts (like the SVC). 

In the case of the SVC interrupt you need to call only the function INT_SYS_InstallHandler(SVCall_IRQn, SVC_Handler, (isr_t *)0); The name of the new handler must be the same as the one you assign on the startup, in this case, SVC_Handler.  

Regards, 

Victor

0 Kudos
Reply

3,899 Views
sardalkar
Contributor I
Hi Victor,
Thank you.
Now we are not getting hard fault interrupt with SVC interrupt.
We have option in IAR compiler to fill up code memory. But our requirement is to fill up unused RAM with predefined value. You have shared above example is for ROM.
How do we modify linker file for RAM (SRAM_U). 
Below is linker file.
***************************************************************************************************************************
/* 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.
 */
define symbol __ram_vector_table_size__ =  isdefinedsymbol(__flash_vector_table__) ? 0 : 0x00000400;
define symbol __ram_vector_table_offset__ =  isdefinedsymbol(__flash_vector_table__) ? 0 : 0x000003FF;
/* Flash */
define symbol m_interrupts_start       = 0x00010000;
define symbol m_interrupts_end         = 0x000103FF;
define symbol m_flash_config_start     = 0x00010400;
define symbol m_flash_config_end       = 0x0001040F;
define symbol m_compd_start            = 0x00010410;
define symbol m_compd_end              = 0x0001042F;
define symbol m_text_start             = 0x00010430;
define symbol m_text_end               = 0x0003FBFF;
/* SRAM_L */
define symbol m_interrupts_ram_start   = 0x1FFFC000;
define symbol m_interrupts_ram_end     = 0x1FFFC000 + __ram_vector_table_offset__;
define symbol m_data_start             = m_interrupts_ram_start + __ram_vector_table_size__;
define symbol m_data_end               = 0x1FFFFFFF;
/* SRAM_U */
define symbol m_data_2_start           = 0x20000000;
define symbol m_data_2_end             = 0x20002FFF;
/*FlexRAM or EEPROM
define symbol m_eeprom_start           = 0x14000000;
define symbol m_eeprom_end             = 0x14000FFF;*/
/* Sizes */
if (isdefinedsymbol(__stack_size__)) {
  define symbol __size_cstack__        = __stack_size__;
} else {
  define symbol __size_cstack__        = 0x00000600;
}
if (isdefinedsymbol(__heap_size__)) {
  define symbol __size_heap__          = __heap_size__;
} else {
  define symbol __size_heap__          = 0x0000600;
}
define exported symbol __VECTOR_TABLE          = m_interrupts_start;
define exported symbol __VECTOR_RAM            = isdefinedsymbol(__flash_vector_table__) ? m_interrupts_start : m_interrupts_ram_start;
define exported symbol __RAM_VECTOR_TABLE_SIZE = __ram_vector_table_size__;
define memory mem with size = 4G;
define region m_flash_config_region   = mem:[from m_flash_config_start to m_flash_config_end];
define region TEXT_region             = mem:[from m_interrupts_start to m_interrupts_end]
                                      | mem:[from m_text_start to m_text_end];
define region DATA_region             = mem:[from m_data_start to m_data_end];
define region DATA_region_2           = mem:[from m_data_2_start to m_data_2_end-__size_cstack__];
define region CSTACK_region           = mem:[from m_data_2_end-__size_cstack__+1 to m_data_2_end];
define region m_interrupts_ram_region = mem:[from m_interrupts_ram_start to m_interrupts_ram_end];
define region COMPILE_DATE            = mem:[from m_compd_start to m_compd_end];
define region EEPROM_PARTNO           = mem:[from 0x14000000 to 0x1400005F];
define region EEPROM_VIN              = mem:[from 0x14000060 to 0x1400009F];
define region EEPROM_RESET            = mem:[from 0x140000A0 to 0x140000CF];
define region EEPROM_IDLE_TIME        = mem:[from 0x140000D0 to 0x140000D3];
define region EEPROM_WAKE_UP          = mem:[from 0x140000D4 to 0x140000DF];
define region EEPROM_DTC              = mem:[from 0x140000E0 to 0x1400056F];
define region EEPROM_HIST             = mem:[from 0x14000570 to 0x14000F63]; 
define region EEPROM_CONFIG           = mem:[from 0x14000F64 to 0x14000FFF]; 
define region MAGICFLAG               = mem:[from 0x1FFFDFF0  size (0x00000010)];
define block CSTACK    with alignment = 8, size = __size_cstack__   { };
define block HEAP      with alignment = 8, size = __size_heap__     { };
define block RW        { readwrite };
define block ZI        { zi };
/* Custom Section Block that can be used to place data at absolute address. */
/* Use __attribute__((section (".customSection"))) to place data here. */
define block customSectionBlock { section .customSection };
define block __CODE_ROM   { section .textrw_init };
define block __CODE_RAM   { section .textrw  };
initialize manually       { section .textrw };
initialize manually       { section .bss };
initialize manually       { section .customSection };
initialize manually       { section .data };
initialize manually       { section __DLIB_PERTHREAD };
do not initialize         { section .noinit, section .bss, section .data, section __DLIB_PERTHREAD, section .customSection };
place at address mem: m_interrupts_start    { readonly section .intvec };
place in m_flash_config_region              { section FlashConfig };
place in TEXT_region                        { readonly };
place in TEXT_region                        { block __CODE_ROM };
place in DATA_region                        { block RW };
place in DATA_region                        { block __CODE_RAM };
place in DATA_region_2                      { block customSectionBlock };
place in DATA_region_2                      { block ZI };
place in DATA_region_2                      { last block HEAP };
place in CSTACK_region                      { block CSTACK };
place in m_interrupts_ram_region            { section m_interrupts_ram };
place in COMPILE_DATE                       { section .COMPILE_DATE};
place in EEPROM_PARTNO                      { section .EEPROM_PARTNO_DATA};
place in EEPROM_VIN                         { section .EEPROM_VIN_DATA};
place in EEPROM_RESET                       { section .EEPROM_RESET_DATA};
place in EEPROM_IDLE_TIME                   { section .EEPROM_IDLE_TIME_DATA};
place in EEPROM_WAKE_UP                     { section .EEPROM_WAKE_UP_DATA};
place in EEPROM_DTC                         { section .EEPROM_DTC_DATA};
place in EEPROM_HIST                        { section .EEPROM_HIST_DATA};
place in EEPROM_CONFIG                      { section .EEPROM_CONFIG_DATA};
place in MAGICFLAG                          { section .MAGICFLAG};
************************************************************************************************************************************************
0 Kudos
Reply

3,899 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello Sandip, 


The example that I mentioned before, can be used for any memory. You just need to define the origin of where you want to start and the length in the variable my_section.

my_section    (rx) : ORIGIN = 0X00000800, LENGTH = 0x20

Regards, 

Victor 

0 Kudos
Reply

3,899 Views
sardalkar
Contributor I
Hello Victor,
We are able to fill up (0xDF) unused ROM with "Fill unused code memory" option from IAR compiler. The ROM/text memory is allocated from 0x00010430 to 0x0003FBFF. For more details, you can refer above linker file.
From 0x00037340 to 0x0003FBF0 are filled with 0xDF. For the testing, How do we generate the SVC_Handler interrupt?
Thank you.
Regards,
Sandip
0 Kudos
Reply

3,899 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello Sandip, 

I'm not sure that I understood correctly your question. Do you want to trigger the SVC interrupt? If so, unfortunately, we don't have an example that shows how to trigger this interrupt, but you could try to write directly to the following register

S32_NVIC->ISPR.

Regards, 

Victor  

0 Kudos
Reply

3,899 Views
sardalkar
Contributor I
Hi Victor,
Yes. We are trying to trigger SVC interrupt, so it will confirm that the DTC is set for illegal opcode.  
We had tried below methods to trigger this interrupt.
1. Writing directly to S32_NVIC->ISPR. Can we write directly core interrupts with this method?     INT_SYS_SetPending(SVCall_IRQn); // SVCall_IRQn = -5,
void INT_SYS_SetPending(IRQn_Type irqNumber)
{
    /* Check IRQ number */
    DEV_ASSERT(0 <= (int32_t)irqNumber);
    DEV_ASSERT(irqNumber <= FEATURE_INTERRUPT_IRQ_MAX);
    /* Set Pending Interrupt */
    S32_NVIC->ISPR[(uint32_t)(irqNumber) >> 5U] = (uint32_t)(1UL << ((uint32_t)(irqNumber) & (uint32_t)0x1FU));
}
   
2. Accessing address where 0xDF is filled.
Jump2SR(TempOpcodeAddress);
vuint32 const OpCode_ADDRESS = 0x00037340;
#define TempOpcodeAddress       (*((vuint32 *)(OpCode_ADDRESS)))
#define Jump2SR(x)          (((void(*)(void))(x))())
Could you please guide us to solve this problem.
Thank you.
Regards,
Sandip
0 Kudos
Reply

3,899 Views
sardalkar
Contributor I

we are unable to trigger the SVC interrupt with above methods.

0 Kudos
Reply

3,899 Views
enwei
NXP Employee
NXP Employee

Hi Sandip,

you should use assemlly instruction "svc" to trigger the SVC exception.

information quoted from  ARMv7-M Architecture Reference Manual ( DDI 0403E.d (ID070218) ):

An exception caused explicitly by the SVC instruction. Application software uses the SVC instruction
to make a call to an underlying operating system. This is called a Supervisor Call. The
SVC
instruction enables the application to issue a Supervisor Call that requires privileged access to the
system and executes in program order with respect to the application. ARMv7-M also supports an
interrupt-driven Supervisor-calling mechanism, PendSV.

This Supervisor Call handles the exception caused by the SVC instruction. SVCall is permanently

enabled and has a configurable priority

Best regard,

Enwei Hu(胡恩伟)

0 Kudos
Reply

3,899 Views
jiri_kral
NXP Employee
NXP Employee

Hi, 

what is your target MCU, S32DS Version and SDK version? 

Jiri 

0 Kudos
Reply