您正在描述的数据(使用程序存储器全24位存储数据)无法在C中定义和初始化,也无法通过C直接读取;访问它的唯一方法是通过封装在C调用的汇编函数或内部函数中。
这里确实有两个问题:
如何与编译器,汇编器和链接器配合使用,以便当您在汇编文件中将24位数据定义为具有符号名的可重定位数据D1
,而不是固定地址处的未命名数据时,编译器可以看到此变量确定其地址
如何访问数据
所述第二质询(如何访问数据)被应答了33EP份DS70613C并应在回答为33FJ份DS70204C(但在33FJ示例手册只使用低16位)。这是33EP参考手册中的示例代码片段,适用于33EP零件+应该适用于33FJ(我没有容易获得的33FJ设备):
(注意:代码使用int
,而使用uint16_t
和会更好#include <stdint.h>
)
int prog_data[10] __attribute__((space(prog))) =
{0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999};
unsigned int lowWord[10], highWord[10];
unsigned int tableOffset, loopCount;
int main(void){
TBLPAG = __builtin_tblpage (prog_data);
tableOffset = __builtin_tbloffset (prog_data);
/* Read all 10 constants into the lowWord and highWord arrays */
for (loopCount = 0; loopCount < 10; loopCount ++)
{
lowWord[loopCount] = __builtin_tblrdl (tableOffset);
highWord[loopCount] = __builtin_tblrdh (tableOffset);
tableOffset +=2;
}
while(1)
;
}
您会注意到,内置函数__builtin_tblrdl()
和__builtin_tblrdh()
用于从程序存储器位置读取数据的低16位字和高16位字,并且 __builtin_tblpage() and __builtin_tbloffset()
可以用于提取地址的页和偏移量。在此特定示例中,highWord数组始终为0,lowowWord数组与在C中定义和初始化的prog_data相匹配。
请注意,此处不使用任何指针!尽管可以使用带有标记的普通变量const
,以便链接器将其定位在只读程序空间中,以便您可以使用标准C指针技术读取内存,而编译器会自动管理分页寄存器对您来说,您只能存储16位数据。您需要访问TBLRDL和TBLRDH内置函数来获取所有24位数据。
至于如何很好地使用编译器/链接器/等,您必须欺骗编译器并告诉它它仅看到16位数据。这是一个示例,用于获取在其他地方声明的变量D1:
#define D1_SIZE 18
extern uint16_t __attribute__((space(prog))) D1[D1_SIZE];
#define READ_DATA(dst, v, len) readData(dst, __builtin_tblpage(v), __builtin_tbloffset(v), len)
void readData(uint32_t *pdst, uint16_t page, uint16_t offset, uint16_t len)
{
TBLPAG = page;
while (len-- > 0)
{
uint16_t lo = __builtin_tblrdl (offset);
uint16_t hi = __builtin_tblrdh (offset);
*pdst++ = (((uint32_t)(hi)) << 16) | ((uint32_t)(lo));
offset += 2;
}
}
...
uint32_t d1copy[D1_SIZE];
READ_DATA(d1copy, D1, D1_SIZE);
这样可以正确读取24位值并将其存储在uint32_t的低24位中。在C中声明的extern D1变量是一个虚拟变量,仅通过利用编译器/汇编器/链接器的协同工作方式来获取起始地址。内置函数处理其余工作。
我不知道如何自动获取数据的大小,因为它是在程序集中定义和初始化的。