cleanup, added timebase code (scheduled tasks, ms delay, time base)

master
Ondřej Hruška 9 years ago
parent 17f768a478
commit 39d47509ec
  1. 13
      Makefile
  2. 59
      init.c
  3. 7
      init.h
  4. 26
      lib/defs_gpio.h
  5. 20
      lib/systick.c
  6. 20
      lib/systick.h
  7. 75
      main.c
  8. 21
      proj.pro
  9. 6
      utils/gpio.c
  10. 27
      utils/gpio.h
  11. 68
      utils/timebase.c
  12. 10
      utils/timebase.h
  13. 3
      utils/usart.c
  14. 2
      utils/usart.h

@ -10,15 +10,16 @@ LDSCRIPT = stm32l100rc.ld
# Main file # Main file
BINARY = main BINARY = main
INCL_DIRS = . lib source INCL_DIRS = . lib utils
SRC_DIR = source
STARTUP_SCRIPT = startup_stm32l100xc.s STARTUP_SCRIPT = startup_stm32l100xc.s
OBJS += $(BINARY).o $(STARTUP_SCRIPT:.s=.o) OBJS += $(BINARY).o
OBJS += lib/gpio.o OBJS += $(STARTUP_SCRIPT:.s=.o)
OBJS += lib/systick.o OBJS += utils/gpio.o
OBJS += lib/usart.o OBJS += utils/usart.o
OBJS += utils/timebase.o
OBJS += init.o
################################################################ ################################################################

@ -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;
}

@ -0,0 +1,7 @@
#pragma once
#include <common.h>
void init_clock(void);
void init_gpios(void);
void init_usart(void);
void init_systick(void);

@ -6,6 +6,32 @@
// DATE : 10/2015 // DATE : 10/2015
// DESCR : Control registers and bit masks for GPIO // 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 // offsets
#define GPIO_MODER_offs 0x00 // GPIO pin mode register, #define GPIO_MODER_offs 0x00 // GPIO pin mode register,

@ -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;
}

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

@ -1,92 +1,33 @@
#include <common.h> #include <common.h>
#include <gpio.h>
#include <systick.h>
#include <usart.h>
#include "utils/usart.h"
#include "utils/timebase.h"
static void init_gpios(void) #include "init.h"
{
gpio_enable(GPIOA);
gpio_enable(GPIOB);
gpio_enable(GPIOC);
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() */ /** Called before main() */
void SystemInit(void) void SystemInit(void)
{ {
init_clock(); init_clock();
systick_setup(16000); init_systick();
init_gpios(); init_gpios();
init_usart(); init_usart();
}
static uint32_t time = 0; schedule_timed_task(blink, 500);
/** 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");
}
} }
int main(void) int main(void)
{ {
while (1) { while (1) {
delay(); delay_ms(1000);
GPIOC_ODR ^= BIT8; GPIOC_ODR ^= BIT8;
usart_tx_string(USART3, "HELLO\r\n"); usart_tx_string(USART3, "HELLO\r\n");

@ -19,8 +19,14 @@ DISTFILES += \
SOURCES += \ SOURCES += \
main.c \ main.c \
lib/gpio.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 += \ HEADERS += \
lib/common.h \ lib/common.h \
@ -28,9 +34,14 @@ HEADERS += \
lib/defs_flash.h \ lib/defs_flash.h \
lib/defs_gpio.h \ lib/defs_gpio.h \
lib/defs_rcc.h \ lib/defs_rcc.h \
lib/gpio.h \
lib/defs_systick.h \ lib/defs_systick.h \
lib/systick.h \
lib/defs_usart.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

@ -41,17 +41,13 @@ void gpio_disable(uint32_t gpio)
void gpio_set_af(uint32_t gpio, uint32_t pins, enum GPIO_AF af) void gpio_set_af(uint32_t gpio, uint32_t pins, enum GPIO_AF af)
{ {
gpio_enable(gpio); 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 afrl = P_REG(gpio, GPIO_AFRL_offs);
io32_t afrh = P_REG(gpio, GPIO_AFRH_offs); io32_t afrh = P_REG(gpio, GPIO_AFRH_offs);
BitFieldLoop(i, m, 16) { BitFieldLoop(i, m, 16) {
if (pins & m) { if (pins & m) {
// set pin mode to AF
*moder &= ~(0b11 << i * 2);
*moder |= MODER_AF << i * 2;
if (i < 8) { if (i < 8) {
*afrl &= ~(0xF << i * 4); *afrl &= ~(0xF << i * 4);
*afrl |= af << i * 4; *afrl |= af << i * 4;

@ -2,33 +2,6 @@
#include "common.h" #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 * Enable GPIO in RCC
* @param gpio GPIO base * @param gpio GPIO base

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

@ -0,0 +1,10 @@
#pragma once
#include <common.h>
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);

@ -73,8 +73,9 @@ void usart_tx_char(uint32_t usart, uint8_t c)
*DR = c; *DR = c;
} }
/** Transmit a string until \0 */ /** 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; char c;
while ((c = *string++) != 0) { while ((c = *string++) != 0) {

@ -28,4 +28,4 @@ bool usart_tx_ready(uint32_t usart);
void usart_tx_char(uint32_t usart, uint8_t c); void usart_tx_char(uint32_t usart, uint8_t c);
/** Transmit a string until \0 */ /** Transmit a string until \0 */
void usart_tx_string(uint32_t usart, char *string); void usart_tx_string(uint32_t usart, const char *string);
Loading…
Cancel
Save