如何在指针中处理 8051 XDATA 内存空间?
How 8051 XDATA memory spaces are handled in pointers?
我正在为包含 8051 内核的 Cypress EZ-USB FX2LP 开发,我使用 SDCC 进行编译。
我注意到我可以(有时?)省略指针的 __xdata
注释,即使使用指向 XDATA 区域的指针,我的固件仍然 运行 正常。
例如,它可以通过以下声明编译和执行:
uint16_t crc16(const uint8_t *data, uint8_t len);
而不是
uint16_t crc16(__xdata const uint8_t *data, uint8_t len);
据我了解,XDATA 是 16 位可寻址的,而 DATA 是 8 位可寻址的。当 SDCC 编译器可以指向 XDATA 时,它们是否会自动将指针提升为 16 位?
"generic" 类型的指针不必与显式 "section" 指针具有相同的位宽是正确的。但是编译器通常不会提升指针。
正如您在评论中透露的那样,您的项目使用 medium
数据模型在 PDATA 部分分配变量。
PDATA段与硬件的XDATA段相同,需要16位地址。但是,它由 8 位指针访问(R0
和 R1
在处理器级别)。地址的上半部分来自 SFR P2
。在其 "normal" 生命周期中,P2
用于存储端口 2 的值。但是如果连接外部存储器,端口 P2 将用于寻址该存储器所需的高位,它是多路复用的.所以 SFR 对于这种用法是免费的。
注1:AFAIR,如果不使用外部代码存储器,您甚至可以拆分端口,使用少于8位的地址存储器,并将剩余位保留为端口位.如果使用外部代码,所有端口 P2 将用于输出程序计数器的上半部分。请务必了解所有含义!
P2
的初始值为0xFF
(对于"all pins are inputs"),但是SDCC的启动代码用0x00
初始化了它。所以一不小心,你访问了外部存储器的前256个字节。
要访问其他"pages"(这是PDATA中的"P",意思是"paged data")你只需在读取或写入之前将它们的高地址位写入P2
.
注意 2:一些库函数可能足够聪明,如果它们越过页面边界就可以更改 P2
。在使用这个之前,请确保它是这样的!
我正在为包含 8051 内核的 Cypress EZ-USB FX2LP 开发,我使用 SDCC 进行编译。
我注意到我可以(有时?)省略指针的 __xdata
注释,即使使用指向 XDATA 区域的指针,我的固件仍然 运行 正常。
例如,它可以通过以下声明编译和执行:
uint16_t crc16(const uint8_t *data, uint8_t len);
而不是
uint16_t crc16(__xdata const uint8_t *data, uint8_t len);
据我了解,XDATA 是 16 位可寻址的,而 DATA 是 8 位可寻址的。当 SDCC 编译器可以指向 XDATA 时,它们是否会自动将指针提升为 16 位?
"generic" 类型的指针不必与显式 "section" 指针具有相同的位宽是正确的。但是编译器通常不会提升指针。
正如您在评论中透露的那样,您的项目使用 medium
数据模型在 PDATA 部分分配变量。
PDATA段与硬件的XDATA段相同,需要16位地址。但是,它由 8 位指针访问(R0
和 R1
在处理器级别)。地址的上半部分来自 SFR P2
。在其 "normal" 生命周期中,P2
用于存储端口 2 的值。但是如果连接外部存储器,端口 P2 将用于寻址该存储器所需的高位,它是多路复用的.所以 SFR 对于这种用法是免费的。
注1:AFAIR,如果不使用外部代码存储器,您甚至可以拆分端口,使用少于8位的地址存储器,并将剩余位保留为端口位.如果使用外部代码,所有端口 P2 将用于输出程序计数器的上半部分。请务必了解所有含义!
P2
的初始值为0xFF
(对于"all pins are inputs"),但是SDCC的启动代码用0x00
初始化了它。所以一不小心,你访问了外部存储器的前256个字节。
要访问其他"pages"(这是PDATA中的"P",意思是"paged data")你只需在读取或写入之前将它们的高地址位写入P2
.
注意 2:一些库函数可能足够聪明,如果它们越过页面边界就可以更改 P2
。在使用这个之前,请确保它是这样的!