Em 5/7/2010 11:01, Olin Lathrop escreveu: > Why start the receiving thread in the ISR? That sounds more complicated > than necessary. The logic above is also imcomplete because you don't che= ck > for and handle the case of the thread still running from last time. And Awaking a thread that was already awoken or even running is innocuous (at least in FreeRTOS). > then how can a thread reasonable handle a communication protocol if it is > run separately for each byte? This makes no sense. The thread just sleeps when there is no more bytes available, waiting for more. > All the interrupt routine should do, if you use interrupts at all, is to = get > the data and leave it lying around someplace the receiving thread can find > it, usually in a FIFO is the data is just a byte stream. The receiving > thread runs all the time, but the call to get the next byte blocks until = one > is available. Now the receiving thread can do a computed GOTO on the opc= ode > byte and run a separate routine per command. These command routines can = get > parameter bytes as appropriate and don't jump back to the start of the ma= in > command loop until their command has been processed. This is essentially > using a state machine to processes a state-dependent input stream, with t= he > PC being the state variable. I find that sort of architecture works well > for handling asynchronous input streams. He is not using a state-machine, he is running a RTOS (probably FreeRTOS, which he already used before). The receiving routine just sits in a loop until a full packet is received, the routine may sleep/yield as many times as it needs, then perhaps return to a calling function with the packet in some buffer and a status. >From the programmer's point of view, it is a simple loop and he can abstract the fact that the bytes may take some time to arrive, he just calls a function "getbyte" and it returns either with the byte or a timeout status. All waiting/sleeping/yielding is done inside this "getbyte" function. >> I would imagine that using an interrupt (rather than consistently >> polling for data) is far more efficient. > Probably not, but efficiency isn't the issue. Once you buy into the > separate receiving thread concept with blocking GET calls, those GET calls > can just as well check a hardware flag to see if there is new data than to > check the software flag that says there is at least one byte in the FIFO. > Things look the same to the receiving thread. Note that while the GET ca= ll > appears to block to the receiving thread, "blocking" in this context real= ly > means checking for new data in a tight look that calls TASK_YIELD whenever > it doesn't find data. This is how threads "block" in a cooperative > multi-tasking system. The thread can also "sleep" for some time (which is usually the timeout) then it won't waste not even one single CPU cycle, and the ISR may awake it when data is available. It may awake either by timeout or because the ISR received some data, and act accordingly. > I have done this sort of thing many times with PICs, and found it to work > well and the input processing to fall out rather naturally. > > The issue with using interrupts for each piece of input data versus polli= ng > the hardware by the receiving thread is not one of efficiency but of > responsiveness to the hardware. Depending on what the system is doing, > there might be too much time between successive invocations of the receiv= ing > thread such that the UART (or whatever your input hardware is) gets overr= un. > Interrupt receiving followed by a FIFO is a bit more complicated and > therefore slightly less efficient, but allows averaging the processing po= wer > over multiple input bytes to be applied to the stream. Usually the probl= em > with the input overrunning the receiving thread is one of latency and > burstiness, not of overall cycles. If you don't have enough cycles long > term, you're screwed anyway. > > The FIFO allows you to go to lunch for several characters at a time, then > catch up by draining a whole bunch of characters from the FIFO in a burst > later. Unless you are using a slow baud rate and know exactly what's goi= ng > on in the CPU, I would go with a interrupt driven input FIFO. Often just= 8 > bytes is enough to smooth out the burstiness of the thread scheduling, but > of course you'll have to do your own math to determine what you need. For > example, if you think a thread may be held off for as long as 1mS (quite a > long time actually) and input is via UART at 115.2Kbaud, then the FIFO ne= eds > to be at least 12 bytes. In that case 16 sounds like a nice round number. > 16 bytes plus maybe another 2 for FIFO control isn't a big deal on most > PICs. If the RTOS's tick is 1ms, the latency may be several ms depending on the number of threads, unless the thread priority is raised above all the others, then it runs at the beginning of each tick. In this case, a "Sleep(1)" will allow the other threads to use the remaining of each tick. The ISR may receive several bytes before the task get a chance to run (and will call "ResumeTask" this same number of times, but only the first does anything). When the task effectively runs, there may be lots of bytes to process, then it processes these bytes at once and sleeps again (or process the resulting packet). Isaac __________________________________________________ Fale com seus amigos de gra=E7a com o novo Yahoo! Messenger = http://br.messenger.yahoo.com/ = -- = http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist