• ARM非对齐操作异常解决过程


    在测试MF固件时,发生一个非常诡异的异常,代码如下:

        CLR_DBG_Commands::Monitor_EraseMemory* cmd = (CLR_DBG_Commands::Monitor_EraseMemory*)msg->m_payload;
    
        debug_printf("EraseMemory addr=0x%08x len=%d
    ", cmd->m_address, cmd->m_length);

    指定第二行代码时,会跳到异常处理程序,发生了6号异常(用法异常Usage Fault)

    我对ARM还是非常陌生,不知道怎么可能发生这个问题。
    在今天之前,这行代码执行了无数次也未曾出错,最近也没有修改该函数或者相关函数的代码,昨天倒是大量修改了其它代码。

    1,百度找资料
    关键点是用法异常Usage Fault,以此为关键字搜索。有资料(http://www.docin.com/p-633872264.html)指出,用法异常包括:执行未定义指令、非对齐操作、除零。
    前后两个显然不可能,中间这个非对齐操作倒是引起了我的注意。因为阅读MFPK代码的时候看到很多对齐操作的设计。

    2,Keil调试
    在Keil中调试这两行代码

    0x080071DA 6A74      LDR      r4,[r6,#0x24]
      1350:         debug_printf("EraseMemory addr=0x%08x len=%d
    ", cmd->m_address, cmd->m_length); 
      1351:  
    0x080071DC A012      ADR      r0,{pc}+4  ; @0x08007228
    0x080071DE E9D41200  LDRD     r1,r2,[r4,#0]
    0x080071E2 F001FD93  BL.W     debug_printf (0x08008D0C)

    抛出异常的是0x080071DE这一行,代码是LDRD r1,r2,[r4,#0],大意是把r4开始,偏移#0的数据加载到r1,下一个字加载到r2
    从寄存其中看到,r4此时是0x200006D2,这是半字对齐而不是字对齐。
    奇怪了,MDK为啥编译一个半字对齐的呢?
    回到第一行代码的
    msg->m_payload,它是关键。因为它就是0x200006D2,如果r4没有字对齐,那么肯定跟这个msg->m_payload有关。
    我们看看
    msg->m_payload是哪里分配的!

    3,寻根
    从代码中看到
    msg->m_payload来自msg->m_payload = pThis->m_receptionBuffer;
    m_receptionBuffer的声明

        COM_HANDLE    m_port;
        UINT8         m_receptionBuffer[ 2048 ];
        UINT32        m_flags;
        UINT32        m_lastPacketSequence;
        WP_Controller m_controller;

    到这里,就明白了!
    因为我昨天把typedef INT32 COM_HANDLE;改为了typedef INT16 COM_HANDLE;

    非对齐操作相关资料
    http://www.docin.com/p-218037008.html

  • 相关阅读:
    锁优化
    无同步方案
    线程安全
    vue 监听路由变化
    ES6-解构赋值
    微信小程序中遮罩层的滚动穿透问题
    JavaScirpt对象原生方法
    JavaScript-window
    JavaScript字符串API
    JavaScript常用数组操作方法,包含ES6方法
  • 原文地址:https://www.cnblogs.com/nnhy/p/7462758.html
Copyright © 2020-2023  润新知