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

How to place FreeRTOS in secure memory and the user tasks in non-secure memory?

I am porting FreeRTOS with TrustZone on LPC5500, I put FreeRTOS in secure memory, and created several user tasks in non-secure memory, as shown below:

But so far, I have not successfully switched from a secure task to a non-secure task.

How to switch from a secure task to a non-secure task?

Parents
  • Hi,

    Sorry it took a bit long to reply. I created an example:

    - Non-secure world first call a Secure API to pass the pointer of the NS thread to Secure world.

    - Non-secure world call a Secure API that execute the test sequence:

         1) Setup Non-secure PSP

         2) Setup Non-secure CONTROL

         3) Create Non-secure stack frame

         4) Trigger PendSV that do the EXC_RETURN

    Please note I didn't enable the FPU in this example, and Secure world used MSP for thread.

    If Secure world use PSP for thread the exception return value is 0xFFFFFFBD.

    regards,

    Joseph

    ================== Secure world =================


    void __attribute__((cmse_nonsecure_entry)) set_thread_addr(uint32_t addr)
    {
        ptr = addr;
        printf ("[Secure world received pointer 0x%x]\n", ptr);
      return;  
    }

    void __attribute__((cmse_nonsecure_entry)) tz_test1(void)
    {
      uint32_t v_MSP_NS;
        uint32_t v_PSP_NS;
        
        v_MSP_NS = __TZ_get_MSP_NS(); // Get Non-secure stack space
        v_PSP_NS = (v_MSP_NS - 0x100) & 0xFFFFFFF8U; // allocate 256 bytes for NS task stack, double word aligned
        
        __TZ_set_PSP_NS(v_PSP_NS); // Set PSP_NS
        __TZ_set_CONTROL_NS(__TZ_get_CONTROL_NS()|0x2); // Set CONTROL_NS to use PSP
        // Create stack frame for exception return
        HW32_REG((v_PSP_NS + 0x1C)) = 0x01000000U; // xPSR
        HW32_REG((v_PSP_NS + 0x18)) = ptr; // PC
        HW32_REG((v_PSP_NS + 0x14)) = 0xFFFFFFFFU; // LR
        HW32_REG((v_PSP_NS + 0x10)) = 0; // r12
        HW32_REG((v_PSP_NS + 0x0C)) = 0; // r3
        HW32_REG((v_PSP_NS + 0x08)) = 0; // r2
        HW32_REG((v_PSP_NS + 0x04)) = 0; // r1
        HW32_REG((v_PSP_NS + 0x00)) = 0; // r0
        printf ("Stack frame created, triggering PendSV...\n");
        
        // Trigger Secure PendSV
        SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
        __DSB();
        __ISB();
        // PendSV should be triggered now

      return ;  
    }


    void __attribute__((naked)) PendSV_Handler(void)
    {
        __asm volatile (
        "LDR    R0,= 0xFFFFFFB9\n\t"
        "BX     R0\n\t"    // Exception return to NS thread
        );    
    }

    ================== Non-secure world =================

    int main(void)
    {
        unsigned int p;
        UART_Config();
        printf("Non-secure Hello world\n");
        printf ("Run test\n");    
        
        p = (unsigned) NS_thread; // Get starting address of thread
        printf ("NS_thread address is 0x%x\n", p);
        set_thread_addr(p); // Pass address of NS_thread
        printf ("Return to NS world #1\n");
        tz_test1();
        printf ("Return to NS world #2\n");
        while(1);
        
    }
        
    void NS_thread(void)
    {
        puts("[NS thread]\n");
      while(1);
        return;
    }    

Reply
  • Hi,

    Sorry it took a bit long to reply. I created an example:

    - Non-secure world first call a Secure API to pass the pointer of the NS thread to Secure world.

    - Non-secure world call a Secure API that execute the test sequence:

         1) Setup Non-secure PSP

         2) Setup Non-secure CONTROL

         3) Create Non-secure stack frame

         4) Trigger PendSV that do the EXC_RETURN

    Please note I didn't enable the FPU in this example, and Secure world used MSP for thread.

    If Secure world use PSP for thread the exception return value is 0xFFFFFFBD.

    regards,

    Joseph

    ================== Secure world =================


    void __attribute__((cmse_nonsecure_entry)) set_thread_addr(uint32_t addr)
    {
        ptr = addr;
        printf ("[Secure world received pointer 0x%x]\n", ptr);
      return;  
    }

    void __attribute__((cmse_nonsecure_entry)) tz_test1(void)
    {
      uint32_t v_MSP_NS;
        uint32_t v_PSP_NS;
        
        v_MSP_NS = __TZ_get_MSP_NS(); // Get Non-secure stack space
        v_PSP_NS = (v_MSP_NS - 0x100) & 0xFFFFFFF8U; // allocate 256 bytes for NS task stack, double word aligned
        
        __TZ_set_PSP_NS(v_PSP_NS); // Set PSP_NS
        __TZ_set_CONTROL_NS(__TZ_get_CONTROL_NS()|0x2); // Set CONTROL_NS to use PSP
        // Create stack frame for exception return
        HW32_REG((v_PSP_NS + 0x1C)) = 0x01000000U; // xPSR
        HW32_REG((v_PSP_NS + 0x18)) = ptr; // PC
        HW32_REG((v_PSP_NS + 0x14)) = 0xFFFFFFFFU; // LR
        HW32_REG((v_PSP_NS + 0x10)) = 0; // r12
        HW32_REG((v_PSP_NS + 0x0C)) = 0; // r3
        HW32_REG((v_PSP_NS + 0x08)) = 0; // r2
        HW32_REG((v_PSP_NS + 0x04)) = 0; // r1
        HW32_REG((v_PSP_NS + 0x00)) = 0; // r0
        printf ("Stack frame created, triggering PendSV...\n");
        
        // Trigger Secure PendSV
        SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
        __DSB();
        __ISB();
        // PendSV should be triggered now

      return ;  
    }


    void __attribute__((naked)) PendSV_Handler(void)
    {
        __asm volatile (
        "LDR    R0,= 0xFFFFFFB9\n\t"
        "BX     R0\n\t"    // Exception return to NS thread
        );    
    }

    ================== Non-secure world =================

    int main(void)
    {
        unsigned int p;
        UART_Config();
        printf("Non-secure Hello world\n");
        printf ("Run test\n");    
        
        p = (unsigned) NS_thread; // Get starting address of thread
        printf ("NS_thread address is 0x%x\n", p);
        set_thread_addr(p); // Pass address of NS_thread
        printf ("Return to NS world #1\n");
        tz_test1();
        printf ("Return to NS world #2\n");
        while(1);
        
    }
        
    void NS_thread(void)
    {
        puts("[NS thread]\n");
      while(1);
        return;
    }    

Children