IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    读取寄存器 data abort dump 案例

    Hacper\'s Blog发表于 2021-10-31 00:25:00
    love 0

    dump原因 DataAbort,Error address (may not be relevant): D4280829

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    
    Software version from AXF file: SDK_1.011.022
    Software version from Dump files: SDK_1.011.022
    ------------------------------------------------------------------
    Error description: DataAbort[AT 801A9D34],Unknown
    Error address (may not be relevant): D4280829
    Error thread: uiNguxTh, stack range (0x7E6AA140..0x7E6AE13B)
    RTC time: 00.00.0000-00:00:00 (dd.mm.yy-hh:mm:ss)
    Gasket registers: PESR=00000000, XESR=00000000, PEAR=00000000, FEAR=00000000, SEAR=00000000, GEAR=00
    FAULT_STATUS=0x00000001
    FAULT_ADDRESS=0xD4280829
    ------------------------------------------------------------------
    

    任务调用栈信息,看调用栈,最后是在执行sdhci_dumpregs函数,data abort 的地址 0xD4280829。

    SDHC 寄存器基地址如下:

    SD Host Controller Registers
    The base addresses of the Host Controller registers are:
    SD1: 0xD4280000
    SD2: 0xD4280800
    SD3: 0xD4281000
    SD4: reserved

    0xD4280829 是 0xD4280800 + 0x29,也就是操作了 SDHCI_POWER_CONTROL 寄存器。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
    #define SDHCI_POWER_CONTROL			                    0x29
    
    static void sdhci_dumpregs(UINT32 base)
    {
    	SDIOLOG_TRACE(": ============== REGISTER DUMP ==============\r\n");
    	SDIOLOG_TRACE(": DMA addr: 0x%08x | Version:  0x%08x\r\n",
    		sdio_readl(base, SD_SYSADDR_LOW_offset),
    		sdio_readw(base, SDHCI_HOST_VERSION));
    	SDIOLOG_TRACE(": Blk size: 0x%08x | Blk cnt:  0x%08x\r\n",
    		sdio_readw(base, SD_BLOCK_SIZE_offset),
    		sdio_readw(base, SD_BLOCK_COUNT_offset));
    	SDIOLOG_TRACE(": Argument: 0x%08x | Trn mode: 0x%08x\r\n",
    		sdio_readl(base, SD_ARG_LOW_offset),
    		sdio_readw(base, SD_TRANSFER_MODE_offset));
    	SDIOLOG_TRACE(": Present:  0x%08x | Host ctl: 0x%08x\r\n",
    		sdio_readl(base, SD_PRESENT_STAT_0_offset),
    		sdio_readw(base, SD_HOST_CTRL_offset));
    	SDIOLOG_TRACE(": Power:    0x%08x | Blk gap:  0x%08x\r\n",
    		sdio_readw(base, SDHCI_POWER_CONTROL), /*导致dump的地方*/
    		sdio_readw(base, SD_BGAP_CTRL_offset));
    	SDIOLOG_TRACE(": Wake-up:  0x%08x | Clock:    0x%08x\r\n",
    		sdio_readb(base, SDHCI_WAKE_UP_CONTROL),
    		sdio_readw(base, SD_CLOCK_CTRL_offset));
    	SDIOLOG_TRACE(": Timeout:  0x%08x | Int stat: 0x%08x\r\n",
    		sdio_readw(base, SD_SW_RESET_CTRL_offset),
    		sdio_readl(base, SD_NORM_INTR_STS_offset));
    	SDIOLOG_TRACE(": Int enab: 0x%08x | Sig enab: 0x%08x\r\n",
    		sdio_readl(base, SD_NORM_INTR_STS_EBLE_offset),
    		sdio_readl(base, SD_NORM_INTR_STS_INTR_EBLE_offset));
    	SDIOLOG_TRACE(": AC12 err: 0x%08x | Slot int: 0x%08x\r\n",
    		sdio_readw(base, SDHCI_ACMD12_ERR),
    		sdio_readw(base, SDHCI_SLOT_INT_STATUS));
    	SDIOLOG_TRACE(": Caps:     0x%08x | Max curr: 0x%08x\r\n",
    		sdio_readl(base, SDHCI_CAPABILITIES),
    		sdio_readl(base, SDHCI_MAX_CURRENT));
    	SDIOLOG_TRACE(": Command:  0x%08x | RX_CFG_REG:0x%08x\r\n",
    		sdio_readw(base, SD_CMD_offset),
    		sdio_readl(base,SDHCI_RX_CFG_REG));
        SDIOLOG_TRACE("SDHCI_HOST_CTRL2: 0x%08x | PRESET_VALUE_FOR_SDR50:0x%08x",
            sdio_readw(base, SDHCI_HOST_CTRL2),
            sdio_readw(base, SDHCI_PRESET_VALUE_FOR_SDR50));
    	SDIOLOG_TRACE(": ===========================================\r\n");
    }
    

    SDHCI_POWER_CONTROL 寄存器地址和描述如下:

    0xD4280800 + 0x29 对应 对应图中标黄区域。

    sdio_readw(base, SDHCI_POWER_CONTROL) ,sdio_readw 读取两个字节的数据,对应地址范围:0xD4280829-0xD428082B。而其中0xD428082A-0xD428082B 已经是下一个寄存器的地址范围了。

    1
    2
    3
    4
    5
    6
    7
    8
    
    static UINT16 sdio_readw(UINT32 base, UINT32 reg)
    {
        volatile UINT16* ptr16;
        UINT16 tmp;
        ptr16 = (volatile UINT16*)(base + reg);
        tmp = *ptr16;
        return tmp;
    }
    

    改成sdio_readb(base, SDHCI_POWER_CONTROL) 不会dump,sdio_readb 读取一个字节,也就是说,并不是0xD4280829这个地址不可用,而是访问数据的方式不正确导致dump。

    1
    2
    3
    4
    5
    6
    7
    8
    
    static UINT8 sdio_readb(UINT32 base, UINT32 reg)
    {
        volatile UINT8* ptr8;
        UINT8 tmp;
        ptr8 = (volatile UINT8*)(base + reg);
        tmp = *ptr8;
        return tmp;
    }
    


沪ICP备19023445号-2号
友情链接