Here I would like to write about the simple fitness device project I had been working on. It is based on the course Real time Bluetooth Networks in Edx.
To build a fitness device which runs on a Real Time Operating System.
The RTOS makes use of 2 event threads and 6 main threads. A Round Robin scheduler is implemented with FIFO queues, blocking and sleeping features. The 2 hardware components used are MK-II Booster Pack and TM4C123GXL microcontroller.
The MK-II Booster Pack has all the necessary sensors embedded on it. It has an LCD display, 2 switches, a joystick, accelerometer, microphone, buzzer light and temperature sensors, while the TM4C123GXL is the microcontroller in which the algorithms are written.
The user code takes inputs from light, microphone, accelerometer, sound sensors and switches. It performs simple measurements of light intensity, sound, calculations for number of steps walked, temperature and it displays these values in a LCD display.
The 2 event threads are run using hardware timer interrupts and the 6 main threads are switched using the SysTick timer. The threads are as follows.
Thread0 : Event thread, samples microphone input at 1000 MHz
Thread1 : Event thread, samples accelerometer input as 10 Hz
Thread2 : Main thread, to detect steps, it runs about 10 Hz
Thread3 : Main thread, take input from buttons and outputs to buzzer or LED.
Thread4 : Main thread, measures temperature. Runs at 1 Hz.
Thread5 : Main thread, output numerical data to LCD, runs at 1 Hz.
Thread6 : Main thread, measures light, runs 1.25 Hz
Thread7 : Main thread, it does not sleep or block, hence keeps the OS running even when all the threads are sleeping or blocking.
A software which manages resources in a computer system such as memory, I/O data, processors, schedules and switches tasks accordingly within the expected timing constraints is called a Real Time Operating System (RTOS).
To build an RTOS, it is essential to understand the SysTick timer, semaphores, FIFO queues, creation of threads, thread switching and launching the OS. The RTOS has the following structures and functions.
A timer has to be present for the switching of the threads to happen. Hence, there is a core device in the Cortex M architecture called SysTick timer which is commonly used to generate periodic interrupts. These interrupts can be used to measure the time and run the threads accordingly. It is a 24 -bit down counter that runs at the bus clock frequency. It has 3 registers.
SysTick Control and Status Register (STCTRL)
SysTick Reload Value Register (STRELOAD)
SysTick Current Value Register (STCURRENT)
To configure the SysTick timer to generate periodic interrupts, the following steps have to be followed.
Once the value in the STCURRENT register decrements to 0, the COUNT bit in the STCTRL register is set and STCURRENT is again reloaded with the value present in the STRELOAD register. Later the COUNT but is cleared. This way, periodic interrupts are generated with SysTick Timer to run the scheduler.The SysTick ISR works on the bus frequency, hence the frequency of interrupt is fbus/n+1.
Where ‘fbus ‘ is the bus frequency and ‘n’ is the reload value in STRELOAD register.
The smallest processing unit in an operating system is called a thread. They are the dynamic execution of a program.
A thread consists of a thread control block, stack and a program.
It is a structure that holds the attributes of the thread. It has one stack pointer which points to the stack for this thread, a link to see that the task control block forms a linked list and other attributes such as sleep and block.
It is the image of each thread and contains the set of codes which is to be executed.
It is an array of contiguously allocated data which has details of respective threads. It shows where the program execution is starting etc. The stack is created using the SetInitialStack() function. The TC’s stack pointer points to the starting of the stack and the program counter (second last register) points to the program associated with the respective thread.
Thread Addition :
The OS_AddThreads() function is used to connect the threads with each other i.e connect programs associated with each thread with the TCB and initial stack.
Launching the OS and switching between the threads :
The OSLaunch() function is used to launch the OS. First configure the SysTick timer is done. Initially, the interrupts are disabled, the STCURRENT value is set to 0 and the SysTick is given the lowest priority. This is so that the event threads are given higher priority and do not switch out before the main thread switches. Set the reload value and enable the clock . The periodic events are also initialized in the OS_Launch. Finally, the Start_OS() function is used to set the stack pointer of the CPU with that of the first thread.
The StartOS function is written in assembly so that it is easy to manipulate the registers of the stack. It sets the first thread to the CPU stack pointer.
Once the thread is initialized and the OS is launched and the first thread is successfully running, after a given time slice mentioned by the SysTick timer, the thread must be switched so that other tasks can run. Hence, once the SysTick timer goes off after the time slice, the SysTick Handler is called to switch the threads.
First we disable the interrupts, push all the stack registers and processor stack pointer of the old thread back to the respective thread’s stack and TCB. Next an OS function is responsible for the sequential execution of the threads. It gives the threads the notion of concurrent processing. The threads do not run simultaneously, but run one at a time, switching between threads. This function is called a scheduler. The scheduler points to the next thread which has to run. (i.e the RunPtr now points to the next thread’s stack pointer). The scheduler skips the blocked or sleeping thread. Later pop the registers and enable the interrupts.
Note : 16 stack registers and the stack pointer in TCB are involved during the thread initialization and switching.
This thread switching is done every time the SysTick goes off. In order to improve the speed of switching, the OS_Suspend function is introduced. If the thread finishes running before the time slice, then it calls the OS_Suspend. This function simply triggers the SysTick interrupt again and the thread is switched in the SysTick handler. The STCURRENT is reset to zero in order to give full time slice to the next thread.
Event Threads :
They occur when there is changes in the hardware status eg, I/O triggering or ADC sampling. They are functions which don’t have any parameters or return values and the time to execute an event thread are short and bounded.
After the successful OS launching and running of threads, we need a synchronize all the threads and run in order to build an real time processing embedded device. Hence, we use the concept of semaphores to synchronize and communicate between the threads.
A semaphore is basically a flag or counter that is used to communicate between the threads. It had 3 functions namely, OS_InitSemaphore, OS_Wait, and OS_Signal
This function is used to initialize and store the semaphore value.
If the OS_wait function is called with the semaphore value less than 0, then the thread will be blocked so that the scheduler skips this thread while switching. This is called blocking semaphore.
This function will just increment the counter and if any thread is blocking on this semaphore, then it will be released.
First In First Out (FIFO) Queue :
This queue is used for creating a buffer interface between threads to store and transfer data. The data produced by threads is stored in this buffer and other threads can process this data as long as the buffer is not empty.
The below snippet is a 1 semaphore implementation where OS_FIFO_Init() function initializes variables and semaphore for the FIFO. The OS_FIFO_Put function stores data from the threads into the buffer and the OS_FIFO_Get() function returns the data from buffer to other threads.
Copyright 2018 Fitness WordPress Theme