Friday, October 12, 2012

5. MQX RTOS Handling Interrupts -2


How to install an application ISR?

By call _int_install_isr(). MQX updates its interrupt vector table appropriately and calls your ISR handler when ever your interrupt occurs.

You might have guessed from my previous post when installing an ISR you have to supply
  • Interrupt Number
  • ISR function pointer
  • data pointer
Whats most frequent things Done in ISR?
  • setting a event bit
  • posting a semaphore, message queues etc.
  • DE-queing a task from task queue
 Whats all  MQX does not allow to place in an ISR?
 Basically, MQX has put some intelligent to stop you doing some stupid thing inside ISR. If you try to perform those illegal operations MQX would return error. You cannot 
  • cannot create/destroy a semaphore/message queue/events
  • cannot wait for an event inside an ISR
  • to cut the chase, you can not create any kernel object inside an ISR
 What you should not call inside an ISR?
  • No IO functions as they may take unpredictable time
  • never call _int_default_isr
  • any wait event function
  • any mutex lock operation
  • never create/destroy a task
  •  
     Next topic explains Semaphores in detail. Click here

Thursday, October 11, 2012

4. MQX RTOS Handing Interrupts -1



MQX handles HW interrupts and exceptions with interrupt service routines (ISR). Please note the sentence ‘exceptions are handled by ISR’. In due course I would discuss my experience with some very interesting problem involving exception ISR.

What an ISR? What goes inside an ISR?
ISR is not a task. It’s a small piece of code which is executed whenever an interrupt occurs. The main functionally of ISR may include
a)      Servicing a device
b)      Clearing an error condition
c)       Singling a task

MQX allows to pass a parameter to the ISR handler whenever application is installing an ISR. This parameter is a pointer. Please note that this pointer should not be at task stack, as it can be called even before task is created.

People keep on saying ISR should be precise. Well, that makes lots of sense as during ISR other interrupts may be disabled. And you definitely not want to miss the interrupts. Are you asking for example?
Hmm, let’s say whenever aeroplane’s engine is getting too hot, cooling procedure should be initiated immediately.  Now, this is how it would work, a sensor would trigger an HW interrupt, and ISR would ask you application to run the Cooling Task. But wait, you application is handling a pervioius ISR which has disabled other interrupts. And you are playing ‘print Hello word’ a zillion time game there in ISR(just kidding!). So you would miss the interrupt.( And lets hope you are not flying on the plane )


Back to serious stuff.

What is Kernel ISR?
MQX provides a kernel ISR(_init_kernel_isr()) which is written in assembly language. The kernel ISR runs before any other ISR. And it
a)      saves the context of the active task.
b)      switches to the interrupt stack .
c)       calls the appropriate ISR .
d)      after the ISR has returned, restores the context of the highest-priority ready task
When MQX starts it installs kernel ISR to all interrupts.

Initializing interrupt handling/Installing interrupts and Default ISR
       When MQX starts, it initializes its ISR vector table which has entry for all interrupts. Each entry consists of  a)   pointer to ISR  b)data to pass as parameter c)   Default exception handler.

Initially ISR for each entry is ‘_int_default_isr()’.
All of this is performed by a MQX kernel function called _int_init(), which loops for all interrupts and does what I mentioned above.

continued in next post. Click here

Good article on ARM exception handling
http://www.csie.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf 

MQX RTOS Tutorial, MQX Tutorial, RTOS Tutorial

Wednesday, October 10, 2012

3. MQX Events. Event Handling, Building an Event based application

Events



Events can be used to synchronize tasks. Just to make it simpler, you can imagine an event a bit in the 32 bit integer number (mostly, that is the word size of a MQX RTOS).
So this is how it would happen:
a) Somebody-1 would be waiting for this bit to be set. Until this bit is set that somebody would be stuck.
b) And Somebody-2 would set that bit so that somebody-1 can proceed further.
So in crude and very layman sense, events in RTOS are nothing but setting/clearing one bit.  

Now let’s add few more technicalities to it.

Somebody-1 above normally would be tasks which would wait for something. And sombebody-2 could be another Task or ISR.
In fact many embedded applications work this way, ISR gets triggered and as ISR handlers should be very small, they normal set an event and exit. So it serves both purposed ISR finishes quickly and also your application logic of waiting gets out of ISR. (in fact this is the most widely approach of designing ISR/task based applications).  

Why not use Setting/Clearing of bits than Events? What extra ROTS event handling adds apart from setting clearing bits?

a)      First and for most, whenever RTOS calls are setting/clearing event bit that part of kernel code is 100% atomic and safe. I mean, as done for other parts of kernel, when updating (here setting/clearing bit) interrupts are disabled.
      (Imagine you try to mimic the events and you are about to clear the bit and suddenly and ISR comes which tries to set the same bit. Well, that would be it for your logic.)  
If you have access to MQX source it would be fun exercise to trace the implementation of set/get event.

b)      Option to wait for single event (one event) or many events in single call.
_event_wait_all -> if you choose this one your wait call would be blocked until all the events(bits) you specified in the mask are set.
_event_wait_any -> if any of the events(bit) specified in the mask is triggered.

c)       RTOS has data structure called run queue and blocked queue. So event wait call need not be a infinite for loop. If you are implementing the events try to think how would be your WaitEvent call. As you don't have those data structure it would have to be infinite loop.
      RTOS has that(run, blocked queue) info, so when it hits a event wait call, it puts that task to blocked list. When it receives the event it checks the blocked queue and puts that task to ready queue.
      Infinite loop are big NO in embedded systems. As in that case, CPU would be performing loop operation and consuming power.

d)      Option to unblock all the tasks. Suppose 3 tasks are waiting for an event, and event is received. There in an option in MQX which would automatically clear the event as soon as it arrives and unblock all the tasks.

e)      You can also pass timer parameter to the wait event calls, means you will only be blocked for x mill secs.


BTW, MQX comes with two type of event handling, one with lightweight event handling and second one is (let’s say) normal event handling. Lightweight APIs are targeted to single processor systems while other one can handle more than one processor. Remember, in first MQX  post when I said MQX can handle more than one processors.


 PS: I intentionally have avoided to put the API names, thinking behind this is concepts are more important than the API names.


Continue reading about events here

One interesting MQX problem I faced can be found here


Tuesday, October 9, 2012

2. Starting MQX, Scheduling and Managing Tasks

I talked about the Task templates in my last post.
The lower the priority value of the task the higher the priority. You can remember this easily by knowing that if you create a task with priority 0, this task will run will interrupts disabled.

There is one more thing you should remember, MQX creates one ready queue for each task up to lowest priority. This creation is done by reading task template at the boot up time. So, you cannot create a task having lower priority than the lowest of task template.

If (hopefully) you are aware of any OS task creation APIs, well this ones is not that much different. Only names would change so I am skipping typing the obvious here.

Scheduling of Tasks 

I won't be able to discuss the topic without describing various states of a task in MQX.
There are three states
1) Blocked : task is not ready because its blocked on some condition to occur. 
2) Ready : task is ready to become active but its not active. This is because its same or lower priority than the active task.
3) Active : Task is running.

Task Creation APIs
 Nothing much different than any other OS. You can create a task by api called '_task_create', you could also create a task which would be in blocked state by api named '_task_create_blocked'. Blocked task can be made ready by _task_ready().

There are other APIs too to get task id, get creator task id, get error code id,  getting/setting exit handler, restarting task, setting error code etc.

Its worth mentioning error code here. Whenever something bad happens to a task it given an error code. If task is allowed to run even after error it may enter to some other error state. But the first error code is not overwritten, this is just to give clear indication to the user whats the original error.


Terminating Task 
A task can terminate itself or it can be terminated by other task. Whenever a task is terminated its children are NOT killed. Whenever a task terminates, MQX frees it all resources like dynamic allocated memory blocks and partition blocks, lightweight semaphore, message queues, mutex etc.


Task Scheduling  
Three policies are provided. Please note all are preemptive.

i) FIFO 


Its default policy. Next task to run here would be that which is waiting for longest. The active task runs until anyone of flowing occurs
-        -Active task voluntarily relinquishes the processor because it calls a blocking function.
-       -Higher priority interrupt occurs
-       -A task having higher priority becomes ready


ii) Round Robin
 Same as FIFO but it has additional constraint that each round robin task a maximum amount of time slice during which it can be active.
You do need to set the time slice for this type of scheduling.  

iii) Task Queues
Look for this space will scribe about it later.

Read about MQX Events. Event Handling, Building an Event based application here