简体   繁体   English

AVR中的内联汇编

[英]inline assembly in avr

void save_context(uint8_t index) {
    context *this_context = contextArray + index;
    uint8_t *this_stack = this_context->stack;


    asm volatile("st %0 r0":  "r"(this_stack));
}

I have something like this. 我有这样的东西。

!!! !!! I would like to store the registers r0 r1 r2... into my stack[] array. 我想将寄存器r0 r1 r2 ...存储到我的stack []数组中。

What I am programming is the context switch. 我正在编程的是上下文切换。 The context has the structure like this: 上下文具有如下结构:

typedef struct context_t {
   uint8_t stack[THREAD_STACK_SIZE];
   void *pstack;
   struct context_t *next;
}context;

My problem is that I am not able to pass the c variable "this_stack" to inline assembly. 我的问题是我无法将c变量“ this_stack”传递给内联程序集。 My aim is to store all the registers, stack pointer and SREG on my stack. 我的目标是将所有寄存器,堆栈指针和SREG存储在我的堆栈中。

After compiling, it gives error: Description Resource Path Location Type 编译后,它给出错误:描述资源路径位置类型

`,' required    5_multitasking      line 754, external location: C:\Users\Jiadong\AppData\Local\Temp\ccDo7xn3.s C/C++ Problem

I looked up the avr inline assembly tutorial. 我查阅了avr内联汇编教程。 But I don't quite get a lot. 但是我并没有得到很多。 Could anyone help me? 有人可以帮我吗?

"label" makes no sense, that should be a constraint. "label"没有意义,应该是一个约束。 It also makes no sense trying to save the stack pointer into an array. 尝试将堆栈指针保存到数组中也没有任何意义。 It might make sense to load the stack pointer with the address of that array, but that's not the save_context . 用该数组的地址加载堆栈指针可能很有意义,但这不是save_context

Anyway, to get the value of SPL which is the stack pointer you can do something like this: 无论如何,要获取SPL的值(即堆栈指针),您可以执行以下操作:

asm volatile("in %0, %1": "=r" (*this_stack) : "I" (_SFR_IO_ADDR(SPL)));

(There is a q constraint but at least my gcc version doesn't like it.) (有一个q约束,但至少我的gcc版本不喜欢它。)

To get true registers, for example r26 you can do: 要获取真实的寄存器,例如r26您可以执行以下操作:

register uint8_t r26_value __asm__("r26");
asm volatile("": "=r" (r26_value));

There is a constraint, "m", documented in the GCC manual , but it doesn't always work on AVR. 在GCC手册中记录了一个约束“ m”,但它并不总是适用于AVR。 Here is an example of how it should work from sanguino/bootloaders/atmega644p/ATmegaBOOT 这是如何从sanguino / bootloaders / atmega644p / ATmegaBOOT运行的示例

asm volatile("...
    ...
    "sts    %0,r16      \n\t"
    ...
    : "=m" (SPMCSR) : ... );

I have found "m" to be fragile though. 我发现“ m”很脆弱。 If a function uses a variable in C code, outside of the inline assembly, the compiler may choose to place it in the Z register and it will try to use Z in assembler too. 如果函数使用C代码中的变量,则在内联汇编之外,编译器可能会选择将其放置在Z寄存器中,并且也会尝试在汇编器中使用Z。 This causes an assembler error when used with the sts instruction. 与sts指令一起使用时,这将导致汇编程序错误。 Looking at the assembler output from the C compiler is the best way to debug this kind of problem. 查看C编译器的汇编程序输出是调试此类问题的最佳方法。

Rather than using an "m" constraint, you can just put the literal address you want into your assembler code. 无需使用“ m”约束,您只需将所需的文字地址放入汇编代码中即可。 For an example, see pins_teensy.c , where timer_0_fract_count is not included in the : 有关示例,请参见pins_teensy.c ,其中timer_0_fract_count不包括在:

asm volatile(
    ...
    "sts    timer0_fract_count, r24"    "\n\t"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM