
Discover how embedded systems combine cpu, memory, io, peripherals. Engage in hands-on hardware with PIC32 and Raspberry Pi boards, writing device drivers for LCDs and sensors, building an operating system.
Create a platform-independent development workspace with three folders: datasheets, os, and drivers, and set up a Mplab X project for a PIC32 device, then review hex output and datasheet specs.
Identify and map the 44-pin device pinout, including 3.3v power, ground, reset, and clock pins. Connect a 20 MHz crystal with load capacitors and configure programming pins and reset pull-up.
Set up a cpu breakout on a breadboard with a 12 MHz crystal, decoupling capacitors, and an LED, then program the microcontroller with the MPLAB Pickit 4 to explore pins.
Explore simulators like MPLAB X and Proteus to develop and debug embedded software for PICs, run code without hardware, and visualize circuits, LEDs, and LCDs.
Introduce decoupling through a base support package and a unified system call interface to portable embedded software across MCUs. Explore tasks with priorities, preemption, and IPC, including periodic executions.
Explore multitasking in single cpu systems, detailing tasks, resources, and the scheduler’s role in ready, running, waiting, and blocked states, including preemption and priorities.
Explore shared resources in a primitive kernel prototype, learning how preemption, race conditions, and mutual exclusion affect LCD and TFT displays through system calls and BSP interactions.
Learn how a preemptive task switch saves each task's 32 registers and stack pointer to preserve its execution context on the stack, then restores it for seamless resumption.
Explore how kernels manage cpu time, perform context switching, and provide inter task communication, contrasting non-preemptive and preemptive scheduling with led-based visualizations and practical examples.
Explore how the system tick, driven by a crystal-fed hardware timer and a prescaler, steers the scheduler; use PWM on timer two to produce 1 kHz and 2 kHz tones.
Explore ISA, API, ABI, and EAB concepts, and how binary compatibility and platform implementations enable same machine code across CPUs. Examine assembly language, instruction encoding, addressing modes, and CPU-memory interaction.
Learn how the MIPS32 register file of 32 four-byte registers interacts with memory via load and store, with emphasis on word alignment and frame pointer, stack pointer, and return address.
Explore the MIPS32 memory layout, with text, static data, heap, and stack. See how registers and memory mapped io use fetch-decode-execute cycles to move data between memory and registers.
Explore the PIC32 microcontroller, a MIPS 32 platform with timers, UART, SPI, I2C, ADC and DMA, and learn assembly basics—from load/store to procedure calls and delay slots.
Explore the microchip embedded connectivity starter kit with harmony three to rapidly prototype adc-based joystick input, spi-driven tft output, and usb/uart interfaces, enhanced by an analog multiplexer.
Assess interrupt latency in a preemptive kernel as time to start context saving after an IRQ; assess interrupt response as latency plus saving time, and recovery as restore and IRET.
Illustrate how the kernel manages interrupts, including timer tick interrupts for the scheduler, external hardware interrupts with edge polarity settings, and core software interrupts for cooperative multitasking.
Test interrupts by toggling red, green, and blue LEDs on pins 22–24 using timer one, core software, and external interrupts triggered by pin 43 on falling edge.
Build an essential board support package for target system, configuring stage one hardware (LEDs, micro SD, SPI-2, UART over USB via the MCP2221), and a boot loader with DFU upgrade.
Set up the system timer in the BSP to generate a 1 kHz system tick using timer1 with a prescaler, configuring interrupts, and initializing BSP for tick handling.
Set up the system tick interrupt within the stage one BSP, enabling timer1 interrupt and routing it to an ISR that clears the interrupt flag and returns from exception.
Wire three leds as digital outputs (red 19, blue 20, green 21), implement bsp leds macros for on/off/toggle, initialize them in bsp, and test with a system test function.
Flash an SOS in Morse code using the blue LED, sending three short, three long, and three short pulses, with a three-second delay in the main loop.
Explain UART basics for two-device serial communication, covering simplex, half duplex, full duplex, asynchronous transfer, baud rate, and the frame with start, data, parity, and stop bits, LSB first, 8N1.
Perform uart testing by sending capital a every two seconds, observe start and stop bits, eight lsb data bits, and echo uppercase received characters back through the serial console.
Learn how spi enables master–slave serial data transfer using MOSI, MISO, SDO, and SDI. Pull the chip select to enable a slave and configure modes by clock polarity and phase.
Demonstrates spi master-slave data exchange with Arduino, prints over uart via printf and scanf, and enables SD card access through a decoupled fat file system driver.
Define the base kernel infrastructure with BSP interrupt macros, create portable types and constants, and implement a preemptive policy with atomic, critical sections, and software interrupts.
Implement task states and priorities by defining an os task state enum and a task control block storing stack pointer, state, id, priority, time out, and idle task.
Implement context switching in assembly for an embedded OS by saving and restoring CPU context, managing idle and highest-priority ready tasks, and driving the scheduler.
Learn task management in embedded systems by implementing OS task create, delete, and set running or waiting. Manage priority changes using TCB and stack initialization, with context switches.
Implement a simple preemptive scheduler that checks the highest priority ready task against the running task, waking tasks on time delays or events and preempting the running one.
Implement a simple event management concept with event control blocks and a fifo, where ECBs store flags, data, sources, and wait mode, linked to a TCB, for 16 event types.
Define data structures for event management and implement a circular buffer FIFO to store events. Cover the event control block, event flags, and basic FIFO operations.
Implement mutexes to enforce mutual exclusion on shared resources, explain lock, unlock, and ownership mechanics, and introduce semaphores and priority inversion protection in an embedded systems OS development context.
Explore the priority inversion problem and implement priority inheritance to avoid it in a mutex-based system, enabling high-priority tasks to proceed by elevating the mutex owner's priority.
Implement inter-task communication via a mailbox, a fifo queue of os messages with sender and data fields, supporting create, delete, push, pull, and blocking or non-blocking behavior.
In this course you will learn how to create an Embedded OS, really from the ground up.
You will be guided step by step in the creation of each and every technical software module composing an embedded operating system, as well as in the development of your own target device on the bench (optional: you can use a free simulator or a ready-to-use Starter Kit), starting with basic electronic components and an industry-standard processor.
You will learn how to create device drivers step-by-step for real hardware components like displays, SD card storage, Wi-Fi, Inertial Movement Units (IMU, i.e. accelerometer and gyroscope), USB communication, analog Joysticks, thermal camera modules and more.
By the end of this course you will master system-level programming in the assembly and C languages, as well as the technical processes governing the interaction between CPU and memory. Thanks to the numerous hands-on experiences and practical demonstrations, you will develop the ability of gaining full control on the machine by manipulating CPU registers, stack, instruction pointer, return addresses, and much more. At the end of the software development part, you will learn how to create a porting to another architecture, like x86.
Although the hardware development part is optional, if you have access to an electronics lab you will also develop the ability of prototyping your circuit, designing and assembling your own target PCB (Printed Circuit Board).