章节列表

优化缩短关中断的时间

2018-05-29 03:39:42 +0000 李述铜

无论是开关全局中断还是关指定中断,都会对中断的响应时间造成影响。

关中断的时间越长,中断被延迟响应的时间也越长,所以在编写代码时,要尽可能地保护关中断的时间要尽可能地短。但是有时会发现,任务或低优先级中断访问资源的时间较长,此时我们需要调整代码,缩短关中断时间。

主要内容

本课时只是介绍两种思路,在具体的应用中请根据实际情况调整。

提取耗时操作

这种思路简而言之是:调整代码,优化访问资源的时间,将部分耗时的操作从原操作中提取出来。

在之间的示例中,可以看到有个链表遍历。如果单就链表遍历本身来看,其速度还是比较快的,但是由于遍历过程中有使用xprintf打印,如果考虑打印是通过串口输出,那么整个遍历过程将会比较耗时。当结点数量很多,串口的波特率较低时,其耗时就更长。

void listPrint (void) {
    uint32_t count = 0;
    tNode *currentNode = 0;

    // 遍历整个链表,然后打印出各个结点对应的序号
    for (currentNode = tListFirst(&list); currentNode != (tNode *) 0; currentNode = tListNext(&list, currentNode)) {
        xprintf("Node %d\n", count);

        // 假设在此期间,突然发生了中断。由于中断操作了链表,导致再次返回任务时
        // 头结点已经从链表中移除。此时,再继续后面的循环发现,
        currentNode = tListNext(&list, currentNode) 为0
        
        // 导致没有办法再扫描链表中后面的其它结点
        if (count++ == 0) {
            interruptByIRQ(IRQ_PRIO_HIGH);
        } 
    }
}

在这种情况下,如果采用关中断的方式,将会导致中断长时间的关闭,产生很大的影响。通过调整代码,我们可以将打印这个耗时操作给提取出来,不在链表遍历过程中执行。这样链表遍历过程就可以快速地执行完毕,从而尽快地让中断执行。

划分为多次开关中断

有时我们会对大块的代码进行开关中断保护,代码块越大,往往执行时间也越多。

但如果对这些大块代码分析可能会发现,并不是所有的代码都涉及到对共享资源的访问。所以有时可以将这些大块代码进行”划分”,将原本对整个大块代码进行开关中断保护,分隔为多块保护。这样就相比之前就允许中断尽可能早的响应。

重点难点

注意事项

注意,视频中我们采用的是用一个数组记录所有结点然后打印,这种处理方式较简单。可考虑采用其它方式记录要打印的结点,比如链表。

此外,在这里只是提供一种解决思路,示例问题仅是用来演示这种思路的应用,示例功能本身并没有什么意义,无需关注。

常见问题