This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Interrupts from the secure world to the non-secure world.

Hello experts,

I am using SAM L11 (Core is Cortex-M23).
I did a simple test of the interrupt.
In the case of the handler was the secure world, it worked as I expected.
The instruction sequences are as the follows.
 *(int*)(0xE000E380) = 0;
 *(int*)(0xE000E100) = 1;
 *(int*)(0xE000E200) = 1;
 for(i=0;i<1000;i++);
However, when Interrupt Target Non-secure Register (0xE000E380) was set,
the HardFault had occurred. As for SAM L11, would it be reasonable behavior?
 *(int*)(0xE000E380) = 1;
 *(int*)(0xE000E100) = 1;
 *(int*)(0xE000E200) = 1; /* HardFault */
 for(i=0;i<1000;i++);
Although I put the vector of the secure world to the non-secure world address, the phenomenon was not changed.
From the specification aspect, how does it work?

Thank you and best regards,

Yasuhiko Koumoto.

  • Hi,

    could you please describe the configuration of the interrupts ? Which are assigned to secure and those not?

    thanks

  • Hi,

    there are no specific configurations.
    I use NVIC registers directly.
    The settings are the followings.
    NVIC_ISER0[0]=1  /* Interrupt Enable */
    NVIC_ISPR0[0]=1  /* make the interrupt pending */

    Because NVIC_ITNS0[0]=1, INT0 target is the only non-secure and all the others are secure.

    Thank you,
    Yasuhiko Koumoto.

  • Where does the code for the interrupt handler reside ?

  • Hi,
    here are the source codes extracted.
    If I use "*(int*)(0xE000E380) = 0;" the vector is
            .pfnSYSTEM_Handler             = (void*) SYSTEM_Handler, /* 0  Main Clock */
    If I use "*(int*)(0xE000E380) = 1;" the vector is
            .pfnSYSTEM_Handler             = (void*) 0x8455, /* 0  Main Clock */
    Here, the address 0x8455 is the SYSTEM_Handler address of the non-secure world.
    That's all.
    Thank you and best regards,
    Yasuhiko  Koumoto.


    /* Cortex-M23 core handlers */
    void NonMaskableInt_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
    void HardFault_Handler    ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
    void SVCall_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
    void PendSV_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
    void SysTick_Handler      ( void ) __attribute__ ((weak, alias("Dummy_Handler")));

    /* Peripherals handlers */
    void SYSTEM_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
    void WDT_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
    void RTC_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));

    __attribute__ ((section(".vectors")))
    const DeviceVectors exception_table = {

            /* Configure Initial Stack Pointer, using linker-generated symbols */
            .pvStack = (void*) (&_estack),

            .pfnReset_Handler              = (void*) Reset_Handler,
            .pfnNonMaskableInt_Handler     = (void*) NonMaskableInt_Handler,
            .pfnHardFault_Handler          = (void*) HardFault_Handler,
            .pvReservedC12                 = (void*) (0UL), /* Reserved */
            .pvReservedC11                 = (void*) (0UL), /* Reserved */
            .pvReservedC10                 = (void*) (0UL), /* Reserved */
            .pvReservedC9                  = (void*) (0UL), /* Reserved */
            .pvReservedC8                  = (void*) (0UL), /* Reserved */
            .pvReservedC7                  = (void*) (0UL), /* Reserved */
            .pvReservedC6                  = (void*) (0UL), /* Reserved */
            .pfnSVCall_Handler             = (void*) SVCall_Handler,
            .pvReservedC4                  = (void*) (0UL), /* Reserved */
            .pvReservedC3                  = (void*) (0UL), /* Reserved */
            .pfnPendSV_Handler             = (void*) PendSV_Handler,
            .pfnSysTick_Handler            = (void*) SysTick_Handler,

            /* Configurable interrupts */
            .pfnSYSTEM_Handler             = (void*) SYSTEM_Handler, /* 0  Main Clock */
    //        .pfnSYSTEM_Handler             = (void*) 0x8455, /* 0  Main Clock */
            .pfnWDT_Handler                = (void*) WDT_Handler,    /* 1  Watchdog Timer */
            .pfnRTC_Handler                = (void*) RTC_Handler,    /* 2  Real-Time Counter */
            .pfnEIC_0_Handler              = (void*) EIC_0_Handler,  /* 3  External Interrupt Controller */
            .pfnEIC_1_Handler              = (void*) EIC_1_Handler,  /* 4  External Interrupt Controller */
            .pfnEIC_2_Handler              = (void*) EIC_2_Handler,  /* 5  External Interrupt Controller */
            .pfnEIC_3_Handler              = (void*) EIC_3_Handler,  /* 6  External Interrupt Controller */
            .pfnEIC_OTHER_Handler          = (void*) EIC_OTHER_Handler, /* 7  External Interrupt Controller */
            .pfnFREQM_Handler              = (void*) FREQM_Handler,  /* 8  Frequency Meter */
    ---[snip]---
            .pfnPTC_Handler                = (void*) PTC_Handler,    /* 42 Peripheral Touch Controller */
            .pfnTRNG_Handler               = (void*) TRNG_Handler,   /* 43 True Random Generator */
            .pfnTRAM_Handler               = (void*) TRAM_Handler    /* 44 TrustRAM */
    };

    void SYSTEM_Handler(void)
    {
     //*(int*)(0xE000E280) = 1;
     //*(int*)(0xE000E100) = 1;
     printf("SYSTEM Handler in Secure Region.\n\r");
    }


    int main(void)
    {
     volatile int i;
     /* Initializes MCU, drivers and middleware */
     atmel_start_init();

     printf("Secure application is running.\r\n");

     /* Set non-secure main stack (MSP_NS) */
     __TZ_set_MSP_NS(*((uint32_t *)(CONF_TZ_START_NS)));
     
     *(int*)(0xE000E380) = 0;
     *(int*)(0xE000E100) = 1;
     *(int*)(0xE002E100) = 1;
     
     *(int*)(0xE000E200) = 1;
     for(i=0;i<1000;i++);
     *(int*)(0xE000E200) = 1;
     for(i=0;i<1000;i++);
     *(int*)(0xE000E200) = 1;
     for(i=0;i<1000;i++);
     
     /* Get non-secure reset handler */
     NonSecure_ResetHandler = (funcptr_void)(*((uint32_t *)((CONF_TZ_START_NS) + 4U)));

     /* Start non-secure state software application */
     NonSecure_ResetHandler();

     /* Replace with your application code */
     while (1) {
      __NOP();
     }
    }

  • thank you for the details 

    the one I was after is the configuration of the secure and non secure memory

    I am looking to see where these handlers reside

    if the exception handler for the non secure side resides in secure memory then you will get a security fault.

    please check the settings of the security attribution unit if any and look for the part of the code that declares the non secure memory region.

  • HI,
    it seems that SAM L11 only support the non-secure handler of interrupts for EIC (External Interrupt Controller). Of which interrupt numbers are 4, 5, 6, and 7.
    Of course, EIC must be configured prior to use it.
    I double the interrupt 0 cannot be supported  the non-secure handler.
    As for the security attributes, they are as fllows.
    0x00000000-0x00007bff Secure
    0x00007c00-0x00007fff Non-Secure Callable
    0x00008000-0x0000ffff Non-Secure.
    Best regards,
    Yasuhiko Koumoto.

  • Hi,

    it might be good to analyze the reason for the "hard fault" that you are getting.  The controller offers registers that give you more details.

    This pages might help:
      - http://www.keil.com/support/man/docs/uv4/uv4_cp_armv8_faults.htm
      - http://www.keil.com/appnotes/files/apnt209.pdf

    The appnote does not specifically contain the Cortex-M23, but the concept for analysis is the same.

  • Hi there,

    I think if you target the interrupt to the non-secure world, and you should enable the interrupt in the non-secure world but not the secure world. If you open it in secure world, there will be a fault. So you can have a try.

    Best regards.

  • Hi,

    Has the problem been solved?

    >Although I put the vector of the secure world to the non-secure world address,

    > the phenomenon was not changed. From the specification aspect, how does it work?

    This wouldn't work. Non-secure world cannot execute an interrupt handler in the Secure address space.

    Non-secure world must have its own vector table (with boot code such as reset handler) and the interrupt handlers must in in Non-secure memories.

    regards,

    Joseph

  • Hi Joseph,

    I think I have the same "problem" that Yasuhiko Koumoto occured. I try to describe it.

    //Secure world

    NVIC_SetPriority(TRNG_IRQn, 1);
    NVIC_SetTargetState(TRNG_IRQn);
    NVIC_EnableIRQ(TRNG_IRQn);

    TRNG_INTENSET = TRNG_INTENSET_DATADRY;  // enable int
    TRNG_CTRLA |= TRNG_CTRLA_ENABLE;               // enable device. Hardfault will be occur after this instruction

    But if i change the code into...

    //Secure world

    NVIC_SetPriority(TRNG_IRQn, 1);
    NVIC_SetTargetState(TRNG_IRQn);
    // NVIC_EnableIRQ(TRNG_IRQn);

    TRNG_INTENSET = TRNG_INTENSET_DATADRY;  // enable int
    TRNG_CTRLA |= TRNG_CTRLA_ENABLE;               // enable device. Hardfault will be occur after this instruction

    //Non-secure world

    NVIC_EnableIRQ(TRNG_IRQn);

    The non-secure interrupt will occur.

    And I tried put all 5 instructions into non-secure callable function as follow, it worked.

    void __attribute__((cmse_nonsecure_entry)) in()
    {
    NVIC_SetPriority(TRNG_IRQn, 1);
    NVIC_SetTargetState(TRNG_IRQn);
    NVIC_EnableIRQ(TRNG_IRQn);


    TRNG_INTENSET = TRNG_INTENSET_DATADRY; // enable int
    TRNG_CTRLA |= TRNG_CTRLA_ENABLE; // enable device
    while(1);
    }

    Best regrads,

    Wenchuan

  • With the first code arrangement, it might be possible that your Non-secure world hasn't boot up and hence Non-secure Main stack pointer has not been initialized.