【问题标题】:What is the fastest way to implement my interrupt? [closed]实现中断的最快方法是什么? [关闭]
【发布时间】:2020-12-07 21:18:22
【问题描述】:

我有一个外部中断(在 STM32F031K6 上运行)。我希望它尽可能快地运行——最好在 1uS 内。目前它的运行时间约为 2.2uS。中断如下

void EXTI4_15_IRQHandler(void)
{

    if (ChangeFlag & 1<<3){
        GPIOA->BSRR |= (1<<4);}
    else
        GPIOA->BSRR |= (1<<20);

    ChangeFlag |= 1<<1;

    if (ChangeFlag & 1<<2)
    {
        GPIOA->BSRR |= (1<<12);}
    else
        GPIOA->BSRR |= (1<<28);

    ChangeFlag |= 1<<0;

    EXTI->PR |= 1<<11; //turn off interrupt request
}

特别是像 GPIOA->BSRR |= (1

【问题讨论】:

  • 你使用的是什么编译优化级别?
  • 在不知道ChangeFlag 的类型的情况下不可能以明智的方式回答问题。是uint8_tuint32_t 还是别的什么?是volatile吗?

标签: c embedded stm32 cortex-m


【解决方案1】:

您的示例不完整,我不明白 ChangeFlag 应该做什么。如果 ChangeFlag 是一个不稳定的全局变量,那么那里会有一些优化潜力......

我可以告诉你的是,BSRR 是一个只写寄存器,读写修改它是没有意义的。

只需将 |= 运算符替换为简单的赋值 = 即可省去几条汇编指令。

【讨论】:

    【解决方案2】:

    通过生成掩码,然后对GPIOA-&gt;BSRR 进行一次写入,您将节省大量内存访问

    void EXTI4_15_IRQHandler(void)
    {
        uint32_t mask = 0;
        if (ChangeFlag & 1<<3)
            mask = (1<<4);
        else
            mask = (1<<20);
    
        if (ChangeFlag & 1<<2)
            mask |= (1<<12);
        else
            mask |= (1<<28);
    
        ChangeFlag |= (( 1 << 1 ) | (1 << 0));
        GPIOA->BSRR = mask;
    
        EXTI->PR |= 1<<11; //turn off interrupt request
    }
    

    正如@Vinci 所说,在GPIOx-&gt;BSRR 上使用|= 运算符是没有意义的,因为它是一个只写寄存器,对其执行读-修改-写只是浪费周期。

    如果更改标志是一个 volatile 全局,那么您可以通过将其复制一次来进行保存,将其复制到一个临时文件中并在您的条件中使用它,您必须检查编译后的输出。

    您的部件可以以高达 48 MHz 的频率运行,在 1 μs 内为您提供 48 个时钟周期,在发生异常和运行代码以将状态推送到堆栈之间有 16 个周期,对于弹出所有内容也是如此退出异常退出,即总共 32 个周期用于内务处理,这会使您在异常处理程序执行任何工作之前达到约 666 ns,为了保持在 1 μs 预算内,您的处理程序代码只有 16 个时钟周期。我不确定 1 μs 是否可行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 2010-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多