Пример #1
0
/*
 * See header file for description.
 */
portSTACK_TYPE * ICACHE_FLASH_ATTR
pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{
	#define SET_STKREG(r,v) sp[(r) >> 2] = (portSTACK_TYPE)(v)
    portSTACK_TYPE *sp, *tp;

    /* Create interrupt stack frame aligned to 16 byte boundary */
    sp = (portSTACK_TYPE*) (((INT32U)(pxTopOfStack+1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);

    /* Clear the entire frame (do not use memset() because we don't depend on C library) */
    for (tp = sp; tp <= pxTopOfStack; ++tp)
        *tp = 0;

    /* Explicitly initialize certain saved registers */
    SET_STKREG( XT_STK_PC,      pxCode                        );  /* task entrypoint                  */
    SET_STKREG( XT_STK_A0,      0                           );  /* to terminate GDB backtrace       */
    SET_STKREG( XT_STK_A1,      (INT32U)sp + XT_STK_FRMSZ   );  /* physical top of stack frame      */
    SET_STKREG( XT_STK_A2,      pvParameters   );           /* parameters      */
    SET_STKREG( XT_STK_EXIT,    _xt_user_exit               );  /* user exception exit dispatcher   */

    /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
    #ifdef __XTENSA_CALL0_ABI__
    SET_STKREG( XT_STK_PS,      PS_UM | PS_EXCM     );
    #else
    /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
    SET_STKREG( XT_STK_PS,      PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1) );
    #endif

	return sp;
}
Пример #2
0
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
#endif
{
	StackType_t *sp, *tp;
	XtExcFrame  *frame;
	#if XCHAL_CP_NUM > 0
	uint32_t *p;
	#endif

	/* Create interrupt stack frame aligned to 16 byte boundary */
	sp = (StackType_t *) (((UBaseType_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);

	/* Clear the entire frame (do not use memset() because we don't depend on C library) */
	for (tp = sp; tp <= pxTopOfStack; ++tp)
		*tp = 0;

	frame = (XtExcFrame *) sp;

	/* Explicitly initialize certain saved registers */
	frame->pc   = (UBaseType_t) pxCode;             /* task entrypoint                */
	frame->a0   = 0;                                /* to terminate GDB backtrace     */
	frame->a1   = (UBaseType_t) sp + XT_STK_FRMSZ;  /* physical top of stack frame    */
	frame->exit = (UBaseType_t) _xt_user_exit;      /* user exception exit dispatcher */

	/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
	/* Also set entry point argument parameter. */
	#ifdef __XTENSA_CALL0_ABI__
	frame->a2 = (UBaseType_t) pvParameters;
	frame->ps = PS_UM | PS_EXCM;
	#else
	/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
	frame->a6 = (UBaseType_t) pvParameters;
	frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
	#endif

	#ifdef XT_USE_SWPRI
	/* Set the initial virtual priority mask value to all 1's. */
	frame->vpri = 0xFFFFFFFF;
	#endif

	#if XCHAL_CP_NUM > 0
	/* Init the coprocessor save area (see xtensa_context.h) */
	/* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
         * //p = (uint32_t *) xMPUSettings->coproc_area;
	 */
	p = (uint32_t *)(((uint32_t) pxTopOfStack - XT_CP_SIZE) & ~0xf);
	p[0] = 0;
	p[1] = 0;
	p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN;
	#endif

	return sp;
}
Пример #3
0
void z_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
		size_t stackSize, k_thread_entry_t pEntry,
		void *p1, void *p2, void *p3,
		int priority, unsigned int options)
{
	char *pStack = Z_THREAD_STACK_BUFFER(stack);

	/* Align stack end to maximum alignment requirement. */
	char *stackEnd = (char *)ROUND_DOWN(pStack + stackSize, 16);
#if XCHAL_CP_NUM > 0
	u32_t *cpSA;
	char *cpStack;
#endif

	z_new_thread_init(thread, pStack, stackSize, priority, options);

#ifdef CONFIG_DEBUG
	printk("\nstackPtr = %p, stackSize = %d\n", pStack, stackSize);
	printk("stackEnd = %p\n", stackEnd);
#endif
#if XCHAL_CP_NUM > 0
	/* Ensure CP state descriptor is correctly initialized */
	cpStack = thread->arch.preempCoprocReg.cpStack; /* short hand alias */
	/* Set to zero to avoid bad surprises */
	(void)memset(cpStack, 0, XT_CP_ASA);
	/* Coprocessor's stack is allocated just after the k_thread */
	cpSA = (u32_t *)(thread->arch.preempCoprocReg.cpStack + XT_CP_ASA);
	/* Coprocessor's save area alignment is at leat 16 bytes */
	*cpSA = ROUND_UP(cpSA + 1,
		(XCHAL_TOTAL_SA_ALIGN < 16 ? 16 : XCHAL_TOTAL_SA_ALIGN));
#ifdef CONFIG_DEBUG
	printk("cpStack  = %p\n", thread->arch.preempCoprocReg.cpStack);
	printk("cpAsa    = %p\n",
	       *(void **)(thread->arch.preempCoprocReg.cpStack + XT_CP_ASA));
#endif
#endif
	/* Thread's first frame alignment is granted as both operands are
	 * aligned
	 */
	XtExcFrame *pInitCtx =
		(XtExcFrame *)(stackEnd - (XT_XTRA_SIZE - XT_CP_SIZE));
#ifdef CONFIG_DEBUG
	printk("pInitCtx = %p\n", pInitCtx);
#endif
	/* Explicitly initialize certain saved registers */

	 /* task entrypoint */
	pInitCtx->pc   = (u32_t)z_thread_entry;

	/* physical top of stack frame */
	pInitCtx->a1   = (u32_t)pInitCtx + XT_STK_FRMSZ;

	/* user exception exit dispatcher */
	pInitCtx->exit = (u32_t)z_xt_user_exit;

	/* Set initial PS to int level 0, EXCM disabled, user mode.
	 * Also set entry point argument arg.
	 */
#ifdef __XTENSA_CALL0_ABI__
	pInitCtx->a2 = (u32_t)pEntry;
	pInitCtx->a3 = (u32_t)p1;
	pInitCtx->a4 = (u32_t)p2;
	pInitCtx->a5 = (u32_t)p3;
	pInitCtx->ps = PS_UM | PS_EXCM;
#else
	/* For windowed ABI set also WOE and CALLINC
	 * (pretend task is 'call4')
	 */
	pInitCtx->a6 = (u32_t)pEntry;
	pInitCtx->a7 = (u32_t)p1;
	pInitCtx->a8 = (u32_t)p2;
	pInitCtx->a9 = (u32_t)p3;
	pInitCtx->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
#endif
	thread->callee_saved.topOfStack = pInitCtx;
	thread->arch.flags = 0;
	/* initial values in all other registers/k_thread entries are
	 * irrelevant
	 */
}
Пример #4
0
char* thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_start, int stack_size)
{
    /* Stack layout after task stack initialization
     *
     *                                            +------------------------+
     *                                            |                        | TOP
     *                                            |  thread_control_block  |
     *        stack_start + stack_size        ==> |                        | top_of_stack+1
     *                                            +------------------------+
     *        top_of_stack                    ==> |                        |
     *                                            |        XT_CP_SA        |
     *                                            |       (optional)       |
     *                                            | ...                    | ...
     *                                            | cpstored               | XT_CPSTORED
     *        top_of_stack + 1 - XT_CP_SIZE   ==> | cpenable               | XT_CPENABLE
     *        (cp_state)                          +------------------------+
     *                                            |                        |
     *                                            |      XT_STK_FRAME      |
     *                                            |                        | XT_STK_...
     *                                            | a2 = arg               | XT_STK_A2
     *                                            | a1 = sp + XT_STK_FRMSZ | XT_STK_A1
     *                                            | a0 = sched_task_exit   | XT_STK_A0
     *                                            | ps = PS_UM | PS_EXCM   | XT_STK_PS
     *                                            | pc = task_func         | XT_STK_PC
     *   sp = top_of_stack + 1 - XT_CP_SIZE   ==> | exit = _xt_user_exit   | XT_STK_EXIT
     *                         - XT_STK_FRMSZ     +------------------------+
     *                                            |                        |
     *                                            | remaining stack space  |
     *                                            |   available for data   |
     *        stack_start (preallocated var)  ==> |                        | BOTTOM
     *                                            +------------------------+
     *
     * Initialized stack frame represents the registers as set when the
     * the task function would have been called.
     *
     * Registers in a called function
     *
     *   pc - PC at the beginning in the function
     *   a0 - return address from the function (return address to caller)
     *   a1 - current stack pointer at the beginning in the function
     *   a2 - first argument of the function
     */

    /* stack is [stack_start+0 ... stack_start+stack_size-1] */
    uint8_t *top_of_stack;
    uint8_t *sp;

    top_of_stack = (uint8_t*)((uint32_t)stack_start + stack_size-1);

    /* BEGIN - code from FreeRTOS port for Xtensa from Cadence */

    /* Create interrupt stack frame aligned to 16 byte boundary */
    sp = (uint8_t*)(((uint32_t)(top_of_stack+1) - XT_STK_FRMSZ - XT_CP_SIZE) & ~0xf);

    /* Clear whole stack with a known value to assist debugging */
    #if !defined(DEVELHELP) && !defined(SCHED_TEST_STACK)
        /* Unfortunatly, this affects thread_measure_stack_free function */
        memset(stack_start, 0, stack_size);
    #else
        memset(sp, 0, XT_STK_FRMSZ + XT_CP_SIZE);
    #endif

    /* ensure that stack is big enough */
    assert (sp > (uint8_t*)stack_start);

    XtExcFrame* exc_frame = (XtExcFrame*)sp;

    /* Explicitly initialize certain saved registers for call0 ABI */
    exc_frame->pc   = (uint32_t)task_func;         /* task entry point */
    exc_frame->a0   = (uint32_t)task_exit;         /* task exit point*/
    exc_frame->a1   = (uint32_t)sp + XT_STK_FRMSZ; /* physical top of stack frame */
    exc_frame->exit = (uint32_t)_xt_user_exit;     /* user exception exit dispatcher */

    /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
    /* Also set entry point argument parameter. */
    #ifdef __XTENSA_CALL0_ABI__
    /* for CALL0 ABI set in parameter a2 to task argument */
    exc_frame->ps = PS_UM | PS_EXCM;
    exc_frame->a2 = (uint32_t)arg;               /* parameters for task_func */
    #else
    /* for Windowed Register ABI set PS.CALLINC=01 to handle task entry as
       call4 return address in a4 and parameter in a6 and */
    exc_frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
    exc_frame->a4 = (uint32_t)task_exit;         /* task exit point*/
    exc_frame->a6 = (uint32_t)arg;               /* parameters for task_func */
    #endif

    #ifdef XT_USE_SWPRI
    /* Set the initial virtual priority mask value to all 1's. */
    exc_frame->vpri = 0xFFFFFFFF;
    #endif

    #if XCHAL_CP_NUM > 0
    /* Init the coprocessor save area (see xtensa_context.h) */
    /* No access to TCB here, so derive indirectly. Stack growth is top to bottom. */
    /* p = (uint32_t *) xMPUSettings->coproc_area; */

    uint32_t *p;

    p = (uint32_t *)(((uint32_t) top_of_stack+1 - XT_CP_SIZE));
    p[0] = 0;
    p[1] = 0;
    p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN;
    #endif

    /* END - code from FreeRTOS port for Xtensa from Cadence */
    DEBUG("%s start=%p size=%d top=%p sp=%p free=%u\n",
          __func__, stack_start, stack_size, top_of_stack, sp, sp-(uint8_t*)stack_start);
    return (char*)sp;
}