通过指向 avr 程序集中数组的指针访问数组
我正在使用 C 和 ASM 混合编程 AVR 微控制器,但遇到了一些麻烦。
我的 C 代码中有以下代码:
uint8_t amplitudes32[32] = {.. constant values ..};
uint8_t amplitudes64[64] = {.. constant values ..}
uint8_t* amplitudes;
(amplitudes32/64 基本上是查找表)
有时我希望振幅等于amplitudes32,有时希望它等于amplitudes64。
我通过
在我的 c 代码中使用 amplitudes =amplitudes32;
来完成此操作。
然后,在我的 ASM 中断例程中,我想像这样读入数组的地址:
ldi r30, lo8(amplitudes)
ldi r31, hi8(amplitudes)
然后,我执行更多指令以将特定索引处的数组值获取到特定端口。但是,当我检查输出时,它无法正常工作,并且得到了我不期望的结果。无论数组由什么组成,我都会得到相同的结果。即使当amplitudes指向全零的数组时,它也是相同的。
如果我将汇编代码更改为
ldi r30, lo8(amplitudes64)
ldi r31, hi8(amplitudes64)
那么它会按预期工作。但就像我说的,我需要在不同的时间有一个不同的查找表,并且由于速度问题,我无法在中断例程中做出这个决定,所以如果我可以有一个数组“变量”,那就太好了可以更改中断随后使用的 C 代码。
我做错了什么?
I'm programming an AVR microcontroller using a mix of C and ASM but I'm having a bit of trouble.
I have the following code in my C code:
uint8_t amplitudes32[32] = {.. constant values ..};
uint8_t amplitudes64[64] = {.. constant values ..}
uint8_t* amplitudes;
(amplitudes32/64 are basically look up tables)
And some times I want amplitudes to be equal to amplitudes32 and sometimes want it to be equal to amplitudes64.
I'm doing this by going
amplitudes = amplitudes32;
in my c code.
Then, in my ASM interrupt routine I want to read in the address of the array like this:
ldi r30, lo8(amplitudes)
ldi r31, hi8(amplitudes)
I then do some more instructions to get the value of the array at a certain index out to a particular port. However, when I check the output it's not working properly and I get something I'm not expecting. I get the same thing no matter what the array is made up of.. it's the same even when amplitudes
is pointing to an array of all zeros.
If I change the assembly code to
ldi r30, lo8(amplitudes64)
ldi r31, hi8(amplitudes64)
Then it works as expected. But like I said, I need to have a different look up table at different times and because of speed issues I can't make that decision within the interrupt routine so it'd be nice if I could have an array 'variable' that I could change in my C code which the interrupt then uses.
What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我对 AVR 组装不太熟悉。但是,我相信 lo8 和 hi8 宏返回所提供变量的低/高地址 - 在传递amplitudes64的情况下,您将使用填写r30/r31 >您的 64 个条目表的地址——正是您想要的。但是,如果您传入幅度,您将获取指针的地址,这可能不是您想要的。 (幅度变量需要取消引用才能返回原始表。)
由于取消引用变量在微控制器中通常相对较慢(尤其是在时间敏感的中断内),因此我强烈建议您重新组织代码以具有单个用于在两个表之间进行选择的布尔标志。例如:
最终结果应该只是一个额外的分支指令——可能比取消引用幅度指针的额外时间更快。或者,您可以尝试将两个查找表合并到一个 96 字节表中,然后相应地调整索引。和以前一样,您仍然可以在中断之外执行耗时的决定来使用哪个表(通过修改 C 代码中的标志),以便让中断保持快速和高效。
I'm not intimately familiar with AVR assembly. However, I believe that the lo8 and hi8 macros are returning the low/high address of the supplied variable-- In the case of passing in amplitudes64, you'll fill out r30/r31 with the address of your 64 entry table-- exactly what you want. However, if you pass in amplitudes, you are taking the address of the pointer, which is likely not what you want. (The amplitudes variable would need to be dereferenced to get back to the original table.)
Since dereferencing variables is often comparatively slow in a microcontroller (especially within a time-sensitive interrupt), I strongly suggest that you reorganize your code to have a single boolean flag to select between the two tables. For example:
The end result of this should be just one extra branch instruction-- likely faster than the extra time to dereference the amplitude pointer. Alternatively, you could try merging both lookup tables into one 96 byte table, and just adjust your index accordingly. As before, you can still perform the time consuming decision of which table to use outside of the interrupt (by modifying the flag within your C code), so as to allow the interrupt to remain fast and efficient.