]> code.bitgloo.com Git - clyne/stmos.git/commitdiff
Reviewed stmos, made small format/doc fixes
authorClyne Sullivan <clyne@bitgloo.com>
Fri, 24 Jan 2020 14:15:46 +0000 (09:15 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Fri, 24 Jan 2020 14:15:46 +0000 (09:15 -0500)
24 files changed:
src/crt/crt0.c
src/fs/initrd.c
src/fs/initrd.h
src/fs/stdio.c
src/fs/stdio.h
src/kernel/clock.h
src/kernel/elf.c
src/kernel/elf.h
src/kernel/fault.c
src/kernel/gpio.c
src/kernel/gpio.h
src/kernel/heap.c
src/kernel/heap.h
src/kernel/init.c
src/kernel/serial.c
src/kernel/serial.h
src/kernel/svc.c
src/kernel/task.c
src/kernel/task.h
src/kernel/vfs.c
src/kernel/vfs.h
src/libgpio/gpio.c
src/libgpio/gpio.h
src/user/user.c

index ccdb2ebc1bb669ce479b1b88ec71031607f5a0e4..35c3fa9099583544d0696e93d855aa7355793ddb 100644 (file)
@@ -25,12 +25,20 @@ extern int main(int, char **);
 
 static void stdio_init(void);
 
+/**
+ * Entry point for userland programs.
+ * Sets up stdio, then enters the program's main() before exiting with main()'s
+ * return code.
+ */
 void _start(void)
 {
        stdio_init();
        exit(main(0, 0));
 }
 
+/**
+ * Initializes file handles for stdout, stdin, and stderr.
+ */
 void stdio_init(void)
 {
        stderr = calloc(1, sizeof(FILE));
index de00a4aac6a2e30f14adfc82ebc3184061cda66a..efd586c019965ff812b0722c1b72cdddb4d178e1 100644 (file)
@@ -28,6 +28,7 @@ typedef struct {
        uint32_t size;
 } initrd_info;
 
+// Defined by linker script
 extern uint8_t _binary_initrd_img_start[];
 extern uint8_t _binary_initrd_img_size[];
 
@@ -39,6 +40,10 @@ uint32_t initrd_read(vfs_file_info *info, uint32_t count, uint8_t *buffer);
 int initrd_close(vfs_file_info *info);
 int initrd_seek(vfs_file_info *info, uint32_t offset, int whence);
 
+/**
+ * Gets the start of the offset-th file in the initrd.
+ * @return Pointer to the file, NULL otherwise
+ */
 char *initrd_getfile(uint32_t offset);
 
 static const vfs_volume_funcs initrd_funcs = {
@@ -50,6 +55,9 @@ static const vfs_volume_funcs initrd_funcs = {
        initrd_seek
 };
 
+/**
+ * Custom strncmp() implementation used by this driver.
+ */
 int initrd_strncmp(const char *a, const char *b, unsigned int n)
 {
        for (unsigned int i = 0; i < n; i++) {
@@ -67,10 +75,12 @@ void initrd_init(void)
 
 void *initrd_open(const char *file)
 {
+    // Iterate through all files in the initrd
        char *ptr;
        for (uint32_t i = 0; ptr = initrd_getfile(i), ptr != 0; i++) {
                uint32_t len = *((uint32_t *)ptr);
                if (!initrd_strncmp(file, ptr + 4, len)) {
+            // If we found our file, create an info structure and return it
                        initrd_info *file = (initrd_info *)malloc(
                                sizeof(initrd_info));
                        file->address = ptr + len + 8;
@@ -84,17 +94,18 @@ void *initrd_open(const char *file)
 
 int initrd_close(vfs_file_info *info)
 {
-       // Nothing to do
        free(info->fsinfo);
        return 0;
 }
 
 uint32_t initrd_read(vfs_file_info *info, uint32_t count, uint8_t *buffer)
 {
+    // Confirm this is a valid file
        initrd_info *iinfo = (initrd_info *)info->fsinfo;
        if (iinfo == 0 || iinfo->address == 0)
                return 0;
        
+    // Attempt to read 'count' bytes, breaking if we reach the end of the file
        uint32_t i;
        for (i = 0; i < count; i++) {
                if (info->pos >= iinfo->size)
@@ -129,9 +140,11 @@ char *initrd_getfile(uint32_t offset)
 {
        char *ptr = (char *)initrd_start;
        for (uint32_t i = 0; i < offset; i++) {
+        // Move to the next file
                uint32_t len = *((uint32_t *)ptr);
                uint32_t datalen = *((uint32_t *)(ptr + 4 + len));
                ptr += len + datalen + 8;
+
                if (ptr >= (char *)(initrd_start + initrd_size))
                        return 0;
        }
index 045b2b9892d72562741f39678bcff4b23cb70094..819fee3aafcf2b02de25ea9d26bec81ea56a47cc 100644 (file)
@@ -27,3 +27,4 @@
 void initrd_init(void);
 
 #endif // INITRD_H_
+
index e15003dbd8759d1e2cd92c5932c054e32128fffc..aeb8d739190b4a3fbb763862ec784c6160caaed8 100644 (file)
@@ -39,6 +39,9 @@ const vfs_volume_funcs stdio_funcs = {
 
 void *stdio_open(const char *path)
 {
+    /**
+     * All we need is the correct file handle number.
+     */
        int *id = malloc(sizeof(uint32_t));
 
        if (path[0] == 'o' && path[1] == 'u' && path[2] == 't')
@@ -53,13 +56,13 @@ void *stdio_open(const char *path)
 
 int stdio_close(vfs_file_info *info)
 {
-       // Nothing to do
        free(info->fsinfo);
        return 0;
 }
 
 uint32_t stdio_read(vfs_file_info *info, uint32_t count, uint8_t *buffer)
 {
+    // TODO?
        (void)info;
        (void)count;
        (void)buffer;
@@ -68,6 +71,7 @@ uint32_t stdio_read(vfs_file_info *info, uint32_t count, uint8_t *buffer)
 
 uint32_t stdio_write(vfs_file_info *info, uint32_t count, const uint8_t *buffer)
 {
+    // For now, output to serial
        (void)info;
        for (uint32_t i = 0; i < count; i++)
                serial_put(buffer[i]);
index bf52fa8945c8d440016b4980cf2c3debcb5200aa..e902ca8965f0ff307ce3b1a2b3e2b8a6fdd778df 100644 (file)
@@ -29,3 +29,4 @@
 extern const vfs_volume_funcs stdio_funcs;
 
 #endif // INITRD_H_
+
index e5e46c4b1b7836dbba172ffeb027e5b2f528167a..325a080c17152799b6ba1d51a544a345e5cc769d 100644 (file)
@@ -47,3 +47,4 @@ void clock_udelay(uint32_t count);
 uint32_t clock_millis(void);
 
 #endif // CLOCK_H_
+
index 77333a92b287e9168d1633a9bc582d9454416d6f..db268ce29a65fb42b81ac217f03d5b6524fb4dcb 100644 (file)
 
 #include <string.h>
 
+/**
+ * Finds the section with the given name in the ELF data, e.g. ".bss".
+ * @param ehdr ELF file header
+ * @param name Name of the section
+ * @return Section header of the section, NULL if not found
+ */
 Elf32_Shdr *elf_find_section(Elf32_Ehdr *ehdr, const char *name)
 {
        Elf32_Shdr *shdr = (Elf32_Shdr *)((char *)ehdr + ehdr->e_shoff);
@@ -80,6 +86,7 @@ uint32_t elf_execve(const char *file, char * const argv[], char * const envp[])
        Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfData;
        Elf32_Phdr *phdr = (Elf32_Phdr *)(elfData + ehdr->e_phoff);
 
+    // Search for the loadable program header
        for (Elf32_Half i = 0; i < ehdr->e_phnum; i++) {
                if (phdr->p_type == PT_LOAD) {
                        // There should only be one PT_LOAD section...
@@ -87,6 +94,7 @@ uint32_t elf_execve(const char *file, char * const argv[], char * const envp[])
                                while (1);
                        ELF_OFFSET = (uint32_t)malloc(phdr->p_memsz + 8) & ~7;
 
+            // Copy the program data into RAM for execution
                        uint8_t *src = (uint8_t *)elfData + phdr->p_offset;
                        uint8_t *dst = (uint8_t *)(ELF_OFFSET + phdr->p_vaddr);
                        for (uint32_t j = 0; j < phdr->p_filesz; j++)
@@ -114,7 +122,7 @@ uint32_t elf_execve(const char *file, char * const argv[], char * const envp[])
                        gotArray[i] += ELF_OFFSET;
        }
 
-       // Run any constructors
+       // Run any initial constructors
        Elf32_Shdr *initArraySection = elf_find_section(ehdr, ".init_array");
        if (initArraySection != 0) {
                Elf32_Addr *initArray = (Elf32_Addr *)(ELF_OFFSET +
index 91434012e23486ac18409e17b559c8bfbf0182cc..dd7ffc11e48e6853c3e757054016b993a3485eaa 100644 (file)
@@ -122,3 +122,4 @@ typedef struct {
 } __attribute__((packed)) Elf32_Phdr;
 
 #endif // ELF_H_
+
index db81c1ffd92be6b32f68178cdb2c29811b2ca86c..f43353b740da5ccbd78d392a74ac44eb41e47211 100644 (file)
@@ -24,3 +24,4 @@ void HardFault_Handler(void)
        // TODO have a real fault handler...
        while (1);
 }
+
index 3bd67cb0ae22199dd80a3ea66ba414853af89dc1..7831bf578445054d6e12a351b820a0b2bcb84bf7 100644 (file)
@@ -91,3 +91,4 @@ uint32_t gpio_din(GPIO_TypeDef *port, uint32_t pin)
 {
        return port->IDR & (1 << pin);
 }
+
index ea7e837249fd37eb2127e854e95796608996debd..ed9dfa6cdd60289f5440272cb37d133696eb4122 100644 (file)
@@ -129,3 +129,4 @@ void gpio_dout(GPIO_TypeDef *port, uint32_t pin, uint32_t val);
 uint32_t gpio_din(GPIO_TypeDef *port, uint32_t pin);
 
 #endif // GPIO_H_
+
index 123f7e62ad9af2c5bce8eea3441839823974821a..b125d6e340a9de09c9aa48e3ef53d6403163c263 100644 (file)
 
 #include "heap.h"
 
+// Defines size of alignment on memory allocations
 #define HEAP_ALIGN 4
 
+// Linked list of free'd memory
 static alloc_t *free_blocks;
 static void *heap_end;
 
@@ -34,8 +36,10 @@ void heap_init(void *buf)
 uint32_t heap_free(void)
 {
        uint32_t total = 0;
+    // Count free'd block sizes
        for (alloc_t *node = free_blocks; node != 0; node = node->next)
                total += node->size;
+    // Add remaining free memory to that total
        return total + (0x20018000 - (uint32_t)heap_end);
 }
 
@@ -44,26 +48,29 @@ void *malloc(uint32_t size)
        if (size == 0)
                return 0;
 
+    // Round size to an aligned value
        size = (size + sizeof(alloc_t) + HEAP_ALIGN) & ~(HEAP_ALIGN - 1);
 
+    // Begin searching through free'd blocks to see if we can reuse some memory.
        alloc_t *node = free_blocks;
        alloc_t *prev = 0;
        while (node != 0) {
                if (node->size >= size) {
-                       // get out of the free chain
+                       // If we can use this chunk, remove it from the free_blocks chain
                        if (prev != 0)
                                prev->next = node->next;
                        else
                                free_blocks = node->next;
                        node->next = 0;
 
-                       // split alloc if too big
-                       if (node->size > size + 64) {
+                       // If this chunk is really big, give back the extra space
+                       if (node->size > size + 64) { // TODO why 64..?
                                alloc_t *leftover = (alloc_t *)((uint32_t)node
                                        + sizeof(alloc_t) + size);
                                leftover->size = node->size - size - sizeof(alloc_t);
                                leftover->next = 0;
                                free((uint8_t *)leftover + sizeof(alloc_t));
+
                                node->size = size;
                                return (void *)((uint8_t *)node + sizeof(alloc_t));
                        }
@@ -75,6 +82,7 @@ void *malloc(uint32_t size)
                node = node->next;
        }
 
+    // No reusable chunks, take from the end of the heap
        node = (alloc_t *)heap_end;
        node->size = size;
        node->next = 0;
@@ -86,9 +94,10 @@ void *malloc(uint32_t size)
 
 void *calloc(uint32_t count, uint32_t size)
 {
+    // Simply malloc and zero
        uint8_t *buf = malloc(count * size);
        for (uint32_t i = 0; i < count * size; i++)
-               buf[i] = 0;
+               buf[i] = 0; // TODO safe?
        return buf;
 }
 
@@ -97,24 +106,30 @@ void free(void *buf)
        if (buf == 0)
                return;
 
+    // Get the alloc_t structure of this chunk
        alloc_t *alloc = (alloc_t *)((uint8_t *)buf - sizeof(alloc_t));
        if (alloc->next != 0)
                return;
 
-       // check for adjacent free'd blocks
+    // Search through the free_blocks list to see if this free chunk can merge
+    // into an adjacent free chunk.
        int merged = 0;
        for (alloc_t *prev = 0, *node = free_blocks; node != 0; prev = node, node = node->next) {
+        // If the node after the current one is ours
                if ((uint32_t)node + sizeof(alloc_t) + node->size == (uint32_t)alloc) {
-                       // block before
+            // Merge by adding our node's size to this one
                        merged |= 1;
                        node->size += sizeof(alloc_t) + alloc->size;
                        break;
-                       //alloc = node;
-               } else if ((uint32_t)buf + alloc->size == (uint32_t)node) {
-                       // block after
+               }
+        // Or, if this current node is the one after ours
+        else if ((uint32_t)buf + alloc->size == (uint32_t)node) {
+            // Merge the current node into ours
                        merged |= 1;
                        alloc->size += sizeof(alloc_t) + node->size;
                        alloc->next = node->next;
+
+            // Take the current node's place in the free_blocks chain
                        if (prev != 0)
                                prev->next = alloc;
                        else
@@ -123,9 +138,11 @@ void free(void *buf)
                }
        }
 
+    // If we couldn't merge, simply append to the chain
        if (merged == 0) {
                alloc->next = free_blocks;
                free_blocks = alloc;
        }
 
 }
+
index 82d057e032c298ee4743897eb196533a45227151..054cb8a5d791d4ca2c8d9699cc83493ba0cddfdc 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <stdint.h>
 
+/**
+ * Internal structure place before memory allocations, to track allocation size.
+ */
 typedef struct {
        uint32_t size;
        void *next;
@@ -30,13 +33,14 @@ typedef struct {
 
 /**
  * Initializes memory management of the given heap.
- * No overflow stuff is done, so... be careful.
+ * Note: Heap size is not accounted for.
  * @param buf The heap to use for allocations
  */
 void heap_init(void *buf);
 
 /**
- * Returns the amount of free, allocatable memory, in bytes.
+ * Returns the amount of free, allocatable memory, in bytes, assuming that the
+ * heap has from its initial location to the end of SRAM.
  * @return Amount of free memory in bytes
  */
 uint32_t heap_free(void);
@@ -64,3 +68,4 @@ void *calloc(uint32_t count, uint32_t size);
 void free(void *buf);
 
 #endif // HEAP_H_
+
index 48e18009cc1b04ed97bb6182851145ac5680f725..01bff42ea1393d77071388c9843f9ab28d5b96e6 100644 (file)
@@ -27,6 +27,7 @@
 #include <fs/initrd.h>\r
 #include <arch/stm/stm32l476xx.h>\r
 \r
+// Heap goes after the end of the BSS section\r
 extern uint8_t __bss_end__;\r
 \r
 extern void user_main(void);\r
@@ -34,15 +35,17 @@ void init_idle(void);
 \r
 int main(void)\r
 {\r
+    // Disable interrupts while we get ready\r
        asm("cpsid i");\r
-       // disable cached writes for precise debug info\r
+\r
+       // Disabling cached writes can help give more precise debug info\r
        //*((uint32_t *)0xE000E008) |= 2;\r
 \r
-       // prepare flash latency for 80MHz operation\r
+       // Prepare flash latency for 80MHz operation\r
        FLASH->ACR &= ~(FLASH_ACR_LATENCY);\r
        FLASH->ACR |= FLASH_ACR_LATENCY_4WS;\r
 \r
-       // init core components\r
+       // Initialize core components\r
        clock_init();\r
        heap_init(&__bss_end__);\r
        gpio_init();\r
@@ -51,17 +54,21 @@ int main(void)
        vfs_init();\r
        initrd_init();\r
 \r
-       // enable FPU\r
+       // Enable FPU (TODO why isn't it enabled?)\r
        //SCB->CPACR |= (0xF << 20);\r
 \r
+    // Begin multi-tasking (enables interrupts)\r
        task_init(init_idle, 512);\r
        while (1);\r
 }\r
 \r
 void init_idle(void)\r
 {\r
+    // Start the main userspace task with a 4kB stack\r
        task_start(user_main, 4096);\r
 \r
+    // Idle\r
        while (1)\r
                clock_delay(10);\r
 }\r
+\r
index 2737b7d407a26b916e8ddfa3aab5d207f6742281..2b5cb2d643bcd89533fccf9bb0ab3581cb185740 100644 (file)
@@ -28,9 +28,9 @@ void serial_init(uint32_t baud)
        gpio_mode(GPIOA, 3, ALTERNATE);
        GPIOA->AFR[0] &= ~(0x0000FF00);
        GPIOA->AFR[0] |= 0x00007700;
-       RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN;
 
-       // start usart device
+       // Start usart device
+       RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN;
        USART2->BRR = 80000000L / baud;
        USART2->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
 }
@@ -58,3 +58,4 @@ void serial_gets(char *buf, int max)
        } while (buf[index] != '\r' && index++ < max);
        buf[index] = '\0';
 }
+
index e721d6c9b75c72f1a433fe706a38f586b8468807..9dd75e192ab57add8548d35e6a75cf8ed9c35ad1 100644 (file)
@@ -46,3 +46,4 @@ char serial_get(void);
 void serial_gets(char *buf, int max);
 
 #endif // SERIAL_H_
+
index 7c81e5f8395c1364a0b4a2b9abc3db04db53007a..358fa3d41fb8300b4a3e103ee5c01fed1aafcff7 100644 (file)
@@ -31,6 +31,7 @@ extern void vfs_svc(uint32_t, uint32_t *, uint32_t *args);
 void SVC_Handler(void) {
        uint32_t *stack;
 
+    // Get the appropriate stack (either kernel or process)
        asm("\
                tst lr, #4; \
                ite eq; \
@@ -44,13 +45,13 @@ void SVC_Handler(void) {
        uint32_t *args = (uint32_t *)stack[2];
 
        switch (svc_number) {
-       case -1:
+       case -1: // TODO why?
        case 0: /* Task-related calls
                 * 0 - _exit
                 * 1 - fork
                 * 2 - getpid
                 * 3 - waitpid
-                * 4 - sbrk (TODO bad)
+                * 4 - sbrk (TODO poor implementation)
                 * 5 - execve
                 */
                task_svc(min_number, ret, args);
index 304e6087030bc3a33cb8adeefdc3b46a4287c84b..b6f4fc1bb17f00672dd096903f0c478f6eaf29a3 100644 (file)
@@ -146,8 +146,9 @@ void task_purge(void)
        }
 
        // Free this thread's stack, and task data.
-       // Since we're single core, no one else can claim this memory until
-       // a task switch, after which we're done with this memory anyway.
+    // The scheduler still needs to use the data we're about to free; however,
+       // our single-core implementation keeps us safe from anyone else claiming
+    // this memory in the meantime.
        free(task_current->stack);
        free(task_current->heap);
        free(task_current);
@@ -168,7 +169,8 @@ void task_doexit(void)
 
 /**
  * 'Prepares' task for running.
- * Calls the task's main code, setting task_doexit() (_exit) as the return point.
+ * Calls the task's main code after making task_doexit() (_exit) main's return
+ * point.
  */
 __attribute__ ((naked))
 void task_crt0(void)
@@ -191,7 +193,7 @@ task_t *task_create(void (*code)(void), uint16_t stackSize)
 
        t->heap = 0;
        t->stack = (uint32_t *)malloc(stackSize);
-       void *sp = (uint8_t *)t->stack + stackSize - 68; // excep. stack + regs
+       void *sp = (uint8_t *)t->stack + stackSize - 68; // exception stack + regs
        t->sp = sp;
 
        /*
@@ -215,6 +217,7 @@ task_t *task_create(void (*code)(void), uint16_t stackSize)
 
 void task_init(void (*init)(void), uint16_t stackSize)
 {
+    // Create a dummy current task that we'll "exit" from
        task_current = (task_t *)malloc(sizeof(task_t));
        task_current->next = 0;
        task_current->stack = 0; // free() is called on this
@@ -222,10 +225,12 @@ void task_init(void (*init)(void), uint16_t stackSize)
        task_current->status.state = TASK_SLEEPING;
        task_current->status.value = 1000;
 
+    // Place the init task in the queue to take the dummy task's place
        task_queue = task_create(init, stackSize);
 
        task_disable = 0;
 
+    // Enter userspace process mode
        // bit 0 - priv, bit 1 - psp/msp
        asm("\
                isb; \
@@ -237,7 +242,7 @@ void task_init(void (*init)(void), uint16_t stackSize)
                msr control, r0; \
        ");
 
-       // exit the current (fake) task
+       // Exit the current (fake) task
        task_doexit();
 }
 
@@ -307,9 +312,9 @@ void PendSV_Handler(void)
        if (task_disable != 0)
                asm("bx lr");
 
-       // TODO get back to c, implement task sleeping
+       // TODO get back to c, implement task sleeping TODO did we do this?
 
-       // Save current stack pointer
+       // Finish saving current state
        asm("\
                mrs r0, psp; \
                isb; \
index 5875e3c89a2569b2e80b3cb58cd09620c961ff7f..b67147eb307c67ed24b3646abf695e4fad69de39 100644 (file)
@@ -25,7 +25,6 @@
 
 #define WIFEXITED(w)   (w & (1 << 8))
 #define WEXITSTATUS(w) (w & 0xFF)
-
 typedef uint16_t pid_t;
 
 /**
@@ -66,23 +65,44 @@ void task_init(void (*init)(void), uint16_t stackSize);
 void task_start(void (*task)(void), uint16_t stackSize);
 
 /**
- * Allows task switching to be disabled, for low-level actions.
+ * Allows task switching to be disabled, for low-level/time-critical  operations.
  * Multiple holds can be placed, and all must be removed to continue task
  * switching.
  * @param hold non-zero for hold, zero to remove hold
  */
 void task_hold(uint8_t hold);
 
+/**
+ * Puts the task to sleep for the given duration.
+ * @param ms Milliseconds to sleep for
+ */
 void task_sleep(uint32_t ms);
 
+/**
+ * Called by the task when it's ready to exit.
+ * @param code Task's exit code
+ */
 void task_exit(int code);
 
+/**
+ * Forks the task into two processes.
+ */
 int task_fork(void);
 
+/**
+ * Gets the task's PID.
+ */
 pid_t task_getpid(void);
 
+/**
+ * Waits for a task to change state (TODO confirm).
+ */
 pid_t task_waitpid(pid_t pid, int *wstatus, int options);
 
+/**
+ * TODO
+ */
 void *task_sbrk(uint32_t bytes);
 
 #endif // TASK_H_
+
index 8d4b9753175839c26694d5721b393878b64e0737..b3af7fce3cd0736c8a9df4b2681b3ed41b91b12d 100644 (file)
@@ -61,13 +61,14 @@ void vfs_svc(uint32_t n, uint32_t *ret, uint32_t *args)
 
 void vfs_init(void)
 {
+    // Mark all volumes and files as empty
        for (int i = 0; i < VFS_MAX_VOLS; i++)
                vfs_volumes[i].flags = 0;
        for (int i = 0; i < VFS_MAX_FILES; i++)
                vfs_files[i].flags = 0;
 
        vfs_mount(&stdio_funcs, 0);
-       // order is crucial
+    // Order of opening here may be important TODO confirm
        vfs_open("   in", VFS_FILE_READ);
        vfs_open("   out", VFS_FILE_WRITE);
        vfs_open("   err", VFS_FILE_WRITE);
index ccad67b895387ddf19031dd84fca67377662a77e..be739416cb2284f597057bbe722d77a87f27402f 100644 (file)
@@ -143,3 +143,4 @@ int vfs_seek(int fd, int32_t offset, int whence);
 int32_t vfs_tell(int fd);
 
 #endif // VFS_H_
+
index 522817f62cb21201f96e3dd25e8ff9c3b5f7778a..42c8ac22649b5770cadcbc49a880e3bf8e312226 100644 (file)
@@ -1,7 +1,28 @@
+/**
+ * @file gpio.c
+ * Userspace library for GPIO access
+ *
+ * Copyright (C) 2018 Clyne Sullivan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
 #include "gpio.h"
 
 #include <stdint.h>
 
+// SVC calls get messed up by GCC's optimization...
 #define NOOPTIMIZE __attribute__((optimize(0)))
 
 NOOPTIMIZE
index 7d7c8f792e27c8940c962c57b06e80495e380790..41156b0afb2ae31a6f12845565a598c84d715875 100644 (file)
@@ -1,3 +1,23 @@
+/**
+ * @file gpio.h
+ * Userspace library for GPIO access
+ *
+ * Copyright (C) 2018 Clyne Sullivan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
 #ifndef STMOS_GPIO_H_ 
 #define STMOS_GPIO_H_
 
@@ -55,3 +75,4 @@ void gpioWrite(gpio_pin_t pin, int value);
 int gpioRead(gpio_pin_t pin);
 
 #endif // STMOS_GPIO_H_
+
index f6959360c8dbf593ef5a1478ea39d3f426725a2d..acdf85bf2e68c59f538836a117f46a9c83cd977a 100644 (file)
@@ -23,7 +23,8 @@
 
 void user_main(void)
 {
-       //gpio(GPIO_MODE, 5, OUTPUT);
+    // Just load the init program from the initrd.
+    // (A:/ is stdio, B:/ is initrd)
        execve("B:/init", 0, 0);
 }