From 39d47509eced080481fede02cbad34dd189dc4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 29 Dec 2015 09:47:05 +0100 Subject: [PATCH] cleanup, added timebase code (scheduled tasks, ms delay, time base) --- Makefile | 13 ++++---- init.c | 59 +++++++++++++++++++++++++++++++++ init.h | 7 ++++ lib/defs_gpio.h | 26 +++++++++++++++ lib/systick.c | 20 ----------- lib/systick.h | 20 ----------- main.c | 75 +++++------------------------------------- proj.pro | 21 +++++++++--- {lib => utils}/gpio.c | 6 +--- {lib => utils}/gpio.h | 27 --------------- utils/timebase.c | 68 ++++++++++++++++++++++++++++++++++++++ utils/timebase.h | 10 ++++++ {lib => utils}/usart.c | 3 +- {lib => utils}/usart.h | 2 +- 14 files changed, 205 insertions(+), 152 deletions(-) create mode 100644 init.c create mode 100644 init.h delete mode 100644 lib/systick.c delete mode 100644 lib/systick.h rename {lib => utils}/gpio.c (90%) rename {lib => utils}/gpio.h (69%) create mode 100644 utils/timebase.c create mode 100644 utils/timebase.h rename {lib => utils}/usart.c (96%) rename {lib => utils}/usart.h (93%) diff --git a/Makefile b/Makefile index 34050da..ffad3a8 100644 --- a/Makefile +++ b/Makefile @@ -10,15 +10,16 @@ LDSCRIPT = stm32l100rc.ld # Main file BINARY = main -INCL_DIRS = . lib source -SRC_DIR = source +INCL_DIRS = . lib utils STARTUP_SCRIPT = startup_stm32l100xc.s -OBJS += $(BINARY).o $(STARTUP_SCRIPT:.s=.o) -OBJS += lib/gpio.o -OBJS += lib/systick.o -OBJS += lib/usart.o +OBJS += $(BINARY).o +OBJS += $(STARTUP_SCRIPT:.s=.o) +OBJS += utils/gpio.o +OBJS += utils/usart.o +OBJS += utils/timebase.o +OBJS += init.o ################################################################ diff --git a/init.c b/init.c new file mode 100644 index 0000000..3e0c078 --- /dev/null +++ b/init.c @@ -0,0 +1,59 @@ +#include "init.h" + +#include "utils/gpio.h" +#include "utils/usart.h" + + +void init_gpios(void) +{ + gpio_enable(GPIOA); + gpio_enable(GPIOB); + gpio_enable(GPIOC); + + gpio_set_mode(GPIOC, BIT8 | BIT9 | BIT7, MODER_OUTPUT); +} + + + +void init_clock(void) +{ + // Flash timing - 64-bit access, pre-fetch, latency = 1 + FLASH_ACR |= FLASH_ACR_ACC64; // Cannot write both at once + FLASH_ACR |= FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY; + + // Power on HSI (runs from MSI on start) + RCC_CR |= RCC_CR_HSION; + + // Wait for HSIRDY + while (!(RCC_CR & RCC_CR_HSIRDY)); + + // Select HSI as the core clock source + RCC_CFGR &= ~RCC_CFGR_SW; + RCC_CFGR |= RCC_CFGR_SW_HSI; +} + + + +void init_usart(void) +{ + gpio_set_af(GPIOC, BIT10 | BIT11, AF7); + + // USART at C10 (tx), C11 (rx) + RCC_APB1ENR |= RCC_APB1ENR_USART3EN; + + // RATE 9600Bd 104.1875 (see datasheet for reference) + //USART3_BRR = 0x00683; // 9600 @ 16MHz + USART3_BRR = 0x0008A; // 115200 @ 16MHz + + // USART enable + USART3_CR1 = USART_CR1_UE | USART_CR1_RE | USART_CR1_TE; +} + + + +void init_systick(void) +{ + SysTick_CSR = (SysTick_CSR & ~SysTick_CSR_CLKSOURCE) | SysTick_CSR_CLKSOURCE_CORE; + SysTick_RELOAD = 16000; // 1ms interrupt @ 16MHz core clock + SysTick_CSR |= SysTick_CSR_TICKINT | SysTick_CSR_ENABLE; +} diff --git a/init.h b/init.h new file mode 100644 index 0000000..f8f3e8d --- /dev/null +++ b/init.h @@ -0,0 +1,7 @@ +#pragma once +#include + +void init_clock(void); +void init_gpios(void); +void init_usart(void); +void init_systick(void); diff --git a/lib/defs_gpio.h b/lib/defs_gpio.h index 66900d0..deb8bd9 100644 --- a/lib/defs_gpio.h +++ b/lib/defs_gpio.h @@ -6,6 +6,32 @@ // DATE : 10/2015 // DESCR : Control registers and bit masks for GPIO +enum GPIO_MODE { + MODER_INPUT = 0, + MODER_OUTPUT = 1, + MODER_AF = 2, + MODER_ANALOG = 3, +}; + +enum GPIO_AF { + AF0 = 0, + AF1 = 1, + AF2 = 2, + AF3 = 3, + AF4 = 4, + AF5 = 5, + AF6 = 6, + AF7 = 7, + AF8 = 8, + AF9 = 9, + AF10 = 10, + AF11 = 11, + AF12 = 12, + AF13 = 13, + AF14 = 14, + AF15 = 15, +}; + // offsets #define GPIO_MODER_offs 0x00 // GPIO pin mode register, diff --git a/lib/systick.c b/lib/systick.c deleted file mode 100644 index 6501c5e..0000000 --- a/lib/systick.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "systick.h" - -void systick_setup(uint32_t prescaller) -{ - SysTick_CSR = (SysTick_CSR & ~SysTick_CSR_CLKSOURCE) | SysTick_CSR_CLKSOURCE_CORE; - SysTick_RELOAD = prescaller; - SysTick_CSR |= SysTick_CSR_TICKINT | SysTick_CSR_ENABLE; -} - - -void systick_enable(void) -{ - SysTick_CSR |= SysTick_CSR_ENABLE; -} - - -void systick_disable(void) -{ - SysTick_CSR &= ~SysTick_CSR_ENABLE; -} diff --git a/lib/systick.h b/lib/systick.h deleted file mode 100644 index 8fc016f..0000000 --- a/lib/systick.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "common.h" - -// don't forget to implement the handler: -// void SysTick_Handler(void) - - -/** - * Set up and start systick - * @param prescaller divider (eg. for 1ms @ 16MHz: 16000) - */ -void systick_setup(uint32_t prescaller); - - -/** Enable (start) systick */ -void systick_enable(void); - - -/** Disable (stop) systick */ -void systick_disable(void); diff --git a/main.c b/main.c index 2c8a79d..ce248ed 100644 --- a/main.c +++ b/main.c @@ -1,92 +1,33 @@ #include -#include -#include -#include +#include "utils/usart.h" +#include "utils/timebase.h" -static void init_gpios(void) -{ - gpio_enable(GPIOA); - gpio_enable(GPIOB); - gpio_enable(GPIOC); +#include "init.h" - gpio_set_mode(GPIOC, BIT8 | BIT9 | BIT7, MODER_OUTPUT); - gpio_set_mode(GPIOA, BIT8, MODER_OUTPUT); +void blink(void) { + GPIOC_ODR ^= BIT9; } -static void init_clock(void) -{ - // Flash timing - 64-bit access, pre-fetch, latency = 1 - FLASH_ACR |= FLASH_ACR_ACC64; // Cannot write both at once - FLASH_ACR |= FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY; - - // Power on HSI (runs from MSI on start) - RCC_CR |= RCC_CR_HSION; - - // Wait for HSIRDY - while (!(RCC_CR & RCC_CR_HSIRDY)); - - // Select HSI as the core clock source - RCC_CFGR &= ~RCC_CFGR_SW; - RCC_CFGR |= RCC_CFGR_SW_HSI; -} - - -static void init_usart(void) -{ - gpio_set_af(GPIOC, BIT10 | BIT11, AF7); - - // USART at C11, C12 - RCC_APB1ENR |= RCC_APB1ENR_USART3EN; - - // RATE 9600Bd 104.1875 (see datasheet for reference)8.6875 - //USART3_BRR = 0x00683; // 9600 - USART3_BRR = 0x0008A; // 115200 - - // USART enable - USART3_CR1 = USART_CR1_UE | USART_CR1_RE | USART_CR1_TE; -} - /** Called before main() */ void SystemInit(void) { init_clock(); - systick_setup(16000); + init_systick(); init_gpios(); init_usart(); -} - - -static uint32_t time = 0; - -/** IRQ */ -void SysTick_Handler(void) -{ - time++; - if (time == 500) { - time = 0; - GPIOC_ODR ^= BIT9; - } -} - - - -void delay(void) -{ - for (int i = 0; i < 800000; i++) { - __asm__("nop"); - } + schedule_timed_task(blink, 500); } int main(void) { while (1) { - delay(); + delay_ms(1000); GPIOC_ODR ^= BIT8; usart_tx_string(USART3, "HELLO\r\n"); diff --git a/proj.pro b/proj.pro index 2248207..86419c9 100644 --- a/proj.pro +++ b/proj.pro @@ -19,8 +19,14 @@ DISTFILES += \ SOURCES += \ main.c \ lib/gpio.c \ - lib/systick.c \ - lib/usart.c + lib/usart.c \ + init.c \ + timebase.c \ + gpio.c \ + usart.c \ + utils/gpio.c \ + utils/timebase.c \ + utils/usart.c HEADERS += \ lib/common.h \ @@ -28,9 +34,14 @@ HEADERS += \ lib/defs_flash.h \ lib/defs_gpio.h \ lib/defs_rcc.h \ - lib/gpio.h \ lib/defs_systick.h \ - lib/systick.h \ lib/defs_usart.h \ - lib/usart.h + lib/usart.h \ + init.h \ + timebase.h \ + gpio.h \ + usart.h \ + utils/gpio.h \ + utils/timebase.h \ + utils/usart.h diff --git a/lib/gpio.c b/utils/gpio.c similarity index 90% rename from lib/gpio.c rename to utils/gpio.c index 236e4ae..19a5e86 100644 --- a/lib/gpio.c +++ b/utils/gpio.c @@ -41,17 +41,13 @@ void gpio_disable(uint32_t gpio) void gpio_set_af(uint32_t gpio, uint32_t pins, enum GPIO_AF af) { gpio_enable(gpio); + gpio_set_mode(gpio, pins, MODER_AF); - io32_t moder = P_REG(gpio, GPIO_MODER_offs); io32_t afrl = P_REG(gpio, GPIO_AFRL_offs); io32_t afrh = P_REG(gpio, GPIO_AFRH_offs); BitFieldLoop(i, m, 16) { if (pins & m) { - // set pin mode to AF - *moder &= ~(0b11 << i * 2); - *moder |= MODER_AF << i * 2; - if (i < 8) { *afrl &= ~(0xF << i * 4); *afrl |= af << i * 4; diff --git a/lib/gpio.h b/utils/gpio.h similarity index 69% rename from lib/gpio.h rename to utils/gpio.h index 54de894..11ce96d 100644 --- a/lib/gpio.h +++ b/utils/gpio.h @@ -2,33 +2,6 @@ #include "common.h" -enum GPIO_MODE { - MODER_INPUT = 0, - MODER_OUTPUT = 1, - MODER_AF = 2, - MODER_ANALOG = 3, -}; - -enum GPIO_AF { - AF0 = 0, - AF1 = 1, - AF2 = 2, - AF3 = 3, - AF4 = 4, - AF5 = 5, - AF6 = 6, - AF7 = 7, - AF8 = 8, - AF9 = 9, - AF10 = 10, - AF11 = 11, - AF12 = 12, - AF13 = 13, - AF14 = 14, - AF15 = 15, -}; - - /** * Enable GPIO in RCC * @param gpio GPIO base diff --git a/utils/timebase.c b/utils/timebase.c new file mode 100644 index 0000000..5aa100a --- /dev/null +++ b/utils/timebase.c @@ -0,0 +1,68 @@ +#include "timebase.h" + +volatile uint32_t TIME_MS; + +#define TASK_COUNT 10 + +// --- time scheduler system --- +typedef struct { + /** User callback */ + void (*callback) (void); + /** Callback interval */ + uint32_t interval_ms; + /** Counter, when reaches interval_ms, is cleared and callback is called. */ + uint32_t countup; +} timebase_cb_t; + +static uint8_t scheduled_task_n = 0; +static timebase_cb_t scheduled_tasks[TASK_COUNT]; + + +bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms) +{ + if (scheduled_task_n >= TASK_COUNT) return false; + + // add the task + timebase_cb_t *task = &scheduled_tasks[scheduled_task_n++]; + task->callback = callback; + task->countup = 0; + task->interval_ms = interval_ms; + + return true; +} + + +/** IRQ */ +void SysTick_Handler(void) +{ + TIME_MS++; + + // run scheduled tasks + for (int i = 0; i < scheduled_task_n; i++) { + timebase_cb_t *task = &scheduled_tasks[i]; + if (task->countup++ >= task->interval_ms) { + task->callback(); + task->countup = 0; + } + } +} + + +void delay_ms(uint32_t ms) +{ + uint32_t last_ms = TIME_MS; + + while (ms-- != 0) { + while (TIME_MS == last_ms); + last_ms = TIME_MS; + } +} + + + +void delay_s(uint32_t s) +{ + while (s-- != 0) { + delay_ms(1000); + } +} diff --git a/utils/timebase.h b/utils/timebase.h new file mode 100644 index 0000000..4a2fee5 --- /dev/null +++ b/utils/timebase.h @@ -0,0 +1,10 @@ +#pragma once +#include + +extern volatile uint32_t TIME_MS; + +void delay_ms(uint32_t ms); +void delay_s(uint32_t s); + +/** Schedule a timed task (like a cron job) */ +bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms); diff --git a/lib/usart.c b/utils/usart.c similarity index 96% rename from lib/usart.c rename to utils/usart.c index ad2522b..e8a3aa3 100644 --- a/lib/usart.c +++ b/utils/usart.c @@ -73,8 +73,9 @@ void usart_tx_char(uint32_t usart, uint8_t c) *DR = c; } + /** Transmit a string until \0 */ -void usart_tx_string(uint32_t usart, char *string) +void usart_tx_string(uint32_t usart, const char *string) { char c; while ((c = *string++) != 0) { diff --git a/lib/usart.h b/utils/usart.h similarity index 93% rename from lib/usart.h rename to utils/usart.h index d26bd7e..9440b86 100644 --- a/lib/usart.h +++ b/utils/usart.h @@ -28,4 +28,4 @@ bool usart_tx_ready(uint32_t usart); void usart_tx_char(uint32_t usart, uint8_t c); /** Transmit a string until \0 */ -void usart_tx_string(uint32_t usart, char *string); +void usart_tx_string(uint32_t usart, const char *string);