Forums

Help with small kernel..

Started by Unknown January 20, 2004
Hi, I'm writing a little "kernel" for a small microprocessor.
Right now it just implements tasks, and does scheduling.
That is , I have a timer fire every ms in which the interrupt
handler sets up the kernel stack and pc, and the "kernel"
merly checks if the current task has reached its timeslice.
Now I want to do some abstractios over events.For now interrupts,
but have no idea what that takes. One of the interrupts signals
the press of a button, I want tasks to wait on such an event.
Whats the basis of doing that ? I'd like the interrupt handlers
as small as possible. 
One solution I can think of is to let the interrupt handler append
events to a queue, and on each kernel tick check the event queue
and if there are any task waiting.. but that seems odd. And
rather high latency since little happens until my 1 ms tick.
Basically, how to make tasks wait for events, and how to let 
interrupt handlers signal that an event happened.

Message que seems like one possible answer, I know that
things like this are oftenly done (waiting for a event) in a way that
your function (for example wait_button()) returns 0 if button wasn't
pressed and returns 1 if button was pressed. And in your task you would
have something like:

function task_keypad()
{
  if (wait_button())
  {
      ...
      do_button_routine
      ...
  }
}

I have seen this kind of event handling in Dynamic C (for Rabbit
processors).

Mickey


In article <buir01$l14$1@ls219.htnet.hr>, MArk wrote:
> Message que seems like one possible answer, I know that > things like this are oftenly done (waiting for a event) in a way that > your function (for example wait_button()) returns 0 if button wasn't > pressed and returns 1 if button was pressed. And in your task you would > have something like: > > function task_keypad() > { > if (wait_button()) > { > ... > do_button_routine > ... > } > }
This is no problem. The problem is what does the wait_button() do. How and when should my "kernel" handle the(for this example) button event, what should the interrupt handler for the button do.
"Nils O. Sel&#2013265925;sdal" <noselasd@frisurf.no> wrote in message
news:slrnc0pstk.oe.noselasd@utelsystems.dyndns.org...
> In article <buir01$l14$1@ls219.htnet.hr>, MArk wrote: > > Message que seems like one possible answer, I know that > > things like this are oftenly done (waiting for a event) in a way that > > your function (for example wait_button()) returns 0 if button wasn't > > pressed and returns 1 if button was pressed. And in your task you would > > have something like: > > > > function task_keypad() > > { > > if (wait_button()) > > { > > ... > > do_button_routine > > ... > > } > > } > This is no problem. The problem is what does the wait_button() do. > How and when should my "kernel" handle the(for this example) button event, > what should the interrupt handler for the button do.
wait_button() sees if there's an unhandled button event that needs processed. If there is, the code proceeds without delay. If not, it suspends (moves them to the waiting queue) the current task and appends itself onto the list of tasks waiting for a button event. The interrupt handler for the button handles the hardware and flags the OS that a button event has occured. The OS scheduler, when it gets a button event, sees if there are any processes that are suspended waiting for a button event. If there are, those processes are moved to the ready queue. Almost any college OS text in the last 20 years covers this in detail. Kelly
noselasd@frisurf.no  wrote in message news:<slrnc0pqeu.mi.noselasd@utelsystems.dyndns.org>...
> Hi, I'm writing a little "kernel" for a small microprocessor. > Right now it just implements tasks, and does scheduling. > That is , I have a timer fire every ms in which the interrupt > handler sets up the kernel stack and pc, and the "kernel" > merly checks if the current task has reached its timeslice. > Now I want to do some abstractios over events.For now interrupts, > but have no idea what that takes. One of the interrupts signals > the press of a button, I want tasks to wait on such an event. > Whats the basis of doing that ? I'd like the interrupt handlers > as small as possible. > One solution I can think of is to let the interrupt handler append > events to a queue, and on each kernel tick check the event queue > and if there are any task waiting.. but that seems odd. And > rather high latency since little happens until my 1 ms tick. > Basically, how to make tasks wait for events, and how to let > interrupt handlers signal that an event happened.
When faced with the task of making a very simple kernel for a nonetheless significant project, I chose to abandon the system tick as a basis for task context switch. Instead, the "wait for event queue non-empty" primitive was used as the primary task synchronization feature. The interrupt service routines do indeed insert events in queues as your post suggests. This is now part of the ABCD Proto-Kernel(tm) at http://www.connotech.com/abcd_proto_kernel/abcd_proto_kernel_intro.htm - Thierry Moreau CONNOTECH Experts-conseils inc. 9130 Place de Montgolfier Montreal, Qc H2M 2A1 Tel.: (514)385-5691 Fax: (514)385-5900 e-mail: thierry.moreau@connotech.com
>> Hi, I'm writing a little "kernel" for a small microprocessor. >> Right now it just implements tasks, and does scheduling. >> That is , I have a timer fire every ms in which the interrupt >> handler sets up the kernel stack and pc, and the "kernel" >> merly checks if the current task has reached its timeslice. >> Now I want to do some abstractios over events.For now interrupts, >> but have no idea what that takes. One of the interrupts signals >> the press of a button, I want tasks to wait on such an event. >> Whats the basis of doing that ? I'd like the interrupt handlers >> as small as possible. >> One solution I can think of is to let the interrupt handler append >> events to a queue, and on each kernel tick check the event queue >> and if there are any task waiting.. but that seems odd. And >> rather high latency since little happens until my 1 ms tick. >> Basically, how to make tasks wait for events, and how to let >> interrupt handlers signal that an event happened. > > When faced with the task of making a very simple kernel for a > nonetheless significant project, I chose to abandon the system tick as > a basis for task context switch. Instead, the "wait for event queue > non-empty" primitive was used as the primary task synchronization > feature. The interrupt service routines do indeed insert events in > queues as your post suggests.
Thanks, I'll take a look at it.
<noselasd@frisurf.no> wrote in message
news:slrnc0pqeu.mi.noselasd@utelsystems.dyndns.org...
> One solution I can think of is to let the interrupt handler append > events to a queue, and on each kernel tick check the event queue > and if there are any task waiting.. but that seems odd. And > rather high latency since little happens until my 1 ms tick. > Basically, how to make tasks wait for events, and how to let > interrupt handlers signal that an event happened.
Take a look at http://sourceforge.net/projects/xmk/. It has a preemptive priority based scheduler. It should give you some ideas on how to 'wake-up' threads from an interrupt services without having to check state of every thread on every interrupt.
noselasd@frisurf.no wrote:
> > Hi, I'm writing a little "kernel" for a small microprocessor. > Right now it just implements tasks, and does scheduling. > That is , I have a timer fire every ms in which the interrupt > handler sets up the kernel stack and pc, and the "kernel" > merly checks if the current task has reached its timeslice. > Now I want to do some abstractios over events.For now interrupts, > but have no idea what that takes. One of the interrupts signals > the press of a button, I want tasks to wait on such an event. > Whats the basis of doing that ? I'd like the interrupt handlers > as small as possible.
The classic mechanism is a semaphore. A task does a "P" (pend) operation on a semaphore. If the semaphore count is zero, the task is suspended. One implementation is for the semaphore to point to a queue of tasks waiting on the semaphore. Waiting tasks should be queued in priority order. An interrupt routine can activate a task by performing a "V" operation on a semaphore. If any tasks are waiting on it, the OS then makes the highest priority task ready to run. If the newly ready task has a higher priority than the task which was running when the interrupt occurred, the active task indicator is changed. In order to accomplish this with multiple interrupt nesting allowed, usually the interrupt handler increments the interrupt nesting level. When exiting the interrupt, the OS decrements the nesting level. If it is non-zero, the normal return is made. If zero, the check is made for task switch. If none, a normal exit is done. If switching occurred, magic happens: it saves the state of the old task in its TCB and then performs a return from interrupt which resumes the newly active task. The activation can be done without semaphores by having the interrupt routine directly activate a given task. All this must be done with careful consideration of what code can be interrupted and what must be protected. If interrupts are disabled for too long, interrupt latency suffers. Thad
thierry.moreau@connotech.com (Thierry Moreau) writes:

> When faced with the task of making a very simple kernel for a > nonetheless significant project, I chose to abandon the system tick as > a basis for task context switch. Instead, the "wait for event queue > non-empty" primitive was used as the primary task synchronization > feature. The interrupt service routines do indeed insert events in > queues as your post suggests.
I haven't a wide experience with embedded systems, but the system tick concept always seemed a bit odd to me. One OS we dealt with was slightly annoying since the system tick functionality stole a very useful timer. Basic semaphores, of the type that have been around for many decades, solve the problem. A task waits on a semaphore and is suspended, and the interrupt signals the semaphore which may cause it to wake up. The implementation isn't hard. Each semaphore has a list or array of tasks waiting on it, and when it's signaled one of the tasks becomes runnable again. At the end of the interrupt the task with the highest priority is resumed, which may not necessarily be the task that was interrupted. All other synchronization or IPC mechanisms can be built on top of a semaphore primitive, such as message queues. -- Darin Johnson "Floyd here now!"
On Tue, 20 Jan 2004 08:42:33 +0000, noselas wrote:

> Hi, I'm writing a little "kernel" for a small microprocessor. > Right now it just implements tasks, and does scheduling. > That is , I have a timer fire every ms in which the interrupt > handler sets up the kernel stack and pc, and the "kernel" > merly checks if the current task has reached its timeslice. > Now I want to do some abstractios over events.For now interrupts, > but have no idea what that takes. One of the interrupts signals > the press of a button, I want tasks to wait on such an event. > Whats the basis of doing that ? I'd like the interrupt handlers > as small as possible. > One solution I can think of is to let the interrupt handler append > events to a queue, and on each kernel tick check the event queue > and if there are any task waiting.. but that seems odd. And > rather high latency since little happens until my 1 ms tick. > Basically, how to make tasks wait for events, and how to let > interrupt handlers signal that an event happened.
This problem has been thoroughly thought out and solved with a simple round-robin multitasker in Forth. Free with most/many variants. Whenever a 'pause' is encoutered the cooperative multitasker relinquishes control to the next task. If that task is sleeping then the cost is a simple jump instruction to the next task. Any task can put any other task to sleep, wake another task, or add a task. Pre-emptive multitaskers usually have a lot of overhead to consider. -- Regards, Albert ---------------------------------------------------------------------- AM Research, Inc. The Embedded Systems Experts http://www.amresearch.com 916.780.7623 ----------------------------------------------------------------------