【问题标题】:Dereferncing a pointer doesn't return the real value in the memory address取消引用指针不会返回内存地址中的实际值
【发布时间】: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。但是,如果我将断点放在第三条装配线,我发现寄存器X0x8B15(正确的地址),但寄存器A0x8B(错误的值)。

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


【解决方案1】:

上周我遇到了同样的问题。这似乎是调试固件和您的代码都访问同一位置的问题。如果您在尝试使用代码读取的同一 Flash 位置有一个活动断点,那么您的代码最终会从该位置读取 0x8B。如果您删除或停用所有断点,则正确读取该位置..

【讨论】:

    【解决方案2】:

    除了我之前的答案(见上文或下文..我无法编辑那个)..活动断点用 BREAK 指令(操作码 0x8B)替换该特定闪存位置的现有指令,所以当那个从应用程序代码中读取内存位置,结果将是 0x8B。 所以这并不是一个真正的“问题”,而是在 STM8S 上的 SWIM 调试固件中实现的软件断点的限制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2015-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多