Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | /* * Copyright (c) 2016 Cadence Design Systems, Inc. * SPDX-License-Identifier: Apache-2.0 */ #ifdef CONFIG_INIT_STACKS #include <string.h> #endif /* CONFIG_INIT_STACKS */ #ifdef CONFIG_DEBUG #include <misc/printk.h> #endif #include <kernel_structs.h> #include <wait_q.h> #include <xtensa_config.h> #include <kernel_internal.h> extern void _xt_user_exit(void); /* * @brief Initialize a new thread * * Any coprocessor context data is put at the lower address of the stack. An * initial context, to be "restored" by __return_from_coop(), is put at * the other end of the stack, and thus reusable by the stack when not * needed anymore. * * The initial context is a basic stack frame that contains arguments for * _thread_entry() return address, that points at _thread_entry() * and status register. * * <options> is currently unused. * * @param thread pointer to k_thread memory * @param pStackmem the pointer to aligned stack memory * @param stackSize the stack size in bytes * @param pEntry thread entry point routine * @param p1 first param to entry point * @param p2 second param to entry point * @param p3 third param to entry point * @param priority thread priority * @param options is unused (saved for future expansion) * * @return N/A */ void _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 = K_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 _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 */ memset(cpStack, 0, XT_CP_ASA); /* Set to zero to avoid bad surprises */ /* 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)_thread_entry; /* physical top of stack frame */ pInitCtx->a1 = (u32_t)pInitCtx + XT_STK_FRMSZ; /* user exception exit dispatcher */ pInitCtx->exit = (u32_t)_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 */ } |