对于低级编程,有时有必要说,在给定的内存位置,这就是我的地址所在。对于这篇文章,示例是PIR1寄存器在PIC16F886和相关的微控制器。它总是在地址0x000C找到的。
我采取了这样的方法:
#define pir1 (*(uint8_t*)0xc)现在,我可以用类似于pir1 |= 0x40的东西给变量赋值(好的,我会使用一个#定义的常量,而不是神奇的数字,但是你得到了我的漂移)。这在GCC上编译得很好,即使我使用-Wextra -Wall也没有警告。为了验证我的假设,GCC说出了下面的x86_64:
movl $12, %eax
movb $64, (%rax)这正是我想要的(好吧,我现在知道为什么它是eax,而rax是另一个,这可能是另一个愚蠢的x86怪癖,但因为我无论如何都想要PIC14代码)。
现在,为了针对PIC14,我实际上使用了SDCC编译器。我是这样引用它的
sdcc --std-c99 -mpic14 -p16f886 --use-non-free source.c上面以#define开头的代码提供了以下警告:
source.c:412: warning 88: cast of LITERAL value to 'generic' pointer
from type 'const-int literal'
to type 'unsigned-char generic* fixed' 我试过这样做:
__code __at (0xc) uint8_t PIR1;但这会导致错误消息。
error 33: Attempt to assign value to a constant variable (=)当我尝试做一个任务的时候。
所以我的问题是,如果我错过了一种用C语言做这件事的惯用方式?为什么SDCC要警告我?这里是不是有什么特殊的SDCC特定的恐惧我忽略了?
发布于 2021-09-21 11:32:31
关于警告,它可能是编译器中的一个bug。如前所述,您必须使用(volatile uint8_t*)0xc进行内存映射访问。
SDCC中绝对寻址的标准方法是通过编译器扩展,但是您做错了。__code __at (0xc) uint8_t PIR1;将变量放在不可写的代码部分。这就是您看到错误error 33: Attempt to assign value to a constant variable (=)的原因。记住,PIC14使用哈佛架构。如果地址在RAM中,则使用
volatile __data __at (0xc) uint8_t PIR1;如果它在xdata中,那么使用
volatile __xdata __at (0xc) uint8_t PIR1;请参阅文档中的绝对寻址
发布于 2021-09-21 11:23:28
“警告88:将文字值转换为‘泛型’指针”似乎是假阳性。在宏中没有错误的语法或语言。C标准显式地允许这样的转换,参见C17 6.3.2.3/5:
整数可以转换为任何指针类型。除非如前所述,否则结果是实现定义的,可能不会正确对齐,可能不会指向引用类型的实体,而且可能是陷阱表示。
(在这种情况下,对齐和陷阱并不重要。)
一般来说,嵌入式系统编译器,特别是PIC编译器,有着不符合C标准的坏名声,所以你要么必须弄清楚如何禁用坏警告,要么考虑使用不同的编译器。
与警告无关,您也有一个严重的错误,即缺少的volatile。我建议研究一下:如何从固件访问硬件寄存器?
https://stackoverflow.com/questions/69267755
复制相似问题