davarm wrote:How do I write the equivalent of 'sthx Current->StackPtr' and 'ldhx Current->StackPtr' in assembly language?
// ****************************************************************************#define MAX_TASKS 8#define STACK_DEPTH 30#define SIZEOF_SWITCH_STACK_DROP 6// ****************************************************************************typedef struct TCB{ char *StackPtr; struct TCB *Next; struct TCB *Prev; char Stack[STACK_DEPTH]; // stack int Task; // address of task function};struct TCB *Head;struct TCB *Tail;struct TCB *CurrentTask;// ****************************************************************************void TaskCreate(void (*Task)()) { struct TCB *NewTCB = NULL; NewTCB = malloc(sizeof(struct TCB)); if (NewTCB == NULL) { return; } // save the task address so TaskDestroy can find it NewTCB->Task = (int)Task; // put the task on the stack *(int*)((NewTCB->Stack) + (STACK_DEPTH - 2)) = (int)Task; // load the stack pointer accounting for the rti in the task switch NewTCB->StackPtr = (NewTCB->Stack) + (STACK_DEPTH - SIZEOF_SWITCH_STACK_DROP); // if this is the first element in the list if (Head == NULL) { // make it point to itself Head = NewTCB; Tail = NewTCB; // this is the first task to run // so load CurrentTask with this TCB CurrentTask = NewTCB; } // make all the linked list pointers point to the right things NewTCB->Prev = Tail; Tail->Next = NewTCB; NewTCB->Next = Head; Tail = NewTCB;}// ****************************************************************************void TaskDestroy(void (*Task)()){ struct TCB *TCBItem = Head; do { if ((int)Task == TCBItem->Task) { TCBItem->Prev->Next = TCBItem->Next; TCBItem->Next->Prev = TCBItem->Prev; free(TCBItem); return; } } while (TCBItem->Next != Head);}// ****************************************************************************ISR(TaskTimerInt_Interrupt){ /* RTCSC: RTIF=1 */ setReg8Bits(RTCSC, 0x80); /* Reset real-time counter request flag */ // No need to pshh since this C function has already done it // Save the current stack pointer in CurrentTask->StackPtr __asm tsx; // save the SP in H:X __asm pshx; // push SP low byte __asm pshh; // push SP high byte __asm ldhx CurrentTask; // load the address of CurrentTask __asm pula; // pull the top value from the stack in A __asm sta , x; // store A (really H) where H:X is pointing (CurrentTask->StackPtr) __asm pula; // pull the top value from the stack __asm sta 1, x; // store A (really X) where H:X + 1 is pointing (CurrentTask->StackPtr + 1) // Now point to the next node in the task linked list __asm ldhx CurrentTask; // load H:X with the address of CurrentTask __asm aix #2; // add 2 to equal the location of Current->Next __asm ldhx , x // load H:X with what is pointed to by CurrentTask __asm sthx CurrentTask; // store the address of the next task in CurrentTask // H:X already has the address of CurrentTask in them // Load the next task's stack pointer __asm ldhx ,x // load what is pointed to by H:X which is Current->StackPtr __asm txs; // store H:X into the SP __asm pulh; // pull H __asm rti; // return from interrupt}// ****************************************************************************void main(void){ /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/ PE_low_level_init(); /*** End of Processor Expert internal initialization. ***/ Head = NULL; TaskCreate(Task1); TaskCreate(Task2); // simulate a task switch // this is the exact code as at the end of the ISR __asm ldhx CurrentTask; // load H:X with the address of CurrentTask __asm ldhx , x // load H:X what is pointed to by CurrentTask which is the StackPtr __asm txs; // transfer H:X to stack pointer register __asm pulh // pulh to emulate the task switch code __asm rti; // return from interrupt, i.e. execute the task}// ****************************************************************************
// Now point to the next node in the task linked list >>> __asm ldhx 2,x // load H:X with what is pointed to by CurrentTask __asm sthx CurrentTask; // store the address of the next task in CurrentTask