//--------------------------------------------------------------------------- void ThreadPort_InitStack(Thread_t *pstThread_) { // Initialize the stack for a Thread_t K_USHORT usAddr; K_UCHAR *pucStack; K_USHORT i; // Get the address of the thread's entry function usAddr = (K_USHORT)(pstThread_->pfEntryPoint); // Start by finding the bottom of the stack pucStack = (K_UCHAR*)pstThread_->pwStackTop; // clear the stack, and initialize it to a known-default value (easier // to debug when things go sour with stack corruption or overflow) for (i = 0; i < pstThread_->usStackSize; i++) { pstThread_->pwStack[i] = 0xFF; } // Our context starts with the entry function PUSH_TO_STACK(pucStack, (K_UCHAR)(usAddr & 0x00FF)); PUSH_TO_STACK(pucStack, (K_UCHAR)((usAddr >> 8) & 0x00FF)); // R0 PUSH_TO_STACK(pucStack, 0x00); // R0 // Push status register and R1 (which is used as a constant zero) PUSH_TO_STACK(pucStack, 0x80); // SR PUSH_TO_STACK(pucStack, 0x00); // R1 // Push other registers for (i = 2; i <= 23; i++) //R2-R23 { PUSH_TO_STACK(pucStack, i); } // Assume that the argument is the only stack variable PUSH_TO_STACK(pucStack, (K_UCHAR)(((K_USHORT)(pstThread_->pvArg)) & 0x00FF)); //R24 PUSH_TO_STACK(pucStack, (K_UCHAR)((((K_USHORT)(pstThread_->pvArg))>>8) & 0x00FF)); //R25 // Push the rest of the registers in the context for (i = 26; i <=31; i++) { PUSH_TO_STACK(pucStack, i); } // Set the top o' the stack. pstThread_->pwStackTop = (K_UCHAR*)pucStack; // That's it! the thread is ready to run now. }
void push_nav(QSP_ARG_DECL Gen_Win *gwp) { Gen_Win *current_gwp; // We can push a viewer or anything!? //assert( GW_TYPE(NAVP_GW(np_p)) == GW_NAV_PANEL ); if( nav_stack == NULL ) nav_stack = new_stack(); // We need to keep a stack of panels... if( (current_gwp=TOP_OF_STACK(nav_stack)) != NULL ){ unshow_genwin(QSP_ARG current_gwp); } PUSH_TO_STACK(nav_stack,gwp); //fprintf(stderr,"showing associated panel %s\n",PO_NAME(NAVP_PANEL(gwp))); show_genwin(QSP_ARG gwp); }
/* 1) Setting up the Thread_t stacks Stack consists of 2 separate frames mashed together. a) Exception Stack Frame Contains the 8 registers the CPU pushes/pops to/from the stack on execution of an exception: [ XPSR ] [ PC ] [ LR ] [ R12 ] [ R3 ] [ R2 ] [ R1 ] [ R0 ] XPSR - Needs to be set to 0x01000000; the "T" bit (thumb) must be set for any Thread_t executing on an ARMv6-m processor PC - Should be set with the initial entry point for the Thread_t LR - The base link register. We can leave this as 0, and set to 0xD on first context switch to tell the CPU to resume execution using the stack pointer held in the PSP as the regular stack. This is done by the CPU automagically- this format is part of the architecture, and there's nothing we can do to change or modify it. b) "Other" Register Context [ R11 ] ... [ R4 ] These are the other GP registers that need to be backed up/restored on a context switch, but aren't by default on a CM0 exception. If there were any additional hardware registers to back up, then we'd also have to include them in this part of the context. These all need to be manually pushed to the stack on stack creation, and puhsed/pop as part of a normal context switch. */ void ThreadPort_InitStack(Thread_t *pclThread_) { K_ULONG *pulStack; K_ULONG *pulTemp; K_ULONG ulAddr; K_USHORT i; // Get the entrypoint for the Thread_t ulAddr = (K_ULONG)(pclThread_->pfEntryPoint); // Get the top-of-stack pointer for the Thread_t pulStack = (K_ULONG*)pclThread_->pwStackTop; // Initialize the stack to all FF's to aid in stack depth checking pulTemp = (K_ULONG*)pclThread_->pwStack; for (i = 0; i < pclThread_->usStackSize / sizeof(K_ULONG); i++) { pulTemp[i] = 0xFFFFFFFF; } PUSH_TO_STACK(pulStack, 0); // We need one word of padding, apparently... //-- Simulated Exception Stack Frame -- PUSH_TO_STACK(pulStack, 0x01000000); // XSPR PUSH_TO_STACK(pulStack, ulAddr); // PC PUSH_TO_STACK(pulStack, 0); // LR PUSH_TO_STACK(pulStack, 0x12); PUSH_TO_STACK(pulStack, 0x3); PUSH_TO_STACK(pulStack, 0x2); PUSH_TO_STACK(pulStack, 0x1); PUSH_TO_STACK(pulStack, (K_ULONG)pclThread_->pvArg); // R0 = argument //-- Simulated Manually-Stacked Registers -- PUSH_TO_STACK(pulStack, 0x11); PUSH_TO_STACK(pulStack, 0x10); PUSH_TO_STACK(pulStack, 0x09); PUSH_TO_STACK(pulStack, 0x08); PUSH_TO_STACK(pulStack, 0x07); PUSH_TO_STACK(pulStack, 0x06); PUSH_TO_STACK(pulStack, 0x05); PUSH_TO_STACK(pulStack, 0x04); pulStack++; pclThread_->pwStackTop = pulStack; }