Actions

Enhancing capabilites of atomthreads rtos with thread manipulation and inter-thread communication

From EdWiki

Revision as of 01:16, 8 February 2021 by Emsys19 (Talk | contribs)

Enhancing Capabilities of ATOMTHREADS with Thread Manipulation and Inter-Thread Communication

OBJECTIVE

The objective of the project is to enhance the functionalities of an existing Real-Time Operating System(RTOS), ATOMTHREADS, by implementing extra thread functionalities and light weight inter-Thread communications. The new functionalities which are added conform with the existing architecture of ATOMTHREADS and using the existing framework of ATOMTHREADS.

MOTIVATION

The real-time operating system is software that uses the most resource- and time-effective means to exact results. There is no early or late execution on the real-time operating system, and it is executed on time as suggested. There are two main types of real-time operating systems: Soft, which is less strict on time and accuracy, and hard, which shows the exact execution period and delivers the output at the required time . Thread scheduling ensures effective utilisation of wait time and better program flow and event response. ATOMTHREADS is a free, lightweight, portable, real-time scheduler for embedded systems. It offers the advantages of a real time scheduler without taking much memory space. Hence ATOMTHREADS is ideal for small microcontrollers with a small memory .

Though ATOMTHREADS ensures real time behaviour because of static thread creation , low weight kernel ,still few functionalities are missing in ATOMTHREADS because of which it is less of a complete light weight RTOS. Some missing functionalities are required to make a system , failure-tolerant and robust and some are required to make inter-Thread communication faster for faster response even within the deadline.

So this project aims at adding functionalities to the kernel software of ATOMTHREADS within and using the ATOMTHREADS framework . Following functionalities are added in the framework of the kernel :

  • Forced Suspension of Threads .
  • Forced Resumption of suspended Threads
  • Forced Restart of Threads in case of faulty execution of the Threads/Exceptions
  • Faster communication between Threads and between ISR’s and Threads.

OVERVIEW AND ARCHITECTURE OF ATOMTHREADS RTOS

  • Function Calls
    • OS Init , IDLE THREAD : This is the initialisation of ATOMTHREADS . It makes sure that the kernel queue is not devoid of thread , by putting a IDLE thread in the queue.

RTOS OBJECTS : These are RTOS objects like mutex , timer , queues etc. The suspended list of the Threads for a particular object is maintained in RTOS objects corresponding to which suspension has occurred

    • Queuing and Dequeing of Threads : AtomThreads maintains a ready queue where the threads are queued and dequeued based on suspension by RTOS objects. Scheduler looks at the ready queue while dispatching tasks from queue.
  • Handlers
    • Sys Tick Handlers : This is the handler called on the expiry of systick timer. It looks at the ready queue , picks up the right task for running and then sets the pendSV interrupt.

PendSVInterrupt : This is the handler that SysTick Handler pends to perform the actual context switch between the current task and the next task

    • Thread Shells : This function is called when a new thread is scheduled in for the first time. It will simply call the threads entry point function.This is useful since this allows the tasks to be called with parameters and maintains a commonality in the RTOS.

Description of the added functionalities

Following functionalities were added in the existing framework of ATOMTHREADS

THREADS SUSPENSION

In ATOMTHREADS , Threads are normally suspended while waiting for any resource in RTOS elements (semaphore, mutex etc) . In ATOMTHREADS , The thread suspension is carried out by the RTOS elements (queues , semaphore , mutex , timers etc) and is not given in control of the user created Threads. This poses a problem while developing a health monitoring Thread . Health Monitoring Threads are user threads which are commonly created in automotive and aerospace application to monitor the fault activity of the other threads. Some of the reasons , although inexhaustive, of a faulty operation of a thread can be as follows:

* Higher priority Thread taking more time to execute thereby halting lower priority thread.
* Thread encountered exception and is working with faulty data
* User writes a wrong code in the thread which gives a  anomalous behaviour of the thread.

Health Monitoring Threads are hence created to suspend faulty threads. In that way the whole operation of the system is not compromised, and the system performs a limited functionality following a graceful degradation. So a thread suspension system call was required to be implemented in ATOMTHREADS.

ThreadsSuspension.png

THREADS RESUMPTION

Threads are normally resumed following a suspension if the suspension was caused by RTOS elements (semaphore, mutex etc) . But again, the thread resumption is carried out by the kernel and control is never given to the user threads Carrying forward from the requirement of Thread Suspension from user thread , there is an inarguable requirement of a thread’s resumption from the suspension state based on the user thread request . So a thread resumption system call was required to be implemented in ATOMTHREADS.

ThreadsRestart.png

THREADS RESTART

In ATOMTHREADS , Threads are never restarted either by kernel or by user. There are no system calls for restarting the Threads because there are no system calls for killing the threads . This poses quite of a problem ,because that way a faulty important thread can never be restarted, and a very important system function may fail as a whole. Considering a situation where a lightweight High Priority Thread is on the verge of finishing a functionality but finally encounters an exception because of a faulty UART data coming from any external system/ or Thread stack corruption

In this situation the High Priority Thread can be suspended by the Health Monitoring Thread(if present ) but he functionality of the High Priority Thread will never get executed. In this scenario the system will fail to execute the important functionality which may lead to total failure of the entire system just because of one frame of faulty uart data / or Thread stack corruption 

In these scenarios , Thread Restart is an important functionality which can be executed by either Kernel or Health Monitoring Thread to ensure that the system does not fail because of one frame of faulty uart data /or Thread stack corruption .

ThreadsResumption.png

PIPES IMPLEMENTATIONS

Pipes are very light weight inter Thread communication medium which can be used by both ISRs and Thread to communication with and amongst each other . Pipes are different from messages queues primarily because of their raw nature of communication. Pipes does not have header and footer which makes it easier for ISRs and threads to transfer data without any execution overheads . Pipes doesn’t have any message no ID , and hence they are unidirectional means of communication between two specific threads. This unidirectional means of communication in FIFO eliminates the need of overheads which makes them fast and lightweight.

  • Two TCBs are taken during the formation of pipe
  • The two TCBs are assigned write and read permission only . This is how unidirectionality is maintained
  • A TCB pointer table is maintained inside pipe functionality to check who has the write permission and who has the read by comparing with the current context
  • If one TCB is null it is assumed as ISR
  • ISRs always have write permission
  • The pipe size can be defined by user while creation , but the unit size is one byte.
  • Pipe is implemented as a circular FIFO
  • When FIFO is full , the task is blocked.
  • If ISR is writing then the FIFO behaves as a circular fashion.
Pipes.png

Function Description of the Added Functionalities

Function Name : EnableExceptions

  • File  : ExceptionGeneration.c
  • Include File : ExceptionGeneration.h
  • Prototype : void EnableExceptions( uint8_t exceptionnumber, uint8_t control)
  • Input Arguments exceptionnumber = Exception Number (options available in ExceptionGeneration.h)

control = Enable or disable the exception (options available in ExceptionGeneration.h)

  • Output None
  • Function Description Enables / Disables the exception based on the control and exception number provided in the arguments.


Function Name : atomThreadRestart

  • Include File : atom.h
  • Prototype : uint8_t atomThreadRestart (ATOM_TCB *tcb_ptr)
  • Input Arguments tcb_ptr = Pointer to the Thread control block of the thread to be restarted
  • Output status of the operation(options available in atom.h)
  • Description 1. Reinitialised the Thread control block to default states (same values after creation)

2. Reinitialises the stack of the Thread to default values (same values after creation) 3. Puts the Thread in the ready queue


Function Name : atomThreadSuspend

  • Include File : atom.h
  • Prototype : uint8_t atomThreadSuspend (ATOM_TCB *tcb_ptr)
  • Input Arguments tcb_ptr = Pointer to the Thread control block of the thread to be restarted
  • Output status of the operation(options available in atom.h)
  • Description 1. Dequeues the entry of the Thread from the ready queue.

2. Set the suspended status to TRUE 3. Set the forced suspended status to TRUE. Its required for next forced resumption to be valid. 4. Relinquishes all the RTOS objects

  • This function is protected by critical section.


Function Name : atomThreadResume

  • Include File : atom.h
  • Prototype : uint8_t atomThreadRestart (ATOM_TCB *tcb_ptr)
  • Input Arguments tcb_ptr = Pointer to the Thread control block of the thread to be restarted
  • Output status of the operation(options available in atom.h)
  • Description 1. Enqueue the Entry to the ready queue

2. Set the suspended status to FALSE 3. Set the forced suspended status to FALSE . Its required for next forced suspension to be valid. 4. Set the forced resume status to FALSE 5. Takes back all the RTOS objects.

  • This function is protected by critical section.


Function Name : AddToExceptionThreadList

  • Include File : atom.h
  • Prototype : void AddToExceptionThreadList (ATOM_TCB *tcb_ptr)
  • Input Arguments tcb_ptr = Pointer to the Thread control block of the thread which has caused exception
  • Output none
  • Description 1. Makes an entry of the TCB pointer in the exception Thread List Table. An exception Thread List Table is a table containing all the Threads which has caused exception.
  • This function is protected by critical section.


Function Name : GetExceptionThreadList

  • Include File : atom.h
  • Prototype : uint8_t GetExceptionThreadList (ATOM_TCB *tcb_ptr)
  • Input Arguments tcb_ptr = Pointer to the Thread control block of the thread which has caused exception.
  • Output Gets the number of Thread which has caused exceptions
  • Description 1. Removes an entry of the TCB pointer in the exception Thread List Table.
  • This function is protected by critical section.


Function Name : pipe_remove

  • Include File : None. Its included in C file for internal use. Not to be used by application or kernel functions.
  • Prototype : static uint8_t pipe_remove (ATOM_PIPE *pptr, uint8_t* readbuff,uint8_t size)
  • Input Arguments pptr = Pointer to the pipe object.

readbuff = Destination pointer for the message to be copied into. size = Required number of bytes.


Output Gives the status of the operation (list can be found in atompipe.h) Description Removes a message from a pipe. Assumes that there is a message present, which is already checked by the calling functions with interrupts locked out.


Function Name : pipe_insert

  • Include File : None. Its included in C file for internal use. Not to be used by application or kernel functions.
  • Prototype : static uint8_t pipe_insert (ATOM_PIPE *pptr, uint8_t* writebuff , uint8_t size)
  • Input Arguments pptr = Pointer to the pipe object.

writebuff = Pointer to the write buffer from where pipe data will be copied. size = Required number of bytes.

  • Output Gives the status of the operation (list can be found in atompipe.h)
  • Description Inserts a message onto a pipe. Assumes that the pipe has space for one message, which has already been checked by the calling function with interrupts locked out.


Function Name : atomPipeTimerCallback

  • Include File : None. Its included in C file for internal use. Not to be used by application or kernel functions.
  • Prototype : static void atomPipeTimerCallback (POINTER cb_data)
  • Input Arguments cb_data = Call back structure of the Pipe Timer.
  • Output None
  • Description Timeouts on suspended threads are notified by the timer system through his generic callback. The timer system calls us back with a pointer to the relevant pipe_TIMER object which is used to retrieve the pipe details.This function is protected by critical section.


Function Name : atomPipeCreate

  • Include File : atompipe.h.
  • Prototype : uint8_t atomPipeCreate (ATOM_PIPE *pptr, uint8_t *buff_ptr, uint32_t max_num_bytes)
  • Input Arguments pptr : Pointer to pipe object
  • buff_ptr: Pointer to buffer storage area
  • max_num_bytes: Maximum number of messages in the pipe
  • Output Gives the status of the operation (list can be found in atompipe.h)

Description 1. Creates a Pipe Object for communication


Function Name : atomPipeDelete

  • Include File : atompipe.h.
  • Prototype : uint8_t atomPipeDelete (ATOM_PIPE *pptr)
  • Input Arguments pptr : Pointer to pipe object
  • Output Gives the status of the operation (list can be found in atompipe.h)
  • Description 1. Deletes the Pipe object


Function Name : atomPipeGet

  • Include File : atompipe.h.
  • Prototype : uint8_t atomPipeGet (ATOM_PIPE *pptr, uint8_t* readbuff , uint8_t size, int32_t timeout)
  • Input Arguments pptr Pointer to pipe object

timeout Max system ticks to block (0 = forever, -1 = no block)

readbuff Pointer to which the received message will be copied
  • Output Gives the status of the operation (list can be found in atompipe.h)
  • Description 1. Attempt to retrieve a message from a pipe.

2. Retrieves one message at a time. 3. Messages are copied into the passed readbuff storage area which should be large enough to contain one message of unit_size bytes. 4. Where multiple messages are in the pipe, messages are retrieved in FIFO order.


Function Name : atompipePut

  • Include File : atompipe.h.
  • Prototype : uint8_t atomPipePut (ATOM_PIPE *pptr, uint8_t* writebuff , uint8_t size, int32_t timeout)
  • Input Arguments pptr Pointer to pipe object

timeout Max system ticks to block (0 = forever, -1 = no block)

readbuff Pointer to which the message should be copied out
  • Output Gives the status of the operation (list can be found in atompipe.h)
  • Description 1. Attempt to put a message onto a pipe.

2. Sends one message at a time. Messages are copied from the passed msgptr storage area which should contain a message of bytes


Function Name : SetExceptionFlag

  • Include File : None
  • Prototype : static void SetExceptionFlag()
  • Input Arguments None
  • Output None
  • Description Sets the exception flag in the fault handler for use in the sys tick handler


Function Name : SetExceptionFlag

  • Include File : None
  • Prototype : static void SetExceptionFlag()
  • Input Arguments None
  • Output None
  • Description Sets the exception flag in the fault handler for use in the sys tick handler


Function Name : GetExceptionFlag

  • Include File : atomport.h
  • Prototype : uint8_t GetExceptionFlag()
  • Input Arguments None
  • Output None
  • Description Returns the status of Exception Flag


Function Name : ResetExceptionFlag

  • Include File : None
  • Prototype : static void SetExceptionFlag()
  • Input Arguments None
  • Output None
  • Description Resets the Exception Flag to 0


Function Name : usage_fault_handler

  • Include File : None
  • Prototype : void usage_fault_handler(void)
  • Input Arguments None
  • Output None
  • Description 1. Pushes the LR register

2. Sets the exception flag 3. Gets the current Thread block 4. Adds the current Thread block to the exception list 5. POPs LR 6. Returns via LR


Function Name : bus_fault_handler

  • Include File : None
  • Prototype : void bus_fault_handler (void)
  • Input Arguments None
  • Output None
  • Description 1. Pushes the LR register

2. Sets the exception flag 3. Gets the current Thread block 4. Adds the current Thread block to the exception list 5. POPs LR 6. Returns via LR

Test Cases for the added Functionalities

To test the functionalities of the new functionalities , an architecture is developed contatining Threads ,Exceptions and ISR’s. The architecture is depicted below along the operations of each block

TestCaseGeneration.png

Results

Results.png

Challenges , Learnings and Future Work

Challenges

  • There is not documentation and discussion forums on ATOMTHREADS , hence implementing functionalities conforming to AtomThreads framework required a detailed walk-through of the existing code which was time taking.
  • Since there were context switches , so breakpoints were not helpful in understanding the flow of execution , especially when pendSV is involved
  • Since mostly all the queue, tcbs are pointers (some were pointers to pointers) , so watching the values in the debug window was in vain.
  • Tracking the stack pointers and the CPU registers during the execution of exception and then back to Thread was challenging.
  • Heavy use of assembly language in ThreadRestore and PendSV handlers required a study of the assembly language of the Cortex-M4 processor


Learnings

  • Understanding of Atom Threads RTOS along with the limitations
  • Understanding of different stack pointers and their role in context switching.
  • Approach for implementing RTOS objects or extend RTOS functionalities in a given RTOS framework
  • Understanding of different states and the responsibility of the objects in maintaining the suspended Threads rather than the kernel.
  • Understanding the two different contexts , Interrupt Context and Thread Context and the sections of CPU registers required to maintain the two contexts.
  • Understanding of Exceptions and how to go back to thread mode from Exception Context.
  • Understanding the Thread Control Block Structure and making the modifications as per the need to implement new functionality.
  • Understanding the Stack Region of the Threads and the different registers which are saved during context saving.

Future Work

The future work is written keeping in mind the existing framework of Atomthreads

  • Dynamic Creation of Threads rather than static creation
  • Implementation of Thread Deletion
  • Implementation of Signals to cause event(software events) on another Thread.
  • Implementation of Drivers through System Call Table and developing the systemcall interface between RTOS and Application through SVC calls
  • Implementation of different time slices for Threads of same priority depending on functionality.

References

  • Tiva™ TM4C123GH6PM Microcontroller Datasheet

(https://www.ti.com/lit/ds/spms376e/spms376e.pdf?ts=1612427924240&ref_url=https%253A%252F%252Fwww.google.com%252F)