简体   繁体   English

简单的中断处理/多线程程序?

[英]Simple Interrupt Handling/ Multi-threading program?

I'm new to Embedded programming and multi-threading and I'm trying to understand how Interrupt handlers work in different contexts/scenarios. 我是嵌入式编程和多线程技术的新手,我试图了解中断处理程序如何在不同的上下文/场景下工作。 For the current question, I just want to know how a interrupt handler would work in the following scenario. 对于当前问题,我只想知道在以下情况下中断处理程序将如何工作。

We have a data stream coming from a RS232 interface that is processed by some microcontroller. 我们有来自RS232接口的数据流,该数据流由某些微控制器处理。 An interrupt handler(of void type) has a read() function which reads the incoming data bytes. 中断处理程序(无效类型)具有read()函数,该函数读取传入的数据字节。 If a character is detected then the interrupt handler invokes a function called detectString() which returns TRUE if the string matches the reference string which is "ON". 如果检测到字符,则中断处理程序将调用一个名为detectString()的函数,如果该字符串与参考字符串“ ON”匹配,则该函数返回TRUE If detectString() returns boolean TRUE it invokes a function called LED_ON() which should turn on an LED for 1 minute. 如果detectString()返回boolean TRUE它将调用一个称为LED_ON()的函数,该函数应将LED点亮1分钟。 If it returns false it should turn off the LED. 如果返回假,则应关闭LED。 Lets say the microcontroller has a clock frequency of 20MHz and an addition operation taken 5 clock cycles. 可以说微控制器的时钟频率为20MHz,加法运算需要5个时钟周期。

My questions are as follows 我的问题如下

How do we approach this problem with an FSM? 我们如何使用FSM解决这个问题? The RS232 interface keeps transmitting data even after the LED is turned on. 即使在LED指示灯亮起之后,RS232接口仍继续发送数据。 So am I correct in assuming that the interrupt handler should work with a one thread and the functions that it invokes should work from a different threads? 因此,我是否假设中断处理程序应该在一个线程中工作并且它调用的函数应该在不同的线程中工作是正确的? How would a skeletal program implementing this FSM look like? 实现此FSM的骨架程序是什么样的? (a C pseudocode might really help to understand the backbone of the design) (C伪代码可能确实有助于理解设计的基础)

If you are doing this in an interrupt handler, why would you need different threads? 如果您在中断处理程序中执行此操作,为什么需要其他线程? It shouldn't matter what else you're doing, as long as interrupts are enabled. 只要启用了中断,您在做什么都不重要。

As for FSM, I wouldn't call a "detect_string". 至于FSM,我不会称其为“ detect_string”。 RS232 is going to give you one character at a time. RS232将一次给您一个字符。 It's possible your UART interrupts you only when you've received more than one, but there's usually a time component as well so it would be unwise to count on that. UART可能仅在收到多个中断时才会打断您,但是通常还包含一个时间分量,因此依靠它是不明智的。 Make your FSM take one input character at a time. 使您的FSM一次输入一个输入字符。 Your states would be something like: 您的状态将类似于:

=> 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]

Obviously lots of tinkering you could do with details, but that's the general idea. 显然,您可以修改很多细节,但这是一般的想法。

A preemptive kernel will usually provide the ability for an interrupt to set an event that a higher priority thread is pending on. 抢占式内核通常会提供中断功能,以设置高优先级线程挂起的事件。

As for the interrupts, one way of implementing something like a state machine is to use nested pointers to function, similar to an asynchronous callback, but with optional nesting: For example: 至于中断,实现类似状态机之类的一种方法是使用嵌套指针来执行功能,类似于异步回调,但具有可选的嵌套:例如:

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 */
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM