From c66410f6319284b94e21758539ac25bfb4694d3a Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Tue, 2 Oct 2018 21:26:48 -0400 Subject: [PATCH] folder restructure --- Makefile | 31 ++++-------- include/priv_gpio.h | 24 --------- {include => src/arch}/cmsis/cmsis_gcc.h | 0 {include => src/arch}/cmsis/core_cm4.h | 0 {include => src/arch}/cmsis/core_cmFunc.h | 0 {include => src/arch}/cmsis/core_cmInstr.h | 0 {include => src/arch}/cmsis/core_cmSimd.h | 0 {include => src/arch/stm}/stm32l476xx.h | 0 src/kernel/Makefile | 22 ++++++++ src/{ => kernel}/clock.c | 35 ++++++++++++- {include => src/kernel}/clock.h | 10 +++- src/{ => kernel}/fault.c | 0 src/{ => kernel}/gpio.c | 2 +- {include => src/kernel}/gpio.h | 48 +++++++++--------- src/{ => kernel}/heap.c | 7 ++- {include => src/kernel}/heap.h | 25 ++++------ src/{main.c => kernel/init.c} | 47 ++++-------------- src/{ => kernel}/startup_stm32l476xx.s | 0 src/{ => kernel}/svc.c | 9 ++-- src/{ => kernel}/task.c | 7 +-- {include => src/kernel}/task.h | 6 ++- src/user/Makefile | 22 ++++++++ src/user/priv_gpio.h | 58 ++++++++++++++++++++++ src/user/user.c | 35 +++++++++++++ 24 files changed, 252 insertions(+), 136 deletions(-) delete mode 100644 include/priv_gpio.h rename {include => src/arch}/cmsis/cmsis_gcc.h (100%) rename {include => src/arch}/cmsis/core_cm4.h (100%) rename {include => src/arch}/cmsis/core_cmFunc.h (100%) rename {include => src/arch}/cmsis/core_cmInstr.h (100%) rename {include => src/arch}/cmsis/core_cmSimd.h (100%) rename {include => src/arch/stm}/stm32l476xx.h (100%) create mode 100644 src/kernel/Makefile rename src/{ => kernel}/clock.c (76%) rename {include => src/kernel}/clock.h (82%) rename src/{ => kernel}/fault.c (100%) rename src/{ => kernel}/gpio.c (99%) rename {include => src/kernel}/gpio.h (76%) rename src/{ => kernel}/heap.c (96%) rename {include => src/kernel}/heap.h (70%) rename src/{main.c => kernel/init.c} (62%) rename src/{ => kernel}/startup_stm32l476xx.s (100%) rename src/{ => kernel}/svc.c (91%) rename src/{ => kernel}/task.c (97%) rename {include => src/kernel}/task.h (93%) create mode 100644 src/user/Makefile create mode 100644 src/user/priv_gpio.h create mode 100644 src/user/user.c diff --git a/Makefile b/Makefile index 97343f6..02fbad2 100644 --- a/Makefile +++ b/Makefile @@ -25,37 +25,26 @@ AS = as MCUFLAGS = -mthumb -mcpu=cortex-m4 #-mfloat-abi=hard -mfpu=fpv4-sp-d16 AFLAGS = $(MCUFLAGS) CFLAGS = $(MCUFLAGS) -ggdb \ - -Iinclude -Iinclude/cmsis \ + -I.. \ -fno-builtin -fsigned-char -ffreestanding \ -Wall -Werror -Wextra -pedantic \ -Wno-overlength-strings -Wno-discarded-qualifiers LFLAGS = -T link.ld -CFILES = $(wildcard src/*.c) -AFILES = $(wildcard src/*.s) +OUT = main.elf -OUTDIR = out -OFILES = $(patsubst src/%.c, $(OUTDIR)/%.o, $(CFILES)) \ - $(patsubst src/%.s, $(OUTDIR)/%.asm.o, $(AFILES)) +export -OUT = out/main.elf - -all: $(OUT) - -$(OUT): $(OFILES) +all: + @$(MAKE) -C src/kernel + @$(MAKE) -C src/user @echo " LINK " $(OUT) - @$(CROSS)$(CC) $(CFLAGS) $(LFLAGS) out/*.o -o $(OUT) + @$(CROSS)$(CC) $(CFLAGS) $(LFLAGS) -o $(OUT) $$(find src/ -name "*.o") -$(OUTDIR)/%.o: src/%.c - @echo " CC " $< - @$(CROSS)$(CC) $(CFLAGS) -c $< -o $@ - -$(OUTDIR)/%.asm.o: src/%.s - @echo " AS " $< - @$(CROSS)$(AS) $(AFLAGS) -c $< -o $@ clean: @echo " CLEAN" - @rm -rf out/* - + @$(MAKE) -C src/kernel clean + @$(MAKE) -C src/user clean + @rm -f $(OUT) diff --git a/include/priv_gpio.h b/include/priv_gpio.h deleted file mode 100644 index a97e294..0000000 --- a/include/priv_gpio.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef PRIV_GPIO_H_ -#define PRIV_GPIO_H_ - -#define GPIO_MODE 0 -#define GPIO_TYPE 1 -#define GPIO_PUPD 2 -#define GPIO_SPEED 3 -#define GPIO_OUT 4 - -void gpio(uint32_t call, uint32_t pin, uint32_t value) -{ - register uint32_t r0 asm("r0") = call; - register uint32_t r1 asm("r1") = pin; - register uint32_t r2 asm("r2") = value; - - asm("\ - mov r0, %0; \ - mov r1, %1; \ - mov r2, %2; \ - svc 1; \ - " :: "r" (r0), "r" (r1), "r" (r2)); -} - -#endif // PRIV_GPIO_H_ diff --git a/include/cmsis/cmsis_gcc.h b/src/arch/cmsis/cmsis_gcc.h similarity index 100% rename from include/cmsis/cmsis_gcc.h rename to src/arch/cmsis/cmsis_gcc.h diff --git a/include/cmsis/core_cm4.h b/src/arch/cmsis/core_cm4.h similarity index 100% rename from include/cmsis/core_cm4.h rename to src/arch/cmsis/core_cm4.h diff --git a/include/cmsis/core_cmFunc.h b/src/arch/cmsis/core_cmFunc.h similarity index 100% rename from include/cmsis/core_cmFunc.h rename to src/arch/cmsis/core_cmFunc.h diff --git a/include/cmsis/core_cmInstr.h b/src/arch/cmsis/core_cmInstr.h similarity index 100% rename from include/cmsis/core_cmInstr.h rename to src/arch/cmsis/core_cmInstr.h diff --git a/include/cmsis/core_cmSimd.h b/src/arch/cmsis/core_cmSimd.h similarity index 100% rename from include/cmsis/core_cmSimd.h rename to src/arch/cmsis/core_cmSimd.h diff --git a/include/stm32l476xx.h b/src/arch/stm/stm32l476xx.h similarity index 100% rename from include/stm32l476xx.h rename to src/arch/stm/stm32l476xx.h diff --git a/src/kernel/Makefile b/src/kernel/Makefile new file mode 100644 index 0000000..d22fbf3 --- /dev/null +++ b/src/kernel/Makefile @@ -0,0 +1,22 @@ +CFILES = $(wildcard *.c) +AFILES = $(wildcard *.s) +OFILES = $(patsubst %.c, %.o, $(CFILES)) \ + $(patsubst %.s, %.asm.o, $(AFILES)) + +CFLAGS += -I.. -I../arch/cmsis + +all: $(OFILES) + +%.o: %.c + @echo " CC " $< + @$(CROSS)$(CC) $(CFLAGS) -c $< -o $@ + +%.asm.o: %.s + @echo " AS " $< + @$(CROSS)$(AS) $(AFLAGS) -c $< -o $@ + +clean: + @echo " CLEAN" + @rm -f $(OFILES) + + diff --git a/src/clock.c b/src/kernel/clock.c similarity index 76% rename from src/clock.c rename to src/kernel/clock.c index c94695b..44b7722 100644 --- a/src/clock.c +++ b/src/kernel/clock.c @@ -18,12 +18,19 @@ * along with this program. If not, see . */ -#include -#include +#include "clock.h" +#include // ticks since init volatile uint32_t ticks = 0; +volatile uint8_t tim2_finished = 1; + +void clock_svc(uint32_t *args) +{ + udelay(args[0]); +} + void clock_init(void) { // turn on HSI (16MHz) @@ -53,6 +60,15 @@ void clock_init(void) // SysTick init. 80MHz / 80000 = 1kHz, ms precision SysTick->LOAD = 80000; SysTick->CTRL |= 0x07; // no div, interrupt, enable + + // Prepare TIM2 for microsecond timing + NVIC_EnableIRQ(TIM2_IRQn); + + RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN; + TIM2->DIER |= TIM_DIER_UIE; + TIM2->PSC = 40 - 1; + TIM2->ARR = 100; + TIM2->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN; } void delay(uint32_t count) @@ -61,12 +77,27 @@ void delay(uint32_t count) while (ticks < target); } +void udelay(uint32_t count) +{ + tim2_finished = 0; + TIM2->ARR = count; + TIM2->CR1 |= TIM_CR1_CEN; + while (tim2_finished == 0); +} + void SysTick_Handler(void) { // just keep counting ticks++; + // task switch every four ticks (4ms) if (!(ticks & 3)) SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; } +void TIM2_IRQHandler(void) +{ + TIM2->SR &= ~(TIM_SR_UIF); + tim2_finished |= 1; +} + diff --git a/include/clock.h b/src/kernel/clock.h similarity index 82% rename from include/clock.h rename to src/kernel/clock.h index 7446dd1..c3554f6 100644 --- a/include/clock.h +++ b/src/kernel/clock.h @@ -1,6 +1,6 @@ /** * @file clock.h - * Basic clock utilities + * Clock utilities * * Copyright (C) 2018 Clyne Sullivan * @@ -30,8 +30,14 @@ extern void clock_init(void); /** * Sleeps for given amount of milliseconds. - * @param ms number of milliseconds to sleep for + * @param ms Number of milliseconds to sleep for */ void delay(uint32_t ms); +/** + * Sleeps for the given amount of microseconds. + * @param count Number of microseconds to sleep for + */ +void udelay(uint32_t count); + #endif // CLOCK_H_ diff --git a/src/fault.c b/src/kernel/fault.c similarity index 100% rename from src/fault.c rename to src/kernel/fault.c diff --git a/src/gpio.c b/src/kernel/gpio.c similarity index 99% rename from src/gpio.c rename to src/kernel/gpio.c index 27bfdd3..1c81d11 100644 --- a/src/gpio.c +++ b/src/kernel/gpio.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -#include +#include "gpio.h" static const GPIO_TypeDef *gpio_ports[8] = { GPIOA, GPIOB, GPIOC, GPIOD, diff --git a/include/gpio.h b/src/kernel/gpio.h similarity index 76% rename from include/gpio.h rename to src/kernel/gpio.h index 08feb86..ea7e837 100644 --- a/include/gpio.h +++ b/src/kernel/gpio.h @@ -1,6 +1,6 @@ /** * @file gpio.h - * Abstracts gpio access, makes things easier + * GPIO Abstraction and access * * Copyright (C) 2018 Clyne Sullivan * @@ -21,17 +21,17 @@ #ifndef GPIO_H_ #define GPIO_H_ -#include +#include /** * Helps simplify gpio calls. - * @param p port, e.g. GPIOA - * @param b pin, e.g. 4 + * @param p Port, e.g. A + * @param b Pin, e.g. 4 */ #define GPIO_PORT(p, b) GPIO##p, b /** - * Defines possible modes for a gpio pin + * Defines possible modes for a gpio pin. */ enum GPIO_MODE { @@ -72,59 +72,59 @@ enum GPIO_PUPD }; /** - * Initializes the gpio. + * Prepares for GPIO usage. */ void gpio_init(void); /** * Enables or disables pullup/pulldown for the given pin. - * @param port the port, e.g. GPIOA - * @param pin the pin - * @param pupd pullup/pulldown enable + * @param port The port, e.g. GPIOA + * @param pin The pin + * @param pupd Pullup/pulldown enable * @see GPIO_PUPD */ void gpio_pupd(GPIO_TypeDef *port, uint32_t pin, uint32_t pupd); /** * Sets whether to use push-pull or open drain for the given pin. - * @param port the port - * @param pin the pin - * @param type what to use + * @param port The port + * @param pin The pin + * @param type What type to use * @see GPIO_TYPE */ void gpio_type(GPIO_TypeDef *port, uint32_t pin, uint32_t type); /** * Sets the pin's speed. - * @param port the port - * @param pin the pin - * @param speed the speed to use + * @param port The port + * @param pin The pin + * @param speed The speed to use * @see GPIO_SPEED */ void gpio_speed(GPIO_TypeDef *port, uint32_t pin, uint32_t speed); /** * Sets the pin's i/o mode. - * @param port the port - * @param pin the pin - * @param mode the mode to use + * @param port The port + * @param pin The pin + * @param mode The mode to use * @see GPIO_MODE */ void gpio_mode(GPIO_TypeDef *port, uint32_t pin, uint32_t mode); /** * Sets the state of a digital output pin. - * @param port the port - * @param pin the pin - * @param val non-zero for high, zero for low + * @param port The port + * @param pin The pin + * @param val Non-zero for high, zero for low */ void gpio_dout(GPIO_TypeDef *port, uint32_t pin, uint32_t val); /** * Reads a digital input pin. - * @param port the port - * @param pin the pin - * @return non-zero for high, zero for low + * @param port The port + * @param pin The pin + * @return Non-zero for high, zero for low */ uint32_t gpio_din(GPIO_TypeDef *port, uint32_t pin); diff --git a/src/heap.c b/src/kernel/heap.c similarity index 96% rename from src/heap.c rename to src/kernel/heap.c index 354087f..ff5dd9e 100644 --- a/src/heap.c +++ b/src/kernel/heap.c @@ -18,10 +18,15 @@ * along with this program. If not, see . */ -#include +#include "heap.h" #define HEAP_ALIGN 4 +typedef struct { + uint32_t size; + void *next; +} __attribute__ ((packed)) alloc_t; + static alloc_t *free_blocks; static void *heap_end; diff --git a/include/heap.h b/src/kernel/heap.h similarity index 70% rename from include/heap.h rename to src/kernel/heap.h index acbf81c..c817e4d 100644 --- a/include/heap.h +++ b/src/kernel/heap.h @@ -23,43 +23,38 @@ #include -typedef struct { - uint32_t size; - void *next; -} __attribute__ ((packed)) alloc_t; - /** * Initializes memory management of the given heap. - * No overflow stuff is done, so... - * @param buf the heap to use for allocations + * No overflow stuff is done, so... be careful. + * @param buf The heap to use for allocations */ void heap_init(void *buf); /** - * Returns the amount of free memory, in bytes. - * @return amount of free memory in bytes + * Returns the amount of free, allocatable memory, in bytes. + * @return Amount of free memory in bytes */ uint32_t heap_free(void); /** * Allocates a chunk of memory. - * @param size how many bytes to claim - * @return pointer to the allocated buffer + * @param size How many bytes to claim + * @return Pointer to the allocated buffer */ void *malloc(uint32_t size); /** * Allocates and zeros a chunk of memory. - * @param count how many of whatever to allocate - * @param size byte count of each whatever - * @return pointer to the allocated buffer + * @param count How many of whatever to allocate + * @param size Byte count of each whatever + * @return Pointer to the allocated buffer */ void *calloc(uint32_t count, uint32_t size); /** * Frees the buffer allocated through malloc/calloc. * Please don't double-free. - * @param the buffer to release + * @param The buffer to release */ void free(void *buf); diff --git a/src/main.c b/src/kernel/init.c similarity index 62% rename from src/main.c rename to src/kernel/init.c index bbcd09b..e4ac115 100644 --- a/src/main.c +++ b/src/kernel/init.c @@ -1,6 +1,6 @@ /** - * @file main.c - * Entry point for operating system + * @file init.c + * Kernel initialization procedure * * Copyright (C) 2018 Clyne Sullivan * @@ -18,16 +18,15 @@ * along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include +#include "clock.h" +#include "gpio.h" +#include "heap.h" +#include "task.h" +#include extern uint8_t __bss_end__; -void kmain(void); +extern void user_main(void); int main(void) { @@ -47,35 +46,7 @@ int main(void) // enable FPU //SCB->CPACR |= (0xF << 20); - task_init(kmain); + task_init(user_main); while (1); } -void task2(void); -void kmain(void) -{ - gpio(GPIO_MODE, 5, OUTPUT); - task_start(task2, 512); - - for (int i = 0; i < 8; i++) { - gpio(GPIO_OUT, 5, !(i & 1)); - delay(200); - } -} - -void task3(void); -void task2(void) -{ - delay(400); - task_start(task3, 1024); -} - -void task3(void) -{ - int state = 0; - delay(2500); - while (1) { - gpio(GPIO_OUT, 5, state ^= 1); - delay(500); - } -} diff --git a/src/startup_stm32l476xx.s b/src/kernel/startup_stm32l476xx.s similarity index 100% rename from src/startup_stm32l476xx.s rename to src/kernel/startup_stm32l476xx.s diff --git a/src/svc.c b/src/kernel/svc.c similarity index 91% rename from src/svc.c rename to src/kernel/svc.c index f132571..62324f7 100644 --- a/src/svc.c +++ b/src/kernel/svc.c @@ -20,11 +20,12 @@ */ #include -#include -#include -#include +#include "gpio.h" +#include "clock.h" +#include "task.h" extern void gpio_svc(uint32_t *); +extern void clock_svc(uint32_t *); void svc_handler(uint32_t *args) { @@ -38,6 +39,8 @@ void svc_handler(uint32_t *args) case 1: gpio_svc(args); break; + case 2: + clock_svc(args); default: break; } diff --git a/src/task.c b/src/kernel/task.c similarity index 97% rename from src/task.c rename to src/kernel/task.c index 4da2be1..1a1c16b 100644 --- a/src/task.c +++ b/src/kernel/task.c @@ -18,9 +18,9 @@ * along with this program. If not, see . */ -#include -#include -#include +#include "task.h" +#include "heap.h" +#include task_t *current, *prev; static uint8_t task_disable = 0; @@ -167,6 +167,7 @@ void PendSV_Handler(void) asm("bx lr"); // TODO why, and what does this do + // TODO get back to c, implement task sleeping asm("\ mrs r0, psp; \ isb; \ diff --git a/include/task.h b/src/kernel/task.h similarity index 93% rename from include/task.h rename to src/kernel/task.h index 916a87c..3d331ae 100644 --- a/include/task.h +++ b/src/kernel/task.h @@ -54,8 +54,10 @@ void task_start(void (*task)(void), uint16_t stackSize); */ void task_hold(uint8_t hold); +/** + * Frees the task's resources and removes it from the running task list. + * @param code An unused exit code + */ void _exit(int code); -//int fork(void); - #endif // TASK_H_ diff --git a/src/user/Makefile b/src/user/Makefile new file mode 100644 index 0000000..d22fbf3 --- /dev/null +++ b/src/user/Makefile @@ -0,0 +1,22 @@ +CFILES = $(wildcard *.c) +AFILES = $(wildcard *.s) +OFILES = $(patsubst %.c, %.o, $(CFILES)) \ + $(patsubst %.s, %.asm.o, $(AFILES)) + +CFLAGS += -I.. -I../arch/cmsis + +all: $(OFILES) + +%.o: %.c + @echo " CC " $< + @$(CROSS)$(CC) $(CFLAGS) -c $< -o $@ + +%.asm.o: %.s + @echo " AS " $< + @$(CROSS)$(AS) $(AFLAGS) -c $< -o $@ + +clean: + @echo " CLEAN" + @rm -f $(OFILES) + + diff --git a/src/user/priv_gpio.h b/src/user/priv_gpio.h new file mode 100644 index 0000000..6b349fe --- /dev/null +++ b/src/user/priv_gpio.h @@ -0,0 +1,58 @@ +/** + * @file priv_gpio.h + * GPIO access for unpriviledged processes + * + * 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 . + */ + +#ifndef PRIV_GPIO_H_ +#define PRIV_GPIO_H_ + +// For value flags +#include + +/** + * Possible GPIO calls. + */ +enum GPIO_CALLS { + GPIO_MODE = 0, /**< Change GPIO mode */ + GPIO_TYPE, /**< Change GPIO type (PuPd/ODrain) */ + GPIO_PUPD, /**< Set/clear pullup/pulldown */ + GPIO_SPEED, /**< Set GPIO speed */ + GPIO_OUT, /**< Set GPIO output state */ +}; + +/** + * Provides unpriviledged GPIO access. + * @param call The type of GPIO call to make + * @param pin The pin to modify (0-15 = A, 16-31 = B, ...) + * @param value The value to pass to the call + */ +void gpio(uint32_t call, uint32_t pin, uint32_t value) +{ + register uint32_t r0 asm("r0") = call; + register uint32_t r1 asm("r1") = pin; + register uint32_t r2 asm("r2") = value; + + asm("\ + mov r0, %0; \ + mov r1, %1; \ + mov r2, %2; \ + svc 1; \ + " :: "r" (r0), "r" (r1), "r" (r2)); +} + +#endif // PRIV_GPIO_H_ diff --git a/src/user/user.c b/src/user/user.c new file mode 100644 index 0000000..fc51d29 --- /dev/null +++ b/src/user/user.c @@ -0,0 +1,35 @@ +#include +#include "priv_gpio.h" +#include + +void task1(void); +void task2(void); + + + +void user_main(void) +{ + gpio(GPIO_MODE, 5, OUTPUT); + task_start(task1, 512); + + for (int i = 0; i < 8; i++) { + gpio(GPIO_OUT, 5, !(i & 1)); + delay(200); + } +} + +void task1(void) +{ + delay(400); + task_start(task2, 1024); +} + +void task2(void) +{ + int state = 0; + delay(2500); + while (1) { + gpio(GPIO_OUT, 5, state ^= 1); + delay(500); + } +}