This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

请教关于MSP430 inline ASM 的问题

由于在后台程序和中断程序中都使用了MSP430 的硬件乘法器,于是使用一下保存和恢复寄存器,但是编译过程报错( Illegal mnemonic specified),请问如何解决?

 

/* PUSH Multiplier Register */

//   asm("PUSH.W &MPY32CTL0");

//   asm("PUSH.W &RES1;");

//   asm("PUSH.W &RES0;");

//   asm("PUSH.W &MPY32L;");

//   asm("PUSH.W &OP2L;");

 

……   // ISR code

 

   /* POP Multiplier Register */

//   asm("POP.W  &OP2L");  

//   asm("POP.W  &MPY32L");

//   asm("POP.W  &RES0");

//   asm("POP.W  &RES1");

//   asm("POP.W  &MPY32CTL0");

 

 

  • 您好,

    请问您使用CCS吧?

    以asm("PUSH.W &MPY32L");为例

    在"和PUSH之间加一个Tab,即:

    asm("    PUSH.W &MPY32L");

  • Hi 蝈蝈,

    如您所说,修改后。之前的非法助记符的错误不在提示,取而代之是一下错误? 我是用的是 CCSv4 MSP430 CGT4.0

    "C:\DOCUME~1\MS\LOCALS~1\Temp\0717210", ERROR!   at EOF: [E0300] The following

                                                                    symbols are

                                                                    undefined:

    1 Assembly Error, No Assembly Warnings

     MPY32CTL0

    Errors in Source - Assembler Aborted

    >> Compilation failure

    gmake: *** [source/Interrupt_Handler_DRV92250.obj] Error 1

  • 您好,

    错误提示是说MPY32CTL0没有定义,去头文件中看看硬件乘法器的控制0寄存器是怎么定义的。

  • SFR_16BIT(MPY32CTL0);                         /* MPY32 Control Register 0 */

  • SFR_16BIT(MPY32CTL0);                         /* MPY32 Control Register 0 */

    头文件使用的是ti提供的头文件,包含了对该寄存器的定义,但是仍旧无法识别。

  • MPY32CTL0在C的头文件中定义了,但是在汇编中没有不认识。有以下两种处理办法:

    1、可以将这部分汇编代码放到一个asm文件中,调用汇编函数。

    2、从User's Guide中查MPY32CTL0的地址,直接对地址操作。

    以下是我从TI的e2e中查找的类似的问题,他提供了一种方式,但是我做实验还是报错,供参考:

    P1DIR is actually a C variable that happens to reside right on top of the P1DIR register.

    On assembly level, P1DIR is unknown.

    Usually, since the position of P1DIR is known at compile time, the compiler will not forward a variable of this name to the linker for later linking. It will use the direct location instead when generating the assembly level code.

    In an assembly file, you'd include a different header, where P1DIR would be just a number. But both ways won't help you on inline assembly.

    The mspgcc compiler uses an extended syntax for inline assembly. You code would look like that:

    asm(" bis.b #0x01, %0":"=m"(P1DIR):);

    This tells the compiler that the placeholder %0 is a destination memory location that is associated with the content of the variable P1DIR. Since P1DIR has a fixed memory location, it will generate an instruction like "bis.b #0x01, &0x200".. However, if P1DIR is a local variable on stack something like "bis.b #0x01, 0x02(SP)" will be generated. And if it is a register variable, it will be put on stack first.

    If your code requires a register rather than memory, a "=r" will tell the compiler that your ASM instruction is returning something in a register, and will take it and put it into P1DIR. The compiler will choose the register 8one it doesn't need) and insert it into the instruction.

    A really smart way to do things - just not easy to understand by the existing documentation.

    Whether the comiler you use has something similar, or maybe other means to provide a C variable's location to assembly code, should be written in the compiler documentation.

    E.g. you might add the symbol value for P1DIR to the linker script file, so the liker will find it and put it into the assembly instruction at link stage.

    Or it may be that the compiler provides assembly-level symbols like _P1DIR for the C variables. It depends on the compiler.

  • 使用以下程序,编译后,查看汇编程序,发现汇编正确,但是程序不跑了,也不产生中断了。不知道是不是栈溢出了。CCSv4下如何设置堆栈深度,我可以做个实验试试。

    请问有没有中断保存 硬件乘法器 寄存器 的程序? 以下的是参考 430 5X UG 写的,但是实验却不成功,出现上述问题。

    #pragma vector = TIMER0_B0_VECTOR        // 53

    interrupt void MainISR_TB0(void)

    {

    //   /* PUSH Multiplier Register */

    asm(" PUSH.W &0x04ec ;PUSH.W &MPY32CTL0 ");

    asm(" PUSH.W &0x04e6 ;PUSH.W &RES1  ");

    asm(" PUSH.W &0x04e4 ;PUSH.W &RES0 ");

    asm(" PUSH.W &0x04d0 ;PUSH.W &MPY32L ");

    asm(" PUSH.W &0x04e0 ;PUSH.W &OP2L ");

      /* Enable all maskable interrupts */

      _enable_interrupt();

    …… // ISR routine

    _disable_interrupt();

    /* POP Multiplier Register */

    asm(" POP.W &0x04e0 ;PUSH.W &OP2L ");

    asm(" POP.W &0x04d0 ;PUSH.W &MPY32L ");

    asm(" POP.W &0x04e4 ;PUSH.W &RES0 ");

    asm(" POP.W &0x04e6 ;PUSH.W &RES1  ");

    asm(" POP.W &0x04ec ;PUSH.W &MPY32CTL0 ");

    }

  • 设置堆栈大小:右键点击工程文件,选择build properties,点击Linker下的Basic Options。如图所示

     

  • 总结一下这个问题:

           去除了堆栈溢出的问题后,可以保护实现乘法器的值的出入栈,证明 asm(" POP.W &0x04e4  ;PUSH.W &RES0 ") 这样的方法是可行的。

    thx~

  • Billy Lan,

    您好,非常感谢您对于这个问题的回复和总结!

    很欣赏您这种负责任的态度!

    谢谢!