David Denny's Portfolio

Back to the home page


Real-Time Operating System from Scratch:

Intoduction

This project implements a feature-complete, simple Real-Time Operating System. This RTOS
is created from scratch and driven using a Texas Instruments’ TM4C123GXL Red Board and its
accompanying microcontroller. Through the use of an UART connection, users can interact with
the RTOS, which runs multiple sample tasks and threads at the same time, performing quick,
efficient context switches and requisite memory protection of the Kernel and User Space.

Code

The attached files and code below contian the entirety
of the C code and Headers that implement the RTOS.
These files can also be found on my GitHub:

David Denny RTOS Project Code

Example Shell output from the RTOS
Theory

This page will document the features implemented and available in the RTOS, including the Embedded Systems
concepts that were applied and tested with it. As previously descibed, the RTOS is run with a TI microprocessor,
and uses some external hardware in the form of LEDs and Push Buttons for testing and I/O integration experience.
Also previously described, the primary form of communication between a user and the RTOS is via a UART
connection, and the various screenshots provided are from the shell implemented with it. With that context in
mind, here are the features available in the RTOS:

Example Shell output from the RTOS
Theory (cont.)

Shell Interface: Using the UART connection, a shell is implemented, capturing user inputs and interpreting
those inputs as RTOS commands. These commands include the ability to run/kill tasks, check the status of the RTOS
with common Linux commands like ps() and ipcs(), reboot the RTOS, etc. The shell is perhaps the most important
tasks included with the RTOS.

Preemptive and Cooperative Enforcement: The RTOS can operate in both a Cooperative and Preemptive mode,
toggled using another Shell command. In Cooperative mode, tasks must be willing to yield the CPU. In Preemptive
mode, tasks are forced to yield the CPU after 1ms of execution, forcing a context switch.

Memory Protection: As mentioned, tasks are limited to their allocated memory stack. Upon the task's
creation, a custom malloc() is called, allocating requisite SRAM to the task to use when executing. The
microcontroller's included MPU is utilized to enforce the R/W privileges of each task, preventing the task from
using another task's memory, and strictly protecting the Kernel's stack.

Example Shell output from the RTOS
Tasks

One of the primary purposes of an RTOS is to enable the use of multiple tasks/programs/threads at the "same"
time. As a result, multiple tasks were created to test the various features of the RTOS described below. These
tasks do various things. All of these tasks can be found in the files tasks.c/h:

- Simulating a task that demands a lot of CPU time with LengthyFn(), testing the RTOS's preemptive enforcement.
- A task that visualizes CPU idle time, Idle(). This task runs in the background at the lowest priority, always
toggling an LED and yielding the CPU to other tasks. The brightness of the attached LED visually describes
how idle the CPU is at any given time.
- Simulating a task with high importance with Important(), testing the RTOS's Priority Inheritance and
Enforcement. The priority of each task can also be altered during the RTOS's execution.
- Numerous tasks that simulate the ownership and queuing of semaphores and mutexes.

The physical hardware used in the RTOS
Conclusion

Through this project, I developed a strong understanding of real-time operating
systems and embedded software design. Building the RTOS from scratch sharpened my
skills in C programming, task scheduling, context switching, and memory protection
using the MPU. Implementing features such as preemptive and cooperative modes,
custom stack allocation, and a UART-based shell taught me how low-level hardware
and OS concepts work together in a reliable system. Working directly with the
microcontroller, LEDs, and push buttons also strengthened my experience with
embedded I/O and debugging. Overall, this project solidified my ability to design
and implement robust, hardware-driven software systems.

Back to the home page