folder restructure

master
Clyne Sullivan 6 years ago
parent 231c796f50
commit c66410f631

@ -25,37 +25,26 @@ AS = as
MCUFLAGS = -mthumb -mcpu=cortex-m4 #-mfloat-abi=hard -mfpu=fpv4-sp-d16 MCUFLAGS = -mthumb -mcpu=cortex-m4 #-mfloat-abi=hard -mfpu=fpv4-sp-d16
AFLAGS = $(MCUFLAGS) AFLAGS = $(MCUFLAGS)
CFLAGS = $(MCUFLAGS) -ggdb \ CFLAGS = $(MCUFLAGS) -ggdb \
-Iinclude -Iinclude/cmsis \ -I.. \
-fno-builtin -fsigned-char -ffreestanding \ -fno-builtin -fsigned-char -ffreestanding \
-Wall -Werror -Wextra -pedantic \ -Wall -Werror -Wextra -pedantic \
-Wno-overlength-strings -Wno-discarded-qualifiers -Wno-overlength-strings -Wno-discarded-qualifiers
LFLAGS = -T link.ld LFLAGS = -T link.ld
CFILES = $(wildcard src/*.c) OUT = main.elf
AFILES = $(wildcard src/*.s)
OUTDIR = out export
OFILES = $(patsubst src/%.c, $(OUTDIR)/%.o, $(CFILES)) \
$(patsubst src/%.s, $(OUTDIR)/%.asm.o, $(AFILES))
OUT = out/main.elf all:
@$(MAKE) -C src/kernel
all: $(OUT) @$(MAKE) -C src/user
$(OUT): $(OFILES)
@echo " LINK " $(OUT) @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: clean:
@echo " CLEAN" @echo " CLEAN"
@rm -rf out/* @$(MAKE) -C src/kernel clean
@$(MAKE) -C src/user clean
@rm -f $(OUT)

@ -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_

@ -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)

@ -18,12 +18,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <clock.h> #include "clock.h"
#include <stm32l476xx.h> #include <arch/stm/stm32l476xx.h>
// ticks since init // ticks since init
volatile uint32_t ticks = 0; volatile uint32_t ticks = 0;
volatile uint8_t tim2_finished = 1;
void clock_svc(uint32_t *args)
{
udelay(args[0]);
}
void clock_init(void) void clock_init(void)
{ {
// turn on HSI (16MHz) // turn on HSI (16MHz)
@ -53,6 +60,15 @@ void clock_init(void)
// SysTick init. 80MHz / 80000 = 1kHz, ms precision // SysTick init. 80MHz / 80000 = 1kHz, ms precision
SysTick->LOAD = 80000; SysTick->LOAD = 80000;
SysTick->CTRL |= 0x07; // no div, interrupt, enable 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) void delay(uint32_t count)
@ -61,12 +77,27 @@ void delay(uint32_t count)
while (ticks < target); 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) void SysTick_Handler(void)
{ {
// just keep counting // just keep counting
ticks++; ticks++;
// task switch every four ticks (4ms)
if (!(ticks & 3)) if (!(ticks & 3))
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
} }
void TIM2_IRQHandler(void)
{
TIM2->SR &= ~(TIM_SR_UIF);
tim2_finished |= 1;
}

@ -1,6 +1,6 @@
/** /**
* @file clock.h * @file clock.h
* Basic clock utilities * Clock utilities
* *
* Copyright (C) 2018 Clyne Sullivan * Copyright (C) 2018 Clyne Sullivan
* *
@ -30,8 +30,14 @@ extern void clock_init(void);
/** /**
* Sleeps for given amount of milliseconds. * 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); 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_ #endif // CLOCK_H_

@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <gpio.h> #include "gpio.h"
static const GPIO_TypeDef *gpio_ports[8] = { static const GPIO_TypeDef *gpio_ports[8] = {
GPIOA, GPIOB, GPIOC, GPIOD, GPIOA, GPIOB, GPIOC, GPIOD,

@ -1,6 +1,6 @@
/** /**
* @file gpio.h * @file gpio.h
* Abstracts gpio access, makes things easier * GPIO Abstraction and access
* *
* Copyright (C) 2018 Clyne Sullivan * Copyright (C) 2018 Clyne Sullivan
* *
@ -21,17 +21,17 @@
#ifndef GPIO_H_ #ifndef GPIO_H_
#define GPIO_H_ #define GPIO_H_
#include <stm32l476xx.h> #include <arch/stm/stm32l476xx.h>
/** /**
* Helps simplify gpio calls. * Helps simplify gpio calls.
* @param p port, e.g. GPIOA * @param p Port, e.g. A
* @param b pin, e.g. 4 * @param b Pin, e.g. 4
*/ */
#define GPIO_PORT(p, b) GPIO##p, b #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 enum GPIO_MODE
{ {
@ -72,59 +72,59 @@ enum GPIO_PUPD
}; };
/** /**
* Initializes the gpio. * Prepares for GPIO usage.
*/ */
void gpio_init(void); void gpio_init(void);
/** /**
* Enables or disables pullup/pulldown for the given pin. * Enables or disables pullup/pulldown for the given pin.
* @param port the port, e.g. GPIOA * @param port The port, e.g. GPIOA
* @param pin the pin * @param pin The pin
* @param pupd pullup/pulldown enable * @param pupd Pullup/pulldown enable
* @see GPIO_PUPD * @see GPIO_PUPD
*/ */
void gpio_pupd(GPIO_TypeDef *port, uint32_t pin, uint32_t 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. * Sets whether to use push-pull or open drain for the given pin.
* @param port the port * @param port The port
* @param pin the pin * @param pin The pin
* @param type what to use * @param type What type to use
* @see GPIO_TYPE * @see GPIO_TYPE
*/ */
void gpio_type(GPIO_TypeDef *port, uint32_t pin, uint32_t type); void gpio_type(GPIO_TypeDef *port, uint32_t pin, uint32_t type);
/** /**
* Sets the pin's speed. * Sets the pin's speed.
* @param port the port * @param port The port
* @param pin the pin * @param pin The pin
* @param speed the speed to use * @param speed The speed to use
* @see GPIO_SPEED * @see GPIO_SPEED
*/ */
void gpio_speed(GPIO_TypeDef *port, uint32_t pin, uint32_t speed); void gpio_speed(GPIO_TypeDef *port, uint32_t pin, uint32_t speed);
/** /**
* Sets the pin's i/o mode. * Sets the pin's i/o mode.
* @param port the port * @param port The port
* @param pin the pin * @param pin The pin
* @param mode the mode to use * @param mode The mode to use
* @see GPIO_MODE * @see GPIO_MODE
*/ */
void gpio_mode(GPIO_TypeDef *port, uint32_t pin, uint32_t mode); void gpio_mode(GPIO_TypeDef *port, uint32_t pin, uint32_t mode);
/** /**
* Sets the state of a digital output pin. * Sets the state of a digital output pin.
* @param port the port * @param port The port
* @param pin the pin * @param pin The pin
* @param val non-zero for high, zero for low * @param val Non-zero for high, zero for low
*/ */
void gpio_dout(GPIO_TypeDef *port, uint32_t pin, uint32_t val); void gpio_dout(GPIO_TypeDef *port, uint32_t pin, uint32_t val);
/** /**
* Reads a digital input pin. * Reads a digital input pin.
* @param port the port * @param port The port
* @param pin the pin * @param pin The pin
* @return non-zero for high, zero for low * @return Non-zero for high, zero for low
*/ */
uint32_t gpio_din(GPIO_TypeDef *port, uint32_t pin); uint32_t gpio_din(GPIO_TypeDef *port, uint32_t pin);

@ -18,10 +18,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <heap.h> #include "heap.h"
#define HEAP_ALIGN 4 #define HEAP_ALIGN 4
typedef struct {
uint32_t size;
void *next;
} __attribute__ ((packed)) alloc_t;
static alloc_t *free_blocks; static alloc_t *free_blocks;
static void *heap_end; static void *heap_end;

@ -23,43 +23,38 @@
#include <stdint.h> #include <stdint.h>
typedef struct {
uint32_t size;
void *next;
} __attribute__ ((packed)) alloc_t;
/** /**
* Initializes memory management of the given heap. * Initializes memory management of the given heap.
* No overflow stuff is done, so... * No overflow stuff is done, so... be careful.
* @param buf the heap to use for allocations * @param buf The heap to use for allocations
*/ */
void heap_init(void *buf); void heap_init(void *buf);
/** /**
* Returns the amount of free memory, in bytes. * Returns the amount of free, allocatable memory, in bytes.
* @return amount of free memory in bytes * @return Amount of free memory in bytes
*/ */
uint32_t heap_free(void); uint32_t heap_free(void);
/** /**
* Allocates a chunk of memory. * Allocates a chunk of memory.
* @param size how many bytes to claim * @param size How many bytes to claim
* @return pointer to the allocated buffer * @return Pointer to the allocated buffer
*/ */
void *malloc(uint32_t size); void *malloc(uint32_t size);
/** /**
* Allocates and zeros a chunk of memory. * Allocates and zeros a chunk of memory.
* @param count how many of whatever to allocate * @param count How many of whatever to allocate
* @param size byte count of each whatever * @param size Byte count of each whatever
* @return pointer to the allocated buffer * @return Pointer to the allocated buffer
*/ */
void *calloc(uint32_t count, uint32_t size); void *calloc(uint32_t count, uint32_t size);
/** /**
* Frees the buffer allocated through malloc/calloc. * Frees the buffer allocated through malloc/calloc.
* Please don't double-free. * Please don't double-free.
* @param the buffer to release * @param The buffer to release
*/ */
void free(void *buf); void free(void *buf);

@ -1,6 +1,6 @@
/** /**
* @file main.c * @file init.c
* Entry point for operating system * Kernel initialization procedure
* *
* Copyright (C) 2018 Clyne Sullivan * Copyright (C) 2018 Clyne Sullivan
* *
@ -18,16 +18,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <clock.h> #include "clock.h"
#include <gpio.h> #include "gpio.h"
#include <priv_gpio.h> #include "heap.h"
#include <heap.h> #include "task.h"
#include <stm32l476xx.h> #include <arch/stm/stm32l476xx.h>
#include <task.h>
extern uint8_t __bss_end__; extern uint8_t __bss_end__;
void kmain(void); extern void user_main(void);
int main(void) int main(void)
{ {
@ -47,35 +46,7 @@ int main(void)
// enable FPU // enable FPU
//SCB->CPACR |= (0xF << 20); //SCB->CPACR |= (0xF << 20);
task_init(kmain); task_init(user_main);
while (1); 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);
}
}

@ -20,11 +20,12 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include <gpio.h> #include "gpio.h"
#include <clock.h> #include "clock.h"
#include <task.h> #include "task.h"
extern void gpio_svc(uint32_t *); extern void gpio_svc(uint32_t *);
extern void clock_svc(uint32_t *);
void svc_handler(uint32_t *args) void svc_handler(uint32_t *args)
{ {
@ -38,6 +39,8 @@ void svc_handler(uint32_t *args)
case 1: case 1:
gpio_svc(args); gpio_svc(args);
break; break;
case 2:
clock_svc(args);
default: default:
break; break;
} }

@ -18,9 +18,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <task.h> #include "task.h"
#include <heap.h> #include "heap.h"
#include <stm32l476xx.h> #include <arch/stm/stm32l476xx.h>
task_t *current, *prev; task_t *current, *prev;
static uint8_t task_disable = 0; static uint8_t task_disable = 0;
@ -167,6 +167,7 @@ void PendSV_Handler(void)
asm("bx lr"); asm("bx lr");
// TODO why, and what does this do // TODO why, and what does this do
// TODO get back to c, implement task sleeping
asm("\ asm("\
mrs r0, psp; \ mrs r0, psp; \
isb; \ isb; \

@ -54,8 +54,10 @@ void task_start(void (*task)(void), uint16_t stackSize);
*/ */
void task_hold(uint8_t hold); 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); void _exit(int code);
//int fork(void);
#endif // TASK_H_ #endif // TASK_H_

@ -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)

@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef PRIV_GPIO_H_
#define PRIV_GPIO_H_
// For value flags
#include <kernel/gpio.h>
/**
* 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_

@ -0,0 +1,35 @@
#include <kernel/clock.h>
#include "priv_gpio.h"
#include <kernel/task.h>
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);
}
}
Loading…
Cancel
Save