Skip to content
9 changes: 6 additions & 3 deletions Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ OUTPUT_DIRECTORY = docs
INPUT = src include docs/pages README.md
FILE_PATTERNS = *.c *.h *.md *.s *.ld
RECURSIVE = YES
EXCLUDE_PATTERNS = */tests/* */build/* */literature/*
EXCLUDE_PATTERNS = */tests/* */build/* */literature/* */doc/*

#----------------------------------------------------------
# Documentation Extraction
Expand All @@ -27,7 +27,7 @@ EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
INTERNAL_DOCS = YES
SOURCE_BROWSER = YES
INLINE_SOURCES = NO # Set to YES if you want code in docs
INLINE_SOURCES = YES

#----------------------------------------------------------
# Preprocessing / Macros
Expand All @@ -38,7 +38,9 @@ EXPAND_ONLY_PREDEF = NO
PREDEFINED = __attribute__(x)= \
asm(x)= \
__asm__= \
KERNEL=1
KERNEL=1 \
__packed \
__aligned(x)

#----------------------------------------------------------
# Warnings
Expand All @@ -64,6 +66,7 @@ DOT_IMAGE_FORMAT = svg
CALL_GRAPH = YES
CALLER_GRAPH = YES
DOT_MULTI_TARGETS = YES
CLASS_DIAGRAMS = YES

#----------------------------------------------------------
# Markdown / Main Page
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
OUT_DIR := build/
SRC_DIRS := src/kernel src/user
SRC_DIRS := src/kernel src/user src/kernel/tests

# Find every .c in those dirs
SRCS := $(foreach d,$(SRC_DIRS),$(wildcard $(d)/*.c))
Expand Down
57 changes: 57 additions & 0 deletions docs/pages/memory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Memory Management

The memory management subsystem is responsible for handling the allocation,
deallocation, and organization of memory within the kernel. It ensures that
memory is used efficiently and safely, preventing leaks and corruption.

This subsystem provides a simple kernel heap allocator (`kmalloc`/`kfree`)
and manages memory blocks using a linked list of headers.

## Design

- Implements a **first-fit heap allocator** for dynamic memory allocation.
- Provides **public API functions**:
- `kmalloc_init()` – Initialize the heap region.
- `kmalloc()` – Allocate a memory block.
- `kfree()` – Free a previously allocated block.
- `kmalloc_get_head()` – Retrieve the head of the heap (mainly for testing).
- Uses **linked list of headers** to track free and used memory blocks.
- Performs **block splitting and merging** to reduce fragmentation.
- Aligns allocations to `KMALLOC_ALIGN` for proper memory access.

## Usage Example

```c
#include "memory.h"

extern char heap_start[];
extern char heap_end[];

void kernel_main(void)
{
// Initialize the kernel heap
kmalloc_init(heap_start, heap_end);

// Allocate 128 bytes
void *ptr = kmalloc(128);
if (!ptr)
{
// Handle allocation failure
}

// Use memory
char *data = (char*)ptr;
data[0] = 'X';

// Free the memory
kfree(ptr);
}
```
> **Note**: Always initialize the heap before using `kmalloc`.

## Future Plans
- Implement thread-safe operations for concurrent memory access.
- Integrate virtual memory support for better isolation and protection.
- Implement memory paging and swapping mechanisms.
- Add support for memory-mapped files and devices.
- Provide user-space memory management interfaces.
4 changes: 3 additions & 1 deletion include/clear.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#pragma once

/**
* @brief Clears the terminal screen and moves the cursor to the home position.
*/
void clear(void);

10 changes: 10 additions & 0 deletions include/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,20 @@ extern "C"
// VIC line number for Timer0/1 on Versatile
#define IRQ_TIMER01 4

/**
* @brief C-level IRQ handler called from assembly stub in start.s
* Must clear the source interrupt and (for VIC) write VIC_VECTADDR to ack end of interrupt.
*/
void irq_handler(void);
void irq_enable(void);
void irq_disable(void);

/**
* @brief VersatilePB SP804 timer clock is typically 1 MHz (can be overridden)
*
* @param tick_hz: desired tick frequency (e.g., 100)
* @param timer_clk_hz: input clock to the SP804 (e.g., 1000000)
*/
void interrupts_init_timer0(uint32_t tick_hz, uint32_t timer_clk_hz);

static inline void timer0_start_periodic(uint32_t load)
Expand Down
66 changes: 65 additions & 1 deletion include/memory.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C"
Expand Down Expand Up @@ -32,11 +31,76 @@ extern "C"
struct header *prev; /**< Pointer to the previous block in the linked list. */
};

/**
* @brief Retrieves the head of the kmalloc allocation list.
*
* This function returns a pointer to the head of the memory allocation
* list used by kmalloc. Mainly useful for testing current allocations.
*
* @return Pointer to the head of the kmalloc allocation list.
* Returns NULL if the list is empty.
*/
struct header *kmalloc_get_head(void);

/**
* @brief Initialize the kernel heap for dynamic memory allocation.
*
* This function sets up the initial heap region for `kmalloc`. It aligns
* the start and end addresses according to the kernel alignment
* requirements and initializes the first free memory block.
*
* @param start Pointer to the beginning of the heap memory region.
* Must be less than `limit`.
* @param limit Pointer to the end of the heap memory region.
* Must be greater than `start`.
*
* @note If the heap range is invalid or too small, this function
* will call `kernel_panic()`.
*
* @note The pointers `start` and `limit` are marked `restrict` to indicate
* that their memory regions do not overlap, allowing the compiler
* to optimize pointer arithmetic safely.
*/
void kmalloc_init(void *start, void *limit);

/**
* @brief Allocate a block of memory from the kernel heap.
*
* This function searches the heap for the first free block that is large
* enough to satisfy the requested `size`. If the block is larger than needed,
* it is split into an allocated block and a new free block.
*
* @param size The number of bytes to allocate. Must be > 0.
*
* @return Pointer to the usable memory area of the allocated block, or
* NULL if `size` is zero.
*
* @warning If no suitable block is found, the function will call `kernel_panic`.
* @note The returned pointer points immediately after the block header.
*
*/
void* kmalloc(size_t size);

/**
* @brief Free a previously allocated block of memory.
*
* Marks the block as free and attempts to merge it with adjacent free blocks
* to reduce fragmentation.
*
* @param block Pointer to the memory previously returned by `kmalloc`.
* Must not be NULL.
*
* @note If `block` is NULL, the function does nothing.
* @note If `block` does not correspond to a valid allocated block,
* the function calls `kernel_panic`.
*/
void kfree(void *block);

/**
* @brief Entry point for testing `kmalloc` and `kfree`.
*
* @return int Return 0 on tests passing, 1 on tests failure.
*/
int kmalloc_test(void);
#ifdef __cplusplus
}
Expand Down
64 changes: 32 additions & 32 deletions include/printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ extern "C" {
#endif

/**
* @enum fmt_state_t
* @brief Finite-state machine for parsing format strings.
*
* The printf parser moves between these states as it consumes characters.
* @enum fmt_state_t
* @brief Finite-state machine for parsing format strings.
*
* The printf parser moves between these states as it consumes characters.
*/
typedef enum {
FMT_TEXT, /**< Normal character output. */
Expand All @@ -32,7 +32,7 @@ extern "C" {
} fmt_state_t;

/**
* @brief Bit flags controlling number formatting.
* @brief Bit flags controlling number formatting.
*/
enum {
FLAG_LONG = 1 << 0, /**< 'l' length modifier (long / long long). */
Expand All @@ -42,48 +42,48 @@ extern "C" {
};

/**
* @struct Format_State
* @brief Stores the current numeric value and formatting flags.
*
* This structure is passed to integer-formatting functions during printf
* processing. It represents the transient state for one format specifier.
* @struct Format_State
* @brief Stores the current numeric value and formatting flags.
*
* This structure is passed to integer-formatting functions during printf
* processing. It represents the transient state for one format specifier.
*/
typedef struct {
unsigned long long num; /**< The numeric value to be printed. */
uint8_t flags; /**< Bitmask of FLAG_* constants describing format. */
} Format_State;

/**
* @brief Prints a null-terminated string over UART.
*
* @param s The string to output. If NULL, no output occurs.
* @brief Transmit a null-terminated string over UART.
*
* @param s The string to output. If NULL, no output occurs.
*/
void puts(const char *s);

/**
* @brief Prints a formatted string to the UART output.
*
* @param fmt Format string (supports %c, %s, %d, %u, %x, %X, %p, %%).
* @param ... Variable arguments matching the format specifiers.
*
* This function supports a minimal subset of standard C printf:
* - Signed/unsigned integers (`%d`, `%u`)
* - Hexadecimal (`%x`, `%X`)
* - Pointers (`%p`)
* - Characters (`%c`)
* - Strings (`%s`)
* - Length modifier (`%l`)
* @brief Prints a formatted string to the UART output.
*
* @param fmt Format string (supports %c, %s, %d, %u, %x, %X, %p, %%).
* @param ... Variable arguments matching the format specifiers.
*
* This function supports a minimal subset of standard C printf:
* - Signed/unsigned integers (`%d`, `%u`)
* - Hexadecimal (`%x`, `%X`)
* - Pointers (`%p`)
* - Characters (`%c`)
* - Strings (`%s`)
* - Length modifier (`%l`)
*/
void printf(const char *fmt, ...);

/**
* @brief Reads a line of text from UART into the given buffer.
*
* @param buffer Destination buffer.
* @param length Maximum buffer length (including null terminator).
*
* Blocks until a newline or carriage return is received.
* Supports backspace editing and echoes input characters.
* @brief Reads a line of text from UART into the given buffer.
*
* @param buffer Destination buffer.
* @param length Maximum buffer length (including null terminator).
*
* @note Blocks until a newline or carriage return is received.
* Supports backspace editing and echoes input characters.
*/
void getlines(char *restrict buffer, size_t length);

Expand Down
15 changes: 15 additions & 0 deletions include/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,22 @@ extern "C"
{
#endif

/**
* @brief Compares two null-terminated strings lexicographically.
*
* @param str_1 Pointer to the first string to compare.
* @param str_2 Pointer to the second string to compare.
*
* @return int 0 if strings are equal, -1 if `str_1` < `str_2`, 1 if `str_1` > `str_2`.
*/
int strcmp(const char *str_1, const char *str_2);

/**
* @brief Calculates the length of a null-terminated string.
*
* @param str Pointer to the null-terminated string to be measured.
* @return The number of characters in the string, excluding the null terminator.
*/
size_t strlen(const char *str);

#ifdef __cplusplus
Expand Down
10 changes: 0 additions & 10 deletions src/kernel/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@

volatile uint64_t systicks = 0;

/**
* @brief VersatilePB SP804 timer clock is typically 1 MHz (can be overridden)
*
* @param tick_hz: desired tick frequency (e.g., 100)
* @param timer_clk_hz: input clock to the SP804 (e.g., 1000000)
*/
void interrupts_init_timer0(uint32_t tick_hz, uint32_t timer_clk_hz)
{
if (tick_hz == 0 || timer_clk_hz == 0)
Expand All @@ -33,10 +27,6 @@ void interrupts_init_timer0(uint32_t tick_hz, uint32_t timer_clk_hz)
vic_enable_timer01_irq();
}

/**
* @brief C-level IRQ handler called from assembly stub in start.s
* Must clear the source interrupt and (for VIC) write VIC_VECTADDR to ack end of interrupt.
*/
void irq_handler(void)
{
// Check Timer0 MIS (masked interrupt status)
Expand Down
Loading