Arm 使用GDB在Cortex-M上进行软复位

Arm 使用GDB在Cortex-M上进行软复位,arm,gdb,embedded,cortex-m,thumb,Arm,Gdb,Embedded,Cortex M,Thumb,我正在为一些内部Cortex-M4内核开发一套调试工具。我正在使用gcc/binutils工具链构建嵌入式(无操作系统)ELF映像,并使用改进版的QEMU模拟它们。我在映像的开始(即0)处创建中断向量表,并正确初始化堆栈指针和开始地址(即main的地址) 目标程序按预期运行,使用GDB远程协议构建的调试工具工作正常 我目前试图理解的是如何从GDB启动软重置。也就是说,安排目标程序重新初始化,堆栈指针重置为向量表中的初始值,PC返回起始地址 我已经向自己演示了将PC值设置为0并运行core的操作是

我正在为一些内部Cortex-M4内核开发一套调试工具。我正在使用gcc/binutils工具链构建嵌入式(无操作系统)ELF映像,并使用改进版的QEMU模拟它们。我在映像的开始(即0)处创建中断向量表,并正确初始化堆栈指针和开始地址(即main的地址)

目标程序按预期运行,使用GDB远程协议构建的调试工具工作正常

我目前试图理解的是如何从GDB启动软重置。也就是说,安排目标程序重新初始化,堆栈指针重置为向量表中的初始值,PC返回起始地址

我已经向自己演示了将PC值设置为0并运行core的操作是不合适的,结果是调用了我的“UsageFault”异常处理程序。(我假设核心处于错误的模式,无法执行此类操作)


是否有一种技术,即通过使用GDB远程协议进行寄存器写入,我可以软重置模拟内核,而无需重启QEMU会话?

您可以通过将
SYSRESETREQ
位+键写入
Aircru
寄存器来重新启动软件:

AIRCR_REG_ADDRESS = 0xe000ed0c
AIRCR_KEY = 0x05fa0000
AIRCR_SYSRESETREQ_BIT = 0x00000004

AIRCR_REG = AIRCR_KEY | AIRCR_SYSRESETREQ_BIT
更多信息是


这是一段cortex-M3的代码片段,我使用它跳转到任何位置,其中包含有效代码(包括跳转到0):

IRQn_类型中断=(IRQn_类型)0;
app_fn jump=*(app_fn*)(jumpaddr+sizeof(int))//重置在表中排名第二
uint32\u t堆栈\u adr=*(uint32\u t*)(跳线地址)//堆栈指针在表中位于第一位
//在跳转之前禁用中断
SysTick->CTRL&=~ST\U CTRL\U ENABLE;
while(中断VTOR=(位置&0x1ffffff80);
//信仰的飞跃!
跳跃();
此代码假定
jumpaddr
是向量表的基址,因为堆栈指针在表中位于第一位,重置处理程序在表中位于第二位

禁用中断是必须的,因为在移动堆栈指针(通常会导致异常)后,中断可能会关闭

当然,这样做不会重置任何外围设备,因此在再次启用中断之前需要进行重置

编辑:


您可以找到_set_MSP的内容。

地址0是初始堆栈指针。正确。但是,Cortex-M在thumb模式下阻止从应用程序直接访问SP。由于重新初始化SP是软件重置的一项要求,因此需要另一种方法。Vik下面的回答似乎接近要求,我只需要当我通过GDB向QEMU发送内存写入时,调试实际情况。我正在尝试你的建议。QEMU处理写入数据包,但我不确定是否采取了正确的操作。这看起来是一个合理的解决方案,但是,目前我用来模拟真实CPU的QEMU实例似乎没有模拟所需的CPU区域(SCB)正确。好的,在这种情况下,在设置
Airr
之前也要注册并设置位
VC\u CORERESET
DEMCR=0x00000001
),这会在重置后停止CPU,您可以查看SP、PC,…如果正确重启,谢谢Vik。但我认为我的主要问题是QEMU没有使任何cortexm外围设备(即E0000000-E00FFFFF)在GDB可访问的内存映射中可见。我找到了函数(QEMU)这忽略了写入尝试。因此,我随后尝试在目标(即cortexm的应用程序)中直接写入到Airtr代码。但是,尽管在QEMU中找到了正确的例程来执行重置,但我随后发现另一个QEMU问题阻止了重置的实际进行。我可能需要向QEMU专家提出更多问题。我只是尝试了@Vik的建议,在写入Aircrat之前,先在目标应用程序中设置DEMCR=0x00000001。但它看起来像一个qemu问题目前阻碍了进一步的进展。我需要对此进行进一步调查。我查阅了uu set_MSP。我如何在gcc/gas中为ARM编写代码?我很好奇,从地址0执行的代码在跳转后如何工作-我假设处理器首先需要一个模式切换?不完全确定如何在gcc中编写,但可能很简单例如:
asm volatile(“msr msp,%0”:“=m”(stack_adr));
上述代码是在引导加载程序的特权模式(无操作系统)下执行的。我使用重置为引导加载程序(0x00000000)。谢谢@NeRa,我将在下周尝试。
   IRQn_Type interrupt = (IRQn_Type)0;
   app_fn jump = *(app_fn *)(jumpaddr + sizeof(int));     //Reset is 2nd in table
   uint32_t stack_adr = *(uint32_t *)(jumpaddr);         //Stack pointer is 1st in table

   //Disable interrupts before jumping
   SysTick->CTRL &= ~ST_CTRL_ENABLE;

   while (interrupt <= CANActivity_IRQn)
   {
      NVIC_DisableIRQ(interrupt);
      interrupt++;
   }

   //Set the new stack pointer
   __set_MSP(stack_adr);

   //Set the new vector address
   SCB->VTOR = (location & 0x1FFFFF80);

   //Leap of faith!
   jump();