假设您有一些数据传输外围设备,比如UART,只要它准备好传输更多数据,就会发出中断信号。我们从循环缓冲区发送数据,其中tail是删除数据的地方,head是添加数据的地方,tail == head意味着没有更多的数据需要传输。
我们还假设外围设备没有任何缓冲,并且在它忙于发送当前值时不能传递要发送的下一个值。如果您需要一个具体的,如果组成,例如,考虑一个移位寄存器直接连接到一个CPU的并行I/O端口。
为了使发射机尽可能繁忙,您可能希望在输入发送中断处理程序后尽快发送。当没有要传输的数据时,中断会被屏蔽,即使中断已经打开,处理程序也不会被调用。系统从中断屏蔽开始。
我将使用C来说明事情,尽管问题不是特定于C的。中断处理程序和缓冲区设置如下:
char buf[...];
char * head = buf; ///< write pointer
char * tail = buf; ///< read pointer
char * const first = buf; ///< first byte of the buffer
char * const last = buf+sizeof(buf)-1; ///< last byte of the buffer
/// Sends one byte out. The interrupt handler will be invoked as soon
/// as another byte can be sent.
void transmit(char);
void handler() {
transmit(*tail);
if (tail == last)
tail = first;
else
tail++;
if (tail == head)
mask_interrupt();
}到现在为止还好。现在,让我们看看如何实现putch()。我们可以在突发情况下调用putch(),比设备发送数据的速度快得多。让我们假设调用方知道缓冲区不会溢出。
void putch(char c) {
*head = c;
if (head == last)
head = first;
else
head++;
/***/
unmask_interrupt();
}假设现在发生了这些事情:
putch被调用时,有一个字节被发送。putch在上面标记为/***/的位置时,传输碰巧完成。handler()恰好在那里执行。handler()恰好发送缓冲区中数据的最后一个字节--我们刚才在putch()中前面的行中加载的字节。处理程序掩盖中断,因为没有更多的数据要发送,但是putch在handler()返回后就不正确地取消了它。因此,handler将有另一个通过缓冲区,并将发送缓冲区的价值陈旧的数据,直到tail再次等于head。
我的问题是:在发送handler**?**之前,是增加延迟和检查空缓冲区的唯一修复方法,固定代码如下所示:
void fixed_handler() {
if (head == tail) {
mask_interrupt();
arm_interrupt(); // so that next time we unmask it, we get invoked
return;
}
transmit(*tail);
if (tail == last)
tail = first;
else
tail++;
}这个修复增加了一些延迟,还添加了一个额外的操作(arm_interrupt),当没有更多的数据要发送时,只执行一次。
对于可能的其他方法,可以假设至少存在以下操作:
/// Is the interrupt armed and will the handler fire once unmasked?
bool is_armed();
/// Is the interrupt unmasked?
bool is_unmasked();发布于 2015-09-24 16:30:46
我总是用双缓冲来实现这一点,所以在任何时候,程序和UART都“拥有”不同的缓冲区。
当UART完成其缓冲区的发送时,就会发生一个交换,并屏蔽中断。这样,它就不需要掩盖每一个角色的中断。
发布于 2015-09-24 16:13:36
一个解决方法是防止中断处理程序在putch中运行。
void putch(char c) {
*head = c;
mask_interrupt();
if (head == last)
head = first;
else
head++;
unmask_interrupt();
}这允许我们使用原始的传输第一中断处理程序。这方面的问题是,总的来说,它增加了每个字节执行的操作数。它也增加了峰值延迟时间,因为现在有一些时候,即使硬件已经准备好接收更多的数据和要发送的数据,handler()仍然无法运行。
使发射机再次繁忙的平均延迟由中断处理程序决定。在此基础上的峰值延迟由延迟执行中断处理程序的代码决定。
https://stackoverflow.com/questions/32766195
复制相似问题