Extended timer driver

+ support for delays, blocking and non-blocking
+ improved period precision
! timer_delay_us probably not accurate at all
This commit is contained in:
Steins7 2020-01-15 22:05:51 +01:00
parent ebdbfaedc1
commit 55de91c274
9 changed files with 575 additions and 301 deletions

View File

@ -9,28 +9,24 @@
#define EXTI9_5_IRQ_PRIORITY 8
#define EXTI15_10_IRQ_PRIORITY 8
#define TIM1_IRQ_PRIORITY 4
#define TIM2_IRQ_PRIORITY 4
#define TIM3_IRQ_PRIORITY 4
#define TIM4_IRQ_PRIORITY 4
#define USART1_IRQ_PRIORITY 3
#define USART2_IRQ_PRIORITY 3
#define USART6_IRQ_PRIORITY 3
#define USART3_IRQ_PRIORITY 3
#define I2C1_IRQ_PRIORITY 2
#define I2C1_IRQERR_PRIORITY 1
#define I2C2_IRQ_PRIORITY 2
#define I2C2_IRQERR_PRIORITY 1
#define I2C3_IRQ_PRIORITY 2
#define I2C3_IRQERR_PRIORITY 1
#define SPI1_IRQ_PRIORITY 4
#define SPI2_IRQ_PRIORITY 4
#define SPI3_IRQ_PRIORITY 4
#define SPI4_IRQ_PRIORITY 4
#define SPI5_IRQ_PRIORITY 4
#define ADC1_IRQ_PRIORITY 5
#define ADC1_2_IRQ_PRIORITY 5
/****************************************************************************
* USART Pin and use configuration

View File

@ -95,7 +95,7 @@ void EXTI15_10_IRQHandler() {
#define SYSCFG_EXTI_PH_MASK 7
int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint32_t pin_cfg, OnIO cb) {
int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint8_t pin_cfg, OnIO cb) {
// enable GPIOx subsystem clocking
if (gpio == GPIOA) RCC->APB2ENR |= 1<<2;
@ -104,128 +104,128 @@ int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint32_t pin_cfg, OnIO cb) {
else if (gpio == GPIOD) RCC->APB2ENR |= 1<<5;
else if (gpio == GPIOE) RCC->APB2ENR |= 1<<6;
// ssetup the config bits
uint32_t crx = 0;
uint16_t odr = 0;
for(int i=0; i<8; i++) {
if(pin & (1 << i)) {
crx |= (pin_cfg & 0xF) << (4*i);
odr |= (pin_cfg & 0xF0) << i;
// setup pin mask for crx registers
uint64_t pin_mask = 0;
for(int i=0; i<16; ++i) {
if((pin >> i) & 0x1) {
pin_mask |= 0x1ll << 4*i;
}
}
gpio->CRL |= crx;
crx = 0;
for(int i=8; i<16; i++) {
if(pin & (1 << i)) {
crx |= (pin_cfg & 0xF) << (4*(i-8));
odr |= (pin_cfg & 0xF0) << i;
}
}
gpio->CRH |= crx;
gpio->ODR |= odr;
// clear previous data
uint64_t crx = pin_mask * 0x4; //reset value is 0x4
uint16_t odr = pin;
gpio->CRH &= ~(crx >> 32);
gpio->CRL &= ~(crx & 0xFFFF);
gpio->BSRR |= odr << 16;
/*
if (!cb) return -1; //no callback attached
// set up the new configuration
crx = pin_mask * (pin_cfg & 0xF);
odr = pin_cfg & 0x10;
gpio->CRH |= crx >> 32;
gpio->CRL |= crx & 0xFFFF;
gpio->BSRR |= odr;
//if (!cb) return -1; //no callback attached
return 0;
//TODO manage alternate functions
if (pin_cfg & 0x3) return -1; //callback set, but not in input mode
// ************* Input GPIO + External IRQ *************
uint32_t port_mask = 0;
uint32_t pin_mask = 0;
if (gpio == GPIOA) port_mask = SYSCFG_EXTI_PA_MASK;
else if (gpio == GPIOB) port_mask = SYSCFG_EXTI_PB_MASK;
else if (gpio == GPIOC) port_mask = SYSCFG_EXTI_PC_MASK;
else if (gpio == GPIOD) port_mask = SYSCFG_EXTI_PD_MASK;
else if (gpio == GPIOE) port_mask = SYSCFG_EXTI_PE_MASK;
uint32_t bit_mask = 0x1;
for (int i=0; i<16; i++) {
if (pin_mask & bit_mask) {
// enable clock for SYSCFG, no need for EXTI (interface not clocked)
RCC->APB2ENR = RCC->APB2ENR | (1<<14);
// configure pin Px_i (4 pin config per EXTICR[] register, 4 bits per pin)
// use port Px and bind Px_i --> EXTIi
// i>>2 = i/4 ; i & 0x3 = i%4
gpio->EXTICR[i>>2] = (SYSCFG->EXTICR[i>>2] &
~(0x0000000F << ((i & 3)<<2))) |
(port_mask << ((i & 3)<<2));
// allow pin EXTIi to send an IRQ
EXTI->IMR = EXTI->IMR | bit_mask;
// not a wakeup event
EXTI->EMR = EXTI->EMR & (~bit_mask);
// Configure pin event IRQ on rising (RTSR)/falling (FTSR) edge (rising only here)
if (pin_cfg & PIN_OPT_IRQ_EDGE_RISE) {
EXTI->RTSR = EXTI->RTSR | bit_mask;
} else {
EXTI->RTSR = EXTI->RTSR & (~bit_mask);
}
if (pin_cfg & PIN_OPT_IRQ_EDGE_FALL) {
EXTI->FTSR = EXTI->FTSR | bit_mask;
} else {
EXTI->FTSR = EXTI->FTSR & (~bit_mask);
}
io_cb[i] = cb;
// reset any pending IRQ on PC13
EXTI->PR = bit_mask;
// Setup NVIC
switch (i) {
case 0:
NVIC_SetPriority(EXTI0_IRQn, EXTI0_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI0_IRQn);
break;
case 1:
NVIC_SetPriority(EXTI1_IRQn, EXTI1_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI1_IRQn);
break;
case 2:
NVIC_SetPriority(EXTI2_IRQn, EXTI2_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI2_IRQn);
break;
case 3:
NVIC_SetPriority(EXTI3_IRQn, EXTI3_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI3_IRQn);
break;
case 4:
NVIC_SetPriority(EXTI4_IRQn, EXTI4_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI4_IRQn);
break;
case 5:
case 6:
case 7:
case 8:
case 9:
NVIC_SetPriority(EXTI9_5_IRQn, EXTI9_5_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI9_5_IRQn);
break;
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
NVIC_SetPriority(EXTI15_10_IRQn, EXTI15_10_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI15_10_IRQn);
break;
default:
return 0;
}
}
bit_mask = bit_mask<<1;
}
*/
return 0;
// if (pin_cfg & 0x3) return -1; //callback set, but not in input mode
//
// // ************* Input GPIO + External IRQ *************
//
// uint32_t port_mask = 0;
// uint32_t pin_mask = 0;
//
// if (gpio == GPIOA) port_mask = SYSCFG_EXTI_PA_MASK;
// else if (gpio == GPIOB) port_mask = SYSCFG_EXTI_PB_MASK;
// else if (gpio == GPIOC) port_mask = SYSCFG_EXTI_PC_MASK;
// else if (gpio == GPIOD) port_mask = SYSCFG_EXTI_PD_MASK;
// else if (gpio == GPIOE) port_mask = SYSCFG_EXTI_PE_MASK;
//
// uint32_t bit_mask = 0x1;
//
// for (int i=0; i<16; i++) {
// if (pin_mask & bit_mask) {
// // enable clock for SYSCFG, no need for EXTI (interface not clocked)
// RCC->APB2ENR = RCC->APB2ENR | (1<<14);
//
// // configure pin Px_i (4 pin config per EXTICR[] register, 4 bits per pin)
// // use port Px and bind Px_i --> EXTIi
// // i>>2 = i/4 ; i & 0x3 = i%4
// gpio->EXTICR[i>>2] = (SYSCFG->EXTICR[i>>2] &
// ~(0x0000000F << ((i & 3)<<2))) |
// (port_mask << ((i & 3)<<2));
//
// // allow pin EXTIi to send an IRQ
// EXTI->IMR = EXTI->IMR | bit_mask;
// // not a wakeup event
// EXTI->EMR = EXTI->EMR & (~bit_mask);
//
// // Configure pin event IRQ on rising (RTSR)/falling (FTSR) edge (rising only here)
// if (pin_cfg & PIN_OPT_IRQ_EDGE_RISE) {
// EXTI->RTSR = EXTI->RTSR | bit_mask;
// } else {
// EXTI->RTSR = EXTI->RTSR & (~bit_mask);
// }
//
// if (pin_cfg & PIN_OPT_IRQ_EDGE_FALL) {
// EXTI->FTSR = EXTI->FTSR | bit_mask;
// } else {
// EXTI->FTSR = EXTI->FTSR & (~bit_mask);
// }
//
// io_cb[i] = cb;
//
// // reset any pending IRQ on PC13
// EXTI->PR = bit_mask;
//
// // Setup NVIC
// switch (i) {
// case 0:
// NVIC_SetPriority(EXTI0_IRQn, EXTI0_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI0_IRQn);
// break;
// case 1:
// NVIC_SetPriority(EXTI1_IRQn, EXTI1_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI1_IRQn);
// break;
// case 2:
// NVIC_SetPriority(EXTI2_IRQn, EXTI2_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI2_IRQn);
// break;
// case 3:
// NVIC_SetPriority(EXTI3_IRQn, EXTI3_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI3_IRQn);
// break;
// case 4:
// NVIC_SetPriority(EXTI4_IRQn, EXTI4_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI4_IRQn);
// break;
// case 5:
// case 6:
// case 7:
// case 8:
// case 9:
// NVIC_SetPriority(EXTI9_5_IRQn, EXTI9_5_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI9_5_IRQn);
// break;
// case 10:
// case 11:
// case 12:
// case 13:
// case 14:
// case 15:
// NVIC_SetPriority(EXTI15_10_IRQn, EXTI15_10_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI15_10_IRQn);
// break;
// default:
// return 0;
//}
//}
//bit_mask = bit_mask<<1;
//}
}

View File

@ -5,76 +5,80 @@
extern "C" {
#endif
/* --- GPIO pin mask definitions ---------------------------------------- */
#define PIN_0 (1 << 0)
#define PIN_1 (1 << 1)
#define PIN_2 (1 << 2)
#define PIN_3 (1 << 3)
#define PIN_4 (1 << 4)
#define PIN_5 (1 << 5)
#define PIN_6 (1 << 6)
#define PIN_7 (1 << 7)
#define PIN_8 (1 << 8)
#define PIN_9 (1 << 9)
#define PIN_10 (1 << 10)
#define PIN_11 (1 << 11)
#define PIN_12 (1 << 12)
#define PIN_13 (1 << 13)
#define PIN_14 (1 << 14)
#define PIN_15 (1 << 15)
#define PIN_ALL 0xFFFF
//------------------------------------------------------------------------------
/* GPIO pin mask definitions */
enum io_pin {
PIN_0 = (1 << 0),
PIN_1 = (1 << 1),
PIN_2 = (1 << 2),
PIN_3 = (1 << 3),
PIN_4 = (1 << 4),
PIN_5 = (1 << 5),
PIN_6 = (1 << 6),
PIN_7 = (1 << 7),
PIN_8 = (1 << 8),
PIN_9 = (1 << 9),
PIN_10 = (1 << 10),
PIN_11 = (1 << 11),
PIN_12 = (1 << 12),
PIN_13 = (1 << 13),
PIN_14 = (1 << 14),
PIN_15 = (1 << 15),
PIN_ALL = 0xFFFF
};
/* --- GPIO pin mode definitions ---------------------------------------- */
#define PIN_MODE_INPUT (0)
#define PIN_MODE_OUTPUT (1 << 0)
#define PIN_MODE_ALTFUNC (1 << 3 | 1 << 0)
#define PIN_MODE_ANALOG (0)
//------------------------------------------------------------------------------
/* GPIO pin mode definitions */
enum io_mode {
IO_MODE_INPUT = (0x0),
IO_MODE_OUTPUT = (0x1), // 10Mhz max
IO_MODE_OUTPUT_SLOW = (0x3), // 2MHz max
IO_MODE_OUTPUT_FAST = (0x4) // 50 MHz max
};
/* --- GPIO pin option definitions -------------------------------------- */
/* none for analog pin */
#define PIN_OPT_NONE (0)
//------------------------------------------------------------------------------
/* GPIO pin conf definitions */
enum io_conf {
IO_IN_ANALOG = (0b0 << 2),
IO_IN_FLOATING = (0b1 << 2),
IO_IN_PULL_UP = (0b110 << 2),
IO_IN_PULL_DOWN = (0b010 << 2),
IO_OUT_ALT_FNCT = (0b10 << 2),
IO_OUT_PUSH_PULL = (0b0 << 2),
IO_OUT_OPEN_DRAIN = (0b1 << 2)
};
/* pull up/pull down resistor option */
#define PIN_OPT_RESISTOR_NONE (1 << 2)
#define PIN_OPT_RESISTOR_PULLUP (1 << 4 | 1 << 3)
#define PIN_OPT_RESISTOR_PULLDOWN (1 << 3)
/* push-pull/open drain output option */
#define PIN_OPT_OUTPUT_PUSHPULL (0)
#define PIN_OPT_OUTPUT_OPENDRAIN (1 << 2)
/* output speed option
* - LOW ~ 2MHz max
* - MEDIUM ~ 10MHz max
* - FAST ~ 50MHz max
**/
#define PIN_OPT_OUTPUT_SPEED_LOW (10 << 0)
#define PIN_OPT_OUTPUT_SPEED_MEDIUM (1 << 0)
#define PIN_OPT_OUTPUT_SPEED_FAST (11 << 0)
//------------------------------------------------------------------------------
/* GPIO pin clear */
#define IO_CLEAR (0)
//------------------------------------------------------------------------------
/* alternate function selection option */
#define PIN_OPT_AF0 0x0
#define PIN_OPT_AF1 0x1
#define PIN_OPT_AF2 0x2
#define PIN_OPT_AF3 0x3
#define PIN_OPT_AF4 0x4
#define PIN_OPT_AF5 0x5
#define PIN_OPT_AF6 0x6
#define PIN_OPT_AF7 0x7
#define PIN_OPT_AF8 0x8
#define PIN_OPT_AF9 0x9
#define PIN_OPT_AF10 0xA
#define PIN_OPT_AF11 0xB
#define PIN_OPT_AF12 0xC
#define PIN_OPT_AF13 0xD
#define PIN_OPT_AF14 0xE
#define PIN_OPT_AF15 0xF
/* irq pin option */
#define PIN_OPT_IRQ_EDGE_RISE (1 << 12)
#define PIN_OPT_IRQ_EDGE_FALL (2 << 12)
#define PIN_OPT_IRQ_EDGE_BOTH (3 << 12)
//TODO not supported for now
//enum io_alt_fnct {
// PIN_OPT_AF0 0x0,
// PIN_OPT_AF1 0x1,
// PIN_OPT_AF2 0x2,
// PIN_OPT_AF3 0x3,
// PIN_OPT_AF4 0x4,
// PIN_OPT_AF5 0x5,
// PIN_OPT_AF6 0x6,
// PIN_OPT_AF7 0x7,
// PIN_OPT_AF8 0x8,
// PIN_OPT_AF9 0x9,
// PIN_OPT_AF10 0xA,
// PIN_OPT_AF11 0xB,
// PIN_OPT_AF12 0xC,
// PIN_OPT_AF13 0xD,
// PIN_OPT_AF14 0xE,
// PIN_OPT_AF15 0xF
//};
///* irq pin option */
//#define PIN_OPT_IRQ_EDGE_RISE (1 << 12)
//#define PIN_OPT_IRQ_EDGE_FALL (2 << 12)
//#define PIN_OPT_IRQ_EDGE_BOTH (3 << 12)
//
typedef void (*OnIO)();
/* io_configure
@ -84,7 +88,7 @@ typedef void (*OnIO)();
* function 'cb' if not NULL.
* returns 0 if success
*/
int io_configure(GPIO_TypeDef *gpio, uint16_t pin_mask, uint32_t pin_cfg, OnIO cb);
int io_configure(GPIO_TypeDef *gpio, uint16_t pin_mask, uint8_t pin_cfg, OnIO cb);
/* io_read
*

View File

@ -1,4 +1,4 @@
/**
/*
==============================================================================
##### RCC specific features #####
==============================================================================
@ -176,11 +176,6 @@ static void rcc_set_sysclk(enum rcc_osc osc)
while (((RCC->CFGR & 0xC)>>2) != osc);
}
//void SystemInit(void) {
// Clock_t tmp_clk;
// rcc_config_clock(CLOCK_CONFIG_PERFORMANCE, &tmp_clk);
//}
void rcc_config_clock(uint32_t config, Clock_t *sysclks)
{
struct ClockConfig_t *clk;
@ -245,8 +240,8 @@ void rcc_config_clock(uint32_t config, Clock_t *sysclks)
}
sysclks->ahb_freq = clk->ahb_freq;
sysclks->apb1_freq = clk->apb1_freq;
sysclks->apb2_freq = clk->apb2_freq;
//TODO check timer frequencies
sysclks->apb1_timer_freq = clk->ppre1==RCC_CFGR_PPRE_DIV_NONE ? clk->apb1_freq : 2*clk->apb1_freq;
sysclks->apb2_freq = clk->apb2_freq;
sysclks->apb2_timer_freq = clk->ppre2==RCC_CFGR_PPRE_DIV_NONE ? clk->apb2_freq : 2*clk->apb2_freq;
}

127
src/drivers/tags Normal file
View File

@ -0,0 +1,127 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
!_TAG_PROGRAM_VERSION 0.0.0 /3fdf28bc/
CLOCK_CONFIG_END rcc.h /^ CLOCK_CONFIG_END$/;" e enum:Clock_config
CLOCK_CONFIG_PERFORMANCE rcc.h /^ CLOCK_CONFIG_PERFORMANCE,$/;" e enum:Clock_config
CLOCK_CONFIG_POWERSAVE rcc.h /^ CLOCK_CONFIG_POWERSAVE,$/;" e enum:Clock_config
ClockConfig_t rcc.c /^struct ClockConfig_t {$/;" s file:
Clock_config rcc.h /^enum Clock_config {$/;" g
Clock_t rcc.h /^} Clock_t;$/;" t typeref:struct:_Clock_t
EXTI0_IRQHandler io.c /^void EXTI0_IRQHandler() {$/;" f typeref:typename:void
EXTI15_10_IRQHandler io.c /^void EXTI15_10_IRQHandler() {$/;" f typeref:typename:void
EXTI1_IRQHandler io.c /^void EXTI1_IRQHandler() {$/;" f typeref:typename:void
EXTI2_IRQHandler io.c /^void EXTI2_IRQHandler() {$/;" f typeref:typename:void
EXTI3_IRQHandler io.c /^void EXTI3_IRQHandler() {$/;" f typeref:typename:void
EXTI4_IRQHandler io.c /^void EXTI4_IRQHandler() {$/;" f typeref:typename:void
EXTI9_5_IRQHandler io.c /^void EXTI9_5_IRQHandler() {$/;" f typeref:typename:void
IO_CLEAR io.h /^#define IO_CLEAR /;" d
IO_IN_ANALOG io.h /^ IO_IN_ANALOG = (0b0 << 2),$/;" e enum:io_conf
IO_IN_FLOATING io.h /^ IO_IN_FLOATING = (0b1 << 2),$/;" e enum:io_conf
IO_IN_PULL_DOWN io.h /^ IO_IN_PULL_DOWN = (0b010 << 2),$/;" e enum:io_conf
IO_IN_PULL_UP io.h /^ IO_IN_PULL_UP = (0b110 << 2),$/;" e enum:io_conf
IO_MODE_INPUT io.h /^ IO_MODE_INPUT = (0x0),$/;" e enum:io_mode
IO_MODE_OUTPUT_FAST io.h /^ IO_MODE_OUTPUT_FAST = (0x4) \/\/ 50 MHz max$/;" e enum:io_mode
IO_MODE_OUTPUT_SLOW io.h /^ IO_MODE_OUTPUT_SLOW = (0x3), \/\/ 2MHz max$/;" e enum:io_mode
IO_MODE_OUTPUT io.h /^ IO_MODE_OUTPUT = (0x1), \/\/ 10Mhz max$/;" e enum:io_mode
IO_OUT_ALT_FNCT io.h /^ IO_OUT_ALT_FNCT = (0b10 << 2),$/;" e enum:io_conf
IO_OUT_OPEN_DRAIN io.h /^ IO_OUT_OPEN_DRAIN = (0b1 << 2)$/;" e enum:io_conf
IO_OUT_PUSH_PULL io.h /^ IO_OUT_PUSH_PULL = (0b0 << 2),$/;" e enum:io_conf
OnIO io.h /^typedef void (*OnIO)();$/;" t typeref:typename:void (*)()
OnTick timer.h /^typedef void (*OnTick)(void);$/;" t typeref:typename:void (*)(void)
PIN_0 io.h /^ PIN_0 = (1 << 0),$/;" e enum:io_pin
PIN_10 io.h /^ PIN_10 = (1 << 10),$/;" e enum:io_pin
PIN_11 io.h /^ PIN_11 = (1 << 11),$/;" e enum:io_pin
PIN_12 io.h /^ PIN_12 = (1 << 12),$/;" e enum:io_pin
PIN_13 io.h /^ PIN_13 = (1 << 13),$/;" e enum:io_pin
PIN_14 io.h /^ PIN_14 = (1 << 14),$/;" e enum:io_pin
PIN_15 io.h /^ PIN_15 = (1 << 15),$/;" e enum:io_pin
PIN_1 io.h /^ PIN_1 = (1 << 1),$/;" e enum:io_pin
PIN_2 io.h /^ PIN_2 = (1 << 2),$/;" e enum:io_pin
PIN_3 io.h /^ PIN_3 = (1 << 3),$/;" e enum:io_pin
PIN_4 io.h /^ PIN_4 = (1 << 4),$/;" e enum:io_pin
PIN_5 io.h /^ PIN_5 = (1 << 5),$/;" e enum:io_pin
PIN_6 io.h /^ PIN_6 = (1 << 6),$/;" e enum:io_pin
PIN_7 io.h /^ PIN_7 = (1 << 7),$/;" e enum:io_pin
PIN_8 io.h /^ PIN_8 = (1 << 8),$/;" e enum:io_pin
PIN_9 io.h /^ PIN_9 = (1 << 9),$/;" e enum:io_pin
PIN_ALL io.h /^ PIN_ALL = 0xFFFF$/;" e enum:io_pin
RCC_CFGR_HPRE_DIV_128 rcc.c /^#define RCC_CFGR_HPRE_DIV_128 /;" d file:
RCC_CFGR_HPRE_DIV_16 rcc.c /^#define RCC_CFGR_HPRE_DIV_16 /;" d file:
RCC_CFGR_HPRE_DIV_256 rcc.c /^#define RCC_CFGR_HPRE_DIV_256 /;" d file:
RCC_CFGR_HPRE_DIV_2 rcc.c /^#define RCC_CFGR_HPRE_DIV_2 /;" d file:
RCC_CFGR_HPRE_DIV_4 rcc.c /^#define RCC_CFGR_HPRE_DIV_4 /;" d file:
RCC_CFGR_HPRE_DIV_512 rcc.c /^#define RCC_CFGR_HPRE_DIV_512 /;" d file:
RCC_CFGR_HPRE_DIV_64 rcc.c /^#define RCC_CFGR_HPRE_DIV_64 /;" d file:
RCC_CFGR_HPRE_DIV_8 rcc.c /^#define RCC_CFGR_HPRE_DIV_8 /;" d file:
RCC_CFGR_HPRE_DIV_NONE rcc.c /^#define RCC_CFGR_HPRE_DIV_NONE /;" d file:
RCC_CFGR_PLLMUL rcc.c /^#define RCC_CFGR_PLLMUL(/;" d file:
RCC_CFGR_PPRE_DIV_16 rcc.c /^#define RCC_CFGR_PPRE_DIV_16 /;" d file:
RCC_CFGR_PPRE_DIV_2 rcc.c /^#define RCC_CFGR_PPRE_DIV_2 /;" d file:
RCC_CFGR_PPRE_DIV_4 rcc.c /^#define RCC_CFGR_PPRE_DIV_4 /;" d file:
RCC_CFGR_PPRE_DIV_8 rcc.c /^#define RCC_CFGR_PPRE_DIV_8 /;" d file:
RCC_CFGR_PPRE_DIV_NONE rcc.c /^#define RCC_CFGR_PPRE_DIV_NONE /;" d file:
RCC_HSE rcc.c /^ RCC_HSE,$/;" e enum:rcc_osc file:
RCC_HSI rcc.c /^ RCC_HSI,$/;" e enum:rcc_osc file:
RCC_LSE rcc.c /^ RCC_LSE$/;" e enum:rcc_osc file:
RCC_LSI rcc.c /^ RCC_LSI,$/;" e enum:rcc_osc file:
RCC_PLL rcc.c /^ RCC_PLL,$/;" e enum:rcc_osc file:
SYSCFG_EXTI_PA_MASK io.c /^#define SYSCFG_EXTI_PA_MASK /;" d file:
SYSCFG_EXTI_PB_MASK io.c /^#define SYSCFG_EXTI_PB_MASK /;" d file:
SYSCFG_EXTI_PC_MASK io.c /^#define SYSCFG_EXTI_PC_MASK /;" d file:
SYSCFG_EXTI_PD_MASK io.c /^#define SYSCFG_EXTI_PD_MASK /;" d file:
SYSCFG_EXTI_PE_MASK io.c /^#define SYSCFG_EXTI_PE_MASK /;" d file:
SYSCFG_EXTI_PH_MASK io.c /^#define SYSCFG_EXTI_PH_MASK /;" d file:
TIM1_UP_IRQHandler timer.c /^void TIM1_UP_IRQHandler(void) {$/;" f typeref:typename:void
TIM2_IRQHandler timer.c /^void TIM2_IRQHandler(void) {$/;" f typeref:typename:void
TIM3_IRQHandler timer.c /^void TIM3_IRQHandler(void) {$/;" f typeref:typename:void
TIM4_IRQHandler timer.c /^void TIM4_IRQHandler(void) {$/;" f typeref:typename:void
_Clock_t rcc.h /^typedef struct _Clock_t {$/;" s
_IO_H_ io.h /^#define _IO_H_$/;" d
_RCC_H_ rcc.h /^#define _RCC_H_$/;" d
_TIMER_H_ timer.h /^#define _TIMER_H_$/;" d
_clock_config rcc.c /^static struct ClockConfig_t _clock_config[] = {$/;" v typeref:struct:ClockConfig_t[] file:
ahb_freq rcc.c /^ uint32_t ahb_freq;$/;" m struct:ClockConfig_t typeref:typename:uint32_t file:
ahb_freq rcc.h /^ uint32_t ahb_freq;$/;" m struct:_Clock_t typeref:typename:uint32_t
apb1_freq rcc.c /^ uint32_t apb1_freq;$/;" m struct:ClockConfig_t typeref:typename:uint32_t file:
apb1_freq rcc.h /^ uint32_t apb1_freq;$/;" m struct:_Clock_t typeref:typename:uint32_t
apb1_timer_freq rcc.h /^ uint32_t apb1_timer_freq;$/;" m struct:_Clock_t typeref:typename:uint32_t
apb2_freq rcc.c /^ uint32_t apb2_freq;$/;" m struct:ClockConfig_t typeref:typename:uint32_t file:
apb2_freq rcc.h /^ uint32_t apb2_freq;$/;" m struct:_Clock_t typeref:typename:uint32_t
apb2_timer_freq rcc.h /^ uint32_t apb2_timer_freq;$/;" m struct:_Clock_t typeref:typename:uint32_t
callback1 timer.c /^static OnTick callback1 = 0;$/;" v typeref:typename:OnTick file:
callback2 timer.c /^static OnTick callback2 = 0;$/;" v typeref:typename:OnTick file:
callback3 timer.c /^static OnTick callback3 = 0;$/;" v typeref:typename:OnTick file:
callback4 timer.c /^static OnTick callback4 = 0;$/;" v typeref:typename:OnTick file:
flash_cfg rcc.c /^ uint32_t flash_cfg;$/;" m struct:ClockConfig_t typeref:typename:uint32_t file:
hpre rcc.c /^ uint8_t hpre;$/;" m struct:ClockConfig_t typeref:typename:uint8_t file:
io_cb io.c /^static OnIO io_cb[16]={$/;" v typeref:typename:OnIO[16] file:
io_clear io.c /^void io_clear(GPIO_TypeDef *gpio, uint16_t mask)$/;" f typeref:typename:void
io_conf io.h /^enum io_conf {$/;" g
io_configure io.c /^int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint8_t pin_cfg, OnIO cb) {$/;" f typeref:typename:int
io_mode io.h /^enum io_mode {$/;" g
io_pin io.h /^enum io_pin {$/;" g
io_read io.c /^uint32_t io_read(GPIO_TypeDef *gpio, uint16_t mask)$/;" f typeref:typename:uint32_t
io_set io.c /^void io_set(GPIO_TypeDef *gpio, uint16_t mask)$/;" f typeref:typename:void
io_write_n io.c /^void io_write_n(GPIO_TypeDef *gpio, uint16_t val, uint16_t mask)$/;" f typeref:typename:void
io_write io.c /^void io_write(GPIO_TypeDef *gpio, uint16_t val, uint16_t mask)$/;" f typeref:typename:void
pll_src rcc.c /^ uint8_t pll_src;$/;" m struct:ClockConfig_t typeref:typename:uint8_t file:
pllmul rcc.c /^ uint8_t pllmul;$/;" m struct:ClockConfig_t typeref:typename:uint8_t file:
ppre1 rcc.c /^ uint8_t ppre1;$/;" m struct:ClockConfig_t typeref:typename:uint8_t file:
ppre2 rcc.c /^ uint8_t ppre2;$/;" m struct:ClockConfig_t typeref:typename:uint8_t file:
rcc_config_clock rcc.c /^void rcc_config_clock(uint32_t config, Clock_t *sysclks)$/;" f typeref:typename:void
rcc_osc_off rcc.c /^static void rcc_osc_off(enum rcc_osc osc)$/;" f typeref:typename:void file:
rcc_osc_on rcc.c /^static void rcc_osc_on(enum rcc_osc osc)$/;" f typeref:typename:void file:
rcc_osc rcc.c /^enum rcc_osc {$/;" g file:
rcc_set_sysclk rcc.c /^static void rcc_set_sysclk(enum rcc_osc osc)$/;" f typeref:typename:void file:
timer_config_cb timer.c /^int timer_config_cb(TIM_TypeDef* tmr, OnTick cb) {$/;" f typeref:typename:int
timer_set_period timer.c /^int timer_set_period(TIM_TypeDef *tmr, uint16_t tick) {$/;" f typeref:typename:int
timer_start timer.c /^void timer_start(TIM_TypeDef *tmr) {$/;" f typeref:typename:void
timer_stop timer.c /^void timer_stop(TIM_TypeDef *tmr) {$/;" f typeref:typename:void
timer_tick_init timer.c /^int timer_tick_init(TIM_TypeDef *tmr, uint16_t tick_ms, OnTick cb) {$/;" f typeref:typename:int
timer_wait_ms timer.c /^int timer_wait_ms(TIM_TypeDef* tmr, uint16_t ms, OnTick cb) {$/;" f typeref:typename:int
timer_wait_us timer.c /^int timer_wait_us(TIM_TypeDef* tmr, uint16_t us, OnTick cb) {$/;" f typeref:typename:int
type rcc.c /^ uint8_t type;$/;" m struct:ClockConfig_t typeref:typename:uint8_t file:

View File

@ -2,41 +2,54 @@
extern Clock_t sysclks;
/*
* timerX_isr
//------------------------------------------------------------------------------
/** timerX_isr
* timerX ISR (Interrupt Service Routine)
*/
static OnTick callback1 = 0;
static OnTick callback2 = 0;
static OnTick callback3 = 0;
static OnTick callback4 = 0;
void TIM2_IRQHandler() {
void TIM1_UP_IRQHandler(void) {
if (callback1) callback1();
TIM1->SR &= ~0x1F;
}
void TIM2_IRQHandler(void) {
if (callback2) callback2();
TIM2->SR &= ~0x1F;
}
void TIM3_IRQHandler() {
void TIM3_IRQHandler(void) {
if (callback3) callback3();
TIM3->SR &= ~0x1F;
}
void TIM4_IRQHandler() {
void TIM4_IRQHandler(void) {
if (callback4) callback4();
TIM4->SR &= ~0x1F;
}
/*
* timer_tick_init
* setup timer to call cb function periodically, each tick_ms
*/
int timer_tick_init(TIM_TypeDef *tmr, uint32_t tick_ms, OnTick cb) {
int timer_config_cb(TIM_TypeDef* tmr, uint32_t* clk, OnTick cb) {
IRQn_Type irqn;
uint32_t irq_priority, clk;
//get back the clock frequency
clk = sysclks.apb1_timer_freq;
uint32_t irq_priority;
// get clocks config
if (tmr == TIM1) {
*clk = sysclks.apb2_timer_freq;
// register callback function
callback1 = cb;
irqn = TIM1_UP_IRQn; //every update
irq_priority = TIM1_IRQ_PRIORITY;
// enable timer clocking
RCC->APB2ENR |= 1<<11;
} else if (tmr == TIM2) {
*clk = sysclks.apb1_timer_freq;
if (tmr == TIM2) {
// register callback function
callback2 = cb;
irqn = TIM2_IRQn;
@ -46,6 +59,8 @@ int timer_tick_init(TIM_TypeDef *tmr, uint32_t tick_ms, OnTick cb) {
RCC->APB1ENR |= 1<<0;
} else if (tmr == TIM3) {
*clk = sysclks.apb1_timer_freq;
// register callback function
callback3 = cb;
irqn = TIM3_IRQn;
@ -55,6 +70,8 @@ int timer_tick_init(TIM_TypeDef *tmr, uint32_t tick_ms, OnTick cb) {
RCC->APB1ENR |= 1<<1;
} else if (tmr == TIM4) {
*clk = sysclks.apb1_timer_freq;
// register callback function
callback4 = cb;
irqn = TIM4_IRQn;
@ -63,10 +80,153 @@ int timer_tick_init(TIM_TypeDef *tmr, uint32_t tick_ms, OnTick cb) {
// enable timer clocking
RCC->APB1ENR |= 1<<2;
} else {
return -1;
} else return -1;
// clear pending interrupts
tmr->SR &= !1;
// Enable interrupts
tmr->DIER = (1<<0);
NVIC_SetPriority(irqn,irq_priority);
NVIC_EnableIRQ(irqn);
return 0;
}
//------------------------------------------------------------------------------
int timer_wait_ms(TIM_TypeDef* tmr, uint16_t ms, OnTick cb) {
uint32_t clk = 0;
if(!cb) { //blocking
//get clocks config
if (tmr == TIM1) {
clk = sysclks.apb2_timer_freq;
RCC->APB2ENR |= 1<<11;
}
else {
clk = sysclks.apb1_timer_freq;
if (tmr == TIM2) RCC->APB1ENR |= 1<<0;
else if (tmr == TIM3) RCC->APB1ENR |= 1<<1;
else if (tmr == TIM4) RCC->APB1ENR |= 1<<2;
else return -1; // no such timer
}
} else { //non-blocking
if(timer_config_cb(tmr, &clk, cb)) return -1;
}
// set mode
tmr->CR1 |= (1<<7); //buffering
tmr->CR1 |= (1<<3); //one pulse mode
// set period
tmr->ARR = 0xFFFFFFFF;
// set prescaler 1us
tmr->PSC = 8*(clk/1000)-1; //PSC = clk/f - 1 | don't know why 8 times..
timer_start(tmr);
if(!cb) {
while(tmr->CNT < ms); //waiting for end of delay
}
return 0;
}
int timer_wait_us(TIM_TypeDef* tmr, uint16_t us, OnTick cb) {
uint32_t clk = 0;
if(!cb) { //blocking
//get clocks config
if (tmr == TIM1) {
clk = sysclks.apb2_timer_freq;
RCC->APB2ENR |= 1<<11;
}
else {
clk = sysclks.apb1_timer_freq;
if (tmr == TIM2) RCC->APB1ENR |= 1<<0;
else if (tmr == TIM3) RCC->APB1ENR |= 1<<1;
else if (tmr == TIM4) RCC->APB1ENR |= 1<<2;
else return -1; // no such timer
}
} else { //non-blocking
if(timer_config_cb(tmr, &clk, cb)) return -1;
}
// set mode
tmr->CR1 |= (1<<7); //buffering
tmr->CR1 |= (1<<3); //one pulse mode
// set period
tmr->ARR = 0xFFFFFFFF;
// set prescaler 1us
tmr->PSC = 8*(clk/1000000)-1; //PSC = clk/f - 1 | don't know why 8 times..
timer_start(tmr);
if(!cb) {
while(tmr->CNT < us); //waiting for end of delay
}
return 0;
}
//------------------------------------------------------------------------------
int timer_tick_init(TIM_TypeDef *tmr, uint16_t tick_ms, OnTick cb) {
IRQn_Type irqn;
uint32_t irq_priority, clk;
// get back the clock frequency
if (tmr == TIM1) {
clk = sysclks.apb2_timer_freq;
// register callback function
callback1 = cb;
irqn = TIM1_UP_IRQn; //every update
irq_priority = TIM1_IRQ_PRIORITY;
// enable timer clocking
RCC->APB2ENR |= 1<<11;
} else if (tmr == TIM2) {
clk = sysclks.apb1_timer_freq;
// register callback function
callback2 = cb;
irqn = TIM2_IRQn;
irq_priority = TIM2_IRQ_PRIORITY;
// enable timer clocking
RCC->APB1ENR |= 1<<0;
} else if (tmr == TIM3) {
clk = sysclks.apb1_timer_freq;
// register callback function
callback3 = cb;
irqn = TIM3_IRQn;
irq_priority = TIM3_IRQ_PRIORITY;
// enable timer clocking
RCC->APB1ENR |= 1<<1;
} else if (tmr == TIM4) {
clk = sysclks.apb1_timer_freq;
// register callback function
callback4 = cb;
irqn = TIM4_IRQn;
irq_priority = TIM4_IRQ_PRIORITY;
// enable timer clocking
RCC->APB1ENR |= 1<<2;
} else return -1;
// clear pending interrupts
tmr->SR &= !1;
@ -74,55 +234,41 @@ int timer_tick_init(TIM_TypeDef *tmr, uint32_t tick_ms, OnTick cb) {
tmr->CR1 = (1<<7); //buffering
tmr->DIER = (1<<0); //Enable interrupts
// set prescaler 100us
tmr->PSC = clk/(10000-1); //100µs = (PSC+1)*Tclk
// set prescaler 1ms
tmr->PSC = 8*(clk/1000)-1; //PSC = clk/f - 1 | don't know why 8 times...
// set period
if(timer_tick_period(tmr,tick_ms)) return -1;
//enable counter
tmr->CR1= (1<<0)| tmr->CR1;
if(timer_set_period(tmr,tick_ms)) return -1;
if (cb) {
NVIC_SetPriority(irqn,irq_priority); //enable interuptions
NVIC_EnableIRQ(irqn);
NVIC_SetPriority(irqn,irq_priority);
NVIC_EnableIRQ(irqn); //unmask IRQ
}
return 0;
}
/*
* timer_tick_period
* change the tick_ms period
*/
int timer_tick_period(TIM_TypeDef *tmr, uint32_t tick_ms) {
int timer_set_period(TIM_TypeDef *tmr, uint16_t tick) {
// set period
tmr->ARR = tick_ms*10-1; //tickms = (ARR+1)Tpsc
tmr->ARR = tick-1; //tickms = (ARR+1)Tpsc
// force update to reset counter and prescaler
// force update to reset counter and apply prescaler
tmr->EGR |= 1;
return 0;
}
/*
* timer_start
* reset & enable counting
*/
void timer_start(TIM_TypeDef *tmr) {
// force update to reset counter and prescaler
tmr->EGR |= 1;
// enable counting
tmr->CR1 |= 1;
}
/*
* timer_stop
* stop counting
*/
void timer_stop(TIM_TypeDef *tmr) {
// disable counting
tmr->CR1 &= !1;
}

View File

@ -11,75 +11,78 @@ extern "C" {
typedef void (*OnTick)(void);
/***************************************************************************/
/* timer_wait_ms
* wait for ms millisecoonds function
//------------------------------------------------------------------------------
/** timer_wait_ms
* wait for ms milliseconds function
*/
int timer_wait_ms(TIM_TypeDef *tmr, uint32_t ms, OnTick cb);
int timer_wait_ms(TIM_TypeDef *tmr, uint16_t ms, OnTick cb);
/* timer_wait_us
* wait for us microsecoonds function
/** timer_wait_us
* wait for us microseconds function
*/
int timer_wait_us(TIM_TypeDef *tmr, uint32_t us, OnTick cb);
int timer_wait_us(TIM_TypeDef *tmr, uint16_t us, OnTick cb);
/***************************************************************************/
/* timer_tick_init
//------------------------------------------------------------------------------
/** timer_tick_init
* setup timer to call cb function periodically, each tick_ms
*/
int timer_tick_init(TIM_TypeDef *tmr, uint32_t tick_ms, OnTick cb);
int timer_tick_init(TIM_TypeDef *tmr, uint16_t tick_ms, OnTick cb);
/* timer_tick_period
* change the tick_ms period
/** timer_set_period
* change the period, in ms when called after tick_init,
* otherwise in whatever unit the timer is configured
* reset count when used
*/
int timer_tick_period(TIM_TypeDef *tmr, uint32_t tick_ms);
int timer_set_period(TIM_TypeDef *tmr, uint16_t tick);
/* timer_start
* start counting to generate ticks
/** timer_start
* reset count and start counting
*/
void timer_start(TIM_TypeDef *tmr);
/* timer_stop
* stop and reset counting
/** timer_stop
* stop counting
*/
void timer_stop(TIM_TypeDef *tmr);
/***************************************************************************/
#define PWM_CHANNEL_1 0
#define PWM_CHANNEL_2 1
#define PWM_CHANNEL_3 2
#define PWM_CHANNEL_4 3
/* pwm_init
* setup pwm timer period, each tick_ms
*/
int pwm_init(TIM_TypeDef *pwm, uint32_t period_ms, OnTick cb);
/* pwm_channel_enable
* set up pwm channel
*/
int pwm_channel_enable(TIM_TypeDef *pwm, uint32_t channel, uint32_t dutycycle, uint32_t oe);
/* pwm_channel_disable
* disable pwm channel
*/
int pwm_channel_disable(TIM_TypeDef *pwm, uint32_t channel);
/* pwm_channel_set
* set up dutycycle for pwm channel
*/
int pwm_channel_set(TIM_TypeDef *pwm, uint32_t channel, uint32_t dutycycle);
/* pwm_start
* start counting
*/
#define pwm_start(pwm) timer_start(pwm)
/* pwm_stop
* stop and reset counting
*/
#define pwm_stop(pwm) timer_stop(pwm)
//------------------------------------------------------------------------------
//#define PWM_CHANNEL_1 0
//#define PWM_CHANNEL_2 1
//#define PWM_CHANNEL_3 2
//#define PWM_CHANNEL_4 3
//
///** pwm_init
// * setup pwm timer period, each tick_ms
// */
//int pwm_init(TIM_TypeDef *pwm, uint32_t period_ms, OnTick cb);
//
///** pwm_channel_enable
// * set up pwm channel
// */
//int pwm_channel_enable(TIM_TypeDef *pwm, uint32_t channel, uint32_t dutycycle, uint32_t oe);
//
///** pwm_channel_disable
// * disable pwm channel
// */
//int pwm_channel_disable(TIM_TypeDef *pwm, uint32_t channel);
//
///** pwm_channel_set
// * set up dutycycle for pwm channel
// */
//int pwm_channel_set(TIM_TypeDef *pwm, uint32_t channel, uint32_t dutycycle);
//
///** pwm_start
// * start counting
// */
//#define pwm_start(pwm) timer_start(pwm)
//
///** pwm_stop
// * stop and reset counting
// */
//#define pwm_stop(pwm) timer_stop(pwm)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -16,13 +16,16 @@ int main(void) {
rcc_config_clock(CLOCK_CONFIG_PERFORMANCE, &sysclks);
if(io_configure(GPIOC, PIN_13, PIN_MODE_OUTPUT | PIN_OPT_OUTPUT_PUSHPULL, 0)) return 0;
if(io_configure(GPIOC, PIN_13, IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0))
return 0;
io_write(GPIOC, 1, PIN_13);
timer_tick_init(TIM2, 1000, timeout_cb);
timer_start(TIM2);
//timer_tick_init(TIM2, 1000, timeout_cb);
//timer_start(TIM2);
for(;;){
timer_wait_ms(TIM1, 500, 0);
timer_wait_ms(TIM2, 500, timeout_cb);
}
return 0;