简体   繁体   中英

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. An interrupt handler(of void type) has a read() function which reads the incoming data bytes. 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". If detectString() returns boolean TRUE it invokes a function called LED_ON() which should turn on an LED for 1 minute. If it returns false it should turn off the LED. Lets say the microcontroller has a clock frequency of 20MHz and an addition operation taken 5 clock cycles.

My questions are as follows

How do we approach this problem with an FSM? The RS232 interface keeps transmitting data even after the LED is turned on. 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? (a C pseudocode might really help to understand the backbone of the design)

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". RS232 is going to give you one character at a time. 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. Make your FSM take one input character at a time. 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 */
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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