C语言 使用链接器脚本重定位中断向量表

uqxowvwt  于 2023-01-08  发布在  其他
关注(0)|答案(2)|浏览(210)

我正在尝试将中断向量移动到DTCMRAM。测试代码是简单的定时器中断 Flink LED。在那里我更改了.isr_vector的加载地址:

MEMORY
{
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 2048K
  DTCMRAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K
  RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH = 512K
  RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
  RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
}

/* Define output sections */
SECTIONS
{
_sivector = LOADADDR(.isr_vector);
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    _svector = .;
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
    _evector = .;
  } >ITCMRAM AT> FLASH

之后我在启动的main调用(根据.data copier生成)前添加了数据copyer:

ldr r0, =_svector
  ldr r1, =_evector
  ldr r2, =_sivector
  movs r3, #0
  b LoopCopyVectorInit

CopyVectorInit:
  ldr r4, [r2, r3]
  str r4, [r0, r3]
  adds r3, r3, #4

LoopCopyVectorInit:
  adds r4, r0, r3
  cmp r4, r1
  bcc CopyVectorInit

现在,我想告诉MCU,根据here,使用SCR-〉VTOR可以获得新的向量表。
下面是主代码:

extern uint32_t _sivector;
extern uint32_t _svector;
extern uint32_t _evector;
int main(void)
{
  /* USER CODE BEGIN 1 */

    __disable_irq();
      SCB->VTOR = (uint32_t)*_sivector;
    __DSB();
    __enable_irq();

但在这种情况下,调试器显示_svector和_sivector等于0x24080000和_evector= 0x504f105
重新初始化VTOR的代码行导致错误。显然_svector和_sivector地址错误。为什么?即使注解ITCMRAM AT>,_* 向量变量也携带错误的值。

o7jaxewo

o7jaxewo1#

这样下去是行不通的。
当uC启动时,它在标准位置(这是必需的)没有中断向量表,因此您以故障结束。稍后您可以复制中断向量表并将其设置在您想要的位置。
因此,您的启动代码将永远不会执行,因为重置向量没有设置为任何有意义的值。

extern uint32_t _sivector;
extern uint32_t _svector;
extern uint32_t _evector;

void __attribute__((constructor)) copyVect(void)
{
  memcpy(&_sivector, &_svector, (&_evector - &_svector) * sizeof(uint32_t));
}

int main(void)
{
  /* USER CODE BEGIN 1 */

    __disable_irq();
      SCB->VTOR = (uint32_t)&_sivector;
    __DSB();
    __enable_irq();


x一个一个一个一个x一个一个二个x
顺便说一句,装配文件中的副本不再需要了。

eufgjt7s

eufgjt7s2#

所以,显而易见的问题是,为什么这些值是不正确的。
我认为你需要获取这些变量的地址。SCB->VTOR = (uint32_t)&_sivector,而不是星号。你想要的是那个变量的地址,而不是它的内容(btw中未定义的)作为一个指针被取消引用并转换到uint32_t。
这与将变量放入数据节的逻辑完全相同,链接器脚本中的变量没有可用的值,它们需要作为地址指针,所以就像你使用&_stackstart或任何你称之为它的东西一样,类似的事情应该适用于这里。
编辑:我使用“变量”这个词有点太随意了。链接器脚本定义了一个符号。没有定义的值与它相关联。

相关问题