我是嵌入式编程和多线程的新手,我正在尝试了解中断处理程序如何在不同的上下文/场景中工作。对于当前的问题,我只想知道中断处理程序在以下场景中的工作原理。
我们有一个来自RS232接口的数据流,由某些微控制器处理。中断处理程序(void类型)具有read()
函数,用于读取传入的数据字节。如果检测到一个字符,那么中断处理程序将调用一个名为detectString()
的函数,如果该字符串与“ON”的引用字符串匹配,则返回TRUE
。如果detectString()
返回boolean TRUE
,则会调用名为LED_ON()
的函数,该函数应打开LED 1分钟。如果返回false,则应关闭LED。假设微控制器的时钟频率为20MHz,加法运算需要5个时钟周期。
我的问题如下
我们如何使用FSM解决此问题? 即使在LED打开后,RS232接口也可以保持传输数据。所以我正确地假设中断处理程序应该与一个线程一起工作,并且它调用的函数应该在不同的线程中工作吗? 实现此FSM的骨架程序将如何? (C伪代码可能真的有助于理解设计的主干)
答案 0 :(得分:2)
如果您在中断处理程序中执行此操作,为什么需要不同的线程?只要启用了中断,那么你做的其他事情就不重要了。
对于FSM,我不会调用" detect_string"。 RS232将一次为您提供一个字符。只有当您收到多个UART时,您的UART才有可能中断您,但通常也只是一个时间组件,因此依靠它是不明智的。使FSM一次输入一个输入字符。你的州将是这样的:
=> new state = [Init] (turn LED off if on)
Init: (Get 'O') => new state = [GotO]
Init: (Get anything else) => new state = [Init]
Init: (Timer expires) => who cares? new state = [Init]
GotO: (Get 'N') => new state = [GotON] (turn on LED, set timer)
GotO: (Get anything else) => new state = [Init]
GotO: (Timer expires) => who cares? new state = [GotO]
GotON: (Get anything) => who cares? new state = [GotON]
GotON: (Timer expires) => turn LED off, new state = [Init]
很明显你可以用细节来修补,但这是一般的想法。
答案 1 :(得分:1)
抢占式内核通常会为中断提供设置高优先级线程待处理事件的能力。
对于中断,实现状态机之类的一种方法是使用嵌套指针来运行,类似于异步回调,但具有可选的嵌套:例如:
typedef void (*PFUN)(void);
/* ... */
PFUN pFunInt = UnexpectedInt; /* ptr to function for interrupt */
PFUN pFunIntSeqDone;
/* ... */
void DoSeq(void)
{
pFunIntSeqDone = IntSeqDone;
pFunInt = IntStep0;
/* enable interrupt, start I/O */
}
void IntStep0(void)
{
pFunInt = IntStep1;
/* handle interrupt */
}
void IntStep1(void)
{
pFunInt = IntStep2;
/* handle interrupt */
}
void IntStep2(void)
{
/* done with sequence, disable interrupt */
pFunInt = UnexpectedInt;
pFunIntSeqDone(); /* call end action handler */
}
void IntSeqDone(void)
{
/* interrupt sequence done handling code */
/* set event for pending thread */
}
void UnexpectedInt(void)
{
/* ... error handling code */
}