微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

stm32 NVIC_EnableIRQ等效的裸机?

如何解决stm32 NVIC_EnableIRQ等效的裸机?

我正在使用蓝色药丸,并试图找出中断。我有一个中断处理程序:

void __attribute__ ((interrupt ("TIM4_IRQHandler"))) myhandler()
{
    puts("hi");
    TIM4->EGR |= TIM_EGR_UG; // send an update even to reset timer and apply settings
    TIM4->SR &= ~0x01; // clear UIF
    TIM4->DIER |= 0x01; // UIE
}

我设置了计时器:

    RCC_APB1ENR |= RCC_APB1ENR_TIM4EN;
    TIM4->PSC=7999;
    TIM4->ARR=1000;
    TIM4->EGR |= TIM_EGR_UG; // send an update even to reset timer and apply settings
    TIM4->EGR |= (TIM_EGR_TG | TIM_EGR_UG);
    TIM4->DIER |= 0x01; // UIE enable interrupt
    TIM4->CR1 |= TIM_CR1_CEN;
   

我的计时器似乎没有启动。我认为我实际上并未启用它。我有吗?

我在许多示例代码命令中都看到了

NVIC_EnableIRQ(USART1_IRQn);

NVIC_EnableIRQ()中实际发生了什么?

我已经四处搜寻,但找不到与我的功能类似的实际裸机代码

我似乎错过了关键的一步。

更新2020-09-23 ,感谢此问题的答复者。技巧是将NVIC_ISER寄存器中的中断号位置1。正如我在下面指出的那样,这在STM32F101xx参考手册中似乎没有提到,因此我可能永远无法独自解决这个问题。不是说我有阅读数据表的真正技能。

无论如何,哦,喜悦,我设法使中断开始工作!您可以在此处查看代码https://github.com/blippy/rpi/tree/master/stm32/bare/04-timer-interrupt

解决方法

即使您精疲力尽,您仍可能想要使用CMSIS头文件,这些头文件提供非常基本的ARM Cortex元素(例如NVIC_EnableIRQ)的声明和内联版本。

您可以在https://github.com/ARM-software/CMSIS_5/blob/develop/CMSIS/Core/Include/core_cm3.h#L1508处找到NVIC_EnableIRQ

其定义为:


#define NVIC_EnableIRQ __NVIC_EnableIRQ

__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    __COMPILER_BARRIER();
    NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
    __COMPILER_BARRIER();
  }
}

如果需要,可以忽略__COMPILER_BARRIER()。以前的版本没有使用它。

该定义适用于Cortex M-3芯片。与其他Cortex版本不同。

,

带库仍被认为是裸机。没有操作系统,但是无论如何,这是您希望在此级别上学习的好地方。有人必须为他人编写库。

我打算在这里做一个完整的示例(实际上只需要很少的代码即可完成此操作),但是将从我的使用Timer1的开发板上的代码中提取。

显然,您需要ARM文档(cortex-m3的技术参考手册和armv7-m的体系结构参考手册)以及这部分的数据表和参考手册(两家公司都不需要程序员手册)。

您几乎没有提供与使零件正常工作相关的信息。您永远不要直接陷入中断,它们是高级主题,在最终使中断成为内核之前,您应该尽可能地进行调查。

我更喜欢让uart工作,然后在翻转,计数等操作时使用它来监视计时器寄存器。然后查看/确认已触发状态寄存器,了解/确认如何清除它(有时只是清除读取)。

然后将其启用到NVIC中,并通过轮询查看NVIC已看到它,并且可以清除它。

您没有显示向量表,这是使中断处理程序正常工作的关键。更少的核心启动。

08000000 <_start>:
 8000000:   20005000
 8000004:   080000b9
 8000008:   080000bf
 800000c:   080000bf
...
 80000a0:   080000bf
 80000a4:   080000d1
 80000a8:   080000bf
...
080000b8 <reset>:
 80000b8:   f000 f818   bl  80000ec <notmain>
 80000bc:   e7ff        b.n 80000be <hang>
...
080000be <hang>:
 80000be:   e7fe        b.n 80000be <hang>
...
080000d0 <tim1_handler>:

第一个单词加载堆栈指针,其余为向量,指向处理程序的地址或一个(由我来查找)。

在这种情况下,st参考手册显示中断25在地址0x000000A4处为TIM1_UP。哪个镜像到0x080000A4,这就是处理程序在我的二进制文件中的位置,如果不是,则有两件事,您可以使用VTOR查找对齐的空间,有时会为此创建sram或其他一些闪存空间并将其指向,但是向量表处理程序必须具有正确的指针,否则中断处理程序将无法运行。

volatile unsigned int counter;
void tim1_handler ( void )
{
    counter++;
    PUT32(TIM1_SR,0);
}

volatile不一定是在中断处理程序和前台任务之间共享变量的正确方法,它恰好适用于此编译器/代码,您可以进行研究,甚至更好地检查编译器输出(反汇编二进制文件)以确认这不是问题。

ra=GET32(RCC_APB2ENR);
ra|=1<<11;  //TIM1
PUT32(RCC_APB2ENR,ra);

...

counter=0;
PUT32(TIM1_CR1,0x00001);
PUT32(TIM1_DIER,0x00001);
PUT32(NVIC_ISER0,0x02000000);
for(rc=0;rc<10;)
{
    if(counter>=1221)
    {
        counter=0;
        toggle_led();
        rc++;
    }
}
PUT32(TIM1_CR1,0x00000);
PUT32(TIM1_DIER,0x00000);

tim1的最小初始化和运行时。

请注意,NVIC_ISER0是位25,该位被设置为使能中断25至中断。

在尝试此代码之前,我轮询了计时器状态寄存器以查看其工作方式,与文档进行比较,并根据文档清除中断。然后,借助NVIC_ICPR0确认的知识,1,2寄存器将其中断25。此外,某些供应商提供的某些芯片可能在外设和NVIC之间没有其他门。

然后使用NVIC_ISER0将其发布到内核。

如果您不采取这些可能的步骤,也许您已经采取了这种措施,那么只会使任务变得更糟,并且需要更长的时间(是的,有时候您会很幸运)。

TIM4在向量表中看起来像是中断30,偏移量/地址0x000000B8。 NVIC_ISER0(0xE000E100)覆盖了前32个中断,因此该寄存器中有30个中断。如果您反汇编正在使用库生成的代码,那么我们可以看到正在发生的事情,或者可以在库源代码中查找它(就像有人已经为您所做的那样)。

然后,当然,您的计时器4代码需要正确地初始化计时器,并引发中断,我没有检查。

有些例子,您需要继续看下去。

最小值是

  1. 表格中的向量
  2. 设置中断设置允许寄存器中的位
  3. 启用中断以离开外围设备
  4. 触发中断

不一定按此顺序。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。