STM32调用memcpy导致hardfault(调用memcpy本身,不是memcpy的执行)

STM32 call to memcpy causes hardfault (the call to memcpy itself, not the execution of memcpy)

情况: 我正在使用一个名为嵌入式 disco 的加密库,我有一个在我的 PC 上运行的演示,但是当将它移植到 MCU 时,我遇到了一个硬故障执行库程序。在错误代码中,库试图简单地将一个 strobe_s 结构的内容复制到另一个 strobe_s 中。这样做了两次:一次是 s1,一次是 s2。对于 s1,图书馆只是分配目标。结构到源结构。然而,对于 s2 来说,这样的分配给出了一个硬错误。由于 Cortex-M ISA 需要对齐的内存访问,我认为用 memcpy 替换分配应该可以解决问题。然而,简单地使用调试器进入 memcpy 会导致硬故障! IE。我在 memcpy 所在的行有一个断点,当进入故障处理程序时调用!我已经使用 memcpy 来修复代码其他部分中未对齐的内存访问就好了...

单片机: STM32L552ZET6QU

故障代码:

下面的代码是我对原始库代码的修改,其中对 *s2 的赋值被 memcpy 替换。 library's github 中的原始代码是:

  // s1 = our current strobe state
  *s1 = ss->strobe;
  if (!half_duplex) {
    // s2 = s1
    *s2 = ss->strobe;
  }

我的修改版本:

  // s1 = our current strobe state
  *s1 = ss->strobe;
  if (!half_duplex) {
    // s2 = s1
    // WARNING: The below code will give a HARD FAULT ON THE STM32L552ZE!
    // *s2 = ss->strobe;
    // Fix I tried: Use memcpy instead!
    memcpy((void*) s2, (void*)(&(ss -> strobe)), sizeof(strobe_s));
  }

memcpy的参数值:

就在执行 memcpy 之前,调试器向我显示了相关变量的以下值:

Expr.   Type                Value
----------------------------------------------------
s1      strobe_s *          0x800c374   
s2      strobe_s *          0x800a497 <_fflush_r+66>    
ss      symmetricState *    0x2002f988  
&s1     strobe_s **         0x2002f690  
&s2     strobe_s **         0x2002f68c  
&ss     symmetricState **   0x2002f694

Typedefs:

typedef struct symmetricState_ {
  strobe_s strobe;
  bool isKeyed;
} symmetricState;

/** Keccak's domain: 25 words of size b/25, or b/8 bytes. */
typedef union {
  kword_t w[25];
  uint8_t b[25 * sizeof(kword_t) / sizeof(uint8_t)];
} kdomain_s;

/** The main strobe state object. */
typedef struct strobe_s_ {
  kdomain_s state;
  uint8_t position;
  uint8_t pos_begin;
  uint8_t flags;
  uint8_t initiator;
  uint8_t initialized;  // strobe is initialized if this value is set to 111.
                        // This is because we cannot assume that a boolean would
                        // be set to false initially (C stuff). A uint8_t is a
                        // short value but here we do not care about security
                        // much, rather catching bugs early in a development
                        // environement.
} strobe_s;

问题:

  1. 仅仅 调用 到 memcpy 而没有实际执行 memcpy 中的单个指令怎么可能给出硬错误?
  2. 我该如何解决这个问题?

这里:

s2      strobe_s *          0x800a497 <_fflush_r+66>   

s2是flash(只读)地址。复制到只读内存在语义上都是错误的,如果区域设置为只读,则可能会触发 MPU 故障。

我不清楚原始代码是如何工作的,或者实际上是如何工作的:

 *s1 = ss->strobe;

不过也没有引起问题。当然,即使没有异常,它也不会按预期工作。