【发布时间】:2019-07-18 18:31:42
【问题描述】:
我正在使用STVD IDE 和Cosmic C 编译器在STM8S 上开发一个嵌入式应用程序。我正在尝试逐字节读取闪存以计算CRC。以下是我的代码 sn-p:
uint32_t crc32_buffer(const uint8_t *buf, uint32_t len)
{
uint32_t index = 0;
uint32_t crc = 0xFFFFFFFF;
uint32_t flashIndex = 0;
uint8_t *ptr = buf;
volatile uint8_t value = 0;
volatile uint8_t i = 0;
for (index = 0; index < len; index++)
{
value = *ptr;
flashIndex = (crc & 0xFF) ^ value;
ptr++;
crc = (crc >> 8) ^ table[flashIndex];
if(bytesCntr >= 2685)
{
i++;
}
}
return ~crc;
}
在从 FLASH 读取 2694 字节之前,代码工作正常。在调试会话中查看Memory,我确保FLASH 中的下一个字节的值为0C。检查ptr 的值,我确保它在FLASH 中有这个0C 字节的地址(即0x8B15)。但是,在取消引用 ptr 后,value 变量总是得到 8B 的值,而不是 0C。
我也尝试排除不必要的变量,所以它是这样的:
crc = (crc >> 8) ^ table[(crc & 0xFF) ^ buf[index]];
但是表索引不是应该的,因为内存位置被读取为8B而不是0C。
我发现地址0x8B15之前的字节和之后的字节被正确读取。只有这个地址读错了。
UPDATE-1
value = *ptr;的反汇编如下:
LDW X, (0x11,SP)
LD A, (X)
LD (0x13,SP),A
在读取地址0x8B15 的字节时,如果我在第二条装配线设置断点,然后内存位置中的值被正确读取为0C。但是,如果我将断点放在第三条装配线,我发现寄存器X 有0x8B15(正确的地址),但寄存器A 有0x8B(错误的值)。
UPDATE-2
我在for 循环中添加了一个if 语句用于调试(放置我的断点)。我发现错误读取的内存字节中保存的代码始终是该if语句中的代码。这段代码的反汇编总是和SP有关。即使我更改了代码,有问题的内存字节始终是if 语句中的第一条指令。而且我还注意到错误的读取值总是0x8B,无论什么是正确的值。这是保存在这个内存位置的反汇编:
0x8b15 <crc32_buffer+104> 0x0C01 INC (0x01,SP) INC (_CRC_ONGOING_s,SP)
【问题讨论】:
-
可能不相关,但您可能需要声明
const uint8_t *ptr = buf;,以消除警告。 -
你的一个截图提到了
unsigned char near *。这实际上是一个分段架构吗? near 指针不能跨越段边界,因此这可能与您的问题有关。 -
@SteveSummit 你能解释一下你的意思吗?
-
好的,我不明白你的评论。我敢打赌闪存中存在冲突:您正在并行执行和读取同一地址。 MCU不支持它我不会感到惊讶。您可以尝试在与 CRC 函数不同的内存区域上计算 CRC。
-
STM8 具有哈佛架构,这意味着对指令和数据的访问是通过 2 条独立的总线完成的。在这里,I 和 D 总线都尝试访问相同的地址,所以可能是架构不支持?这只是一个假设。一般来说,我认为这样做不是很干净(某些软件正在读取自身)。通常你会有某种引导加载程序(或内核或任何你称之为的东西)检查软件的其余部分。
标签: c pointers memory embedded