zephyr死机原因追踪

找到这个文件下面的lst文件

根据pc指针找到当前运行的地方,在zephyr.lst文件中可以定位到pc地址

MMFA:MemManage Fault Address Register

BFAR: bus fault  address register

HFSR; hardfault status register

CFSR:configurable fault status register

ICSR:interrupt control and state register

下面以zephyr为例举例说明:

测试代码:


bool is_key_down = false;//该变量在按键中断里面触发,当按键按下,该位被置位为true



int main(void)
{
     for(;;)
     {
        if(is_key_down){
	        uint8_t *hardfault_data = NULL;
	        *hardfault_data = 7;//对空指针进行赋值会导致死机
        }
    }
}

死机分析:

debug过程中代码会停在fault.S的汇编代码这个地方:

SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_exc_spurious)

	mrs r0, MSP
	mrs r1, PSP
	push {r0, lr}
#if defined(CONFIG_EXTRA_EXCEPTION_INFO)
	/* Build _callee_saved_t. To match the struct
	 * definition we push the psp & then r11-r4
	 */
	push { r1, r2 }
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
	mov  r3, r11
	mov  r2, r10
	push {r2, r3}
	mov  r3, r9
	mov  r2, r8
	push {r2, r3}
	push {r4-r7}
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
	push {r4-r11}
#endif
	mov  r3, sp /* pointer to _callee_saved_t */
#endif /* CONFIG_EXTRA_EXCEPTION_INFO */
	mov r2, lr /* EXC_RETURN */
	bl z_arm_fault      //这个函数是c语言写的,主要功能是打印16个内核寄存器信息,以及复位
#if defined(CONFIG_EXTRA_EXCEPTION_INFO)
	/* We do not need to restore any register state here
	 * because we did not use any callee-saved registers
	 * in this routine. Therefore, we can just reset
	 * the MSP to its value prior to entering the function
	 */
	add sp, #40
#endif
	pop {r0, pc}

	.end

z_arm_fault()函数在fault.c中

void z_arm_fault(uint32_t msp, uint32_t psp, uint32_t exc_return,
	_callee_saved_t *callee_regs)
{
	uint32_t reason = K_ERR_CPU_EXCEPTION;
	int fault = SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk;
	bool recoverable, nested_exc;
	z_arch_esf_t *esf;

	/* Create a stack-ed copy of the ESF to be used during
	 * the fault handling process.
	 */
	z_arch_esf_t esf_copy;

	/* Force unlock interrupts */
	arch_irq_unlock(0);

	/* Retrieve the Exception Stack Frame (ESF) to be supplied
	 * as argument to the remainder of the fault handling process.
	 */
	 esf = get_esf(msp, psp, exc_return, &nested_exc);
	__ASSERT(esf != NULL,
		"ESF could not be retrieved successfully. Shall never occur.");

       esf_cp_for_info(esf, fault);

#ifdef CONFIG_DEBUG_COREDUMP
	z_arm_coredump_fault_sp = POINTER_TO_UINT(esf);
#endif

	reason = fault_handle(esf, fault, &recoverable);
	if (recoverable) {
		return;
	}

	/* Copy ESF */
#if !defined(CONFIG_EXTRA_EXCEPTION_INFO)
	memcpy(&esf_copy, esf, sizeof(z_arch_esf_t));
	ARG_UNUSED(callee_regs);
#else
	/* the extra exception info is not present in the original esf
	 * so we only copy the fields before those.
	 */
	memcpy(&esf_copy, esf, offsetof(z_arch_esf_t, extra_info));
	esf_copy.extra_info = (struct __extra_esf_info) {
		.callee = callee_regs,
		.exc_return = exc_return,
		.msp = msp
	};
#endif /* CONFIG_EXTRA_EXCEPTION_INFO */

	/* Overwrite stacked IPSR to mark a nested exception,
	 * or a return to Thread mode. Note that this may be
	 * required, if the retrieved ESF contents are invalid
	 * due to, for instance, a stacking error.
	 */
        //LOG_INF("-->nested_exc:0x%x\r\n\r\n",nested_exc);
	if (nested_exc) {
		if ((esf_copy.basic.xpsr & IPSR_ISR_Msk) == 0) {
			esf_copy.basic.xpsr |= IPSR_ISR_Msk;
		}
	} else {
		esf_copy.basic.xpsr &= ~(IPSR_ISR_Msk);
	}
	//while(1);当你想在debug模式下看层级调用关系,而不是要代码自动复位,把while(1)加上就行了
	z_arm_fatal_error(reason, &esf_copy);
}

z_arm_fatal_error(reason, &esf_copy);这个函数就是就是读取内核的16个寄存器信息

void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
{

	if (esf != NULL) {
		esf_dump(esf);
	}
	z_fatal_error(reason, esf);
}

static void esf_dump(const z_arch_esf_t *esf)
{
	LOG_ERR("r0/a1:  0x%08x  r1/a2:  0x%08x  r2/a3:  0x%08x",
		esf->basic.a1, esf->basic.a2, esf->basic.a3);
	LOG_ERR("r3/a4:  0x%08x r12/ip:  0x%08x r14/lr:  0x%08x",
		esf->basic.a4, esf->basic.ip, esf->basic.lr);
	LOG_ERR(" xpsr:  0x%08x", esf->basic.xpsr);
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
	for (int i = 0; i < 16; i += 4) {
		LOG_ERR("s[%2d]:  0x%08x  s[%2d]:  0x%08x"
			"  s[%2d]:  0x%08x  s[%2d]:  0x%08x",
			i, (uint32_t)esf->s[i],
			i + 1, (uint32_t)esf->s[i + 1],
			i + 2, (uint32_t)esf->s[i + 2],
			i + 3, (uint32_t)esf->s[i + 3]);
	}
	LOG_ERR("fpscr:  0x%08x", esf->fpscr);
#endif
#if defined(CONFIG_EXTRA_EXCEPTION_INFO)
	const struct _callee_saved *callee = esf->extra_info.callee;

	if (callee != NULL) {
		LOG_ERR("r4/v1:  0x%08x  r5/v2:  0x%08x  r6/v3:  0x%08x",
			callee->v1, callee->v2, callee->v3);
		LOG_ERR("r7/v4:  0x%08x  r8/v5:  0x%08x  r9/v6:  0x%08x",
			callee->v4, callee->v5, callee->v6);
		LOG_ERR("r10/v7: 0x%08x  r11/v8: 0x%08x    psp:  0x%08x",
			callee->v7, callee->v8, callee->psp);
	}
#endif /* CONFIG_EXTRA_EXCEPTION_INFO */
	LOG_ERR("Faulting instruction address (r15/pc): 0x%08x",
		esf->basic.pc);
}

参考手册:STM32 Cortex®-M33 MCUs programming manual

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值