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'


  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?
  • \$\begingroup\$ Are you sure they should be uppercase? \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 24 '14 at 0:10
  • \$\begingroup\$ I tried lowercase and it was the same situation \$\endgroup\$ – robomon Mar 24 '14 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\$ – Dave Tweed Mar 24 '14 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\$ – jonk Mar 24 '14 at 0:41
  • \$\begingroup\$ I am using msp430-gcc \$\endgroup\$ – robomon Mar 24 '14 at 5:43

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"    \

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.