+============================================================================+
| |
| O S I T O - K v 0 . 1 |
| |
| PREEMPTIVE MULTITASKING OPERATING SYSTEM KERNEL |
| |
| FOR THE XTENSA LX106 MICROPROCESSOR |
| |
| OPERATOR'S REFERENCE MANUAL |
| |
| REVISION 3 -- FEB 2026 |
| |
+============================================================================+
*** IMPORTANT NOTICE ***
This manual describes the installation, configuration, and operation
of the Osito-K Preemptive Kernel, Version 0.1. The operator should
read this document in its entirety before attempting to initialize
the system. Improper configuration may result in unpredictable
behavior of the processing unit.
SECTION PAGE
------- ----
I. SYSTEM OVERVIEW ........................................ 1
II. HARDWARE SPECIFICATIONS ................................ 2
III. SYSTEM REQUIREMENTS .................................... 3
IV. INSTALLATION PROCEDURE ................................. 4
V. BUILDING THE SYSTEM FROM SOURCE ........................ 5
VI. LOADING THE SYSTEM INTO MEMORY ......................... 6
VII. SYSTEM INITIALIZATION SEQUENCE ......................... 7
VIII. OPERATOR CONSOLE COMMANDS .............................. 8
IX. INTER-PROCESS COMMUNICATION ............................ 9
X. FILESYSTEM (OsitoFS) ................................... 10
XI. 3D GRAPHICS AND ELITE FLIGHT DEMO ...................... 11
XII. ZFORTH INTERACTIVE LANGUAGE ............................ 12
XIII. SYSTEM ARCHITECTURE .................................... 13
XIV. MEMORY MAP ............................................. 14
XV. SOURCE FILE DIRECTORY .................................. 15
XVI. KNOWN LIMITATIONS ...................................... 16
XVII. WARRANTY AND DISCLAIMER ................................ 17
Osito-K (from Spanish osito, "little bear") is a bare-metal preemptive multitasking kernel engineered for the Xtensa LX106 processor. A naranjositos.tech project. The system operates without the assistance of any vendor SDK, communicating directly with the hardware registers of the processing unit.
The kernel provides the following capabilities:
- Priority-based preemptive scheduling at a rate of 100 ticks per second. Higher-priority tasks always preempt lower-priority ones; tasks at the same priority level are scheduled round-robin.
- Hardware interrupt-driven context switching with full preservation of all 16 general-purpose registers, the Processor Status word, the Shift Amount Register, and the Exception Program Counter.
- Two-tier memory allocation: a fixed-block pool (8 KB, 256 x 32-byte blocks) for fast O(1) alloc/free, and a general-purpose heap allocator (8 KB) with first-fit allocation and automatic coalescing.
- Inter-process communication via counting semaphores, mutexes, and bounded message queues with blocking and non-blocking modes.
- Software timers with one-shot and periodic modes, serviced by the kernel tick interrupt at zero additional hardware cost.
- General-purpose I/O with automatic IOMUX configuration for all 17 GPIO pins, including the special RTC-domain GPIO16.
- Flat filesystem (OsitoFS) on SPI flash with contiguous allocation, bitmap-based sector management, and up to 128 files on ~3.8 MB of storage. Inspired by the BBC Micro's DFS.
- Interrupt-driven serial communications with a 64-byte receive buffer and cooperative mutual exclusion for output operations.
- An interactive operator console with 25+ built-in commands for system monitoring, file operations, hardware control, 3D graphics, and an Elite flight demo.
- zForth interactive language — a minimal Forth interpreter with hardware syscalls for framebuffer graphics, wireframe 3D rendering, and task scheduling. Scripts stored on OsitoFS.
- 3D wireframe graphics with fixed-point math, 3x3 matrix rotation, perspective projection, and Elite ship models (Cobra, Sidewinder, Viper, Coriolis). All running at 80 MHz with no floating point.
The Osito-K kernel is designed to exploit the full capabilities of the following high-performance computing platform:
+==========================================================================+
| WEMOS D1 COMPUTING MODULE |
| TECHNICAL SPECIFICATIONS |
+==========================================================================+
| |
| PROCESSOR |
| ......... |
| Model ............... Tensilica Xtensa LX106 |
| Architecture ........ 32-bit RISC, Harvard |
| Clock Speed ......... 80,000,000 cycles/second (80 MHz) |
| Instruction Set ..... Xtensa ISA, CALL0 ABI |
| Register File ....... 16 general-purpose, 32-bit wide |
| Register Windows .... None (CALL0 convention) |
| Pipeline ............ In-order, single issue |
| Interrupt Levels .... 2 (Level-1 maskable, NMI) |
| Memory Management ... None (flat address space) |
| |
| MEMORY SUBSYSTEM |
| ................ |
| Data RAM (DRAM) ..... 81,920 bytes (80 KB) |
| Instruction RAM ..... 32,768 bytes (32 KB) |
| Flash Storage ....... 4,194,304 bytes (4 MB) |
| Flash Interface ..... Memory-mapped, cached (irom0) |
| Flash Mode .......... DOUT (Dual Output) |
| |
| PERIPHERALS |
| ........... |
| UART Channels ....... 2 (UART0 active, 115200 baud) |
| Hardware Timers ..... 2 (FRC1 assigned to kernel) |
| GPIO Pins ........... 17 (active low/high, multiplexed) |
| SPI Controllers ..... 2 |
| I2C Bus ............. 1 (software-emulated) |
| WiFi Transceiver .... IEEE 802.11 b/g/n (reserved for future use) |
| ADC ................. 1 channel, 10-bit resolution |
| |
| POWER |
| ..... |
| Operating Voltage ... 3.3V |
| Supply (USB) ........ 5.0V via Micro-USB connector |
| |
| FORM FACTOR |
| ........... |
| Board Dimensions .... 34.2mm x 25.6mm |
| Weight .............. Approximately 3 grams |
| |
+==========================================================================+
NOTE: The 80 MHz clock provides ample processing power for the
simultaneous execution of up to eight (8) independent programs.
The operator should not be concerned about resource exhaustion
under normal workloads.
The following items are required prior to system assembly:
ITEM PURPOSE
---- -------
Wemos D1 Mini board Target computing hardware
USB cable (Micro-B) Power supply and serial link
Host computer (Windows) Assembly and loading station
xtensa-lx106-elf-gcc Cross-compilation toolchain
esptool (Python) Firmware loading utility
Serial terminal program Operator console access
The cross-compilation toolchain may be obtained from the Espressif Systems
distribution archive. The operator should place the toolchain binaries in
the tools/xtensa-lx106-elf/ directory.
Step 1. Obtain the system source distribution and place it in a suitable working directory:
C:\Users\operator\osito-k\
Step 2. Ensure the cross-compilation toolchain is accessible. Add the toolchain to the command search path:
export PATH="/c/Users/operator/osito-k/tools/xtensa-lx106-elf/bin:$PATH"
Step 3. Verify the toolchain installation by invoking:
xtensa-lx106-elf-gcc --version
The system should respond with the compiler identification string. If no response is received, consult the toolchain installation documentation.
Step 4. Ensure the Python esptool module is installed:
py -m esptool version
To assemble the kernel from its component source modules, issue the following command from the system root directory:
make
The assembler will process all source modules and produce the following output files:
build/osito.elf Executable and Linkable Format image
build/osito.map Memory allocation map
build/osito0x00000.bin Binary image for flash programming
Upon successful assembly, the system will display a summary of memory utilization:
=== Osito-K build complete ===
text data bss dec hex filename
24742 9992 37232 71966 1191e build/osito.elf
NOTE: The .bss segment includes all task stacks, the memory pool,
the heap arena, and the filesystem sector buffer, which accounts
for the majority of RAM allocation.
IMPORTANT: The image version parameter MUST be set to 1.
Version 2 images are not compatible with this hardware.
The flash mode MUST be DOUT. QIO mode will cause boot failure.
Step 1. Connect the Wemos D1 computing module to the host computer via the USB cable.
Step 2. Determine the serial port assignment (typically COM4 on
Windows systems).
Step 3. Transfer the system image to the flash memory:
make flash
Or manually:
py -m esptool --chip esp8266 --port COM4 --baud 460800 \
write_flash --flash_mode dout --flash_size 4MB \
--flash_freq 40m 0x00000 build/osito0x00000.bin
Step 4. The loading utility will display progress indicators. Wait for the message:
Hard resetting via RTS pin...
The system is now loaded and will begin execution automatically upon the next power-on or reset event.
CAUTION: To restore the factory firmware at any time, the
operator may execute:
py -m esptool --port COM4 write_flash 0x0 \
backup/wemos_d1_full_backup.bin
Upon power application, the kernel performs the following initialization sequence automatically:
PHASE OPERATION DESCRIPTION
----- --------- -----------
1 ROM Bootloader Hardware self-test, flash load
2 _start (crt0.S) Set stack pointer, VECBASE, clear BSS
3 nosdk_init Disable watchdog, PLL to 80 MHz
4 uart_init Serial port: 115200 8N1, RX interrupts
5 pool_init Memory pool: 256 blocks x 32 bytes
6 heap_init Heap allocator: 8192 bytes
7 fs_init Mount filesystem (if formatted)
8 sched_init Scheduler: idle task created
9 input_init Joystick ADC + button GPIO setup
10 video_init Framebuffer 128x64 (1024 bytes)
11 task_create (x2) Input (pri=2) and Shell (pri=3)
12 timer_init FRC1 armed: 100 Hz, prescaler /16
13 sched_start Context loaded, rfe — system live
The operator console will display the following banner:
=============================
Osito-K v0.1
Bare-metal kernel for ESP8266
=============================
pool: initialized 256 blocks x 32 bytes = 8192 bytes
heap: 8192 bytes
fs: mounted, 0 files, 958 sectors
sched: initialized, idle task created
video: framebuffer 128x64 (1024 bytes)
sched: created task 'input' (id=1)
sched: created task 'shell' (id=2)
timer: FRC1 configured at 100 Hz (load=50000)
Starting kernel...
sched: starting scheduler
osito>
The osito> prompt indicates the system is operational and awaiting
operator input.
NOTE: The serial console operates at 74880 baud during the ROM
bootloader phase, then 115200 baud during kernel operation.
Some terminal programs may display garbled output during the
initial boot phase. This is normal and expected.
The Osito-K interactive shell accepts the following commands at the
osito> prompt. Commands are terminated by pressing the RETURN key.
The BACKSPACE key may be used to correct input errors.
+----------+----------------------------------------------------------+
| COMMAND | DESCRIPTION |
+----------+----------------------------------------------------------+
| | |
| ps | Display a listing of all active tasks in the system. |
| | For each task: ID, Priority, State, Ticks, Name. |
| | |
| mem | Display memory pool utilization statistics. |
| | |
| heap | Display heap allocator statistics: free, used, largest |
| | contiguous block, and fragmentation count. |
| | |
| heap test| Demonstrate heap allocation and coalescing by allocating |
| | and freeing several blocks with interleaved patterns. |
| | |
| ticks | Display the current system tick counter and the |
| | equivalent elapsed time in seconds. |
| | |
| gpio | Display the state of all safe GPIO pins: direction, |
| | value, and Wemos D1 board label (D0-D8). |
| | |
| gpio | Read a specific pin. Returns 0 or 1. |
| read N | |
| | |
| gpio | Set pin N as output HIGH or LOW. |
| high N | |
| low N | |
| | |
| gpio | Blink the onboard LED (GPIO2) five times. |
| blink | |
| | |
| fs | Filesystem commands (see Section X for details). |
| | |
| pri N P | Change the priority of task N to level P. Takes effect |
| | at the next scheduling decision. Priority 0 is lowest. |
| | |
| timer | Arm a one-shot software timer for 1 second. Reports |
| | the actual elapsed ticks when it fires. |
| | |
| forth | Enter the zForth interactive REPL. Type Forth code |
| | at the prompt. Press Ctrl+C to return to the shell. |
| | |
| run F | Execute a .zf Forth script stored in OsitoFS. |
| | Usage: run <filename> |
| | |
| joy | Joystick live monitor. Displays ADC value, button state, |
| | and input events in real time. Press Ctrl+C to exit. |
| | |
| fbtest | Draw a test pattern on the 128x64 framebuffer: |
| | border, title text, and character set sample. |
| | |
| fixtest | Run the fixed-point 16.16 math test suite: sin, cos, |
| | sqrt, div, lerp, and distance approximation. |
| | |
| mat3test | Run the 3D matrix/vector math test: rotations, |
| | projections, and matrix multiplication. |
| | |
| wiretest | Render a static wireframe cube to the framebuffer. |
| | |
| wirespin | Animate a spinning wireframe cube (~5 seconds). |
| | Press Ctrl+C to stop early. |
| | |
| ship [N] | Display Elite ship model (1=cobra, 2=sidewinder, |
| | 3=viper, 4=coriolis). No argument lists all. |
| | |
| shipspin | Cycle through all ship models with rotation animation. |
| | |
| elite | Launch the Elite flight demo. Keyboard controls: |
| | a/d=yaw, w/s=pitch, n=next ship. Press Ctrl+C to exit. |
| | |
| uname | Display system identification: kernel version, CPU, |
| | clock speed, memory sizes, tick rate, max tasks. |
| | |
| help | Display a summary of available commands. |
| | |
| reboot | Perform an immediate software reset of the processor. |
| | |
+----------+----------------------------------------------------------+
Task States:
STATE MEANING
----- -------
free Task slot is unoccupied and available for allocation
ready Task is eligible for execution and awaiting its turn
run Task is currently in possession of the processor
block Task is voluntarily suspended (waiting for a resource)
dead Task has terminated and its slot may be reclaimed
Sample session:
osito> ps
ID Pri State Ticks Name
0 0 ready 1 idle
1 2 ready 0 input
2 3 run 206 shell
osito> uname
Osito-K v0.1 xtensa-lx106 ESP8266 @ 80MHz DRAM:80KB IRAM:32KB tick:100Hz tasks:8
osito> mem
Memory pool:
Block size: 32 bytes
Total: 256 blocks (8192 bytes)
Free: 256 blocks
Used: 0 blocks
osito> heap
Heap:
Total: 8192 bytes
Free: 8188 bytes
Used: 0 bytes
Largest: 8188 bytes
Fragments: 1
osito> forth
zf: ready (Ctrl+C exit)
1 2 + .
3 ok
: sq dup * ;
ok
7 sq .
49 ok
[Ctrl+C]
osito> fs write test.zf : cube dup dup * * ; 5 cube .
wrote 29 bytes to 'test.zf'
osito> run test.zf
125 ok
osito> timer
timer: armed 1s one-shot... FIRED! (100 ticks)
active timers: 0
osito> ticks
Tick count: 808 (8 seconds)
Osito-K provides three IPC primitives for synchronization and data exchange between tasks:
Counting Semaphores:
FUNCTION DESCRIPTION
-------- -----------
sem_init(&s, count) Initialize with given count
sem_wait(&s) Decrement; block if count is zero
sem_trywait(&s) Non-blocking attempt (returns -1 if zero)
sem_post(&s) Increment; wake one blocked task
sem_count(&s) Read current count
Semaphores are used for resource counting and event signaling. A semaphore initialized to 1 functions as a mutual exclusion lock (mutex). The UART output subsystem uses this mechanism to prevent interleaved output from concurrent tasks.
Message Queues:
FUNCTION DESCRIPTION
-------- -----------
mq_init(&q, buf, sz, n) Initialize queue with buffer, message size, depth
mq_send(&q, msg) Enqueue message; block if full
mq_recv(&q, msg) Dequeue message; block if empty
mq_trysend(&q, msg) Non-blocking send (returns -1 if full)
mq_tryrecv(&q, msg) Non-blocking receive (returns -1 if empty)
mq_count(&q) Number of messages currently queued
Messages are copied by value. The queue is implemented as a circular
buffer with head and tail pointers. The ping shell command demonstrates
message queue operation by sending a message from the shell task to the
heartbeat task.
Software Timers:
FUNCTION DESCRIPTION
-------- -----------
swtimer_init(&t, cb, arg) Initialize with callback and argument
swtimer_start(&t, tk, mode) Arm for tk ticks (ONESHOT or PERIODIC)
swtimer_stop(&t) Disarm the timer
swtimer_active_count() Number of currently armed timers
Timers are serviced by the kernel tick ISR at 100 Hz. Callbacks execute
in interrupt context and must be brief. The timer shell command
demonstrates one-shot timer operation.
OsitoFS is a flat filesystem on SPI flash, inspired by the BBC Micro's Disc Filing System (DFS). It provides persistent file storage across power cycles.
Design Characteristics:
Property Value
-------- -----
Maximum files 128
Maximum filename length 23 characters (+ null terminator)
Maximum file size ~3.8 MB (limited by flash capacity)
Allocation strategy Contiguous (no fragmentation within files)
Sector size 4,096 bytes
Data sectors available 958 (~3,832 KB)
Directory structure Flat (no subdirectories)
Flash Layout:
ADDRESS SIZE CONTENTS
------- ---- --------
0x00000 256 KB Kernel firmware image
0x40000 4 KB Superblock (magic, version, statistics)
0x41000 4 KB File table (128 entries x 32 bytes)
0x42000 3,832KB Data area (958 sectors)
0x400000 --- End of 4 MB flash
Shell Commands:
COMMAND DESCRIPTION
------- -----------
fs format Create a fresh filesystem (erases all files)
fs ls List all files with size and sector count
fs df Display free space in KB and bytes
fs write NAME DATA Create a file with the given text content
fs overwrite NAME DATA Overwrite an existing file (or create new)
fs append NAME DATA Append data to an existing file
fs mv OLD NEW Rename a file
fs cat NAME Print file contents to the console
fs xxd NAME Hex dump of file contents (up to 256 bytes)
fs rm NAME Delete a file and reclaim its sectors
fs upload NAME SIZE Receive binary file via UART (see below)
fs help Show filesystem command summary
Sample filesystem session:
osito> fs format
fs: formatting...
fs: formatted, 958 sectors (3832 KB) available
osito> fs write hello.txt Hello from Osito-K!
wrote 18 bytes to 'hello.txt'
osito> fs overwrite hello.txt Goodbye!
wrote 8 bytes to 'hello.txt'
osito> fs cat hello.txt
Goodbye!
osito> fs append hello.txt See you later.
appended 14 bytes to 'hello.txt'
osito> fs cat hello.txt
Goodbye! See you later.
osito> fs mv hello.txt message.txt
renamed 'hello.txt' -> 'message.txt'
osito> fs ls
Name Size Sec
message.txt 22 1
osito> fs rm message.txt
deleted
Binary Upload Protocol:
The fs upload command enables transfer of binary files from a host
computer to OsitoFS. This is essential for loading program images that
exceed the shell's 128-byte command buffer.
PROTOCOL SEQUENCE
-----------------
1. Host sends: fs upload <name> <size>\r\n
2. Device sends: READY\n
3. For each 4096-byte sector:
a. Host sends up to 4096 bytes of raw data
b. Device writes sector to flash
c. Device sends '#' (ACK)
4. Device sends: \nOK 0x<crc16>\n
The host MUST wait for the '#' acknowledgment before transmitting the next sector. This prevents overflow of the 64-byte UART receive buffer during flash erase/write operations (~30 ms per sector).
A Python upload utility is provided at tools/upload.py:
py tools/upload.py COM4 game.bin game.bin
py tools/upload.py COM4 data.bin data.bin --baud 74880
NOTE: The filesystem uses ROM SPI functions (SPIRead, SPIWrite,
SPIEraseSector) for all flash operations. All buffers passed to
these functions must be 4-byte aligned. The filesystem handles
alignment internally using a staging buffer when necessary.
IMPORTANT: The `fs format` command will erase all files
irrecoverably. The operator should exercise caution.
Osito-K includes a complete wireframe 3D rendering pipeline, built entirely with integer arithmetic on a processor with no floating-point unit. This system powers the Elite flight demo.
Fixed-Point Math (16.16):
All 3D computation uses fix16_t — a 32-bit signed integer where the
upper 16 bits represent the integer part and the lower 16 bits the
fractional part. A 256-entry sine table provides trigonometric functions
with 1.4-degree resolution. Division and square root are computed
iteratively without hardware support.
3D Pipeline:
Model vertices (fix16 xyz)
|
v
mat3_rotate_x/y/z ← 3x3 rotation matrix, angle_t (0-255)
|
v
mat3_transform ← apply rotation to each vertex
|
v
project() ← perspective projection to 2D (128x64)
|
v
fb_line() ← Bresenham line drawing to framebuffer
|
v
fb_flush() ← stream 1024 bytes to UART/display
Ship Models:
Geometry data from the original BBC Micro Elite (bbcelite.com), scaled to fix16 coordinates:
MODEL VERTICES EDGES DESCRIPTION
----- -------- ----- -----------
Cube 8 12 Test model (unit cube)
Cobra Mk III 28 38 Player ship (iconic)
Sidewinder 10 15 Common pirate/enemy
Viper 15 20 Police patrol ship
Coriolis 16 28 Space station (rotating)
Elite Flight Demo:
The elite command launches an interactive flight demo:
- Keyboard:
a/d= yaw,w/s= pitch,n= next ship model - Starfield: pseudo-random dots scrolling with velocity
- HUD: speed indicator, compass, ship name
- Renders at ~15-20 FPS on the 80 MHz processor
- Press Ctrl+C to exit
Osito-K includes zForth, a minimal Forth interpreter adapted for bare-metal embedded use. zForth replaces the earlier Tiny BASIC interpreter and bytecode VM, saving approximately 4 KB of IRAM.
Characteristics:
Property Value
-------- -----
Cell size 32-bit signed integer (int32_t)
Dictionary 2,048 bytes
Data stack depth 16 cells
Return stack depth 16 cells
Number formats Decimal, hexadecimal (0x prefix)
Context persistence Yes (definitions survive between sessions)
Source github.com/zevv/zForth (MIT license)
Built-in Words (core.zf bootstrap):
The core bootstrap defines essential control flow and convenience words:
CATEGORY WORDS
-------- -----
Arithmetic + - * / % 1+ 1- dup drop swap rot over pick
Comparison = != < > <= >= <0 =0 not
Logic & | ^ << >>
Control if else fi unless begin again until do loop
Variables variable constant allot ! @ +!
I/O emit . cr br tell s" ."
Stack >r r> i j
Hardware Syscalls:
zForth programs can access Osito-K hardware through numbered syscalls:
WORD STACK EFFECT DESCRIPTION
---- ------------ -----------
emit ( c -- ) Print character to UART
. ( n -- ) Print number
tell ( addr len -- ) Print string from dictionary
fb-clear ( -- ) Clear 128x64 framebuffer
fb-pixel ( x y -- ) Set pixel
fb-line ( x0 y0 x1 y1 -- ) Draw line (Bresenham)
fb-flush ( -- ) Send framebuffer to display
fb-text ( col row a l -- ) Draw text string
yield ( -- ) Yield CPU to other tasks
ticks ( -- n ) Push system tick count
delay ( n -- ) Sleep for n ticks
wire-render ( m rx ry rz -- ) Render 3D wireframe model
wire-models ( -- n ) Push number of models
The wire-render syscall accepts a model index (0=cube, 1=cobra,
2=sidewinder, 3=viper, 4=coriolis) and three rotation angles
(0-255 = 0-360 degrees).
Example: Spinning Cobra from Forth:
osito> forth
zf: ready (Ctrl+C exit)
: spin 20 0 do fb-clear dup i 8 * i 8 * 0 wire-render fb-flush 3 delay loop drop ;
ok
1 spin
ok
Running Scripts from OsitoFS:
osito> fs write demo.zf fb-clear 1 30 45 0 wire-render fb-flush
wrote 46 bytes to 'demo.zf'
osito> run demo.zf
ok
NOTE: The earlier Tiny BASIC interpreter and bytecode VM have been
removed to conserve IRAM. Their source code is preserved in git
history (commits 434697a through 11d5a48) and may be restored as
an optional compile-time feature if desired.
+============================+
| HARDWARE LAYER |
| Xtensa LX106 @ 80 MHz |
| DRAM 80KB / IRAM 32KB |
+============================+
|
+------------+-------------+
| |
+------+------+ +--------+--------+
| VECTORS | | FRC1 TIMER |
| vectors.S | | timer_tick.c |
| crt0.S | | 100 Hz tick |
+------+------+ +--------+--------+
| |
v v
+------+---------------------------+------+
| CONTEXT SWITCH ENGINE |
| context_switch.S |
| Save a0-a15, PS, SAR, EPC1 (80 bytes) |
| Switch to ISR stack (512 bytes) |
| Call os_exception_handler() |
| Restore next task context + rfe |
+-----------------+-----------------------+
|
+----------+-----------+
| SCHEDULER |
| sched.cpp |
| Priority-based + |
| round-robin select |
| task_create/yield |
| task_delay_ticks |
+----------+-----------+
|
+-----------+-----+------+-----------+
| | | |
+-----+---+ +----+----+ +-----+----+ +----+-----+
| IDLE | | INPUT | | SHELL | | (slots |
| task 0 | | task 1 | | task 2 | | 3 - 7) |
| pri=0 | | pri=2 | | pri=3 | | avail. |
+---------+ +---------+ +-----+----+ +----------+
| |
+----+----+ +-----+-----+
| IPC | | SHELL |
| sem/mq | | COMMANDS |
| swtimer | | 25+ cmds |
+---------+ +-----+-----+
|
+----------+-------------+-------------+
| | | |
+-----+--+ +----+-----+ +----+-----+ +-----+----+
| UART | | POOL | | HEAP | | OsitoFS |
| TX/RX | | 32Bx256 | | 8KB | | SPI flash|
| mutex | | free list| | 1st fit | | 3.8 MB |
+--------+ +----------+ +----------+ +----------+
GPIO Subsystem:
+-----------------------------------------------------------+
| GPIO DRIVER (gpio.cpp) |
| |
| GPIO 0-15: Standard peripheral (0x60000300) |
| - IOMUX auto-configuration per pin |
| - Direction via GPIO_ENABLE register |
| - Read/write via GPIO_IN / GPIO_OUT registers |
| |
| GPIO 16: RTC domain (separate registers) |
| - RTC_GPIO_OUT, RTC_GPIO_ENABLE, RTC_GPIO_IN |
| |
| Wemos D1 Pin Mapping: |
| D0=GPIO16 D1=GPIO5 D2=GPIO4 D3=GPIO0 |
| D4=GPIO2 D5=GPIO14 D6=GPIO12 D7=GPIO13 |
| D8=GPIO15 (GPIO 6-11 reserved for SPI flash) |
+-----------------------------------------------------------+
INSTRUCTION RAM (32 KB)
=======================
0x40100000 +---------------------+ VECBASE
| Exception Vectors | vectors.S
| +0x10 Debug |
| +0x20 NMI |
| +0x30 Kernel |
| +0x50 User <--- | FRC1 / INUM7 / UART land here
| +0x70 Double |
0x4010007C +---------------------+
| ISR Entry/Exit | context_switch.S
| Scheduler hot path | sched.cpp (critical sections)
| Timer handler | timer_tick.c
| All kernel code | ~10 KB total
0x40107FFF +---------------------+ End of IRAM
DATA RAM (80 KB)
================
0x3FFE8000 +---------------------+ DRAM_START
| .data (initialized) | Global variables
| .rodata | String constants
+---------------------+
| .bss (zeroed) | Uninitialized globals
| task_pool[8] | 8 x TCB structs
| stack_pool[8] | 8 x 1536 bytes = 12 KB
| pool_memory | 256 x 32 bytes = 8 KB
| heap_memory | 8 KB
| sec_buf[4096] | Filesystem sector buffer
| rx_buf[64] | UART receive ring buffer
| isr_stack[512] | Dedicated interrupt stack
+---------------------+
| <<< free space >>> | ~46 KB available
| |
0x3FFFBFF0 +---------------------+ Initial stack pointer
0x3FFFBFFF +---------------------+ DRAM_END
SPI FLASH (4 MB)
=================
0x00000000 +---------------------+
| Firmware image | ~13 KB (kernel + data)
0x00003FFF +---------------------+
| (unused) |
0x00040000 +---------------------+ FS_FLASH_BASE
| OsitoFS Superblock | 4 KB (magic, version, stats)
0x00041000 +---------------------+
| File Table | 4 KB (128 entries x 32 bytes)
0x00042000 +---------------------+
| Data Area | 958 sectors = 3,832 KB
| | Contiguous file storage
0x00400000 +---------------------+ FS_FLASH_END (4 MB boundary)
FLASH-MAPPED CODE (irom0)
=========================
0x40200000 +---------------------+
| .irom0.text | Bulk code (if cache enabled)
| String literals | Mapped through cache
0x405FFFFF +---------------------+
FILE LINES DESCRIPTION
---- ----- -----------
Boot sequence
~~~~~~~~~~~~~
src/boot/vectors.S 90 Exception vector table at VECBASE
src/boot/crt0.S 70 CPU init: SP, VECBASE, BSS, jump
src/boot/nosdk_init.c 81 WDT off, PLL 80MHz, IOMUX setup
Kernel core
~~~~~~~~~~~
src/kernel/context_switch.S 239 Full ISR save/restore, stack switch
src/kernel/sched.cpp 267 Priority scheduler, task management
src/kernel/timer_tick.c 148 FRC1 config, exception dispatcher
src/kernel/task.h 155 TCB struct, offsets, API protos
Synchronization and IPC
~~~~~~~~~~~~~~~~~~~~~~~
src/kernel/sem.cpp 116 Counting semaphores and mutexes
src/kernel/sem.h 64 Semaphore API declarations
src/kernel/mq.cpp 101 Bounded message queues
src/kernel/mq.h 61 Message queue API declarations
src/kernel/timer_sw.cpp 113 Software timers (one-shot/periodic)
src/kernel/timer_sw.h 65 Software timer API declarations
Memory management
~~~~~~~~~~~~~~~~~
src/mem/pool_alloc.cpp 107 Fixed-block allocator, free list
src/mem/pool_alloc.h 32 Pool API declarations
src/mem/heap.cpp 178 First-fit heap, auto-coalescing
src/mem/heap.h 46 Heap API declarations
Filesystem
~~~~~~~~~~
src/fs/ositofs.cpp 724 Flat filesystem on SPI flash
src/fs/ositofs.h 101 Filesystem API declarations
Drivers
~~~~~~~
src/drivers/uart.cpp 175 UART0: TX, RX IRQ, ring buf, mutex
src/drivers/uart.h 46 UART API declarations
src/drivers/gpio.cpp 128 GPIO 0-16, IOMUX auto-config
src/drivers/gpio.h 46 GPIO API declarations
src/drivers/adc.cpp 68 SAR ADC (10-bit, A0 pin)
src/drivers/adc.h 21 ADC API declarations
src/drivers/input.cpp 121 Joystick input (ADC + button)
src/drivers/input.h 34 Input event API declarations
src/drivers/font.cpp 185 4x6 bitmap font (ASCII 32-126)
src/drivers/font.h 19 Font API declarations
src/drivers/video.cpp 270 Framebuffer 128x64, Bresenham lines
Math library
~~~~~~~~~~~~
src/math/fixedpoint.h 120 Fixed-point 16.16 types and inlines
src/math/fixedpoint.cpp 162 sin/cos tables, div, sqrt, print
src/math/matrix3.h 72 3D vector/matrix types and inlines
src/math/matrix3.cpp 165 Rotation, multiply, transform, project
3D graphics
~~~~~~~~~~~
src/gfx/wire3d.h 53 Wireframe model struct, render API
src/gfx/wire3d.cpp 140 Render pipeline: rotate→project→draw
src/gfx/ships.h 40 Elite ship model declarations
src/gfx/ships.cpp 285 Ship vertex/edge data (4 models)
src/game/game.h 18 Game API declarations
src/game/game.cpp 220 Elite flight demo (HUD, starfield)
zForth language
~~~~~~~~~~~~~~~
src/forth/zforth.c 887 Core interpreter (adapted, MIT)
src/forth/zforth.h 119 API header (ctx, eval, push/pop)
src/forth/zfconf.h 28 Config: int32 cells, 2KB dict
src/forth/zf_host.cpp 400 Host callbacks, REPL, file runner
src/forth/setjmp.h 25 jmp_buf typedef for Xtensa CALL0
src/forth/setjmp.S 44 setjmp/longjmp (6 registers, 24B)
User interface
~~~~~~~~~~~~~~
src/shell/shell.cpp 830 Interactive console, 25+ commands
src/shell/shell.h 20 Shell entry point declaration
src/main.cpp 70 kernel_main: init and launch
System headers
~~~~~~~~~~~~~~
include/osito.h 27 Master include
include/kernel/config.h 59 System constants
include/kernel/types.h 80 Freestanding type definitions
include/hw/esp8266_regs.h 143 Peripheral register addresses
include/hw/esp8266_iomux.h 70 Pin multiplexing definitions
include/hw/esp8266_rom.h 68 ROM function prototypes
Tools
~~~~~
tools/upload.py 171 Binary upload utility (Python)
Build system
~~~~~~~~~~~~
ld/osito.ld 84 Linker script (IRAM/DRAM/irom0)
ld/rom_functions.ld 76 ROM function address bindings
Makefile 155 Build system
tools/flash.sh 45 Flash utility script
tools/monitor.sh 17 Serial monitor script
-----
TOTAL ~8,000 lines of source
The operator should be aware of the following limitations in the current release:
-
ROM String Functions. The
ets_strlenfunction resident in the processor's mask ROM has been observed to cause processor exceptions when invoked from preemptible task context. The system uses inline string length computation to avoid this condition. -
Serial Baud Rate. The ROM bootloader transmits at 74880 baud before kernel initialization sets the UART to 115200 baud. Brief garbled output during the boot phase is expected.
-
WiFi Subsystem. The IEEE 802.11 radio transceiver is present on the hardware but is not initialized or controlled by this release. WiFi support is planned for Version 0.2.
-
Watchdog Timer. The hardware watchdog is disabled during operation. A software watchdog facility is planned for a future release.
-
Task Termination. Tasks are designed to run indefinitely. No mechanism for graceful task exit and resource reclamation is provided in this release.
-
Filesystem Limitations. Files are allocated contiguously.
fs_appendcan extend a file only within its pre-allocated sectors; it cannot reallocate.fs_overwritewill delete and recreate if the new data exceeds the original sector count. External fragmentation may prevent allocation of large files even when sufficient total free space exists. -
SPI Flash Alignment. All SPI flash operations require 4-byte aligned buffers. The filesystem handles this internally, but callers of the raw ROM functions (SPIRead, SPIWrite) must ensure proper alignment.
-
Stack Size. Task stacks are limited to 1,536 bytes. Functions must avoid allocating large arrays on the stack. The filesystem uses a shared global sector buffer to stay within this constraint.
+============================================================================+
| |
| THIS SOFTWARE IS PROVIDED TO THE OPERATOR "AS IS" WITHOUT WARRANTY |
| OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, |
| OR NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS. |
| |
| THE AUTHORS SHALL NOT BE HELD LIABLE FOR ANY DAMAGES ARISING FROM |
| THE USE OF THIS SOFTWARE, INCLUDING BUT NOT LIMITED TO DAMAGE TO |
| THE COMPUTING HARDWARE, LOSS OF DATA, LOSS OF PRODUCTIVITY, OR |
| EXISTENTIAL DREAD EXPERIENCED WHILE DEBUGGING EXCEPTION VECTORS |
| AT THREE O'CLOCK IN THE MORNING. |
| |
| THE 80 MHz CLOCK SPEED IS A NOMINAL VALUE. ACTUAL PERFORMANCE |
| MAY VARY DEPENDING ON AMBIENT TEMPERATURE, COSMIC RAY FLUX, AND |
| THE GENERAL DISPOSITION OF THE HARDWARE ON ANY GIVEN DAY. |
| |
| THE FILESYSTEM STORES DATA ON SPI FLASH MEMORY WHICH HAS A FINITE |
| NUMBER OF WRITE CYCLES. THE AUTHORS ACCEPT NO RESPONSIBILITY FOR |
| DATA LOSS DUE TO FLASH WEAR, POWER INTERRUPTION DURING WRITE |
| OPERATIONS, OR THE OPERATOR'S FAILURE TO MAINTAIN ADEQUATE BACKUPS |
| OF IRREPLACEABLE FILES CONTAINING ~8,000 LINES OF KERNEL CODE. |
| |
| Osito-K IS A PROJECT OF NARANJOSITOS.TECH |
| https://naranjositos.tech/ |
| |
+============================================================================+
Osito-K v0.1
Copyright (C) 2026 naranjositos.tech
All rights reserved.
https://naranjositos.tech/
Written for the Xtensa LX106 processor.
Assembled and tested on the Wemos D1 Mini computing module.
~8,000 lines of code. 80 KB of RAM. 3.8 MB of persistent storage.
One Forth interpreter. Four spaceships. Zero floating-point units.
No bears or orange cats were harmed in the making of this kernel.