如何将变量放在SDCC中的特定内存位置

6tr1vspr  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(124)

对于低级编程,有时有必要说,在给定的内存位置,这是我的地址。对于这篇文章,示例是PIC 16F886和相关微控制器中的PIR1寄存器。它总是在地址0x000C处找到。
我采取了这样的方法:

#define pir1 (*(uint8_t*)0xc)

字符串
现在我可以用类似pir1 |= 0x40的东西赋值给变量(好吧,我会使用#defined常量而不是幻数,但你会得到我的漂移)。这在GCC上编译得很好,即使我使用-Wextra -Wall也没有警告。为了检查我的假设,GCC吐出以下x86_64:

movl    $12, %eax
movb    $64, (%rax)


正是我想要的(好吧,我不知道为什么一会儿是eax,一会儿是rax,这可能是另一个愚蠢的x86怪癖,但无关紧要,因为我想要PIC 14代码)
现在,为了针对PIC 14,我实际上使用了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特定的恐惧,我忽略了这里?

irlmq6kh

irlmq6kh1#

关于警告,这可能是编译器中的一个bug。
SDCC中绝对寻址的标准方法是通过编译器扩展,但您这样做是错误的。__code __at (0xc) uint8_t PIR1;将变量放在不可写的代码段中。这就是为什么您会看到错误error 33: Attempt to assign value to a constant variable (=)。请记住PIC 14使用哈佛架构。如果地址在RAM中,则使用

volatile __data __at (0xc) uint8_t PIR1;

字符串
如果在扩展数据中,则使用

volatile __xdata __at (0xc) uint8_t PIR1;


请参见文档中的绝对寻址
Godbolt演示

aiqt4smr

aiqt4smr2#

“警告88:将LITERAL值转换为'generic'指针”似乎是一个误报。您的宏在语法或语言方面没有任何错误。C标准明确允许此类转换,请参阅C17 6.3.2.3/5:
一个整数可以被转换为任何指针类型。除了前面指定的,结果是实现定义的,可能没有正确对齐,可能没有指向引用类型的实体,并且可能是一个陷阱表示。
(在这种情况下,对齐和陷阱无关紧要。)
一般来说,嵌入式系统编译器,特别是PIC编译器,都有不符合标准C的坏名声,所以你要么必须弄清楚如何禁用坏警告,要么考虑使用不同的编译器。
与警告无关,您还有一个严重的bug,即缺少volatile

相关问题