On Sat, 2003-12-20 at 11:10, Bruce Partridge wrote: > Repost with correct tag. > > I am running a controller on an 18F452. I am using a 4Mhz clock, with a > 32Khz crystal on timer1. The controller is battery operated, and sleeps > when not in use. The clock is maintained by timer1 waking the unit up and > updating. > > My problem is that I have several high priority tasks that need to be > serviced regularly in relatively short time frames. For example, several > times per second, several sensors need to be read and the results acted > upon. Also the lcd display needs to be updated, and I need to respond to > buttons. These tasks are not very long, but so far, I am just checking > whether they need to be run in the timer1 isr, and then running them as > required in the mainline. > > I have now added a task that takes several seconds to run. Worse, the time > it takes to run depends on external conditions. Sometimes it will take one > second, and sometimes it will take 15 seconds. There is also another long > task, but not as long. It is run before the longer task. > > My current thoughts are to run the clock by itself on timer1 as a high > priority interrupt. The buttons would also be on high priority interrupts. > Then the other short tasks would be on another timer at a lower priority. > The whole task would run in the isr. > > I would then have two long tasks run one after another in the mainline. > > Is this the right way to do this. > > Bruce Partridge This seems alright however there are a couple of gotchas that I can think of. 1. Memory. Be careful about memory allocation, especially for temporary variables and particularly if you are writing in assembler. There is no guarantee at what point your code will be interrupted. If you are sharing temporary variable memory space you may have data in a temporary variable that you may overwrite in the high priority process. Most high level compilers should catch/prevent this in one way or another. touch wood :-). 2. Race Conditions. If your low priority processes use shared variables that are also accessed by high priority processes the arbitrary interruption can cause race conditions. EXAMPLE -- Highly contrived C Code Process A Process B i++; i++; Assembler movf i ---->INTERRUPT--> movf i addlw 1 movwf i <---RETURN<----- addlw 1 movwf i In this example i is incremented only once despite both processes attempting to increment i Problems caused by this kind of behaviour can be extremely difficult to diagnose and can cause problems at weird times and weird locations. the best way to solve this kind of problem is to implement semaphores or locks for these variables, however be aware of race conditions in your semaphores and be aware of point 3. One way of doing this may be to clear the Global Interrupt Enable bit when doing any operation on a shared variable and then set it again afterward. This assumes that the GIE bit is always set during the normal processes. 3. Deadlock Deadlock is caused by a process waiting for a resource that does not become available, such as a semaphore. Often caused by two competing processes waiting for two semaphores, where each process holds one and cannot proceed until one process holds both ( A Starvation Deadlock. cf. Dining Philosophers Problem). Using the GIE bit as a semaphore SHOULD not cause this problem (Caveat Emptor). Other forms of deadlock may occur. Good Luck Mark Hore -- http://www.piclist.com#nomail Going offline? Don't AutoReply us! email listserv@mitvma.mit.edu with SET PICList DIGEST in the body