3
\$\begingroup\$

I am writing a simple task scheduler for my MSP430F5529 USB launchpad. I need to update stack pointer(SP), then enable interrupts and then update program counter (PC). But I am getting an error with my inline assembly code.

void start_scheduler(void) { asm volatile("mov.w task1stack, SP \n" "EINT \n" "mov.w func1, PC \n" ); } 
  • task1stack is the stack area for the task execution. It is an array.
  • func1 is a function.
  • instead of uppercase for 'SP' and 'PC', I tried lowercase also. But the error was still present.

But with the above code, compiler is showing the following error

kernel.c:(.text+0x8e): undefined reference to `SP' kernel.c:(.text+0x96): undefined reference to `PC' 

Questions:

  1. How to update SP and PC ?
  2. Can "mov.w task1stack, SP \n" copy array address to SP? Is my syntax correct?
  3. Can "mov.w func1, PC \n" copy the func1 address to PC? Is my syntax correct?
\$\endgroup\$
5
  • \$\begingroup\$ Are you sure they should be uppercase? \$\endgroup\$ Commented Mar 24, 2014 at 0:10
  • \$\begingroup\$ I tried lowercase and it was the same situation \$\endgroup\$ Commented Mar 24, 2014 at 0:20
  • \$\begingroup\$ I don't know about the MSP430 specifically, but on most CPUs, "move to PC" is called "jump" or "branch" (or sometimes "call" or "return"). \$\endgroup\$ Commented Mar 24, 2014 at 0:30
  • 1
    \$\begingroup\$ Whose tool are you using? I think it may be important. gcc tools use AT&T syntax, not TI's or IAR's. \$\endgroup\$ Commented Mar 24, 2014 at 0:41
  • \$\begingroup\$ I am using msp430-gcc \$\endgroup\$ Commented Mar 24, 2014 at 5:43

1 Answer 1

4
\$\begingroup\$

Mainly out of idle curiosity, I looked up how FreeRTOS handles context switching. They define two macros to handle this as follows. Perhaps this will offer some clues about the syntax. Evidently, the stack pointer is known as "r1".

From MSP430 CPU:

The processor contains 16 16-bit registers, of which 4 are dedicated to special purposes: R0 is the program counter, R1 is the stack pointer, R2 is the status register, and R3 is a special register called the constant generator, providing access to 6 commonly used constant values without requiring an additional operand. R3 always reads as 0 and writes to it are ignored. R4 through R15 are available for general use.

/* * Macro to save a task context to the task stack. This simply pushes all the * general purpose msp430 registers onto the stack, followed by the * usCriticalNesting value used by the task. Finally the resultant stack * pointer value is saved into the task control block so it can be retrieved * the next time the task executes. */ #define portSAVE_CONTEXT() \ asm volatile ( "push r4 \n\t" \ "push r5 \n\t" \ "push r6 \n\t" \ "push r7 \n\t" \ "push r8 \n\t" \ "push r9 \n\t" \ "push r10 \n\t" \ "push r11 \n\t" \ "push r12 \n\t" \ "push r13 \n\t" \ "push r14 \n\t" \ "push r15 \n\t" \ "mov.w usCriticalNesting, r14 \n\t" \ "push r14 \n\t" \ "mov.w pxCurrentTCB, r12 \n\t" \ "mov.w r1, @r12 \n\t" \ ); /* * Macro to restore a task context from the task stack. This is effectively * the reverse of portSAVE_CONTEXT(). First the stack pointer value is * loaded from the task control block. Next the value for usCriticalNesting * used by the task is retrieved from the stack - followed by the value of all * the general purpose msp430 registers. * * The bic instruction ensures there are no low power bits set in the status * register that is about to be popped from the stack. */ #define portRESTORE_CONTEXT() \ asm volatile ( "mov.w pxCurrentTCB, r12 \n\t" \ "mov.w @r12, r1 \n\t" \ "pop r15 \n\t" \ "mov.w r15, usCriticalNesting \n\t" \ "pop r15 \n\t" \ "pop r14 \n\t" \ "pop r13 \n\t" \ "pop r12 \n\t" \ "pop r11 \n\t" \ "pop r10 \n\t" \ "pop r9 \n\t" \ "pop r8 \n\t" \ "pop r7 \n\t" \ "pop r6 \n\t" \ "pop r5 \n\t" \ "pop r4 \n\t" \ "bic #(0xf0),0(r1) \n\t" \ "reti \n\t" \ ); 
\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.