Monday, February 24, 2014

Task Management: Just Exit Vs Exit and delete

① Exiting Task

The aeroplane went down for landing. After touched down the runway, it got signal to lift off, and it took off. Exiting task does the same. It resets all the TCB parameters. And, if there is pending activation requests, it starts the task freshly. But, remember that it is removed from Ready queue and added again to maintain the order of activation (precedence) of tasks which are in the same priority. Also remember that the scheduling is done without saving the context of the executing task since it is assumed to exit and no more existing.
Remember one more important thing. The task is not deleted. It should be able to be activated again. So, the TCB is needed to be brought back to the state of after task creation. Especially, the parameters passed by the user in cre_tsk() need to be restored. All allocated items are kept as it is.

② Exiting and Deleting task

Just releasing the resources and calling scheduler not to save current context, but only schedule others. Remember the scheduler (dispatcher) itself acts as unlocking of critical section. It unlocks the critical section before getting scheduled to any other execution point. Whether all calls to the dispatcher has the critical section locked needs to be checked. Otherwise, the masking of interrupt level itself is considered as masking of execution of dispatcher. Masking of any interrupt level just above the task level will cause the dispatcher not to be scheduled and always return to the same task.

The precedence is as follows as per specification.
Precedence:
1) Interrupt Handlers, time event handlers, CPU exception handlers
2) Dispatcher (one of the kernel processes) (Assume this Highest priority task) - Interrupt Level 16
3) Tasks - Interrupt Level 16
③ uITRON implementation of ext_tsk

void ext_tsk(void)
{
        If the called from ISR or Dispatch disabled state or from dispatcher
                return E_CTX;
        Enter critical section
        Take the TCB
        Reset the task priority and base priority to what user had set initially
        if there is taks exception handler defined {
                clear the pending exception pattern
                Disable the exception handling
                Reset backup of task context to NULL, since it is no more going to be used
                /* Hopefully the backup context is not referred, if this is called from
                   inside exception handler */
        }
        Remove the tcb from the Ready queue (it should be in ready queue)
        If (it is holding any mutex) {
                unlock all mutexes as specified below
                set the head pointer to the locked mutex as NULL
        }
        if (there are pending activation requests) {
                Reduce the count by one
                /* Same as sta_tsk and act_tsk. But, one difference is here, you
                   cut the tree on which you are sitting on. You are going to edit the
                   context of yours which exists on the same stack space where the
                   program itself is running. So, atleast you have to make sure that
                   the stack pointer is apart from the context area */
                Set the initial context just above the bottom of the stack
                call assembly routine to reset the stack pointer to just above the context
                /* context initialization same as of sta_tsk, act_tsk */
                context's argument register = stacd
                Initialize context's Link register (return address) = ext_tsk function
                According to task attributes such as enabled FPU,
                        Initialize/Enabling of the FPU related registers
                Initialize program status register
                context's program counter = task start address;
                Initialize other values and counts of the context;
                status = READY;
                wake-up and suspend count and overrun count = 0;
                Add the task to the Ready Queue of priority
                /* Anyway, the scheduler will be called */
                call scheduler not to save current context, but only schedule others
                /* It No more returns here */
        }
        status = DORMANT;
        call scheduler not to save current context, but only schedule others
        /* It No more returns here */
}

void unlock_all_mutexes()
{
        /* Parse through all mutexes locked by the task */
        Take the first mutex locked by the Task
        while (there is mutex locked by the task) {
                Keep the next mutex linked to this mutex (belongs to the same task)
                Isolate(unlink) this mutex by setting the next field to zero
                /* Grant this mutex to one waiting task and wake it up */
                For all tasks waiting in this mutex's queue (from head having highest priority tasks) {
                        Take a task.
                        If it is waiting as Timeout, remove it from timer queue
                        Remove the task from the mutex's queue
                        Set tcb status as Ready
                        /* Sanity check and lock assignment as if it called loc_mtx */
                        If the mutex attribute is Ceiling and the task has higher base priority {
                        /* When ths task is waiting, base priority is changed by chg_pri() */
                                Error code parameter of tcb = E_ILUSE
                                Add the task to the Ready queue
                                If the task's priority is higher than the current task's priority
                                        Set to call scheduler when quitting this function
                                Take next task and continue checking from first
                        } else {
                                If the mutex has CEILING attribute and
                                the ceiling priority is higher than the task priority{
                                        the task (tcb) priority is set to the ceiling priority
                                } else {
                                        the task's priority is set as current highest
                                            priority locking the mutex
                                }
                                Set the task as locking task
                                Add the mutex in the task's queue of mutexes
                                If the task's priority is higher than the current task's priority
                                        Set to call scheduler when quitting this function
                        }
                }
                Assign the next mutex as this mutex
        }
}

④ uITRON implementation of exd_tsk()

void exd_tsk(void)
{
        Enter critical section
        Take the TCB
        Remove the tcb from the Ready queue (it should be in ready queue)
        If (it is holding any mutex) {
                unlock all mutexes as specified in ext_tsk()
        }
        Release the memory allocated for any element in TCB
        /* Bring back the task to non-existent state so that the task entry can be allocated to any other task */
        Assigning NULL to the task entry etc.
        call scheduler not to save current context, but only schedule others
        /* It No more returns here */
}

Unexpectedly Exiting and Deleting is easier than just exiting..

Task Management: Cancel activation

① Cancellation of activations

It is just simple that it makes the pending number of activations to zero in the task control block and returns the (cancelled) pending number of activations.

And, to note that the pending count is count of activations raised when the task is not in Dormant state. When the task exists, it is re-used to activate the task again. But, when the task is deleted, all counts just vanish.

② uITRON Implementation of can_act()

ER can_act(ID tskid)
{
        Sanity check on arguments
        Enter critical section
        Get the count of number of pending activations from the task control block
        Make the number of pending activations for the task to zero
        Exit critical section
        return the count
}

 

Task Management: Start Task Vs Activate Task

 ① About act_tsk()

The fair part of making a simple function into a task is done by act_tsk(). It does the job of setting up the stack memory, setting up the initial register values of the context as if the task now sleeping just before the task's start function. And, it has been called from task exit processing function. The argument will be the value set in the extended information. So, it needs to initialize particular registers to simulate the scenario which is depend on the ABI (Application Binary Interface) specification of the exeuction environment( CPU, compiler, etc). Other registers can be arbitrary values.

② Difference between the act_tsk and sta_tsk

Both are almost same except two things.
1) In sta_tsk(), the argument of the task function is passed from user. But, in act_tsk(), the extended information pointer is passed to the task start function.
2) In act_tsk(), the activation count is accumulated. But, sta_tsk() is not like that. It just starts the task.

③ uITRON implementation of sta_tsk()

ER sta_tsk(ID tskid, VP_INT stacd)
{
        Sanity check on arguments;
        Enter critical section;
        if (task is in the dormant state) {
                Move to the high address of stack space (bottom);
                Assume that the context is saved in the stack, so move up one
                context size from the bottom and assign it as current stack
                pointer of the context;
                /* The contents of registers when the task begins executing are
                   not guaranteed. So, not all of the registers but few
                  important registers of the context needs to be initialized */
                /* This will be hardware dependent portion */
                /* Especially, all special purpose register value needs to be initialized */
                /* As if ext_tsk is called by default when exiting the task function, */
                Initialize context's Link register (return address) = ext_tsk function
                According to task attributes such as enabled FPU,
                        Initialize/Enabling of the FPU related registers
                Initialize program status register
                context's program counter = task start address;
                context's argument register = stacd
                Initialize other values and counts of the context;
                status = READY;
                wake-up and suspend count and overrun count = 0;
                Add the task to the Ready Queue of priority
                If (the tw-task priority is higher than the current){
                        Call scheduler
                        Return error code from scheduler
                } else {
                        Exit critical section and return error code from it (E_OK)
                        (return E_OK)
                }
                exit critical section and return
        }
        exit critical section and return error code
}

④ uITRON Implementation of act_tsk()

ER act_tsk(ID tskid)
{
        Sanity check on arguments;
        Enter critical section;
        if (task is in the dormant state) {
                Move to the high address of stack space (bottom);
                Assume that the context is saved in the stack, so move up one
                context size from the bottom and assign it as current stack
                pointer of the context;
                /* The contents of registers when the task begins executing are
                   not guaranteed. So, not all of the registers but few
                  important registers of the context needs to be initialized */
                /* This will be hardware dependent portion */
                /* Especially, all special purpose register value needs to be initialized */
                /* As if ext_tsk is called by default when exiting the task function, */
                Initialize context's Link register (return address) = ext_tsk function
                According to task attributes such as enabled FPU,
                        Initialize/Enabling of the FPU related registers
                Initialize program status register
                context's program counter = task start address;
                context's argument register = argument passed using extended information
                Initialize other values and counts of the context;
                status = READY;
                wake-up and suspend count and overrun count = 0;
                Add the task in the ready queue
                Add the task to the Ready Queue of priority
                If (the tw-task priority is higher than the current){
                        Call scheduler
                        Return error code from scheduler
                } else {
                        Exit critical section and return error code from it (E_OK)
                        (return E_OK)
                }
                exit critical section and return
        }
        Otherwise, add the call into the activation count;
        If the activation count is more than the maximum,
                set it to the maximum and set error code to E_QOVR;
        exit critical section and return error code
}

If you want your task to run as many times as you revive it, then use act_tsk..

Task Management: Create Task

① Creating Task

All the parameters from user side are passed. They are Task Start address, Stack size, Priority, stack space address if have preferred address space, as only allocation and initialization to default are performed here. Some more attributes such as Task has to be activated just with this call also passed here. Task moves from Non-existent state to Dormant state. If the task is activated inside, taks enters to Ready queue for the first time.

② ITRON implementation of cre_tsk()

ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
{
        /* Clear distinction between the system calls that can be called from non-task contexts */
        If (called from ISR)
                return E_CTX;
        Sanity check on arguments;
        Enter Critical section;
        Allocate memory for TCB and stack;
        Initialize TCB as follows;
        state = DORMANT, activated=0, lock acquired=0
        base priority=current priority=assigned by user
        stack pointer=Address of the stack space
        exception handler=NULL;
        Initialize the stack space excluding the space for context as
         in sta_tsk the initial context will be formed inside the stack space
        Exit critical section
        if the activate flag is set
                activate the task;
        return E_OK;
}

Create just takes backup of arguments and allocates resources..

Bluetooth Related

1) What is Bluetooth and WLAN frequency range?

Bluetooth - ISM (Industrial, Scientific, Medical) band 2.4 MHz + 83 MHz wide
WiFi too same 2.4 MHz + 83 MHz wide

2) Do not they corrupt each other as both working on the same frequency?

Ofcourse. But, each follow different protocols that facilitates to overcome the loss of data due to inteference.

"Bluetooh Hops Away and Tries Again"
 
Bluetooth divides the band into 79 different 1 MHz channels. And, it uses FHSS (Frequency Hop Spread Spectrum) which means Bluetooth hops into these different channels in predefined manner in sync with peer to transmit the data. For example, one bit on 8th channel, next bit on 29th, next bit on 21th, like that. So, if the WiFi channel (explained next) interference causes a loss of data in Bluetooth, as it hops to the next frequency channel, there is chance to get the data.
 
"WiFi slows down and Tries Again"

WiFi on the other hand, divides the band into 22 MHz channels with fixed frequency range (DSSS - Direct Sequence Spread Spectrum) which is fixed for data transmission of one node. There could be maximum of 11 overlapping channels or 3 non-overlapping channels. (So, there can be no more than three different WiFi networks operating in close proximity to one another.) When Bluetooth interferes WLAN channel, WLAN assumes that collision occured due to stations trying to transmit simultaneously and does retransmission of data similar to Ethernet.
 
There are few methods for co-existence. Recently, WLAN is getting moved to 5.2 GHz frequency band.

3) Difference between different Ethernet protocols?

WLAN - CSMA/CA Carrier Sense Multiple Access/Collision Avoidance - Make sure the medium is idle before Transmission. Cannot listen the medium when transmitting, so cannot detect collision. Transmit full frame. If not acknowledged, retransmit.
 
10BASE Ethernet - Half duplex - CSMA/CD Collision Detection - Wait for the medium to be free, transmit single bit and listen the medium if any collision occured. If so, retry after random period. If no, transmit next bit.
 
100Mbps/Full duplex - Separate wires for transmit and reception and direct connection with peer. So, medium itself made collision free.

4) Does low power Bluetooth use the same band?

Yes. Uses same frequency spectrum range 2.4 GHz ~ 2.4835 GHz ISM Band as of classic Bluetooth. But, uses different set of channels, instead of 79 1MHz channels, uses 40 2MHz channels.

Range is 50m (Classic is 100m)
DataRate 1Mbps (Classic is 1~3Mbps)
Peak current consumption <15ms (Classic is < 30ms)

Bluetooth smart - 極低電力で動作する無線通信規格Bluetooth Low Energy (BLE)に対応を提示するブランド名
                           きょくていでんりょくでどうさするむせんつうしんきかく Bluetooth Low Engegyにたいおうをていじするブランドな

                        BLEはBluetooth 4.0で採用されている、通信可能距離が短く(50m)、通信速度は低速(1Mbps)、ボタン電池で数年稼動する(アイドルの時数uA、動作する時に<15mA)
                        BLEはBluetooth 4.0でさいようされている、つうしんかのうきょりはみじかく、つうしんそくどはていそく、ボタンでんちですうねんかどうさせる

                        小型の機器で使われる(時計、リモコン、。。。。)
                        こがたのききでつかわれる

Bluetooth smart ready - is brand name for computers which support BLE as well as Bluetooth classic

(http://e-words.jp/w/Bluetooth20Smart.html)
(http://en.wikipedia.org/wiki/Bluetooth_low_energy)

5) What is the specification for ANT?

ANT - proprietary open access multicast wireless sensor network
Communicates over the same RF spectrum of 2.4GHz (ISM Band)
When working, consumes around 60uA current.

Bluetooth was not designed for large wireless sensor networks. Still, it can form star network of maximum 8 devices (one master and 7 slaves). But, ANT is for large wireless sensor network. ANT supports file transfer of upto 60 kbps.
 
ANT uses adaptive isochronous networking topology. This scheme is very flexible and within a fixed frequency band, data is transmitted in different time slots. Transmission occurs when there is no interference in the frequency band. The radio transmits for less than 150us  per message. The available number of time slots also determined by the messaging period (time interval between data transfer of each node). If the radio band is crowded, ANT allows application to hop to alternative 1MHz channel in the 2.4 GHz band.

6) What are the products supported?

・ARM based System-On-Chip (ARMベースのシステムオンチップ)
・(Single Chip) IC (シングルチップIC)
・Development Kits (開発キット)
・プロトコルスタック

into four different categories:
1) Bluetooth Low Energy
2) ANT
3) 2.4 GHz RF
4) 1GHz RF

7) Bluetooth support over Linux

BlueZ Linux Bluetooth protocol stack is official Bluetooth stack for Linux.

Directory: linux/net/bluetooth
Configuration option:
Networking support -> Bluetooth subsystem support
 
8) WLAN support over Linux

WLAN has built in support in Linux. Do you remember, WLAN does not have any separate stack as it just uses the same protocol stack with just at hardware level few WLAN drivers and some thin layer to manage the connections comes.

9) PAN setup over Linux

 

 it never ends...

Thursday, February 13, 2014

Task exception: Refer status

① Difference between sns_tex and ref_tex

sns_tex() returns only the disable state of task exception handler. But, ref_tex() returns the enable/status of task exception and pending exception pattern.

② uITRON implementation of sns_tex

BOOL sns_tex()
{
        /* if there is not running task, return TRUE */
        if (task running is just idle task)
                return TRUE;
        Otherwise, take the TCB of whoever executing this task
        Enter critical section
        If exception handler is not defined at all
                Exit critical section and return TRUE;
        If exception is disabled
                Exit critical section and return TRUE;
        otherwise
                Exit critical section and return FALSE;
}
③ uITRON implementation of ref_tex

ER ref_tex(ID tskid, T_RTEX *pk_rtex)
{
        Sanity check on arguments
        Enter critical section
        If the task is in the dormant state or task exception handling
        routine is not defined
                Exit critical section and return E_OBJ
        Assign the texstat field with the exception enable/disable status
        Assign the pndptn field with exception pending pattern
        Exit critical section and return E_OK
}
Exception handler a dog in my house..

Task exception: Enable and Disable of exception

① Enable and Disable of Task Exception

Disabling is just disabling the task exception flag. But, enabling of task exception is not only the enabling of the task exception, but immediately executing the exception handler if there are pending exceptions. Remember in RTOS at each point of instruction execution, the prioritized execution should be secured.

② uITRON implementation of ena_tex

ER ena_tex()
{
        Sanity check on arguments
        Enter critical section
        Get the TCB of the calling task
        Set the flag Exception enabled on the TCB
        if (there is pending exception and Task execution is not inside exception handler)
                raise the exception
        Exit critical section
        return E_OK;
}
③ uITRON implementation of dis_tex

ER dis_tex()
{
        Sanity check on arguments
        Enter critical section
        Get the TCB of the calling task
        Set the flag Exception disabled on the TCB
        Exit critical section
        return E_OK;
}
RTOS is an box of springs each with own compression...

Thursday, February 06, 2014

uITRON: Task Exception Handler - Define and Raise

① Task exception handling routine

Task exception handling routine will run in the same task's context that means in the same priority, stack and with the same context variables which are shared between other tasks such as error code. But, in the view point of the task itself, it is a out-of-myway execution which means the execution path of exception handler is completely independent and asynchronous similar to interrupt handler. So, from the view point of task itself, a separate context which is independent of the task's context is reserved for the exception handler except when the task itself raises the exception handling. When the task itself raises the exception handling the system call executes the exception handler before returning to the task. So, it is more like function call which synchronous to the task execution. So, separate context is not reserved in this case.

② uITRON implementation of  def_tex()

ER def_tex(ID tskid, T_DTEX *pk_dtex)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        Take task ID if the the task is self
        if (the task does not have exception handler already defined) {
                Assume pending pattern = 0;
                Assume status is Disabled.
                Assume stack pointer is NULL;
                Set the pending pattern = 0;
                Set the status Disabled;
                Set the stack pointer as NULL;
                Assign the exception handler given in parameter;
        } else {
                Just overwrite the exception handler given in parameter;
        }
        /* If both are null, then nothing to do. */
        Exit critical section and return E_OK;
}
③ uITRON implementation of ras_tex()

ER ras_tex(ID tskid, TEXPTN rasptn)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        Take task ID if the the task is self
        Get the Task Control Block from the Task ID
        Logical OR the pattern given in the parameter with TCB's exception pattern
        If task exception status is not disabled and not inside task exception handler
        {
                /* Execute the exception handler or do preparation to execute in future */
                Preserve the task's context pointer in the exception block
                /* Mainly the exception handler needs to be executed in task's context */
                If (the task itself raising task exception) {
                        /* Task status is ready and */
                        /* Task ID is at the head of ready queue and */
                        /* But, Not in interrupt context. */
                        /* This is the context to run exception handler. */
                        /* So, Just call as a function call before returning to task */
                        /* till all pending patterns are cleared */
                        Take the extended information pointer from the TCB
                        while (there are pending exceptions) {
                                Take the pending pattern from TCB;
                                Make the pending pattern to zero in the TCB
                                Take the exception handler pointer
                                exit from critical section
                                Call the exception handler with pending pattern and extended information
                                enter critical section
                        }
                        /* its over */
                        Assign the exception block's context to NULL;
                        /* I'm out of exception handler */
                } else {
                        /* In the following two contexts, it enters here */
                        /* 1) This task is Ready. But, now inside interrupt handler. */
                        /* Just volatile registers are inside the context. Anyhow, the */
                        /* exception handler needs to be executed in the task's context */
                        /* just after coming out of interrupt handler */
                        /* 2) The task is preempted. The task has all registers and */
                        /* shared context variables inside the context. The handler */
                        /* needs to be executed when the task is yielded to run */
                        /* For the exception handler, the register set is not needed. */
                        /* But, all other context is required. There are some processing of */
                        /* creating new context for exception handler and switching of context */
                        /* is required. So, internal wrapper function is assigned to execute when */
                        /* the task become ready to run. */
                        Assign internal wrapper function
                        Calculate the pointer one context unit down to currently saved
                        Initialize the new context for exception handler.
                        if (task is preempted) {
                        /* task is not ready */
                                Take copy of the shared context variables into exception handler's
                        }
                        Set the internal handler function as execution function
                        Set the new context pointer as task's context
                }
        }
        /* otherwise nothing to do now */
        Exit critical section and return E_OK;
}
void wrapper_internal(ER ercd)
{
        /* Remember that you should not forget take in the error code updated */
        /* in other contexts. It is the only shared context variable to updated. */
        /* All others are read-only */
        Take tcb of the task executing
        Take the exception block
        Enter critical section
        Take the pending pattern from TCB;
        Take the extended information
        If (task was preempted one)
                /* shared context variables are saved by this exception module */
                Update the error code in the task's context
        Make the pending pattern to zero in the TCB
        for each valid bit in the pending pattern {
        till (there are pending exceptions) {
                /* Till all pending pattern is cleared */
                Take the exception handler
                exit critical section
                execute the exception handler
                enter critical section
                Take the pending pattern from TCB;
                Make the pending pattern to zero in the TCB
        }
        Restore back the task's context pointer from the exception block
        Reschedule the tasks;
}

A soft interrupt...