Пример #1
0
void UsageFault_Handler(void) {
    //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info
    //Get thread context. Contains main registers including PC and LR
    struct port_extctx ctx;
    memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx));
    (void)ctx;
    //Interrupt status register: Which interrupt have we encountered, e.g. HardFault?
    FaultType faultType = (FaultType)__get_IPSR();
    (void)faultType;
    //Flags about hardfault / busfault
    //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference
    bool isUndefinedInstructionFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 0) ? true : false);
    bool isEPSRUsageFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 1) ? true : false);
    bool isInvalidPCFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 2) ? true : false);
    bool isNoCoprocessorFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 3) ? true : false);
    bool isUnalignedAccessFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 8) ? true : false);
    bool isDivideByZeroFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 9) ? true : false);
    (void)isUndefinedInstructionFault;
    (void)isEPSRUsageFault;
    (void)isInvalidPCFault;
    (void)isNoCoprocessorFault;
    (void)isUnalignedAccessFault;
    (void)isDivideByZeroFault;
    //Cause debugger to stop. Ignored if no debugger is attached
    while(1) {}
}
Пример #2
0
void HardFault_Handler(void) {
    //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info
    //Get thread context. Contains main registers including PC and LR
    struct port_extctx ctx;
    memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx));
    (void)ctx;
    //Interrupt status register: Which interrupt have we encountered, e.g. HardFault?
    FaultType faultType = (FaultType)__get_IPSR();
    (void)faultType;
    //For HardFault/BusFault this is the address that was accessed causing the error
    uint32_t faultAddress = SCB->BFAR;
    (void)faultAddress;
    //Flags about hardfault / busfault
    //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference
    bool isFaultPrecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 1) ? true : false);
    bool isFaultImprecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 2) ? true : false);
    bool isFaultOnUnstacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 3) ? true : false);
    bool isFaultOnStacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 4) ? true : false);
    bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 7) ? true : false);
    (void)isFaultPrecise;
    (void)isFaultImprecise;
    (void)isFaultOnUnstacking;
    (void)isFaultOnStacking;
    (void)isFaultAddressValid;
    //Cause debugger to stop. Ignored if no debugger is attached
    while(1) {}
}
Пример #3
0
void MemManage_Handler(void) {
    //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info
    //Get thread context. Contains main registers including PC and LR
    struct port_extctx ctx;
    memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx));
    (void)ctx;
    //Interrupt status register: Which interrupt have we encountered, e.g. HardFault?
    FaultType faultType = (FaultType)__get_IPSR();
    (void)faultType;
    //For HardFault/BusFault this is the address that was accessed causing the error
    uint32_t faultAddress = SCB->MMFAR;
    (void)faultAddress;
    //Flags about hardfault / busfault
    //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference
    bool isInstructionAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 0) ? true : false);
    bool isDataAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 1) ? true : false);
    bool isExceptionUnstackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 3) ? true : false);
    bool isExceptionStackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 4) ? true : false);
    bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 7) ? true : false);
    (void)isInstructionAccessViolation;
    (void)isDataAccessViolation;
    (void)isExceptionUnstackingFault;
    (void)isExceptionStackingFault;
    (void)isFaultAddressValid;
    while(1) {}
}
Пример #4
0
static void process_exception()
{
#if USE_EXCEPTION_RECORD
	TASK_STACKED_CTX_STRU* msp;
#endif



#if USE_EXCEPTION_RECORD
    exception_record.restart_cause = __get_IPSR();
    exception_record.CFSR = 0;
	msp = (TASK_STACKED_CTX_STRU*)__get_PSP();
	if ((uint32_t)msp < BASE_SRAM || (uint32_t)msp >= (BASE_SRAM + RAM_SIZE) || ((uint32_t)msp & 3))
		msp = NULL;
	exception_record.MMFAR = msp->pc.as_int;

	exception_record.BFAR = msp->lr.as_int;
    exception_record.cur_task = (unsigned int)CURRENT_TASK;
    if (((unsigned int) CURRENT_TASK > BASE_SRAM)
			&& ((unsigned int) CURRENT_TASK < (BASE_SRAM + RAM_SIZE)))
    {
    	exception_record.task_name = CURRENT_TASK->name[0]
				+ (CURRENT_TASK->name[1] << 8) + (CURRENT_TASK->name[2] << 16)
				+ (CURRENT_TASK->name[3] << 24);
	} else
    {
    	exception_record.task_name = 0;
    }
    exception_record.record_crc = exception_crc((const unsigned int*)&exception_record);
#endif

}
Пример #5
0
/**
\brief Test case: TC_CoreFunc_PSP
\details
- Check if __get_PSP and __set_PSP intrinsic can be used to manipulate process stack pointer.
*/
void TC_CoreFunc_PSP (void) {
  // don't use stack for this variables
  static uint32_t orig;
  static uint32_t psp;
  static uint32_t result;

  orig = __get_PSP();

  psp = orig + 0x12345678U;
  __set_PSP(psp);

  result = __get_PSP();

  __set_PSP(orig);

  ASSERT_TRUE(result == psp);
}
Пример #6
0
void HardFault_Handler(void)
{
  uint32_t r_sp ;

  r_sp = __get_PSP(); //??SP??
//  PERROR(ERROR,Memory Access Error!);
  printf("r_sp = 0x%x",r_sp);
 
  while (1);
}
Пример #7
0
/**
 * @brief   Exception exit redirection to _port_switch_from_isr().
 */
void _port_irq_epilogue(void) {

  port_lock_from_isr();
  if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) {

    /* The port_extctx structure is pointed by the PSP register.*/
    struct port_extctx *ctxp = (struct port_extctx *)__get_PSP();

    /* Adding an artificial exception return context, there is no need to
       populate it fully.*/
    ctxp--;

    /* Writing back the modified PSP value.*/
    __set_PSP((uint32_t)ctxp);

    /* Setting up a fake XPSR register value.*/
    ctxp->xpsr = (regarm_t)0x01000000;

    /* The exit sequence is different depending on if a preemption is
       required or not.*/
    if (chSchIsRescRequiredI()) {
      /* Preemption is required we need to enforce a context switch.*/
      ctxp->pc = (regarm_t)_port_switch_from_isr;
#if CORTEX_USE_FPU
      /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/
      (void) __get_FPSCR();
#endif
    }
    else {
      /* Preemption not required, we just need to exit the exception
         atomically.*/
      ctxp->pc = (regarm_t)_port_exit_from_isr;
    }

#if CORTEX_USE_FPU
    {
      uint32_t fpccr;

      /* Saving the special register SCB_FPCCR into the reserved offset of
         the Cortex-M4 exception frame.*/
      (ctxp + 1)->fpccr = (regarm_t)(fpccr = FPU->FPCCR);

      /* Now the FPCCR is modified in order to not restore the FPU status
         from the artificial return context.*/
      FPU->FPCCR = fpccr | FPU_FPCCR_LSPACT_Msk;
    }
#endif

    /* Note, returning without unlocking is intentional, this is done in
       order to keep the rest of the context switch atomic.*/
    return;
  }
  port_unlock_from_isr();
}
Пример #8
0
/**
 * @brief   PendSV vector.
 * @details The PendSV vector is used for exception mode re-entering after a
 *          context switch.
 */
void PendSV_Handler(void) {

  /* The port_extctx structure is pointed by the PSP register.*/
  struct port_extctx *ctxp = (struct port_extctx *)__get_PSP();

  /* Discarding the current exception context and positioning the stack to
     point to the real one.*/
  ctxp++;

  /* Writing back the modified PSP value.*/
  __set_PSP((uint32_t)ctxp);
}
Пример #9
0
void dumpFaultHandler(UInt32 * stack)
{
    UInt32 r0,r1,r2,r3,r12,lr,pc,psr;
    
    r0 = stack[0];
    r1 = stack[1];
    r2 = stack[2];
    r3 = stack[3];
    r12 = stack[4];
    lr = stack[5];
    pc = stack[6];
    psr = stack[7];

    debugPrintf("HARDFAULT EXCEPTION\r\n");
    debugPrintf("[ Dump stack and fault register from base 0x%x]\r\n", stack );
    debugPrintf("R0  = 0x%x\r\n", r0);
    debugPrintf("R1  = 0x%x\r\n", r1);
    debugPrintf("R2  = 0x%x\r\n", r2);
    debugPrintf("R3  = 0x%x\r\n", r3);
    debugPrintf("R12 = 0x%x\r\n", r12);
    debugPrintf("LR  = 0x%x\r\n", lr);
    debugPrintf("PC  = 0x%x\r\n", pc);
    debugPrintf("psr = 0x%x\r\n", psr);
    debugPrintf("PSP = 0x%x\r\n", __get_PSP() );

    // Bus fault address 
    debugPrintf("BFAR = %x\r\n", BFAR );
    // MemManage Fault address 
    debugPrintf("MMAR = %x\r\n", MMAR );
    // MemManage Fault Status
    debugPrintf("MMSR = %x\r\n", MMSR  );
    // Hard Fault Status
    debugPrintf("HSFR = %x\r\n", (*(volatile UInt32 *)(0xE000ED2C)) );
    // Debug Fault Status
    debugPrintf("DFSR = %x\r\n", (*(volatile UInt32 *)(0xE000ED30)) );
    // Auxiliary Fault Status
    debugPrintf("AFSR = %x\r\n", (*(volatile UInt32 *)(0xE000ED3C)) );
    
    //MMSR = 0; //cradok de chez cradok
    
    // test virtual memory
//    if( BFAR > 0x80000 && BFAR < 0x10000000)
//    {
//        debugPrintf("read/write to virtual address\r\n");
//        stack[6] = stack[6] +2; //arm +4
//    }
//    else
//    {
        dumpKernel();
        while(1);
//    }
            
}
Пример #10
0
/**
 * @brief   Exception exit redirection to _port_switch_from_isr().
 */
void _port_irq_epilogue(void) {

    port_lock_from_isr();
    if ((SCB_ICSR & ICSR_RETTOBASE) != 0) {
        struct extctx *ctxp;

        /* Current PSP value.*/
        ctxp = (struct extctx *)__get_PSP();

        /* Adding an artificial exception return context, there is no need to
           populate it fully.*/
        ctxp--;
        __set_PSP((unsigned long)ctxp);
        ctxp->xpsr = (regarm_t)0x01000000;

        /* The exit sequence is different depending on if a preemption is
           required or not.*/
        if (chSchIsPreemptionRequired()) {
            /* Preemption is required we need to enforce a context switch.*/
            ctxp->pc = (regarm_t)_port_switch_from_isr;
#if CORTEX_USE_FPU
            /* Triggering a lazy FPU state save.*/
            (void)__get_FPSCR();
#endif
        }
        else {
            /* Preemption not required, we just need to exit the exception
               atomically.*/
            ctxp->pc = (regarm_t)_port_exit_from_isr;
        }

#if CORTEX_USE_FPU
        {
            uint32_t fpccr;

            /* Saving the special register SCB_FPCCR into the reserved offset of
               the Cortex-M4 exception frame.*/
            (ctxp + 1)->fpccr = (regarm_t)(fpccr = SCB_FPCCR);

            /* Now the FPCCR is modified in order to not restore the FPU status
               from the artificial return context.*/
            SCB_FPCCR = fpccr | FPCCR_LSPACT;
        }
#endif

        /* Note, returning without unlocking is intentional, this is done in
           order to keep the rest of the context switch atomic.*/
        return;
    }
    port_unlock_from_isr();
}
Пример #11
0
/* stack dump and information dump
 * for stack dump, a common rules is:
 * 0x2000xxxx (r7) 0x0000xxxx(lr), r7 will in stack and lr will in flash.
 * usually 12th long word is the address which calls panic().
 */
void panic(char *infostr)
{
	uint32_t sp;
	uint32_t size;
	fsave();
	
	kprintf("PANIC: %s\n", infostr);
#if 0
	if(get_psr() & 0xFF){
		/* in exception context, dump exception stack */
		sp = __get_MSP();
		if((sp>(uint32_t)_irq_stack_start) && (sp<(uint32_t)_irq_stack_start+1024))
		{
			size = (uint32_t)_irq_stack_start+1024-sp;
			kprintf("exception stacks: sp=0x%x depth=%d bytes\n", sp, size);
			dump_buffer((uint8_t *)sp, size);
		}
		else
			kprintf("broken MSP: 0x%x\n", sp);
	}

	
	if((current>=&systask[0]) && (current<&systask[MAX_TASK_NUMBER]))
	{
		/* dump task stack */
		sp = __get_PSP();
		if((sp>(uint32_t)current->stack_base) && (sp<(uint32_t)current->stack_base+current->stack_size))
		{
			size = (uint32_t)current->stack_base+current->stack_size-sp;
			kprintf("task stacks: sp=0x%x depth=%d bytes\n", sp, size);
			dump_buffer((uint8_t *)sp, size);
		}
		else
			kprintf("broken PSP: 0x%x\n", sp);

		/* dump current task info */
		kprintf("current=0x%x last sp=0x%x stack_base=0x%x taskname=%s state=%d taskq=0x%x\n", 
			current, current->sp, current->stack_base, current->name, current->state, current->taskq);
	}
	else
		kprintf("current is overwriten! current=0x%x\n", current);
#endif // 0

	/* dump system ready queue */

	/* dump memory usage */
	memory_dump();
	
    while(1);
}
Пример #12
0
/**
 * @brief   NMI vector.
 * @details The NMI vector is used for exception mode re-entering after a
 *          context switch.
 */
void NMI_Handler(void) {

  /* The port_extctx structure is pointed by the PSP register.*/
  struct port_extctx *ctxp = (struct port_extctx *)__get_PSP();

  /* Discarding the current exception context and positioning the stack to
     point to the real one.*/
  ctxp++;

  /* Writing back the modified PSP value.*/
  __set_PSP((uint32_t)ctxp);

  /* Restoring the normal interrupts status.*/
  port_unlock_from_isr();
}
Пример #13
0
/*!
 * \brief An MQX-provided default ISR for unhandled interrupts. The function
 * depends on the PSP.
 *
 * The function changes the state of the active task to UNHANDLED_INT_BLOCKED and
 * blocks the task.
 * \n The function uses the default I/O channel to display at least:
 * \li Vector number that caused the unhandled exception.
 * \li Task ID and task descriptor of the active task.
 *
 * \n Depending on the PSP, more information might be displayed.
 *
 * \param[in] parameter Parameter passed to the default ISR.
 *
 * \note
 * Since the ISR uses printf() to display information to the default I/O channel,
 * default I/O must not be on a channel that uses interrupt-driven I/O or the
 * debugger.
 *
 * \warning Blocks the active task.
 *
 * \see _int_install_unexpected_isr
 */
void _int_unexpected_isr
(
    void   *parameter
)
{ /* Body */
    KERNEL_DATA_STRUCT_PTR     kernel_data;
    TD_STRUCT_PTR              td_ptr;

    _GET_KERNEL_DATA(kernel_data);
    td_ptr = kernel_data->ACTIVE_PTR;

#if MQXCFG_PRINT_MEM_DUMP
#error  "MQXCFG_PRINT_MEM_DUMP functionality is currently not supported. This feature will be supported again in future release.\
         Please set MQXCFG_PRINT_MEM_DUMP to zero."
#endif

#if MQXCFG_PRINT_MEM_DUMP
    {
        unsigned int                psp, msp, i;
        printf("\n\r*** UNHANDLED INTERRUPT ***\n\r");
        printf("Vector #: 0x%02x Task Id: 0x%0x Td_ptr 0x%x\n\r",
        (unsigned int)parameter, (unsigned int)td_ptr->TASK_ID, (unsigned int)td_ptr);

        psp = __get_PSP();
        msp = __get_MSP();
        printf("PSP: 0x%08x MSP: 0x%08x PSR: 0x%08x\n\r", psp, msp, (unsigned int)__get_xPSR());

        printf("\n\r\n\rMemory dump:\n\r");
        for (i = 0; i < 32; i += 4) {
            printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", psp + i * 4, ((unsigned int*)psp)[i], ((unsigned int*)psp)[i + 1], ((unsigned int*)psp)[i + 2], ((unsigned int*)psp)[i + 3]);
        }

        printf("\n\r\n\rMemory dump:\n\r");
        for (i = 0; i < 32; i += 4) {
            printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", msp + i * 4, ((unsigned int*)msp)[i], ((unsigned int*)msp)[i + 1], ((unsigned int*)msp)[i + 2], ((unsigned int*)msp)[i + 3]);
        }
    }
#endif /* MQXCFG_PRINT_MEM_DUMP */
    _INT_DISABLE();
    if (td_ptr->STATE != UNHANDLED_INT_BLOCKED) {
        td_ptr->STATE = UNHANDLED_INT_BLOCKED;
        td_ptr->INFO  = (_mqx_uint)parameter;

        _QUEUE_UNLINK(td_ptr);
    } /* Endif */
   _INT_ENABLE();

} /* Endbody */
Пример #14
0
/**
 * @brief   PendSV vector.
 * @details The PendSV vector is used for exception mode re-entering after a
 *          context switch.
 * @note    The PendSV vector is only used in compact kernel mode.
 */
void PendSVVector(void) {
    struct extctx *ctxp;

    /* Current PSP value.*/
    ctxp = (struct extctx *)__get_PSP();

    /* Discarding the current exception context and positioning the stack to
       point to the real one.*/
    ctxp++;

#if CORTEX_USE_FPU
    /* Restoring the special register SCB_FPCCR.*/
    SCB_FPCCR = (uint32_t)ctxp->fpccr;
    SCB_FPCAR = SCB_FPCAR + sizeof (struct extctx);
#endif
    __set_PSP((unsigned long)ctxp);
}
Пример #15
0
/**
 * @brief   Exception exit redirection to _port_switch_from_isr().
 */
void _port_irq_epilogue(void) {

  port_lock_from_isr();
  if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) {
    struct port_extctx *ctxp;

#if CORTEX_USE_FPU
      /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/
      (void) __get_FPSCR();
#endif

    /* The port_extctx structure is pointed by the PSP register.*/
    ctxp = (struct port_extctx *)__get_PSP();

    /* Adding an artificial exception return context, there is no need to
       populate it fully.*/
    ctxp--;

    /* Setting up a fake XPSR register value.*/
    ctxp->xpsr = (regarm_t)0x01000000;
#if CORTEX_USE_FPU
    ctxp->fpscr = (regarm_t)FPU->FPDSCR;
#endif

    /* Writing back the modified PSP value.*/
    __set_PSP((uint32_t)ctxp);

    /* The exit sequence is different depending on if a preemption is
       required or not.*/
    if (chSchIsPreemptionRequired()) {
      /* Preemption is required we need to enforce a context switch.*/
      ctxp->pc = (regarm_t)_port_switch_from_isr;
    }
    else {
      /* Preemption not required, we just need to exit the exception
         atomically.*/
      ctxp->pc = (regarm_t)_port_exit_from_isr;
    }

    /* Note, returning without unlocking is intentional, this is done in
       order to keep the rest of the context switch atomic.*/
    return;
  }
  port_unlock_from_isr();
}
Пример #16
0
/**
 * @brief   PendSV vector.
 * @details The PendSV vector is used for exception mode re-entering after a
 *          context switch.
 * @note    The PendSV vector is only used in compact kernel mode.
 */
void PendSV_Handler(void) {
  struct port_extctx *ctxp;

#if CORTEX_USE_FPU
  /* Enforcing unstacking of the FP part of the context.*/
  FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk;
#endif

  /* The port_extctx structure is pointed by the PSP register.*/
  ctxp = (struct port_extctx *)__get_PSP();

  /* Discarding the current exception context and positioning the stack to
     point to the real one.*/
  ctxp++;

  /* Writing back the modified PSP value.*/
  __set_PSP((uint32_t)ctxp);
}
Пример #17
0
/**
 * @brief   PendSV vector.
 * @details The PendSV vector is used for exception mode re-entering after a
 *          context switch.
 * @note    The PendSV vector is only used in compact kernel mode.
 */
void PendSVVector(void) {
  struct extctx *ctxp;

#if CORTEX_USE_FPU
  /* Enforcing unstacking of the FP part of the context.*/
  SCB_FPCCR &= ~FPCCR_LSPACT;
#endif

  /* Current PSP value.*/
  ctxp = (struct extctx *)__get_PSP();

  /* Discarding the current exception context and positioning the stack to
     point to the real one.*/
  ctxp++;

  /* Restoring real position of the original stack frame.*/
  __set_PSP((unsigned long)ctxp);
}
Пример #18
0
/**
 * @brief   PendSV vector.
 * @details The PendSV vector is used for exception mode re-entering after a
 *          context switch.
 * @note    The PendSV vector is only used in compact kernel mode.
 */
void PendSV_Handler(void) {

  /* The port_extctx structure is pointed by the PSP register.*/
  struct port_extctx *ctxp = (struct port_extctx *)__get_PSP();

  /* Discarding the current exception context and positioning the stack to
     point to the real one.*/
  ctxp++;

#if CORTEX_USE_FPU
  /* Restoring the special register FPCCR.*/
  FPU->FPCCR = (uint32_t)ctxp->fpccr;
  FPU->FPCAR = FPU->FPCAR + sizeof (struct port_extctx);
#endif

  /* Writing back the modified PSP value.*/
  __set_PSP((uint32_t)ctxp);
}
Пример #19
0
void _int_unexpected_isr
   (
      /* [IN] the parameter passed to the default ISR, the vector */
      pointer parameter
   )
{ /* Body */
   KERNEL_DATA_STRUCT_PTR     kernel_data;
   TD_STRUCT_PTR              td_ptr;
   //PSP_INT_CONTEXT_STRUCT_PTR exception_frame_ptr;
   uint_32                    psp, msp, i;

   _GET_KERNEL_DATA(kernel_data);
   td_ptr = kernel_data->ACTIVE_PTR;
   //exception_frame_ptr = kernel_data->INTERRUPT_CONTEXT_PTR;

   printf("\n\r*** UNHANDLED INTERRUPT ***\n\r"); 
   printf("Vector #: 0x%02x Task Id: 0x%0x Td_ptr 0x%x\n\r",
      (uint_32)parameter, (uint_32)td_ptr->TASK_ID, (uint_32)td_ptr);

   psp = __get_PSP();
   msp = __get_MSP();
   printf("PC: 0x%08x LR: 0x%08x PSP: 0x%08x MSP: 0x%08x PSR: 0x%08x\n\r", __get_PC(), __get_LR(), psp, msp, __get_PSR());

   printf("\n\r\n\rMemory dump:\n\r");
   for (i = 0; i < 32; i += 4) {
       printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", psp + i * 4, ((uint_32*)psp)[i], ((uint_32*)psp)[i + 1], ((uint_32*)psp)[i + 2], ((uint_32*)psp)[i + 3]);
   }

   printf("\n\r\n\rMemory dump:\n\r");
   for (i = 0; i < 32; i += 4) {
       printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", msp + i * 4, ((uint_32*)msp)[i], ((uint_32*)msp)[i + 1], ((uint_32*)msp)[i + 2], ((uint_32*)msp)[i + 3]);
   }

   _INT_ENABLE();
   if (td_ptr->STATE != UNHANDLED_INT_BLOCKED) {
      td_ptr->STATE = UNHANDLED_INT_BLOCKED;
      td_ptr->INFO  = (_mqx_uint)parameter;

      _QUEUE_UNLINK(td_ptr);
   } /* Endif */
   _INT_DISABLE();

} /* Endbody */
Пример #20
0
/**
 * @brief   Exception exit redirection to _port_switch_from_isr().
 */
void _port_irq_epilogue(void) {

  port_lock_from_isr();
  if ((SCB_ICSR & ICSR_RETTOBASE) != 0) {
    struct extctx *ctxp;

#if CORTEX_USE_FPU
    /* Enforcing a lazy FPU state save. Note, it goes in the original
       context because the FPCAR register has not been modified.*/
    (void)__get_FPSCR();
#endif

    /* Current PSP value.*/
    ctxp = (struct extctx *)__get_PSP();

    /* Adding an artificial exception return context, there is no need to
       populate it fully.*/
    ctxp--;
    ctxp->xpsr = (regarm_t)0x01000000;
#if CORTEX_USE_FPU
    ctxp->fpscr = (regarm_t)SCB_FPDSCR;
#endif
    __set_PSP((unsigned long)ctxp);

    /* The exit sequence is different depending on if a preemption is
       required or not.*/
    if (chSchIsPreemptionRequired()) {
      /* Preemption is required we need to enforce a context switch.*/
      ctxp->pc = (regarm_t)_port_switch_from_isr;
    }
    else {
      /* Preemption not required, we just need to exit the exception
         atomically.*/
      ctxp->pc = (regarm_t)_port_exit_from_isr;
    }

    /* Note, returning without unlocking is intentional, this is done in
       order to keep the rest of the context switch atomic.*/
    return;
  }
  port_unlock_from_isr();
}
Пример #21
0
/* This SVC handler is called when sfn returns */
uint32_t tfm_core_partition_return_handler(uint32_t lr)
{
    int32_t res;

    if (!(lr & EXC_RETURN_STACK_PROCESS)) {
        /* Partition return SVC called with MSP active.
         * This should not happen!
         */
        ERROR_MSG("Partition return SVC called with MSP active!");
        tfm_secure_api_error_handler();
    }

    /* Store return value from secure partition */
    int32_t retVal = *(int32_t *)__get_PSP();

    if (!is_iovec_api_call()) {
        if ((retVal > TFM_SUCCESS) &&
            (retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) {
            /* Secure function returned a reserved value */
#ifdef TFM_CORE_DEBUG
            LOG_MSG("Invalid return value from secure partition!");
#endif
            /* FixMe: error can be traced to specific secure partition
             * and Core is not compromised. Error handling flow can be
             * refined
             */
            tfm_secure_api_error_handler();
        }
    }

    res = tfm_return_from_partition(&lr);
    if (res != TFM_SUCCESS) {
        /* Unlock errors indicate ctx database corruption or unknown anomalies
         * Halt execution
         */
        ERROR_MSG("Secure API error during unlock!");
        tfm_secure_api_error_handler();
    }

    return lr;
}
Пример #22
0
void *_sbrk(int incr) {
  extern char __HeapLimit; /* Defined by the linker */
  static char *heap_end = 0;
  char *prev_heap_end;

  if (heap_end == 0) {
    heap_end = &__HeapLimit;
  }
  prev_heap_end = heap_end;
#if 0
  char * stack = (char*) __get_PSP();

  if (heap_end + incr >  stack) {
    _write (STDERR_FILENO, "Heap and stack collision\n", 25);
    errno = ENOMEM;
    return  (void *)-1;
  }
#endif
  heap_end += incr;
  return (void *) prev_heap_end;
}
Пример #23
0
/**
 * @brief   SVC vector.
 * @details The SVC vector is used for exception mode re-entering after a
 *          context switch.
 * @note    The PendSV vector is only used in advanced kernel mode.
 */
void SVC_Handler(void) {
  struct port_extctx *ctxp;

#if CORTEX_USE_FPU
  /* Enforcing unstacking of the FP part of the context.*/
  FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk;
#endif

  /* The port_extctx structure is pointed by the PSP register.*/
  ctxp = (struct port_extctx *)__get_PSP();

  /* Discarding the current exception context and positioning the stack to
     point to the real one.*/
  ctxp++;

  /* Restoring real position of the original stack frame.*/
  __set_PSP((uint32_t)ctxp);

  /* Restoring the normal interrupts status.*/
  port_unlock_from_isr();
}
Пример #24
0
/* Note: On ARMv7-M the return_handler is executed in NP mode. */
void debug_deprivilege_and_return(void * debug_handler, void * return_handler,
                                  uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3)
{
    /* Source box: Get the current stack pointer. */
    /* Note: The source stack pointer is only used to assess the stack
     *       alignment and to read the xpsr. */
    uint32_t src_sp = context_validate_exc_sf(__get_PSP());

    /* Destination box: The debug box. */
    uint8_t dst_id = g_debug_box.box_id;

    /* Copy the xPSR from the source exception stack frame. */
    uint32_t xpsr = vmpu_unpriv_uint32_read((uint32_t) &((uint32_t *) src_sp)[7]);

    /* Destination box: Forge the destination stack frame. */
    /* Note: We manually have to set the 4 parameters on the destination stack,
     *       so we will set the API to have nargs=0. */
    uint32_t dst_sp = context_forge_exc_sf(src_sp, dst_id, (uint32_t) debug_handler, (uint32_t) return_handler, xpsr, 0);
    ((uint32_t *) dst_sp)[0] = a0;
    ((uint32_t *) dst_sp)[1] = a1;
    ((uint32_t *) dst_sp)[2] = a2;
    ((uint32_t *) dst_sp)[3] = a3;

    /* Suspend the OS. */
    g_priv_sys_hooks.priv_os_suspend();

    /* Stop all lower-than-SVC-priority interrupts. FIXME Enable debug box to
     * do things that require interrupts. One idea would be to provide an SVC
     * to re-enable interrupts that can only be called by the debug box during
     * debug handling. */
    __set_BASEPRI(__UVISOR_NVIC_MIN_PRIORITY << (8U - __NVIC_PRIO_BITS));

    context_switch_in(CONTEXT_SWITCH_FUNCTION_DEBUG, dst_id, src_sp, dst_sp);

    /* Upon execution return debug_handler will be executed. Upon return from
     * debug_handler, return_handler will be executed. */
    return;
}
Пример #25
0
/**
 * @brief   IRQ epilogue code.
 *
 * @param[in] lr        value of the @p LR register on ISR entry
 */
void _port_irq_epilogue(regarm_t lr) {

  if (lr != (regarm_t)0xFFFFFFF1U) {
    struct port_extctx *ctxp;

    port_lock_from_isr();

    /* The extctx structure is pointed by the PSP register.*/
    ctxp = (struct port_extctx *)__get_PSP();

    /* Adding an artificial exception return context, there is no need to
       populate it fully.*/
    ctxp--;

    /* Writing back the modified PSP value.*/
    __set_PSP((uint32_t)ctxp);

    /* Setting up a fake XPSR register value.*/
    ctxp->xpsr = (regarm_t)0x01000000;

    /* The exit sequence is different depending on if a preemption is
       required or not.*/
    if (chSchIsRescRequiredI()) {
      /* Preemption is required we need to enforce a context switch.*/
      ctxp->pc = (regarm_t)_port_switch_from_isr;
    }
    else {
      /* Preemption not required, we just need to exit the exception
         atomically.*/
      ctxp->pc = (regarm_t)_port_exit_from_isr;
    }

    /* Note, returning without unlocking is intentional, this is done in
       order to keep the rest of the context switch atomic.*/
  }
}
Пример #26
0
/**
  * @brief   Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */     
       
/* Switch Thread mode Stack from Main to Process -----------------------------*/
  /* Initialize memory reserved for Process Stack */
  for(Index = 0; Index < SP_PROCESS_SIZE; Index++)
  {
    PSPMemAlloc[Index] = 0x00;
  }

  /* Set Process stack value */ 
  __set_PSP((uint32_t)PSPMemAlloc + SP_PROCESS_SIZE);
  
  /* Select Process Stack as Thread mode Stack */
  __set_CONTROL(SP_PROCESS);

  /* Get the Thread mode stack used */
  if((__get_CONTROL() & 0x02) == SP_MAIN)
  {
    /* Main stack is used as the current stack */
    CurrentStack = SP_MAIN;
  }
  else
  {
    /* Process stack is used as the current stack */
    CurrentStack = SP_PROCESS;

    /* Get process stack pointer value */
    PSPValue = __get_PSP();	
  }
  
/* Switch Thread mode from privileged to unprivileged ------------------------*/
  /* Thread mode has unprivileged access */
  __set_CONTROL(THREAD_MODE_UNPRIVILEGED | SP_PROCESS);

  /* Unprivileged access mainly affect ability to:
      - Use or not use certain instructions such as MSR fields
      - Access System Control Space (SCS) registers such as NVIC and SysTick */

  /* Check Thread mode privilege status */
  if((__get_CONTROL() & 0x01) == THREAD_MODE_PRIVILEGED)
  {
    /* Thread mode has privileged access  */
    ThreadMode = THREAD_MODE_PRIVILEGED;
  }
  else
  {
    /* Thread mode has unprivileged access*/
    ThreadMode = THREAD_MODE_UNPRIVILEGED;
  }

/* Switch back Thread mode from unprivileged to privileged -------------------*/  
  /* Try to switch back Thread mode to privileged (Not possible, this can be
     done only in Handler mode) */
  __set_CONTROL(THREAD_MODE_PRIVILEGED | SP_PROCESS);

  /* Generate a system call exception, and in the ISR switch back Thread mode
    to privileged */
  __SVC();

  /* Check Thread mode privilege status */
  if((__get_CONTROL() & 0x01) == THREAD_MODE_PRIVILEGED)
  {
    /* Thread mode has privileged access  */
    ThreadMode = THREAD_MODE_PRIVILEGED;
  }
  else
  {
    /* Thread mode has unprivileged access*/
    ThreadMode = THREAD_MODE_UNPRIVILEGED;
  }

  while (1)
  {
  }
}
Пример #27
0
void BusFault_Handler(void)
{
    printf("\r\n BusFault_Handler interrupt!\r\n");
    rt_hw_hard_fault_exception((struct exception_stack_frame *)__get_PSP());
    while(1);
}
Пример #28
0
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  /* STM32F4xx HAL library initialization:
       - Configure the Flash prefetch
       - Systick timer is configured by default as source of time base, but user 
         can eventually implement his proper time base source (a general purpose 
         timer for example or other time source), keeping in mind that Time base 
         duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and 
         handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();

  /* Configure the system clock to have a system clock = 180 MHz */
  SystemClock_Config();

  /* Configure LED1*/
  BSP_LED_Init(LED1);

  /* Switch Thread mode Stack from Main to Process -----------------------------*/
  /* Initialize memory reserved for Process Stack */
  for(Index = 0; Index < SP_PROCESS_SIZE; Index++)
  {
    PSPMemAlloc[Index] = 0x00;
  }

  /* Set Process stack value */
  __set_PSP((uint32_t)PSPMemAlloc + SP_PROCESS_SIZE);

  /* Select Process Stack as Thread mode Stack */
  __set_CONTROL(SP_PROCESS);

  /* Execute ISB instruction to flush pipeline as recommended by Arm */
  __ISB(); 

  /* Get the Thread mode stack used */
  if((__get_CONTROL() & 0x02) == SP_MAIN)
  {
    /* Main stack is used as the current stack */
    CurrentStack = SP_MAIN;
  }
  else
  {
    /* Process stack is used as the current stack */
    CurrentStack = SP_PROCESS;

    /* Get process stack pointer value */
    PSPValue = __get_PSP();
  }

  /* Switch Thread mode from privileged to unprivileged ------------------------*/
  /* Thread mode has unprivileged access */
  __set_CONTROL(THREAD_MODE_UNPRIVILEGED | SP_PROCESS);
  
  /* Execute ISB instruction to flush pipeline as recommended by Arm */
  __ISB(); 

  /* Unprivileged access mainly affect ability to:
      - Use or not use certain instructions such as MSR fields
      - Access System Control Space (SCS) registers such as NVIC and SysTick */

  /* Check Thread mode privilege status */
  if((__get_CONTROL() & 0x01) == THREAD_MODE_PRIVILEGED)
  {
    /* Thread mode has privileged access  */
    ThreadMode = THREAD_MODE_PRIVILEGED;
  }
  else
  {
    /* Thread mode has unprivileged access*/
    ThreadMode = THREAD_MODE_UNPRIVILEGED;
  }

  /* Switch back Thread mode from unprivileged to privileged -------------------*/
  /* Try to switch back Thread mode to privileged (Not possible, this can be
     done only in Handler mode) */
  __set_CONTROL(THREAD_MODE_PRIVILEGED | SP_PROCESS);

  /* Execute ISB instruction to flush pipeline as recommended by Arm */
  __ISB(); 

  /* Generate a system call exception, and in the ISR switch back Thread mode
    to privileged */
  __SVC();

  /* Check Thread mode privilege status */
  if((__get_CONTROL() & 0x01) == THREAD_MODE_PRIVILEGED)
  {
    /* Thread mode has privileged access  */
    ThreadMode = THREAD_MODE_PRIVILEGED;
  }
  else
  {
    /* Thread mode has unprivileged access*/
    ThreadMode = THREAD_MODE_UNPRIVILEGED;
  }

  /* Infinite loop */
  while (1)
  {
    /* Turn ON LED once test finished */
    BSP_LED_On(LED1);
  }
}
Пример #29
0
static int32_t tfm_return_from_partition(uint32_t *excReturn)
{
    uint32_t current_partition_idx =
            tfm_spm_partition_get_running_partition_idx();
    const struct spm_partition_runtime_data_t *curr_part_data, *ret_part_data;
    uint32_t current_partition_flags;
    uint32_t return_partition_idx;
    uint32_t return_partition_flags;
    uint32_t psp = __get_PSP();
    size_t i;
    struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
    struct iovec_args_t *iovec_args;

    if (current_partition_idx == SPM_INVALID_PARTITION_IDX) {
        return TFM_SECURE_UNLOCK_FAILED;
    }

    curr_part_data = tfm_spm_partition_get_runtime_data(current_partition_idx);
    return_partition_idx = curr_part_data->caller_partition_idx;

    if (return_partition_idx == SPM_INVALID_PARTITION_IDX) {
        return TFM_SECURE_UNLOCK_FAILED;
    }

    ret_part_data = tfm_spm_partition_get_runtime_data(return_partition_idx);

    return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx);
    current_partition_flags = tfm_spm_partition_get_flags(
            current_partition_idx);

    tfm_secure_lock--;

    if((return_partition_flags & SPM_PART_FLAG_APP_ROT) == 0) {
        /* Re-enable NS exceptions when secure service returns to NS client.
         * FixMe:
         * To be removed when pre-emption and context management issues have
         * been analysed and resolved.
         */
        TFM_NS_EXC_ENABLE();
    }

#if (TFM_LVL != 1) && (TFM_LVL != 2)
    /* Deconfigure completed partition environment */
    tfm_spm_partition_sandbox_deconfig(current_partition_idx);
    if (tfm_secure_api_initializing) {
        /* Restore privilege for thread mode during TF-M init. This is only
         * have to be done if the partition is not trusted.
         */
        if ((current_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
            CONTROL_Type ctrl;

            ctrl.w = __get_CONTROL();
            ctrl.b.nPRIV = 0;
            __set_CONTROL(ctrl.w);
            __DSB();
            __ISB();
        }
    } else {
        /* Configure the caller partition environment in case this was a
         * partition to partition call and returning to untrusted partition
         */
        if (tfm_spm_partition_sandbox_config(return_partition_idx)
            != SPM_ERR_OK) {
            ERROR_MSG("Failed to configure sandbox for partition!");
            tfm_secure_api_error_handler();
        }
        if (return_partition_flags & SPM_PART_FLAG_APP_ROT) {
            /* Restore share status */
            tfm_spm_partition_set_share(
                return_partition_idx,
                tfm_spm_partition_get_runtime_data(
                    return_partition_idx)->share);
        }
    }
#endif

#if TFM_LVL == 1
    if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) ||
        (tfm_secure_api_initializing)) {
        /* In TFM level 1 context restore is only done when
         * returning to NS or after initialization
         */
        /* Restore caller context */
        restore_caller_ctx(svc_ctx,
            (struct tfm_exc_stack_t *)ret_part_data->stack_ptr);
        *excReturn = ret_part_data->lr;
        __set_PSP(ret_part_data->stack_ptr);
        extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
        uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
       __set_PSPLIM(psp_stack_bottom);

        /* FIXME: The condition should be removed once all the secure service
         *        calls are done via the iovec veneers */
        if (curr_part_data->iovec_api) {
            iovec_args = (struct iovec_args_t *)
                         ((uint32_t)&REGION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
                         sizeof(struct iovec_args_t));

            for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) {
                curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len;
            }
            tfm_clear_iovec_parameters(iovec_args);
        }
    }
#else
    /* Restore caller context */
    restore_caller_ctx(svc_ctx,
        (struct tfm_exc_stack_t *)ret_part_data->stack_ptr);
    *excReturn = ret_part_data->lr;
    __set_PSP(ret_part_data->stack_ptr);
    __set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx));
    /* Clear the context entry before returning */
    tfm_spm_partition_set_stack(
                current_partition_idx, psp + sizeof(struct tfm_exc_stack_t));

    /* FIXME: The condition should be removed once all the secure service
     *        calls are done via the iovec veneers */
    if (curr_part_data->iovec_api) {
        iovec_args = (struct iovec_args_t *)
                     (tfm_spm_partition_get_stack_top(current_partition_idx) -
                     sizeof(struct iovec_args_t));

        for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) {
            curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len;
        }
        tfm_clear_iovec_parameters(iovec_args);
    }
#endif

    tfm_spm_partition_cleanup_context(current_partition_idx);

    tfm_spm_partition_set_state(current_partition_idx,
                                SPM_PARTITION_STATE_IDLE);
    tfm_spm_partition_set_state(return_partition_idx,
                                SPM_PARTITION_STATE_RUNNING);

    return TFM_SUCCESS;
}
Пример #30
0
static int32_t tfm_start_partition(const struct tfm_sfn_req_s *desc_ptr,
                                                             uint32_t excReturn)
{
    uint32_t caller_partition_idx = desc_ptr->caller_part_idx;
    const struct spm_partition_runtime_data_t *curr_part_data;
    uint32_t caller_flags;
    register uint32_t partition_idx;
    uint32_t psp = __get_PSP();
    uint32_t partition_psp, partition_psplim;
    uint32_t partition_state;
    uint32_t partition_flags;
    struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
    uint32_t caller_partition_id;
    int32_t client_id;
    struct iovec_args_t *iovec_args;

    caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);

    /* Check partition state consistency */
    if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0)
        != (!desc_ptr->ns_caller)) {
        /* Partition state inconsistency detected */
        return TFM_SECURE_LOCK_FAILED;
    }

    if((caller_flags & SPM_PART_FLAG_APP_ROT) == 0) {
        /* Disable NS exception handling while secure service is running.
         * FixMe:
         * This restriction is applied to limit the number of possible attack
         * vectors.
         * To be removed when pre-emption and context management issues have
         * been analysed and resolved.
         */
        TFM_NS_EXC_DISABLE();
    }

    partition_idx = get_partition_idx(desc_ptr->sp_id);

    curr_part_data = tfm_spm_partition_get_runtime_data(partition_idx);
    partition_state = curr_part_data->partition_state;
    partition_flags = tfm_spm_partition_get_flags(partition_idx);
    caller_partition_id = tfm_spm_partition_get_partition_id(
                                                          caller_partition_idx);

    if (tfm_secure_api_initializing) {
#if TFM_LVL != 1
        /* Make thread mode unprivileged while untrusted partition init is
         * executed
         */
        if ((partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
            CONTROL_Type ctrl;

            ctrl.w = __get_CONTROL();
            ctrl.b.nPRIV = 1;
            __set_CONTROL(ctrl.w);
            __DSB();
            __ISB();
        }
#endif
    } else if (partition_state == SPM_PARTITION_STATE_RUNNING ||
        partition_state == SPM_PARTITION_STATE_SUSPENDED ||
        partition_state == SPM_PARTITION_STATE_BLOCKED) {
        /* Recursion is not permitted! */
        return TFM_ERROR_PARTITION_NON_REENTRANT;
    } else if (partition_state != SPM_PARTITION_STATE_IDLE) {
        /* The partition to be called is not in a proper state */
        return TFM_SECURE_LOCK_FAILED;
    }

#if TFM_LVL == 1
    /* Prepare switch to shared secure partition stack */
    /* In case the call is coming from the non-secure world, we save the iovecs
     * on the stop of the stack. So the memory area, that can actually be used
     * as stack by the partitions starts at a lower address
     */
    partition_psp =
        (uint32_t)&REGION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
        sizeof(struct iovec_args_t);
    partition_psplim =
        (uint32_t)&REGION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
#else
    partition_psp = curr_part_data->stack_ptr;
    partition_psplim = tfm_spm_partition_get_stack_bottom(partition_idx);
#endif
    /* Store the context for the partition call */
    tfm_spm_partition_set_caller_partition_idx(partition_idx,
                                               caller_partition_idx);
    tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn);

    if ((caller_flags & SPM_PART_FLAG_APP_ROT)) {
        tfm_spm_partition_set_caller_client_id(partition_idx,
                                               caller_partition_id);
    } else {
        client_id = tfm_nspm_get_current_client_id();
        if (client_id >= 0)
        {
            return TFM_SECURE_LOCK_FAILED;
        }
        tfm_spm_partition_set_caller_client_id(partition_idx, client_id);
    }

#if (TFM_LVL != 1) && (TFM_LVL != 2)
    /* Dynamic partitioning is only done is TFM level 3 */
    tfm_spm_partition_sandbox_deconfig(caller_partition_idx);

    /* Configure partition execution environment */
    if (tfm_spm_partition_sandbox_config(partition_idx) != SPM_ERR_OK) {
        ERROR_MSG("Failed to configure sandbox for partition!");
        tfm_secure_api_error_handler();
    }
#endif

    /* Default share to scratch area in case of partition to partition calls
     * this way partitions always get default access to input buffers
     */
    /* FixMe: return value/error handling TBD */
    tfm_spm_partition_set_share(partition_idx, desc_ptr->ns_caller ?
        TFM_BUFFER_SHARE_NS_CODE : TFM_BUFFER_SHARE_SCRATCH);

#if TFM_LVL == 1
    /* In level one, only switch context and return from exception if in
     * handler mode
     */
    if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) {
        if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
            /* Save the iovecs on the common stack. The vectors had been sanity
             * checked already, and since then the interrupts have been kept
             * disabled. So we can be sure that the vectors haven't been
             * tampered with since the check.
             */
            iovec_args = (struct iovec_args_t *)
                    ((uint32_t)&REGION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
                     sizeof(struct iovec_args_t));
            if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) !=
                SPM_ERR_OK) {
                return TFM_ERROR_GENERIC;
            }
            tfm_copy_iovec_parameters(iovec_args,
                                      &(curr_part_data->iovec_args));

            /* Prepare the partition context, update stack ptr */
            psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
                                                        iovec_args,
                                                     (uint32_t *)partition_psp);
        } else {
            /* Prepare the partition context, update stack ptr */
            psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
                                                  (uint32_t *)partition_psp);
        }
        __set_PSP(psp);
        __set_PSPLIM(partition_psplim);
    }
#else
    if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
        /* Save the iovecs on the stack of the partition. The vectors had been
         * sanity checked already, and since then the interrupts have been kept
         * disabled. So we can be sure that the vectors haven't been tampered
         * with since the check.
         */
        iovec_args =
        (struct iovec_args_t *)(tfm_spm_partition_get_stack_top(partition_idx) -
        sizeof(struct iovec_args_t));
        if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) !=
            SPM_ERR_OK) {
            return TFM_ERROR_GENERIC;
        }
        tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->iovec_args));

        /* Prepare the partition context, update stack ptr */
        psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
                                                    iovec_args,
                                                    (uint32_t *)partition_psp);
    } else {
        /* Prepare the partition context, update stack ptr */
        psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
                                              (uint32_t *)partition_psp);
    }
    __set_PSP(psp);
    __set_PSPLIM(partition_psplim);
#endif

    tfm_spm_partition_set_state(caller_partition_idx,
                                SPM_PARTITION_STATE_BLOCKED);
    tfm_spm_partition_set_state(partition_idx, SPM_PARTITION_STATE_RUNNING);
    tfm_secure_lock++;

    return TFM_SUCCESS;
}