u/EmbSoft3

Bare-metal OS for Cortex-M7 from scratch
▲ 10 r/osdev

Bare-metal OS for Cortex-M7 from scratch

https://i.redd.it/sv0w5efvh32h1.gif

Hi everyone,

I'm not entirely sure if I should post in this thread since my OS targets embedded hardware. However, after sharing it on the embedded sub, I think my work might interest some of you.

For a while now, I've been working on Mk, a bare-metal OS that I developed in C and Assembly with no external dependencies (no HAL and no RTOS).

It was designed to run on the STM32F746G-DISCO and STM32F746G-Eval2 boards. They embed an ARM Cortex-M7 running at 216MHz, 8MB of RAM and no MMU. Initially, my goal was just to implement a small scheduler, but I stacked layers one after the other to make it as complete as possible. Currently, I think I've added enough layers to claim it's a small OS.

Mk features:

A Kernel

  • Preemptive, priority-based multitasking scheduler (fixed-priority, O(1) selection via CLZ)
  • Trusted Execution Environment (TEE) using the Cortex-M7 MPU (privileged and unprivileged mode)
  • Synchronization primitives: mutex, semaphore, event flags, mailbox
  • Fixed-size memory pools
  • Synchronous and asynchronous callback execution system

A Dynamic ELF Loader

Mk can load and execute external .elf files at runtime, relocated into 64 KB pages of external SDRAM. Programs reference Mk's own API symbols directly via extern — the full kernel symbol table is embedded in the firmware at a fixed address — so external applications require no copy of the kernel API in their own binary. Shared libraries can be added to overcome the 64 KB page limit. See the sym2srec tool for details on the symbol embedding mechanism.

A File System

  • FAT32 with multi-partition support
  • Concurrent access from multiple tasks (per-volume mutex)
  • Full POSIX-like API for file and directory manipulation
  • Supports SD/MMC cards and USB Mass Storage Class (MSC) devices

A USB Stack

  • Multitasking USB host stack built on the STM32F7 OTG peripheral
  • Supported device classes: HUB, HID (keyboard, mouse, joystick, gamepad), MSC

A Graphical Engine

  • Hardware-accelerated 2D rendering
  • Drawing primitives (rectangles, circles, lines, arcs), BMP 24/32-bit image rendering
  • Full Unicode text rendering (UTF-8/16/32)
  • UI widget library: buttons, text fields, edit fields, graphs, cursors, layers

A Shell

Built-in interactive shell with support for both native and dynamically loaded commands.

Links

Short demo of Mk in action: https://www.youtube.com/watch?v=cj7DHqhJ5gc

This is my first operating system, and I hope you'll find it interesting. There are still a few bugs to iron out, though I've done my best to eliminate as many as possible.

For those who'd like to dig into how it works, here are the key files:

Boot sequence: The system enters the ResetHandler() routine. The system is then initialized in mk_system_init(), which calls mk_main(), responsible for launching the kernel and all other subsystems.

Kernel core: The kernel lives under these sources and includes directories. Every system call is dispatched through the SVC exception, handled in mk_scheduler_handle().

Application prototype: A minimal application example can be found here (a simple BlinkLed). It must be paired with a linker script, an application descriptor (mk_application_data) and compiled with the following flags: -fPIC -shared. Symbol resolution at runtime is handled in mk_application_loadDynamic() and in this sources directory.

Other example applications can be found here: a Pong game and the built-in Shell.

Graphical Engine: The graphics engine is composed of several tasks that execute painting callbacks, input-listening callbacks, and process drawing requests submitted by applications. Each module is isolated and interactions between components go through asynchronous requests. The rendering pipeline entry point is mk_display_painter(), the listening entry point is mk_display_listener() and the request manager entry point is mk_display_handler().

File System: The file system layer is handled by multiple tasks running in parallel. One dedicated task is responsible for managing concurrent accesses to a given file. Each access is performed through synchronous or asynchronous requests, handled in mk_file_handle().

An early version of the documentation can be found here. It still needs some work.

I'd be happy to answer any questions or discuss any part of the implementation.

reddit.com
u/EmbSoft3 — 2 days ago

Custom bare-metal OS for STM32F7 with dynamic ELF loading

https://i.redd.it/jsl4apqvuw0h1.gif

Hi everyone,

I wanted to share a project I've been working on for a while. It started quite simply: I wanted to write my own minimalist kernel from scratch to see how far I could go. Once the kernel was stable and functional, I just kept going stacking layers on top of it until it became an operating system.

The project is called Mk, and it runs on the STM32F746G-Eval2 and STM32F746G-DISCO boards with zero external dependencies (no HAL, no RTOS).

The current stack includes:

  • A preemptive O(1) scheduler.
  • An MPU-based security layer to separate privileged and unprivileged modes.
  • A dynamic ELF loader to run applications from an SD card at runtime.
  • A multitasking USB host stack (Hub, HID, MSC) and a custom FAT32 driver.
  • A 2D graphical engine using the hardware ChromART (DMA2D) accelerator.

To enable dynamic loading without statically linking applications to the kernel, I developed a companion tool called Sym2srec. It extracts the kernel symbol tables from the ELF image and embeds them into an S-Record file, allowing external applications to resolve Mk kernel symbols dynamically at runtime through a generated GNU hash table.

Projects:

Short demo: https://www.youtube.com/watch?v=cj7DHqhJ5gc

Hope you like it!

reddit.com
u/EmbSoft3 — 9 days ago