P3) alongside the existing P1 and P2. The OS uses a circular linked-list queue (ProcessQueue) fed by sched_enqueue / sched_dequeue, so adding a process is a matter of registering memory regions, initialising a Process PCB, and enqueuing it before the scheduler starts.
Create the process source file
Create Section attribute —
User/P3/main.c. Model it on User/P2/main.c, which uses the same pattern: a named section attribute, a disable_irq / enable_irq critical section around the UART print, and an infinite loop.__attribute__((section(".p3_text"))) tells the compiler to emit this function into the .p3_text output section instead of the default .text section. The linker script maps .p3_text to the p3_ram memory region (added in the next step), which places p3_start at the correct physical address independently of the OS code.Critical section — disable_irq() and enable_irq() clear and set the I-bit in the ARM CPSR respectively. The timer IRQ fires the schedule() function, which saves and restores the current process PCB. Wrapping the PRINT call prevents the scheduler from preempting the process mid-print, which would interleave UART output from multiple processes.Update the linker scripts
Both linker scripts need a new memory region for Then add the output section after the Then add the matching output section and symbols after the
p3_ram and p3_stack, and a new output section that places .p3_text into that region.linker/linker_beagle.ldAdd the memory regions after the existing p2_stack entry:.p2_text block, following the same pattern used for P1 and P2:linker/linker_qemu.ldThe QEMU address map starts at 0x00010000 for the OS. P1 is at 0x00060000 and P2 at 0x00080000, so place P3 immediately after P2’s stack:.p2_bss block:Add platform defines to the .venv files
The These values must match the
.venv files are loaded by the Makefile (include $(OS_DIR)/.venv.qemu or .venv.beagle) and become C preprocessor defines via PLATFORM_FLAGS. Add the base address and stack address for P3 to both files.OS/.venv.beagle — append after the P2_STACK line:OS/.venv.qemu — append after the P2_STACK line:ORIGIN values chosen for p3_ram and p3_stack in the corresponding linker script.Update the Makefile PLATFORM_FLAGS
Open
Makefile and extend the PLATFORM_FLAGS variable to pass the two new defines to the compiler. Add -DP3_BASE and -DP3_STACK after the existing -DP2_STACK line:Initialise and enqueue P3 in os.c
Open Inside Then enqueue P3 so the scheduler can run it:
OS/os.c. There are three changes:- Declare a static
Processfor P3 alongsidep0,p1, andp2. - Call
process_initto set up its PCB —pcis the base address of its text section andspis the top of its stack. - Call
sched_enqueueto add it to the ready queue before the scheduler starts.
main, after the existing process_init calls:process_init (OS/process.c) zeroes the general-purpose registers, sets spsr to 0x00000013 (SVC mode, IRQs enabled), and stores pc and sp directly in the PCB. PROCESS_STACK_SIZE is 0x1000 (4 KB), so sp points to the top of the stack region, matching the LENGTH = 4K declared in the linker script.Verify that the Makefile picks up the new source file automatically
The You should see output from all three processes interleaved on the console:
C_SRC variable in the Makefile uses a shell glob:$(PROGRAM_DIR) is User, so User/**/*.c matches User/P1/main.c, User/P2/main.c, and User/P3/main.c automatically. No Makefile change is needed for the source file itself. Build to confirm:The maximum number of concurrent processes is limited by available RAM on the
target board. Each process requires at least one
LENGTH = 64K code region
plus one LENGTH = 4K stack region in the linker script, plus a Process
struct (~80 bytes) in OS RAM. On the BeagleBone Black, the usable DDR3 range
starts at 0x80000000; stay well below the top of physical memory and leave
headroom for the OS heap and BSS.