Compare commits
36 Commits
cbe6409f69
...
6d95bce6df
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d95bce6df | |||
| ebc7ad4235 | |||
| bc4bab4704 | |||
| a4ca0d30c3 | |||
| 89c81b8c42 | |||
| 24e412446d | |||
| 7ab6622908 | |||
| ba9bc57a49 | |||
| 947df53ecb | |||
| 80c027370b | |||
| b1d25561b4 | |||
| 507f1e6863 | |||
| 3e3d4d2bff | |||
| b37eb1dd6e | |||
| 0b483c535b | |||
| a02bcecaec | |||
| 699569ec99 | |||
| 3e97d4fe7e | |||
| 5c89df4324 | |||
| 1741d47546 | |||
| 97dad53621 | |||
| 9681755168 | |||
| 5e4d87474a | |||
| d5c70a3a04 | |||
| 93b383be49 | |||
| dd1756221d | |||
| 173e16eb2e | |||
| b7951f2211 | |||
| 7cb33f65a5 | |||
| c09d2cda67 | |||
| 34fb4dac76 | |||
| 432310a52d | |||
| 7e69bfd89c | |||
| ddd05da6eb | |||
| 7ba9063d02 | |||
| fb1c11132f |
@ -9,10 +9,8 @@
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#include "exti.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
#define AFIO_BASE_ADDRESS 0x40010000
|
||||
|
||||
union EVCR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t PIN:4;
|
||||
uint32_t PORT:3;
|
||||
uint32_t EVOE:1;
|
||||
@ -29,7 +29,7 @@ union EVCR {
|
||||
};
|
||||
|
||||
union MAPR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t SPI1_REMAP:1;
|
||||
uint32_t I2C1_REMAP:1;
|
||||
uint32_t USART1_REMAP:1;
|
||||
@ -54,7 +54,7 @@ union MAPR {
|
||||
};
|
||||
|
||||
union EXTICR1 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t EXTI0:4;
|
||||
uint32_t EXTI1:4;
|
||||
uint32_t EXTI2:4;
|
||||
@ -65,7 +65,7 @@ union EXTICR1 {
|
||||
};
|
||||
|
||||
union EXTICR2 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t EXTI4:4;
|
||||
uint32_t EXTI5:4;
|
||||
uint32_t EXTI6:4;
|
||||
@ -76,7 +76,7 @@ union EXTICR2 {
|
||||
};
|
||||
|
||||
union EXTICR3 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t EXTI8:4;
|
||||
uint32_t EXTI9:4;
|
||||
uint32_t EXTI10:4;
|
||||
@ -87,7 +87,7 @@ union EXTICR3 {
|
||||
};
|
||||
|
||||
union EXTICR4 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t EXTI12:4;
|
||||
uint32_t EXTI13:4;
|
||||
uint32_t EXTI14:4;
|
||||
@ -98,7 +98,7 @@ union EXTICR4 {
|
||||
};
|
||||
|
||||
union MAPR2 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1:5;
|
||||
uint32_t TIM9_REMAP:1;
|
||||
uint32_t TIM10_REMAP:1;
|
||||
@ -111,7 +111,7 @@ union MAPR2 {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) AFIO {
|
||||
struct AFIO {
|
||||
union EVCR EVCR;
|
||||
union MAPR MAPR;
|
||||
union EXTICR1 EXTICR1;
|
||||
|
||||
152
drv/bkp.c
Normal file
152
drv/bkp.c
Normal file
@ -0,0 +1,152 @@
|
||||
/** @file bkp.c
|
||||
* Module handling the Backup (BKP) domain functionalities.
|
||||
*
|
||||
* This module includes management of the Real Time Clock (RTC), Tamper
|
||||
* protection system and a limited space (20 bytes) for persistent data storage
|
||||
*
|
||||
* All features present in this module stay running in standby mode / when
|
||||
* no-longer powered, so long as VBAT is maintained
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "bkp.h"
|
||||
#include "bkp_regs.h"
|
||||
#include "rcc.h"
|
||||
#include "nvic.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
uint32_t compute_prescaler(uint32_t period_ms, enum BkpRtcClockSrc clock_src);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
//static volatile struct BKP* bkp_regs = (struct BKP*)BKP_BASE_ADDRESS;
|
||||
static volatile struct RCC* rcc_regs = (struct RCC*)RCC_BASE_ADDRESS;
|
||||
static volatile struct RTC* rtc_regs = (struct RTC*)RTC_BASE_ADDRESS;
|
||||
|
||||
static BkpRtcCallback rtc_callback;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
|
||||
enum BkpRtcIrq irq_mask, BkpRtcCallback callback)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE);
|
||||
|
||||
//start RTC
|
||||
rcc_regs->BDCR.RTCSEL = clock_src + 1;
|
||||
rcc_regs->BDCR.RTCEN = 1;
|
||||
|
||||
uint32_t prescaler = compute_prescaler(period_ms, clock_src);
|
||||
|
||||
//wait for registers to synchronize
|
||||
rtc_regs->CRL.RSF = 0;
|
||||
while (rtc_regs->CRL.RSF != 1) {}
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
|
||||
//enable core configuration
|
||||
rtc_regs->CRL.CNF = 1;
|
||||
|
||||
//configure core registers
|
||||
rtc_regs->PRLH.PRL = prescaler >> 16;
|
||||
rtc_regs->PRLL.PRL = prescaler;
|
||||
|
||||
//apply irq config
|
||||
rtc_regs->CRH.word |= irq_mask & 0x7;
|
||||
|
||||
//disable/apply core configuration
|
||||
rtc_regs->CRL.CNF = 0;
|
||||
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
|
||||
if (callback) {
|
||||
rtc_callback = callback;
|
||||
nvic_enable(NVIC_IRQ_RTC);
|
||||
}
|
||||
}
|
||||
|
||||
void bkp_set_rtc_alam(uint32_t offset)
|
||||
{
|
||||
uint32_t alarm = bkp_read_rtc() + offset;
|
||||
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
|
||||
//enable core configuration
|
||||
rtc_regs->CRL.CNF = 1;
|
||||
|
||||
//write alarm value
|
||||
rtc_regs->ALRH.RTC_ALR = alarm >> 16;
|
||||
rtc_regs->ALRL.RTC_ALR = alarm;
|
||||
|
||||
//disable/apply core configuration
|
||||
rtc_regs->CRL.CNF = 0;
|
||||
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
}
|
||||
|
||||
uint32_t bkp_read_rtc(void)
|
||||
{
|
||||
//wait for core registers to be synchronized, immediate most of the time
|
||||
while (rtc_regs->CRL.RSF != 1) {}
|
||||
|
||||
uint32_t time = rtc_regs->CNTH.RTC_CNT << 16;
|
||||
time |= rtc_regs->CNTL.RTC_CNT << 0;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
void bkp_reset(void)
|
||||
{
|
||||
rcc_regs->BDCR.BDRST = 1;
|
||||
rcc_regs->BDCR.BDRST = 0;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Computes the prescaler value based on the clock source and the required
|
||||
* period
|
||||
*/
|
||||
uint32_t compute_prescaler(uint32_t period_ms, enum BkpRtcClockSrc clock_src)
|
||||
{
|
||||
uint32_t prescaler;
|
||||
|
||||
switch (clock_src) {
|
||||
case BKP_RTC_CLOCK_SRC_LSE:
|
||||
prescaler = 32768000; //32.768kHz
|
||||
break;
|
||||
case BKP_RTC_CLOCK_SRC_LSI:
|
||||
prescaler = 40000000; //40khz
|
||||
break;
|
||||
case BKP_RTC_CLOCK_SRC_HSE:
|
||||
prescaler = 62500000; //8Mhz / 128
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return prescaler / period_ms;
|
||||
}
|
||||
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
void hdr_rtc(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_RTC);
|
||||
|
||||
//copy and clear and pass along src flags
|
||||
enum BkpRtcIrq src = rtc_regs->CRL.word & 0x7;
|
||||
rtc_regs->CRL.word &= ~(0x7);
|
||||
rtc_callback(src);
|
||||
}
|
||||
|
||||
102
drv/bkp.h
Normal file
102
drv/bkp.h
Normal file
@ -0,0 +1,102 @@
|
||||
/** @file bkp.h
|
||||
* Module handling the Backup (BKP) domain functionalities.
|
||||
*
|
||||
* This module includes management of the Real Time Clock (RTC), Tamper
|
||||
* protection system and a limited space (20 bytes) for persistent data storage
|
||||
*
|
||||
* All features present in this module stay running in standby mode / when
|
||||
* no-longer powered, so long as VBAT is maintained
|
||||
*/
|
||||
|
||||
#ifndef _BKP_H_
|
||||
#define _BKP_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available clock sources for the RTC. See bkp_configure_rtc() for more
|
||||
* information
|
||||
*/
|
||||
enum BkpRtcClockSrc {
|
||||
BKP_RTC_CLOCK_SRC_LSE = 0x0,
|
||||
BKP_RTC_CLOCK_SRC_LSI = 0x1,
|
||||
BKP_RTC_CLOCK_SRC_HSE = 0x2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Available IRQ sources. This enum is passed to the RTC callback to allow
|
||||
* differentiating IRQ sources
|
||||
*/
|
||||
enum BkpRtcIrq {
|
||||
BKP_RTC_IRQ_NONE = 0,
|
||||
BKP_RTC_IRQ_SECOND = 0x1 << 0,
|
||||
BKP_RTC_IRQ_ALARM = 0x1 << 1,
|
||||
BKP_RTC_IRQ_OVERFLOW = 0x1 << 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Prototype of the IRQ callbacks that the applicative code can provide
|
||||
*/
|
||||
typedef void (*BkpRtcCallback)(enum BkpRtcIrq src);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the RTC, starting it immediately. Configuration is saved between
|
||||
* boots as long as VBAT is present
|
||||
*
|
||||
* The RTC can run on a period of up to 1s and using one of 3 clocks. Clock
|
||||
* choice is a question of compromise :
|
||||
* - LSE consumes the less energy and continues to run in standby mode, but
|
||||
* requires an extra oscillator circuit
|
||||
* - LSI consumes little but isn't very accurate and requires extra calibration
|
||||
* (see bkp_callibrate_lsi)
|
||||
* - HSE consumes the most.
|
||||
* WARNING : once configured, the clock source can only changed by reseting the
|
||||
* whole backup domain via bkp_reset()
|
||||
* Clocks must be enabled prior to calling this function
|
||||
*
|
||||
* Mulitple IRQs can be enabled and redirected to single callback. The alarm
|
||||
* IRQ, triggered at the tick value specified by bkp_set_rtc_alam() can be
|
||||
* rerouted to an exti line for wakeup from stop and standby, in wich case it
|
||||
* doesn't need to be enabled here.
|
||||
*
|
||||
* Ensure backup domain writes are enabled (see pwr_configure_bkp_write()) while
|
||||
* calling this function
|
||||
*/
|
||||
void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
|
||||
enum BkpRtcIrq irq_mask, BkpRtcCallback callback);
|
||||
|
||||
/**
|
||||
* Configure the alarm to trigger after the specified time in ticks, which can
|
||||
* be viewed as an offset to the current time value. This offset is only precise
|
||||
* to the tick and thus if the tick changes right after this function is
|
||||
* called, the observed offset will be close to 1 tick short
|
||||
*/
|
||||
void bkp_set_rtc_alam(uint32_t offset);
|
||||
|
||||
/**
|
||||
* Returns the current counter value of the RTC
|
||||
*/
|
||||
uint32_t bkp_read_rtc(void);
|
||||
|
||||
/**
|
||||
* Resets the entire backup domain, composed of everything configured through
|
||||
* this module
|
||||
*/
|
||||
void bkp_reset(void);
|
||||
|
||||
//unimplemented functions
|
||||
void bkp_configure_tamper();
|
||||
void bkp_calibrate_lsi(void);
|
||||
void bkp_configure_lse(bool enable);
|
||||
|
||||
|
||||
#endif //_BKP_H_
|
||||
|
||||
196
drv/bkp_regs.h
Normal file
196
drv/bkp_regs.h
Normal file
@ -0,0 +1,196 @@
|
||||
/** @file bkp_regs.h
|
||||
* Module defining the Backup (bkp) domain registers.
|
||||
*
|
||||
* Mainly made to be used by the bkp module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _BKP_REGS_H_
|
||||
#define _BKP_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define BKP_BASE_ADDRESS 0x40006C00
|
||||
#define RCC_BASE_ADDRESS 0x40021020
|
||||
#define RTC_BASE_ADDRESS 0x40002800
|
||||
|
||||
union BKP_DR {
|
||||
struct {
|
||||
uint32_t D:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union BKP_RTCCR {
|
||||
struct {
|
||||
uint32_t CAL:7;
|
||||
uint32_t CCO:1;
|
||||
uint32_t ASOE:1;
|
||||
uint32_t ASOS:1;
|
||||
uint32_t reserved1:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union BKP_CR {
|
||||
struct {
|
||||
uint32_t TPE:1;
|
||||
uint32_t TPAL:1;
|
||||
uint32_t reserved1:30;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union BKP_CSR {
|
||||
struct {
|
||||
uint32_t CTE:1;
|
||||
uint32_t CTI:1;
|
||||
uint32_t TPIE:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t TEF:1;
|
||||
uint32_t TIF:1;
|
||||
uint32_t reserved2:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct BKP {
|
||||
union BKP_DR DR[20];
|
||||
union BKP_RTCCR RTCCR;
|
||||
union BKP_CR CR;
|
||||
union BKP_CSR CSR;
|
||||
};
|
||||
|
||||
|
||||
union RCC_BDCR {
|
||||
struct {
|
||||
uint32_t LSEON:1;
|
||||
uint32_t LSERDY:1;
|
||||
uint32_t LSEBYP:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t RTCSEL:2;
|
||||
uint32_t reserved2:5;
|
||||
uint32_t RTCEN:1;
|
||||
uint32_t BDRST:1;
|
||||
uint32_t reserved3:15;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct RCC {
|
||||
union RCC_BDCR BDCR;
|
||||
};
|
||||
|
||||
|
||||
union RTC_CRH {
|
||||
struct {
|
||||
uint32_t SECIE:1;
|
||||
uint32_t ALRIE:1;
|
||||
uint32_t OWIE:1;
|
||||
uint32_t reserved1:29;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_CRL {
|
||||
struct {
|
||||
uint32_t SECF:1;
|
||||
uint32_t ALRF:1;
|
||||
uint32_t OWF:1;
|
||||
uint32_t RSF:1;
|
||||
uint32_t CNF:1;
|
||||
uint32_t RTOFF:1;
|
||||
uint32_t reserved1:26;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_PRLH {
|
||||
struct {
|
||||
uint32_t PRL:4;
|
||||
uint32_t reserved1:28;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_PRLL {
|
||||
struct {
|
||||
uint32_t PRL:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_DIVH {
|
||||
struct {
|
||||
uint32_t RTC_DIV:4;
|
||||
uint32_t reserved1:28;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_DIVL {
|
||||
struct {
|
||||
uint32_t RTC_DIV:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_CNTH {
|
||||
struct {
|
||||
uint32_t RTC_CNT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_CNTL {
|
||||
struct {
|
||||
uint32_t RTC_CNT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_ALRH {
|
||||
struct {
|
||||
uint32_t RTC_ALR:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_ALRL {
|
||||
struct {
|
||||
uint32_t RTC_ALR:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct RTC {
|
||||
union RTC_CRH CRH;
|
||||
union RTC_CRL CRL;
|
||||
union RTC_PRLH PRLH;
|
||||
union RTC_PRLL PRLL;
|
||||
union RTC_DIVH DIVH;
|
||||
union RTC_DIVL DIVL;
|
||||
union RTC_CNTH CNTH;
|
||||
union RTC_CNTL CNTL;
|
||||
union RTC_ALRH ALRH;
|
||||
union RTC_ALRL ALRL;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_BKP_REGS_H_
|
||||
|
||||
32
drv/dma.c
32
drv/dma.c
@ -121,13 +121,13 @@ void dma_stop(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
reg_reset(dma1->CHANNELS[channel].CCR, DMA_CCR_EN);
|
||||
dma1->CHANNELS[channel].CCR.EN = 0;
|
||||
if (dma1_callbacks[channel]) {
|
||||
nvic_disable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
}
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
reg_reset(dma2->CHANNELS[channel].CCR, DMA_CCR_EN);
|
||||
dma2->CHANNELS[channel].CCR.EN;
|
||||
if (dma2_callbacks[channel]) {
|
||||
nvic_disable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
}
|
||||
@ -207,11 +207,11 @@ static void start_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
volatile struct DMA_CHANNEL* regs = &dma->CHANNELS[channel];
|
||||
|
||||
//registers should already be configured, apply transfer config
|
||||
reg_write(regs->CNDTR, DMA_CNDTR_NDT, size);
|
||||
regs->CNDTR.NDT = size;
|
||||
regs->CMAR = (uint32_t)mem;
|
||||
|
||||
//only start transfer when everything is configured
|
||||
reg_set(regs->CCR, DMA_CCR_EN);
|
||||
regs->CCR.EN = 1;
|
||||
}
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
@ -221,7 +221,7 @@ void hdr_dma1_channel1(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL1);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 1) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF1);
|
||||
dma1->IFCR.CGIF1 = 1;
|
||||
|
||||
dma1_callbacks[0](src, dma1_cb_params[0]);
|
||||
}
|
||||
@ -231,7 +231,7 @@ void hdr_dma1_channel2(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL2);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 5) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF2);
|
||||
dma1->IFCR.CGIF2 = 1;
|
||||
|
||||
dma1_callbacks[1](src, dma1_cb_params[1]);
|
||||
}
|
||||
@ -241,7 +241,7 @@ void hdr_dma1_channel3(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL3);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 9) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF3);
|
||||
dma1->IFCR.CGIF3 = 1;
|
||||
|
||||
dma1_callbacks[2](src, dma1_cb_params[2]);
|
||||
}
|
||||
@ -251,7 +251,7 @@ void hdr_dma1_channel4(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL4);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 13) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF4);
|
||||
dma1->IFCR.CGIF4 = 1;
|
||||
|
||||
dma1_callbacks[3](src, dma1_cb_params[3]);
|
||||
}
|
||||
@ -261,7 +261,7 @@ void hdr_dma1_channel5(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL5);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 17) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF5);
|
||||
dma1->IFCR.CGIF5 = 1;
|
||||
|
||||
dma1_callbacks[4](src, dma1_cb_params[4]);
|
||||
}
|
||||
@ -271,7 +271,7 @@ void hdr_dma1_channel6(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL6);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 21) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF6);
|
||||
dma1->IFCR.CGIF6 = 1;
|
||||
|
||||
dma1_callbacks[5](src, dma1_cb_params[5]);
|
||||
}
|
||||
@ -281,7 +281,7 @@ void hdr_dma1_channel7(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL7);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 25) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF7);
|
||||
dma1->IFCR.CGIF7 = 1;
|
||||
|
||||
dma1_callbacks[6](src, dma1_cb_params[6]);
|
||||
}
|
||||
@ -291,7 +291,7 @@ void hdr_dma2_channel1(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA2_CHANNEL1);
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 1) & 0x7;
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF1);
|
||||
dma2->IFCR.CGIF1 = 1;
|
||||
|
||||
dma2_callbacks[0](src, dma2_cb_params[0]);
|
||||
}
|
||||
@ -301,7 +301,7 @@ void hdr_dma2_channel2(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA2_CHANNEL2);
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 5) & 0x7;
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF2);
|
||||
dma2->IFCR.CGIF2 = 1;
|
||||
|
||||
dma2_callbacks[1](src, dma2_cb_params[1]);
|
||||
}
|
||||
@ -311,7 +311,7 @@ void hdr_dma2_channel3(void)
|
||||
nvic_clear_pending(NVIC_IRQ_DMA2_CHANNEL3);
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 9) & 0x7;
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF3);
|
||||
dma2->IFCR.CGIF3 = 1;
|
||||
|
||||
dma2_callbacks[2](src, dma2_cb_params[2]);
|
||||
}
|
||||
@ -322,13 +322,13 @@ void hdr_dma2_channel4_5(void)
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 13) & 0x7;
|
||||
if (src != 0) {
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF4);
|
||||
dma2->IFCR.CGIF4 = 1;
|
||||
dma1_callbacks[3](src, dma2_cb_params[3]);
|
||||
}
|
||||
|
||||
src = (dma2->IFCR.word >> 17) & 0x7;
|
||||
if (src != 0) {
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF5);
|
||||
dma2->IFCR.CGIF5 = 1;
|
||||
dma1_callbacks[4](src, dma2_cb_params[4]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,8 +11,6 @@
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
@ -22,7 +20,7 @@
|
||||
#define DMA2_BASE_ADDRESS 0x40020400
|
||||
|
||||
union DMA_ISR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t GIF1:1;
|
||||
uint32_t TCIF1:1;
|
||||
uint32_t HTIF1:1;
|
||||
@ -56,38 +54,8 @@ union DMA_ISR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_ISR_GIF1 reg_def( 0, 1)
|
||||
#define DMA_ISR_TCIF1 reg_def( 1, 1)
|
||||
#define DMA_ISR_HTIF1 reg_def( 2, 1)
|
||||
#define DMA_ISR_TEIF1 reg_def( 3, 1)
|
||||
#define DMA_ISR_GIF2 reg_def( 4, 1)
|
||||
#define DMA_ISR_TCIF2 reg_def( 5, 1)
|
||||
#define DMA_ISR_HTIF2 reg_def( 6, 1)
|
||||
#define DMA_ISR_TEIF2 reg_def( 7, 1)
|
||||
#define DMA_ISR_GIF3 reg_def( 8, 1)
|
||||
#define DMA_ISR_TCIF3 reg_def( 9, 1)
|
||||
#define DMA_ISR_HTIF3 reg_def(10, 1)
|
||||
#define DMA_ISR_TEIF3 reg_def(11, 1)
|
||||
#define DMA_ISR_GIF4 reg_def(12, 1)
|
||||
#define DMA_ISR_TCIF4 reg_def(13, 1)
|
||||
#define DMA_ISR_HTIF4 reg_def(14, 1)
|
||||
#define DMA_ISR_TEIF4 reg_def(15, 1)
|
||||
#define DMA_ISR_GIF5 reg_def(16, 1)
|
||||
#define DMA_ISR_TCIF5 reg_def(17, 1)
|
||||
#define DMA_ISR_HTIF5 reg_def(18, 1)
|
||||
#define DMA_ISR_TEIF5 reg_def(19, 1)
|
||||
#define DMA_ISR_GIF6 reg_def(20, 1)
|
||||
#define DMA_ISR_TCIF6 reg_def(21, 1)
|
||||
#define DMA_ISR_HTIF6 reg_def(22, 1)
|
||||
#define DMA_ISR_TEIF6 reg_def(23, 1)
|
||||
#define DMA_ISR_GIF7 reg_def(24, 1)
|
||||
#define DMA_ISR_TCIF7 reg_def(25, 1)
|
||||
#define DMA_ISR_HTIF7 reg_def(26, 1)
|
||||
#define DMA_ISR_TEIF7 reg_def(27, 1)
|
||||
#define DMA_ISR_reserved1 reg_def(28, 4)
|
||||
|
||||
union DMA_IFCR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t CGIF1:1;
|
||||
uint32_t CTCIF1:1;
|
||||
uint32_t CHTIF1:1;
|
||||
@ -121,38 +89,8 @@ union DMA_IFCR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_IFCR_CGIF1 reg_def( 0, 1)
|
||||
#define DMA_IFCR_CTCIF1 reg_def( 1, 1)
|
||||
#define DMA_IFCR_CHTIF1 reg_def( 2, 1)
|
||||
#define DMA_IFCR_CTEIF1 reg_def( 3, 1)
|
||||
#define DMA_IFCR_CGIF2 reg_def( 4, 1)
|
||||
#define DMA_IFCR_CTCIF2 reg_def( 5, 1)
|
||||
#define DMA_IFCR_CHTIF2 reg_def( 6, 1)
|
||||
#define DMA_IFCR_CTEIF2 reg_def( 7, 1)
|
||||
#define DMA_IFCR_CGIF3 reg_def( 8, 1)
|
||||
#define DMA_IFCR_CTCIF3 reg_def( 9, 1)
|
||||
#define DMA_IFCR_CHTIF3 reg_def(10, 1)
|
||||
#define DMA_IFCR_CTEIF3 reg_def(11, 1)
|
||||
#define DMA_IFCR_CGIF4 reg_def(12, 1)
|
||||
#define DMA_IFCR_CTCIF4 reg_def(13, 1)
|
||||
#define DMA_IFCR_CHTIF4 reg_def(14, 1)
|
||||
#define DMA_IFCR_CTEIF4 reg_def(15, 1)
|
||||
#define DMA_IFCR_CGIF5 reg_def(16, 1)
|
||||
#define DMA_IFCR_CTCIF5 reg_def(17, 1)
|
||||
#define DMA_IFCR_CHTIF5 reg_def(18, 1)
|
||||
#define DMA_IFCR_CTEIF5 reg_def(19, 1)
|
||||
#define DMA_IFCR_CGIF6 reg_def(20, 1)
|
||||
#define DMA_IFCR_CTCIF6 reg_def(21, 1)
|
||||
#define DMA_IFCR_CHTIF6 reg_def(22, 1)
|
||||
#define DMA_IFCR_CTEIF6 reg_def(23, 1)
|
||||
#define DMA_IFCR_CGIF7 reg_def(24, 1)
|
||||
#define DMA_IFCR_CTCIF7 reg_def(25, 1)
|
||||
#define DMA_IFCR_CHTIF7 reg_def(26, 1)
|
||||
#define DMA_IFCR_CTEIF7 reg_def(27, 1)
|
||||
#define DMA_IFCR_reserved1 reg_def(28, 4)
|
||||
|
||||
union DMA_CCR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t EN:1;
|
||||
uint32_t TCIE:1;
|
||||
uint32_t HTIE:1;
|
||||
@ -170,32 +108,15 @@ union DMA_CCR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_CCR_EN reg_def( 0, 1)
|
||||
#define DMA_CCR_TCIE reg_def( 1, 1)
|
||||
#define DMA_CCR_HTIE reg_def( 2, 1)
|
||||
#define DMA_CCR_TEIE reg_def( 3, 1)
|
||||
#define DMA_CCR_DIR reg_def( 4, 1)
|
||||
#define DMA_CCR_CIRC reg_def( 5, 1)
|
||||
#define DMA_CCR_PINC reg_def( 6, 1)
|
||||
#define DMA_CCR_MINC reg_def( 7, 1)
|
||||
#define DMA_CCR_PSIZE reg_def( 8, 2)
|
||||
#define DMA_CCR_MSIZE reg_def(10, 2)
|
||||
#define DMA_CCR_PL reg_def(12, 2)
|
||||
#define DMA_CCR_MEM2MEM reg_def(14, 1)
|
||||
#define DMA_CCR_reserved1 reg_def(15, 17)
|
||||
|
||||
union DMA_CNDTR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t NDT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_CNDTR_NDT reg_def( 0, 16)
|
||||
#define DMA_CNDTR_reserved1 reg_def(16, 16)
|
||||
|
||||
struct __attribute__((packed)) DMA_CHANNEL {
|
||||
struct DMA_CHANNEL {
|
||||
union DMA_CCR CCR;
|
||||
union DMA_CNDTR CNDTR;
|
||||
uint32_t CPAR;
|
||||
@ -203,7 +124,7 @@ struct __attribute__((packed)) DMA_CHANNEL {
|
||||
uint32_t reserved1;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) DMA {
|
||||
struct DMA {
|
||||
union DMA_ISR ISR;
|
||||
union DMA_IFCR IFCR;
|
||||
struct DMA_CHANNEL CHANNELS[7];
|
||||
|
||||
87
drv/exti.c
87
drv/exti.c
@ -11,7 +11,6 @@
|
||||
#include "exti_regs.h"
|
||||
|
||||
#include "nvic.h"
|
||||
#include "afio.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
@ -24,13 +23,11 @@ static ExtiCallback callbacks[19];
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback)
|
||||
void exti_configure(enum ExtiLine line_mask, enum ExtiConfig config_mask,
|
||||
ExtiCallback callback)
|
||||
{
|
||||
exti_reset(line_mask);
|
||||
|
||||
afio_map_exti(line_mask, port);
|
||||
|
||||
//configure edge detections
|
||||
if (config_mask & EXTI_CONFIG_RISING_EDGE) {
|
||||
regs->RTSR.word |= line_mask;
|
||||
@ -48,7 +45,7 @@ void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
|
||||
regs->EMR.word |= line_mask;
|
||||
if (callback) {
|
||||
//register callbacks for each line selected
|
||||
for (uint8_t i = 0; i < 16; ++i) {
|
||||
for (uint8_t i = 0; i < 19; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
callbacks[i] = callback;
|
||||
}
|
||||
@ -66,6 +63,15 @@ void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
|
||||
if (line_mask & 0x7c00) {
|
||||
nvic_enable(NVIC_IRQ_EXTI15_10);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_PVD) {
|
||||
nvic_enable(NVIC_IRQ_PVD);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_RTC) {
|
||||
nvic_enable(NVIC_IRQ_RTC_ALARM);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_USB) {
|
||||
nvic_enable(NVIC_IRQ_USB_WAKEUP);
|
||||
}
|
||||
|
||||
//enable irqs in last to avoid triggers during config
|
||||
regs->IMR.word |= line_mask;
|
||||
@ -94,56 +100,6 @@ void exti_reset(enum ExtiLine line_mask)
|
||||
nvic_disable(NVIC_IRQ_EXTI15_10);
|
||||
}
|
||||
|
||||
afio_map_exti(0xFFFF, 0x0);
|
||||
}
|
||||
|
||||
void exti_configure_specific(enum ExtiLineSpecific line_mask,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback)
|
||||
{
|
||||
//reset is identical to normal lines
|
||||
exti_reset_specific(line_mask);
|
||||
|
||||
//configure edge detections
|
||||
if (config_mask & EXTI_CONFIG_RISING_EDGE) {
|
||||
regs->RTSR.word |= line_mask;
|
||||
} else {
|
||||
regs->RTSR.word &= ~line_mask;
|
||||
}
|
||||
|
||||
if (config_mask & EXTI_CONFIG_FALLING_EDGE) {
|
||||
regs->FTSR.word |= line_mask;
|
||||
} else {
|
||||
regs->FTSR.word &= ~line_mask;
|
||||
}
|
||||
|
||||
//reconfigure events/irqs
|
||||
regs->EMR.word |= line_mask;
|
||||
if (callback) {
|
||||
//register callbacks for each line selected
|
||||
for (uint8_t i = 0; i < 16; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
callbacks[i] = callback;
|
||||
}
|
||||
}
|
||||
|
||||
//enable interrupts lines in nvic
|
||||
if (line_mask & EXTI_LINE_PVD) {
|
||||
nvic_enable(NVIC_IRQ_PVD);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_RTC) {
|
||||
nvic_enable(NVIC_IRQ_RTC_ALARM);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_USB) {
|
||||
nvic_enable(NVIC_IRQ_USB_WAKEUP);
|
||||
}
|
||||
|
||||
//enable irqs in last to avoid triggers during config
|
||||
regs->IMR.word |= line_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void exti_reset_specific(enum ExtiLineSpecific line_mask)
|
||||
{
|
||||
//disable events/irqs
|
||||
regs->IMR.word &= ~line_mask;
|
||||
regs->EMR.word &= ~line_mask;
|
||||
@ -163,6 +119,7 @@ void exti_reset_specific(enum ExtiLineSpecific line_mask)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void exti_reset_peripheral(void)
|
||||
{
|
||||
//reset peripheral config
|
||||
@ -182,8 +139,6 @@ void exti_reset_peripheral(void)
|
||||
nvic_disable(NVIC_IRQ_PVD);
|
||||
nvic_disable(NVIC_IRQ_RTC_ALARM);
|
||||
nvic_disable(NVIC_IRQ_USB_WAKEUP);
|
||||
|
||||
afio_map_exti(0xFFFF, 0x0);
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
@ -193,35 +148,35 @@ void exti_reset_peripheral(void)
|
||||
void hdr_exti0(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI0);
|
||||
reg_set(regs->PR, EXTI_PR_PR0);
|
||||
regs->PR.PR0 = 1;
|
||||
callbacks[0]();
|
||||
}
|
||||
|
||||
void hdr_exti1(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI1);
|
||||
reg_set(regs->PR, EXTI_PR_PR1);
|
||||
regs->PR.PR1 = 1;
|
||||
callbacks[1]();
|
||||
}
|
||||
|
||||
void hdr_exti2(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI2);
|
||||
reg_set(regs->PR, EXTI_PR_PR2);
|
||||
regs->PR.PR2 = 1;
|
||||
callbacks[2]();
|
||||
}
|
||||
|
||||
void hdr_exti3(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI3);
|
||||
reg_set(regs->PR, EXTI_PR_PR3);
|
||||
regs->PR.PR3 = 1;
|
||||
callbacks[3]();
|
||||
}
|
||||
|
||||
void hdr_exti4(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI4);
|
||||
reg_set(regs->PR, EXTI_PR_PR4);
|
||||
regs->PR.PR4 = 1;
|
||||
callbacks[4]();
|
||||
}
|
||||
|
||||
@ -250,21 +205,21 @@ void hdr_exti15_10(void)
|
||||
void hdr_pvd(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_PVD);
|
||||
reg_set(regs->PR, EXTI_PR_PR16);
|
||||
regs->PR.PR16 = 1;
|
||||
callbacks[16]();
|
||||
}
|
||||
|
||||
void hdr_rtc_alarm(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_RTC_ALARM);
|
||||
reg_set(regs->PR, EXTI_PR_PR17);
|
||||
regs->PR.PR17 = 1;
|
||||
callbacks[17]();
|
||||
}
|
||||
|
||||
void hdr_usb_wakeup(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_USB_WAKEUP);
|
||||
reg_set(regs->PR, EXTI_PR_PR18);
|
||||
regs->PR.PR18 = 1;
|
||||
callbacks[18]();
|
||||
}
|
||||
|
||||
|
||||
63
drv/exti.h
63
drv/exti.h
@ -10,16 +10,11 @@
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available exti lines. These lines correspond to gpios
|
||||
* Available exti lines. The numbered lines correspond to gpios while the
|
||||
* remaining are directly mapped to peripherals
|
||||
*/
|
||||
enum ExtiLine {
|
||||
EXTI_LINE_0 = (0x1 << 0),
|
||||
@ -38,12 +33,6 @@ enum ExtiLine {
|
||||
EXTI_LINE_13 = (0x1 << 13),
|
||||
EXTI_LINE_14 = (0x1 << 14),
|
||||
EXTI_LINE_15 = (0x1 << 15),
|
||||
};
|
||||
|
||||
/**
|
||||
* Available exti lines. These lines correspond to specific peripherals
|
||||
*/
|
||||
enum ExtiLineSpecific {
|
||||
EXTI_LINE_PVD = (0x1 << 16),
|
||||
EXTI_LINE_RTC = (0x1 << 17),
|
||||
EXTI_LINE_USB = (0x1 << 18),
|
||||
@ -64,43 +53,31 @@ typedef void (*ExtiCallback)(void);
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configure lines on a single GPIO port. The ExtiLine enum can be used as a
|
||||
* mask to configure multiple lines at the same time. Every line can only be
|
||||
* configured for a single port, reconfiguring it will override the previous
|
||||
* configuration. Each line is linked to the pins of the same id (ex : pin 1 for
|
||||
* exti 1). When possible, it is recommanded to use the lowest id possible for
|
||||
* better performance. The ExtiConfig enum can be used as mask. If no callback
|
||||
* is specified, the interrupt won't be enabled, but an event will still be sent
|
||||
* to wake the cpu up.
|
||||
* Configure lines to call a single callback. The ExtiLine enum can be used as a
|
||||
* mask to configure multiple lines at the same time.
|
||||
*
|
||||
* Note: wich port is linked to a line can be changed atfer the fact using
|
||||
* afio_map_exti()
|
||||
* Every numbered line must be linked to a gpio port using afio_map_exti(). Each
|
||||
* line is linked to the pins of the same id (ex : pin 1 for exti 1). When
|
||||
* possible, it is recommended to use the lowest id possible for better
|
||||
* performance. Each pin must be configured independently through the gpio
|
||||
* driver module
|
||||
*
|
||||
* The remaining lines are linked to specific peripherals which must be
|
||||
* configured independently through the corresponding driver module.
|
||||
*
|
||||
* The ExtiConfig enum can be used as mask. If no callback is specified, the
|
||||
* interrupt won't be enabled, but an event will still be sent to wake the cpu
|
||||
* up.
|
||||
*/
|
||||
void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback);
|
||||
void exti_configure(enum ExtiLine line_mask, enum ExtiConfig config_mask,
|
||||
ExtiCallback callback);
|
||||
|
||||
/**
|
||||
* Resets lines. The ExtiLine enum can be used as a mask to configure multiple
|
||||
* lines at the same time
|
||||
* Resets lines. The ExtiLine enum can be used as a mask to reset multiple lines
|
||||
* at the same time
|
||||
*/
|
||||
void exti_reset(enum ExtiLine line_mask);
|
||||
|
||||
/**
|
||||
* Configure lines for specific, non-gpio peripherals. The ExtiLineSpecific enum
|
||||
* can be used as a mask to configure multiple lines at the same time. The
|
||||
* ExtiConfig enum can be used as mask. If no callback is specified, the
|
||||
* interrupt won't be enabled, but an event will still be sent to wake the cpu
|
||||
* up
|
||||
*/
|
||||
void exti_configure_specific(enum ExtiLineSpecific line_mask,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback);
|
||||
|
||||
/**
|
||||
* Resets lines for specific, non-gpio peripherals. The ExtiLineSpecific enum
|
||||
* can be used as a mask to configure multiple lines at the same time.
|
||||
*/
|
||||
void exti_reset_specific(enum ExtiLineSpecific line_mask);
|
||||
|
||||
/**
|
||||
* Resets all lines. The exti peripheral is returned to its reset configuration
|
||||
*/
|
||||
|
||||
142
drv/exti_regs.h
142
drv/exti_regs.h
@ -11,8 +11,6 @@
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
@ -21,7 +19,7 @@
|
||||
#define EXTI_BASE_ADDRESS 0x40010400
|
||||
|
||||
union EXTI_IMR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t MR0:1;
|
||||
uint32_t MR1:1;
|
||||
uint32_t MR2:1;
|
||||
@ -46,29 +44,8 @@ union EXTI_IMR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_IMR_MR0 reg_def( 0, 1)
|
||||
#define EXTI_IMR_MR1 reg_def( 1, 1)
|
||||
#define EXTI_IMR_MR2 reg_def( 2, 1)
|
||||
#define EXTI_IMR_MR3 reg_def( 3, 1)
|
||||
#define EXTI_IMR_MR4 reg_def( 4, 1)
|
||||
#define EXTI_IMR_MR5 reg_def( 5, 1)
|
||||
#define EXTI_IMR_MR6 reg_def( 6, 1)
|
||||
#define EXTI_IMR_MR7 reg_def( 7, 1)
|
||||
#define EXTI_IMR_MR8 reg_def( 8, 1)
|
||||
#define EXTI_IMR_MR9 reg_def( 9, 1)
|
||||
#define EXTI_IMR_MR10 reg_def(10, 1)
|
||||
#define EXTI_IMR_MR11 reg_def(11, 1)
|
||||
#define EXTI_IMR_MR12 reg_def(12, 1)
|
||||
#define EXTI_IMR_MR13 reg_def(13, 1)
|
||||
#define EXTI_IMR_MR14 reg_def(14, 1)
|
||||
#define EXTI_IMR_MR15 reg_def(15, 1)
|
||||
#define EXTI_IMR_MR16 reg_def(16, 1)
|
||||
#define EXTI_IMR_MR17 reg_def(17, 1)
|
||||
#define EXTI_IMR_MR18 reg_def(18, 1)
|
||||
#define EXTI_IMR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_EMR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t MR0:1;
|
||||
uint32_t MR1:1;
|
||||
uint32_t MR2:1;
|
||||
@ -93,29 +70,8 @@ union EXTI_EMR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_EMR_MR0 reg_def( 0, 1)
|
||||
#define EXTI_EMR_MR1 reg_def( 1, 1)
|
||||
#define EXTI_EMR_MR2 reg_def( 2, 1)
|
||||
#define EXTI_EMR_MR3 reg_def( 3, 1)
|
||||
#define EXTI_EMR_MR4 reg_def( 4, 1)
|
||||
#define EXTI_EMR_MR5 reg_def( 5, 1)
|
||||
#define EXTI_EMR_MR6 reg_def( 6, 1)
|
||||
#define EXTI_EMR_MR7 reg_def( 7, 1)
|
||||
#define EXTI_EMR_MR8 reg_def( 8, 1)
|
||||
#define EXTI_EMR_MR9 reg_def( 9, 1)
|
||||
#define EXTI_EMR_MR10 reg_def(10, 1)
|
||||
#define EXTI_EMR_MR11 reg_def(11, 1)
|
||||
#define EXTI_EMR_MR12 reg_def(12, 1)
|
||||
#define EXTI_EMR_MR13 reg_def(13, 1)
|
||||
#define EXTI_EMR_MR14 reg_def(14, 1)
|
||||
#define EXTI_EMR_MR15 reg_def(15, 1)
|
||||
#define EXTI_EMR_MR16 reg_def(16, 1)
|
||||
#define EXTI_EMR_MR17 reg_def(17, 1)
|
||||
#define EXTI_EMR_MR18 reg_def(18, 1)
|
||||
#define EXTI_EMR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_RTSR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t TR0:1;
|
||||
uint32_t TR1:1;
|
||||
uint32_t TR2:1;
|
||||
@ -140,29 +96,8 @@ union EXTI_RTSR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_RTSR_TR0 reg_def( 0, 1)
|
||||
#define EXTI_RTSR_TR1 reg_def( 1, 1)
|
||||
#define EXTI_RTSR_TR2 reg_def( 2, 1)
|
||||
#define EXTI_RTSR_TR3 reg_def( 3, 1)
|
||||
#define EXTI_RTSR_TR4 reg_def( 4, 1)
|
||||
#define EXTI_RTSR_TR5 reg_def( 5, 1)
|
||||
#define EXTI_RTSR_TR6 reg_def( 6, 1)
|
||||
#define EXTI_RTSR_TR7 reg_def( 7, 1)
|
||||
#define EXTI_RTSR_TR8 reg_def( 8, 1)
|
||||
#define EXTI_RTSR_TR9 reg_def( 9, 1)
|
||||
#define EXTI_RTSR_TR10 reg_def(10, 1)
|
||||
#define EXTI_RTSR_TR11 reg_def(11, 1)
|
||||
#define EXTI_RTSR_TR12 reg_def(12, 1)
|
||||
#define EXTI_RTSR_TR13 reg_def(13, 1)
|
||||
#define EXTI_RTSR_TR14 reg_def(14, 1)
|
||||
#define EXTI_RTSR_TR15 reg_def(15, 1)
|
||||
#define EXTI_RTSR_TR16 reg_def(16, 1)
|
||||
#define EXTI_RTSR_TR17 reg_def(17, 1)
|
||||
#define EXTI_RTSR_TR18 reg_def(18, 1)
|
||||
#define EXTI_RTSR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_FTSR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t TR0:1;
|
||||
uint32_t TR1:1;
|
||||
uint32_t TR2:1;
|
||||
@ -187,29 +122,8 @@ union EXTI_FTSR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_FTSR_TR0 reg_def( 0, 1)
|
||||
#define EXTI_FTSR_TR1 reg_def( 1, 1)
|
||||
#define EXTI_FTSR_TR2 reg_def( 2, 1)
|
||||
#define EXTI_FTSR_TR3 reg_def( 3, 1)
|
||||
#define EXTI_FTSR_TR4 reg_def( 4, 1)
|
||||
#define EXTI_FTSR_TR5 reg_def( 5, 1)
|
||||
#define EXTI_FTSR_TR6 reg_def( 6, 1)
|
||||
#define EXTI_FTSR_TR7 reg_def( 7, 1)
|
||||
#define EXTI_FTSR_TR8 reg_def( 8, 1)
|
||||
#define EXTI_FTSR_TR9 reg_def( 9, 1)
|
||||
#define EXTI_FTSR_TR10 reg_def(10, 1)
|
||||
#define EXTI_FTSR_TR11 reg_def(11, 1)
|
||||
#define EXTI_FTSR_TR12 reg_def(12, 1)
|
||||
#define EXTI_FTSR_TR13 reg_def(13, 1)
|
||||
#define EXTI_FTSR_TR14 reg_def(14, 1)
|
||||
#define EXTI_FTSR_TR15 reg_def(15, 1)
|
||||
#define EXTI_FTSR_TR16 reg_def(16, 1)
|
||||
#define EXTI_FTSR_TR17 reg_def(17, 1)
|
||||
#define EXTI_FTSR_TR18 reg_def(18, 1)
|
||||
#define EXTI_FTSR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_SWIER {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t SWIER0:1;
|
||||
uint32_t SWIER1:1;
|
||||
uint32_t SWIER2:1;
|
||||
@ -234,29 +148,8 @@ union EXTI_SWIER {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_SWIER_SWIER0 reg_def( 0, 1)
|
||||
#define EXTI_SWIER_SWIER1 reg_def( 1, 1)
|
||||
#define EXTI_SWIER_SWIER2 reg_def( 2, 1)
|
||||
#define EXTI_SWIER_SWIER3 reg_def( 3, 1)
|
||||
#define EXTI_SWIER_SWIER4 reg_def( 4, 1)
|
||||
#define EXTI_SWIER_SWIER5 reg_def( 5, 1)
|
||||
#define EXTI_SWIER_SWIER6 reg_def( 6, 1)
|
||||
#define EXTI_SWIER_SWIER7 reg_def( 7, 1)
|
||||
#define EXTI_SWIER_SWIER8 reg_def( 8, 1)
|
||||
#define EXTI_SWIER_SWIER9 reg_def( 9, 1)
|
||||
#define EXTI_SWIER_SWIER10 reg_def(10, 1)
|
||||
#define EXTI_SWIER_SWIER11 reg_def(11, 1)
|
||||
#define EXTI_SWIER_SWIER12 reg_def(12, 1)
|
||||
#define EXTI_SWIER_SWIER13 reg_def(13, 1)
|
||||
#define EXTI_SWIER_SWIER14 reg_def(14, 1)
|
||||
#define EXTI_SWIER_SWIER15 reg_def(15, 1)
|
||||
#define EXTI_SWIER_SWIER16 reg_def(16, 1)
|
||||
#define EXTI_SWIER_SWIER17 reg_def(17, 1)
|
||||
#define EXTI_SWIER_SWIER18 reg_def(18, 1)
|
||||
#define EXTI_SWIER_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_PR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t PR0:1;
|
||||
uint32_t PR1:1;
|
||||
uint32_t PR2:1;
|
||||
@ -281,28 +174,7 @@ union EXTI_PR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_PR_PR0 reg_def( 0, 1)
|
||||
#define EXTI_PR_PR1 reg_def( 1, 1)
|
||||
#define EXTI_PR_PR2 reg_def( 2, 1)
|
||||
#define EXTI_PR_PR3 reg_def( 3, 1)
|
||||
#define EXTI_PR_PR4 reg_def( 4, 1)
|
||||
#define EXTI_PR_PR5 reg_def( 5, 1)
|
||||
#define EXTI_PR_PR6 reg_def( 6, 1)
|
||||
#define EXTI_PR_PR7 reg_def( 7, 1)
|
||||
#define EXTI_PR_PR8 reg_def( 8, 1)
|
||||
#define EXTI_PR_PR9 reg_def( 9, 1)
|
||||
#define EXTI_PR_PR10 reg_def(10, 1)
|
||||
#define EXTI_PR_PR11 reg_def(11, 1)
|
||||
#define EXTI_PR_PR12 reg_def(12, 1)
|
||||
#define EXTI_PR_PR13 reg_def(13, 1)
|
||||
#define EXTI_PR_PR14 reg_def(14, 1)
|
||||
#define EXTI_PR_PR15 reg_def(15, 1)
|
||||
#define EXTI_PR_PR16 reg_def(16, 1)
|
||||
#define EXTI_PR_PR17 reg_def(17, 1)
|
||||
#define EXTI_PR_PR18 reg_def(18, 1)
|
||||
#define EXTI_PR_reserved1 reg_def(19, 13)
|
||||
|
||||
struct __attribute__((packed)) EXTI {
|
||||
struct EXTI {
|
||||
union EXTI_IMR IMR;
|
||||
union EXTI_EMR EMR;
|
||||
union EXTI_RTSR RTSR;
|
||||
|
||||
@ -34,15 +34,13 @@ void flash_configure(enum FlashPreset preset)
|
||||
//apply new configuration
|
||||
switch (preset) {
|
||||
case FLASH_PRESET_LOW_CLOCK_SPEED:
|
||||
reg_set(regs->ACR, FLASH_ACR_HLFCYA); //half cycle for power saving
|
||||
regs->ACR.HLFCYA = 1; //half cycle for power saving
|
||||
break;
|
||||
case FLASH_PRESET_MEDIUM_CLOCK_SPEED:
|
||||
reg_reset(regs->ACR, FLASH_ACR_LATENCY);
|
||||
reg_write(regs->ACR, FLASH_ACR_LATENCY, 0x1);
|
||||
regs->ACR.LATENCY = 0x1;
|
||||
break;
|
||||
case FLASH_PRESET_HIGH_CLOCK_SPEED:
|
||||
reg_reset(regs->ACR, FLASH_ACR_LATENCY);
|
||||
reg_write(regs->ACR, FLASH_ACR_LATENCY, 0x2);
|
||||
regs->ACR.LATENCY = 0x2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -11,8 +11,6 @@
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
@ -21,7 +19,7 @@
|
||||
#define FLASH_BASE_ADDRESS 0x40022000
|
||||
|
||||
union FLASH_ACR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t LATENCY:3;
|
||||
uint32_t HLFCYA:1;
|
||||
uint32_t PRFTBE:1;
|
||||
@ -31,62 +29,56 @@ union FLASH_ACR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define FLASH_ACR_LATENCY reg_def(0, 3)
|
||||
#define FLASH_ACR_HLFCYA reg_def(3, 1)
|
||||
#define FLASH_ACR_PRFTBE reg_def(4, 1)
|
||||
#define FLASH_ACR_PRFTBS reg_def(5, 1)
|
||||
#define FLASH_ACR_reserved1 reg_def(6, 26)
|
||||
|
||||
union FLASH_KEYR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_OPTKEYR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_SR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_CR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_AR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_OBR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_WRPR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) FLASH {
|
||||
struct FLASH {
|
||||
union FLASH_ACR ACR;
|
||||
union FLASH_KEYR KEYR;
|
||||
union FLASH_OPTKEYR OPTKEYR;
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
#define GPIO_BASE_ADDRESS 0x40010800
|
||||
|
||||
union GPIO_CRL {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t MODE0:2;
|
||||
uint32_t CNF0:2;
|
||||
uint32_t MODE1:2;
|
||||
@ -41,7 +41,7 @@ union GPIO_CRL {
|
||||
};
|
||||
|
||||
union GPIO_CRH {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t MODE8:2;
|
||||
uint32_t CNF8:2;
|
||||
uint32_t MODE9:2;
|
||||
@ -63,7 +63,7 @@ union GPIO_CRH {
|
||||
};
|
||||
|
||||
union GPIO_IDR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t IDR0:1;
|
||||
uint32_t IDR1:1;
|
||||
uint32_t IDR2:1;
|
||||
@ -86,7 +86,7 @@ union GPIO_IDR {
|
||||
};
|
||||
|
||||
union GPIO_ODR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t ODR0:1;
|
||||
uint32_t ODR1:1;
|
||||
uint32_t ODR2:1;
|
||||
@ -109,7 +109,7 @@ union GPIO_ODR {
|
||||
};
|
||||
|
||||
union GPIO_BSRR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t BS0:1;
|
||||
uint32_t BS1:1;
|
||||
uint32_t BS2:1;
|
||||
@ -147,7 +147,7 @@ union GPIO_BSRR {
|
||||
};
|
||||
|
||||
union GPIO_BRR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t BR0:1;
|
||||
uint32_t BR1:1;
|
||||
uint32_t BR2:1;
|
||||
@ -170,7 +170,7 @@ union GPIO_BRR {
|
||||
};
|
||||
|
||||
union GPIO_LCKK {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t LCK0:1;
|
||||
uint32_t LCK1:1;
|
||||
uint32_t LCK2:1;
|
||||
@ -193,7 +193,7 @@ union GPIO_LCKK {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) GPIO_PORT {
|
||||
struct GPIO_PORT {
|
||||
union GPIO_CRL CRL;
|
||||
union GPIO_CRH CRH;
|
||||
union GPIO_IDR IDR;
|
||||
@ -204,7 +204,7 @@ struct __attribute__((packed)) GPIO_PORT {
|
||||
uint32_t reserved1[249];
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) GPIO {
|
||||
struct GPIO {
|
||||
struct GPIO_PORT PORTS[7];
|
||||
};
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
#define NVIC1_BASE_ADDRESS 0xE000E100
|
||||
#define NVIC2_BASE_ADDRESS 0xE000EF00
|
||||
|
||||
struct __attribute__((packed)) NVIC1 {
|
||||
struct NVIC1 {
|
||||
uint32_t ISERX[3];
|
||||
uint32_t ICERX[3];
|
||||
uint32_t ISPRX[3];
|
||||
@ -28,7 +28,7 @@ struct __attribute__((packed)) NVIC1 {
|
||||
uint32_t IPRX[20];
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) NVIC2 {
|
||||
struct NVIC2 {
|
||||
uint32_t INTID;
|
||||
};
|
||||
|
||||
|
||||
61
drv/pwr.c
Normal file
61
drv/pwr.c
Normal file
@ -0,0 +1,61 @@
|
||||
/** @file pwr.c
|
||||
* Module handling the power management's control
|
||||
*
|
||||
* The module provides functions to enter the different sleep states, control
|
||||
* and filter wakeup events (WKUP and RTC) and configure power voltage
|
||||
* detection
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "pwr.h"
|
||||
#include "pwr_regs.h"
|
||||
#include "scb.h"
|
||||
#include "rcc.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct PWR* regs = (struct PWR*)PWR_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void pwr_sleep(void)
|
||||
{
|
||||
scb_configure_deepsleep(false);
|
||||
__asm("wfi");
|
||||
}
|
||||
|
||||
void pwr_stop(enum PwrWakeupSpeed speed)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
|
||||
scb_configure_deepsleep(true);
|
||||
regs->CR.PDDS = 0;
|
||||
regs->CR.LPDS = speed;
|
||||
__asm("wfi");
|
||||
rcc_configure(RCC_PRESET_SPEED);
|
||||
}
|
||||
|
||||
void pwr_standby(void)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
|
||||
scb_configure_deepsleep(true);
|
||||
regs->CR.PDDS = 1;
|
||||
__asm("wfi");
|
||||
rcc_configure(RCC_PRESET_SPEED);
|
||||
}
|
||||
|
||||
void pwr_configure_bkp_write(bool enable)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
|
||||
regs->CR.DBP = enable;
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
|
||||
51
drv/pwr.h
Normal file
51
drv/pwr.h
Normal file
@ -0,0 +1,51 @@
|
||||
/** @file pwr.h
|
||||
* Module handling the power management's control
|
||||
*
|
||||
* The module provides functions to enter the different sleep states, control
|
||||
* and filter wakeup events (WKUP and RTC) and configure power voltage
|
||||
* detection
|
||||
*/
|
||||
|
||||
#ifndef _PWR_H_
|
||||
#define _PWR_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
enum PwrWakeupSpeed {
|
||||
PWR_WAKEUP_SPEED_FAST, //faster wakeup, higher consumption in stop mode
|
||||
PWR_WAKEUP_SPEED_SLOW, //slower wakeup, lower consumption in stop mode
|
||||
};
|
||||
|
||||
enum PwrPvdThreshold {
|
||||
PWR_PVD_THRESHOLD_2_2V,
|
||||
PWR_PVD_THRESHOLD_2_3V,
|
||||
PWR_PVD_THRESHOLD_2_4V,
|
||||
PWR_PVD_THRESHOLD_2_5V,
|
||||
PWR_PVD_THRESHOLD_2_6V,
|
||||
PWR_PVD_THRESHOLD_2_7V,
|
||||
PWR_PVD_THRESHOLD_2_8V,
|
||||
PWR_PVD_THRESHOLD_2_9V,
|
||||
|
||||
};
|
||||
|
||||
typedef void (*PwrPvdCallback)(void);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
void pwr_sleep(void);
|
||||
void pwr_stop(enum PwrWakeupSpeed speed);
|
||||
void pwr_standby(void);
|
||||
|
||||
bool pwr_wakeup_event(void);
|
||||
bool pwr_standby_exit(void);
|
||||
|
||||
void pwr_configure_bkp_write(bool enable);
|
||||
void pwr_configure_wakeup_pin(bool enable);
|
||||
void pwr_configure_pvd(enum PwrPvdThreshold treshold);
|
||||
|
||||
|
||||
#endif //_PWR_H_
|
||||
|
||||
56
drv/pwr_regs.h
Normal file
56
drv/pwr_regs.h
Normal file
@ -0,0 +1,56 @@
|
||||
/** @file pwr_regs.h
|
||||
* Module defining Power control (PWR) registers.
|
||||
*
|
||||
* Mainly made to be used by the pwr module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _PWR_REGS_H_
|
||||
#define _PWR_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define PWR_BASE_ADDRESS 0x40007000
|
||||
|
||||
union PWR_CR {
|
||||
struct {
|
||||
uint32_t LPDS:1;
|
||||
uint32_t PDDS:1;
|
||||
uint32_t CWUF:1;
|
||||
uint32_t CSBF:1;
|
||||
uint32_t PVDE:1;
|
||||
uint32_t PLS:3;
|
||||
uint32_t DBP:1;
|
||||
uint32_t reserved1:23;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union PWR_CSR {
|
||||
struct {
|
||||
uint32_t WUF:1;
|
||||
uint32_t SBF:1;
|
||||
uint32_t PVDO:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t EWUP:1;
|
||||
uint32_t reserved2:23;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct PWR {
|
||||
union PWR_CR CR;
|
||||
union PWR_CSR CSR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_PWR_REGS_H_
|
||||
|
||||
52
drv/rcc.c
52
drv/rcc.c
@ -60,6 +60,16 @@ void rcc_configure(enum RccPreset preset)
|
||||
regs->APB2ENR = apb2_enr;
|
||||
}
|
||||
|
||||
void rcc_configure_lsi(bool enable)
|
||||
{
|
||||
regs->CSR.LSION = enable;
|
||||
|
||||
//ensure LSI is enabled
|
||||
if (enable) {
|
||||
while (regs->CSR.LSIRDY != 0x1) {}
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_enable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask,
|
||||
enum RccApb2 apb2_mask)
|
||||
{
|
||||
@ -113,26 +123,26 @@ void rcc_get_clocks(struct RccClocks* clocks)
|
||||
static void apply_default_preset(void)
|
||||
{
|
||||
//ensures HSI is enabled
|
||||
reg_set(regs->CR, RCC_CR_HSION);
|
||||
regs->CR.HSION = 1;
|
||||
while (regs->CR.HSIRDY != 0x1);
|
||||
|
||||
//set HSI as main clock source and disable prescalers
|
||||
regs->CFGR.word &= ~0x077fff3;
|
||||
|
||||
//disable all options
|
||||
reg_reset(regs->CR, RCC_CR_HSITRIM);
|
||||
reg_write(regs->CR, RCC_CR_HSITRIM, 0x10);
|
||||
reg_reset(regs->CR, RCC_CR_HSEON);
|
||||
reg_reset(regs->CR, RCC_CR_HSEBYP);
|
||||
reg_reset(regs->CR, RCC_CR_CCSON);
|
||||
reg_reset(regs->CR, RCC_CR_PLLON);
|
||||
regs->CR.HSITRIM = 0;
|
||||
regs->CR.HSITRIM = 0x10;
|
||||
regs->CR.HSEON = 0;
|
||||
regs->CR.HSEBYP = 0;
|
||||
regs->CR.CCSON = 0;
|
||||
regs->CR.PLLON = 0;
|
||||
|
||||
//disable all interrupts
|
||||
reg_reset(regs->CIR, RCC_CIR_LSIRDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_LSERDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_HSIRDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_HSERDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_PLLRDYIE);
|
||||
regs->CIR.LSIRDYIE = 0;
|
||||
regs->CIR.LSERDYIE = 0;
|
||||
regs->CIR.HSIRDYIE = 0;
|
||||
regs->CIR.HSERDYIE = 0;
|
||||
regs->CIR.PLLRDYIE = 0;
|
||||
|
||||
//reconfigure flash
|
||||
flash_configure(FLASH_PRESET_LOW_CLOCK_SPEED);
|
||||
@ -149,35 +159,35 @@ static void apply_speed_preset(void)
|
||||
apply_default_preset();
|
||||
|
||||
//try enabling HSE, fallback to HSI if HSE fails
|
||||
reg_set(regs->CR, RCC_CR_HSEON);
|
||||
regs->CR.HSEON = 1;
|
||||
for (uint32_t i=0; i<1000; ++i) {
|
||||
__asm__("nop");
|
||||
}
|
||||
if (regs->CR.HSERDY == 0x1) {
|
||||
reg_set(regs->CFGR, RCC_CFGR_PLLSCR);
|
||||
regs->CFGR.PLLSCR = 1;
|
||||
} else {
|
||||
reg_reset(regs->CR, RCC_CR_HSEON);
|
||||
regs->CR.HSEON = 0;
|
||||
}
|
||||
|
||||
//configure PLL, fallback to HSI if PLL fails
|
||||
reg_write(regs->CFGR, RCC_CFGR_PLLMUL, 0x7); //PLL x9
|
||||
reg_set(regs->CR, RCC_CR_PLLON);
|
||||
regs->CFGR.PLLMUL = 0x7; //PLL x9
|
||||
regs->CR.PLLON = 1;
|
||||
for (uint32_t i=0; i<1000; ++i) {
|
||||
__asm__("nop");
|
||||
}
|
||||
if (regs->CR.PLLRDY != 0x1) {
|
||||
reg_reset(regs->CR, RCC_CR_PLLON);
|
||||
regs->CR.PLLON = 0;
|
||||
return; //clock low enough, no need for prescalers
|
||||
}
|
||||
|
||||
//configure prescalers
|
||||
reg_write(regs->CFGR, RCC_CFGR_PPRE1, 0x4); // /2
|
||||
reg_write(regs->CFGR, RCC_CFGR_ADCPRE, 0x2); // /6
|
||||
regs->CFGR.PPRE1 = 0x4; // /2
|
||||
regs->CFGR.ADCPRE = 0x2; // /6
|
||||
|
||||
//reconfigure flash
|
||||
flash_configure(FLASH_PRESET_HIGH_CLOCK_SPEED);
|
||||
|
||||
//switch to PLL output
|
||||
reg_write(regs->CFGR, RCC_CFGR_SW, 0x2);
|
||||
regs->CFGR.SW = 0x2;
|
||||
}
|
||||
|
||||
|
||||
13
drv/rcc.h
13
drv/rcc.h
@ -95,6 +95,13 @@ enum RccApb2 {
|
||||
RCC_APB2_TIM11 = (0x1 << 21),
|
||||
};
|
||||
|
||||
enum RccRtcClockSrc {
|
||||
RCC_RTC_CLOCK_SRC_NONE = 0x0,
|
||||
RCC_RTC_CLOCK_SRC_LSE = 0x1,
|
||||
RCC_RTC_CLOCK_SRC_LSI = 0x2,
|
||||
RCC_RTC_CLOCK_SRC_HSE = 0x3,
|
||||
};
|
||||
|
||||
struct RccClocks {
|
||||
uint32_t ahb_freq;
|
||||
uint32_t apb1_freq;
|
||||
@ -112,6 +119,12 @@ struct RccClocks {
|
||||
*/
|
||||
void rcc_configure(enum RccPreset preset);
|
||||
|
||||
/**
|
||||
* Configures the Low Speed Internal (LSI) oscillator for low power
|
||||
* applications.
|
||||
*/
|
||||
void rcc_configure_lsi(bool enable);
|
||||
|
||||
/**
|
||||
* Enables peripherals on the different buses. The enums values can used as
|
||||
* masks to enable multiple peripherals at the same time. Invalid values will be
|
||||
|
||||
228
drv/rcc_regs.h
228
drv/rcc_regs.h
@ -11,8 +11,6 @@
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
@ -21,7 +19,7 @@
|
||||
#define RCC_BASE_ADDRESS 0x40021000
|
||||
|
||||
union RCC_CR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t HSION:1;
|
||||
uint32_t HSIRDY:1;
|
||||
uint32_t reserved1:1;
|
||||
@ -39,22 +37,8 @@ union RCC_CR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CR_HSION reg_def( 0, 1)
|
||||
#define RCC_CR_HSIRDY reg_def( 1, 1)
|
||||
#define RCC_CR_reserved1 reg_def( 2, 1)
|
||||
#define RCC_CR_HSITRIM reg_def( 3, 5)
|
||||
#define RCC_CR_HSICAL reg_def( 8, 8)
|
||||
#define RCC_CR_HSEON reg_def(16, 1)
|
||||
#define RCC_CR_HSERDY reg_def(17, 1)
|
||||
#define RCC_CR_HSEBYP reg_def(18, 1)
|
||||
#define RCC_CR_CCSON reg_def(19, 1)
|
||||
#define RCC_CR_reserved2 reg_def(20, 4)
|
||||
#define RCC_CR_PLLON reg_def(24, 1)
|
||||
#define RCC_CR_PLLRDY reg_def(25, 1)
|
||||
#define RCC_CR_reserved3 reg_def(26, 6)
|
||||
|
||||
union RCC_CFGR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t SW:2;
|
||||
uint32_t SWS:2;
|
||||
uint32_t HPRE:4;
|
||||
@ -72,22 +56,8 @@ union RCC_CFGR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CFGR_SW reg_def( 0, 2)
|
||||
#define RCC_CFGR_SWS reg_def( 2, 2)
|
||||
#define RCC_CFGR_HPRE reg_def( 4, 4)
|
||||
#define RCC_CFGR_PPRE1 reg_def( 8, 3)
|
||||
#define RCC_CFGR_PPRE2 reg_def(11, 3)
|
||||
#define RCC_CFGR_ADCPRE reg_def(14, 2)
|
||||
#define RCC_CFGR_PLLSCR reg_def(16, 1)
|
||||
#define RCC_CFGR_PLLXTPRE reg_def(17, 1)
|
||||
#define RCC_CFGR_PLLMUL reg_def(18, 4)
|
||||
#define RCC_CFGR_USBPRE reg_def(22, 1)
|
||||
#define RCC_CFGR_reserved1 reg_def(23, 1)
|
||||
#define RCC_CFGR_MCO reg_def(24, 3)
|
||||
#define RCC_CFGR_reserved2 reg_def(27, 5)
|
||||
|
||||
union RCC_CIR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t LSIRDYF:1;
|
||||
uint32_t LSERDYF:1;
|
||||
uint32_t HSIRDYF:1;
|
||||
@ -113,30 +83,8 @@ union RCC_CIR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CIR_LSIRDYF reg_def( 0, 1)
|
||||
#define RCC_CIR_LSERDYF reg_def( 1, 1)
|
||||
#define RCC_CIR_HSIRDYF reg_def( 2, 1)
|
||||
#define RCC_CIR_HSERDYF reg_def( 3, 1)
|
||||
#define RCC_CIR_PLLRDYF reg_def( 4, 1)
|
||||
#define RCC_CIR_reserved1 reg_def( 5, 2)
|
||||
#define RCC_CIR_CSSF reg_def( 7, 1)
|
||||
#define RCC_CIR_LSIRDYIE reg_def( 8, 1)
|
||||
#define RCC_CIR_LSERDYIE reg_def( 9, 1)
|
||||
#define RCC_CIR_HSIRDYIE reg_def(10, 1)
|
||||
#define RCC_CIR_HSERDYIE reg_def(11, 1)
|
||||
#define RCC_CIR_PLLRDYIE reg_def(12, 1)
|
||||
#define RCC_CIR_RSE2 reg_def(13, 3)
|
||||
#define RCC_CIR_LSIRDYC reg_def(16, 1)
|
||||
#define RCC_CIR_LSERDYC reg_def(17, 1)
|
||||
#define RCC_CIR_HSIRDYC reg_def(18, 1)
|
||||
#define RCC_CIR_HSERDYC reg_def(19, 1)
|
||||
#define RCC_CIR_PLLRDYC reg_def(20, 1)
|
||||
#define RCC_CIR_reserved3 reg_def(21, 2)
|
||||
#define RCC_CIR_CSSC reg_def(23, 1)
|
||||
#define RCC_CIR_reserved4 reg_def(24, 8)
|
||||
|
||||
union RCC_APB2RSTR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t AFIORST:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t IOPARST:1;
|
||||
@ -162,30 +110,8 @@ union RCC_APB2RSTR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB2RSTR_AFIORST reg_def( 0, 1)
|
||||
#define RCC_APB2RSTR_reserved1 reg_def( 1, 1)
|
||||
#define RCC_APB2RSTR_IOPARST reg_def( 2, 1)
|
||||
#define RCC_APB2RSTR_IOPBRST reg_def( 3, 1)
|
||||
#define RCC_APB2RSTR_IOPCRST reg_def( 4, 1)
|
||||
#define RCC_APB2RSTR_IOPDRST reg_def( 5, 1)
|
||||
#define RCC_APB2RSTR_IOPERST reg_def( 6, 1)
|
||||
#define RCC_APB2RSTR_IOPFRST reg_def( 7, 1)
|
||||
#define RCC_APB2RSTR_IOPGRST reg_def( 8, 1)
|
||||
#define RCC_APB2RSTR_ADC1RST reg_def( 9, 1)
|
||||
#define RCC_APB2RSTR_ACD2RST reg_def(10, 1)
|
||||
#define RCC_APB2RSTR_TIM1RST reg_def(11, 1)
|
||||
#define RCC_APB2RSTR_SPI1RST reg_def(12, 1)
|
||||
#define RCC_APB2RSTR_TIM8RST reg_def(13, 1)
|
||||
#define RCC_APB2RSTR_USART1RST reg_def(14, 1)
|
||||
#define RCC_APB2RSTR_ADC3RST reg_def(15, 1)
|
||||
#define RCC_APB2RSTR_reserved2 reg_def(16, 3)
|
||||
#define RCC_APB2RSTR_TIM9RST reg_def(19, 1)
|
||||
#define RCC_APB2RSTR_TIM10RST reg_def(20, 1)
|
||||
#define RCC_APB2RSTR_TIM11RST reg_def(21, 1)
|
||||
#define RCC_APB2RSTR_reserved3 reg_def(22, 10)
|
||||
|
||||
union RCC_APB1RSTR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t TIM2RST:1;
|
||||
uint32_t TIM3RST:1;
|
||||
uint32_t TIM4RST:1;
|
||||
@ -219,38 +145,8 @@ union RCC_APB1RSTR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB1RSTR_TIM2RST reg_def( 0, 1)
|
||||
#define RCC_APB1RSTR_TIM3RST reg_def( 1, 1)
|
||||
#define RCC_APB1RSTR_TIM4RST reg_def( 2, 1)
|
||||
#define RCC_APB1RSTR_TIM5RST reg_def( 3, 1)
|
||||
#define RCC_APB1RSTR_TIM6RST reg_def( 4, 1)
|
||||
#define RCC_APB1RSTR_TIM7RST reg_def( 5, 1)
|
||||
#define RCC_APB1RSTR_TIM12RST reg_def( 6, 1)
|
||||
#define RCC_APB1RSTR_TIM13RST reg_def( 7, 1)
|
||||
#define RCC_APB1RSTR_TIM14RST reg_def( 8, 1)
|
||||
#define RCC_APB1RSTR_reserved1 reg_def( 9, 2)
|
||||
#define RCC_APB1RSTR_WWDGRST reg_def(11, 1)
|
||||
#define RCC_APB1RSTR_reserved2 reg_def(12, 2)
|
||||
#define RCC_APB1RSTR_SPI2RST reg_def(14, 1)
|
||||
#define RCC_APB1RSTR_SPI3RST reg_def(15, 1)
|
||||
#define RCC_APB1RSTR_reserved3 reg_def(16, 1)
|
||||
#define RCC_APB1RSTR_USART2RST reg_def(17, 1)
|
||||
#define RCC_APB1RSTR_USART3RST reg_def(18, 1)
|
||||
#define RCC_APB1RSTR_UART4RST reg_def(19, 1)
|
||||
#define RCC_APB1RSTR_UART5RST reg_def(20, 1)
|
||||
#define RCC_APB1RSTR_I2C12RST reg_def(21, 1)
|
||||
#define RCC_APB1RSTR_I2C2RST reg_def(22, 1)
|
||||
#define RCC_APB1RSTR_USB2RST reg_def(23, 1)
|
||||
#define RCC_APB1RSTR_reserved4 reg_def(24, 1)
|
||||
#define RCC_APB1RSTR_CANRST reg_def(25, 1)
|
||||
#define RCC_APB1RSTR_reserved5 reg_def(26, 1)
|
||||
#define RCC_APB1RSTR_BKPRST reg_def(27, 1)
|
||||
#define RCC_APB1RSTR_PWRRST reg_def(28, 1)
|
||||
#define RCC_APB1RSTR_DACRST reg_def(29, 1)
|
||||
#define RCC_APB1RSTR_reserved6 reg_def(30, 2)
|
||||
|
||||
union RCC_AHBENR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t DMA1EN:1;
|
||||
uint32_t DMA2EN:1;
|
||||
uint32_t SRAMEN:1;
|
||||
@ -267,21 +163,8 @@ union RCC_AHBENR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_AHBENR_DMA1EN reg_def( 0, 1)
|
||||
#define RCC_AHBENR_DMA2EN reg_def( 1, 1)
|
||||
#define RCC_AHBENR_SRAMEN reg_def( 2, 1)
|
||||
#define RCC_AHBENR_reserved1 reg_def( 3, 1)
|
||||
#define RCC_AHBENR_FLITFEN reg_def( 4, 1)
|
||||
#define RCC_AHBENR_reserved2 reg_def( 5, 1)
|
||||
#define RCC_AHBENR_CRCEN reg_def( 6, 1)
|
||||
#define RCC_AHBENR_reserved3 reg_def( 7, 1)
|
||||
#define RCC_AHBENR_FSMCEN reg_def( 8, 1)
|
||||
#define RCC_AHBENR_reserved4 reg_def( 9, 1)
|
||||
#define RCC_AHBENR_SDIOEN reg_def(10, 1)
|
||||
#define RCC_AHBENR_reserved5 reg_def(11, 21)
|
||||
|
||||
union RCC_APB2ENR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t AFIOEN:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t IOPAEN:1;
|
||||
@ -307,30 +190,8 @@ union RCC_APB2ENR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB2ENR_AFIOEN reg_def( 0, 1)
|
||||
#define RCC_APB2ENR_reserved1 reg_def( 1, 1)
|
||||
#define RCC_APB2ENR_IOPAEN reg_def( 2, 1)
|
||||
#define RCC_APB2ENR_IOPBEN reg_def( 3, 1)
|
||||
#define RCC_APB2ENR_IOPCEN reg_def( 4, 1)
|
||||
#define RCC_APB2ENR_IOPDEN reg_def( 5, 1)
|
||||
#define RCC_APB2ENR_IOPEEN reg_def( 6, 1)
|
||||
#define RCC_APB2ENR_IOPFEN reg_def( 7, 1)
|
||||
#define RCC_APB2ENR_IOPGEN reg_def( 8, 1)
|
||||
#define RCC_APB2ENR_ADC1EN reg_def( 9, 1)
|
||||
#define RCC_APB2ENR_ACD2EN reg_def(10, 1)
|
||||
#define RCC_APB2ENR_TIM1EN reg_def(11, 1)
|
||||
#define RCC_APB2ENR_SPI1EN reg_def(12, 1)
|
||||
#define RCC_APB2ENR_TIM8EN reg_def(13, 1)
|
||||
#define RCC_APB2ENR_USART1EN reg_def(14, 1)
|
||||
#define RCC_APB2ENR_ADC3EN reg_def(15, 1)
|
||||
#define RCC_APB2ENR_reserved2 reg_def(16, 3)
|
||||
#define RCC_APB2ENR_TIM9EN reg_def(19, 1)
|
||||
#define RCC_APB2ENR_TIM10EN reg_def(20, 1)
|
||||
#define RCC_APB2ENR_TIM11EN reg_def(21, 1)
|
||||
#define RCC_APB2ENR_reserved3 reg_def(22, 10)
|
||||
|
||||
union RCC_APB1ENR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t TIM2EN:1;
|
||||
uint32_t TIM3EN:1;
|
||||
uint32_t TIM4EN:1;
|
||||
@ -364,63 +225,8 @@ union RCC_APB1ENR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB1ENR_TIM2EN reg_def( 0, 1)
|
||||
#define RCC_APB1ENR_TIM3EN reg_def( 1, 1)
|
||||
#define RCC_APB1ENR_TIM4EN reg_def( 2, 1)
|
||||
#define RCC_APB1ENR_TIM5EN reg_def( 3, 1)
|
||||
#define RCC_APB1ENR_TIM6EN reg_def( 4, 1)
|
||||
#define RCC_APB1ENR_TIM7EN reg_def( 5, 1)
|
||||
#define RCC_APB1ENR_TIM12EN reg_def( 6, 1)
|
||||
#define RCC_APB1ENR_TIM13EN reg_def( 7, 1)
|
||||
#define RCC_APB1ENR_TIM14EN reg_def( 8, 1)
|
||||
#define RCC_APB1ENR_reserved1 reg_def( 9, 2)
|
||||
#define RCC_APB1ENR_WWDGEN reg_def(11, 1)
|
||||
#define RCC_APB1ENR_reserved reg_def(12, 2)
|
||||
#define RCC_APB1ENR_SPI2EN reg_def(14, 1)
|
||||
#define RCC_APB1ENR_SPI3EN reg_def(15, 1)
|
||||
#define RCC_APB1ENR_reserved2 reg_def(16, 1)
|
||||
#define RCC_APB1ENR_USART2EN reg_def(17, 1)
|
||||
#define RCC_APB1ENR_USART3EN reg_def(18, 1)
|
||||
#define RCC_APB1ENR_UART4EN reg_def(19, 1)
|
||||
#define RCC_APB1ENR_UART5EN reg_def(20, 1)
|
||||
#define RCC_APB1ENR_I2C12EN reg_def(21, 1)
|
||||
#define RCC_APB1ENR_I2C2EN reg_def(22, 1)
|
||||
#define RCC_APB1ENR_USB2EN reg_def(23, 1)
|
||||
#define RCC_APB1ENR_reserved3 reg_def(24, 1)
|
||||
#define RCC_APB1ENR_CANEN reg_def(25, 1)
|
||||
#define RCC_APB1ENR_reserved4 reg_def(26, 1)
|
||||
#define RCC_APB1ENR_BKPEN reg_def(27, 1)
|
||||
#define RCC_APB1ENR_PWREN reg_def(28, 1)
|
||||
#define RCC_APB1ENR_DACEN reg_def(29, 1)
|
||||
#define RCC_APB1ENR_reserved5 reg_def(30, 2)
|
||||
|
||||
union RCC_BDCR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t LSEON:1;
|
||||
uint32_t LSERDY:1;
|
||||
uint32_t LSEBYP:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t RTCSEL:2;
|
||||
uint32_t reserved2:5;
|
||||
uint32_t RTCEN:1;
|
||||
uint32_t BDRST:1;
|
||||
uint32_t reserved3:15;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_BDCR_LSEON reg_def( 0, 1)
|
||||
#define RCC_BDCR_LSERDY reg_def( 1, 1)
|
||||
#define RCC_BDCR_LSEBYP reg_def( 2, 1)
|
||||
#define RCC_BDCR_reserved1 reg_def( 3, 5)
|
||||
#define RCC_BDCR_RTCSEL reg_def( 8, 2)
|
||||
#define RCC_BDCR_reserved2 reg_def(10, 5)
|
||||
#define RCC_BDCR_RTCEN reg_def(15, 1)
|
||||
#define RCC_BDCR_BDRST reg_def(16, 1)
|
||||
#define RCC_BDCR_reserved3 reg_def(17, 15)
|
||||
|
||||
union RCC_CSR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t LSION:1;
|
||||
uint32_t LSIRDY:1;
|
||||
uint32_t reserved1:22;
|
||||
@ -436,19 +242,7 @@ union RCC_CSR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CSR_LSION reg_def( 0, 1)
|
||||
#define RCC_CSR_LSIRDY reg_def( 1, 1)
|
||||
#define RCC_CSR_reserved1 reg_def( 2, 22)
|
||||
#define RCC_CSR_RMVF reg_def(24, 1)
|
||||
#define RCC_CSR_reserved2 reg_def(25, 1)
|
||||
#define RCC_CSR_PINRSTF reg_def(26, 1)
|
||||
#define RCC_CSR_PORRSTF reg_def(27, 1)
|
||||
#define RCC_CSR_SFTRSTF reg_def(28, 1)
|
||||
#define RCC_CSR_IWDGRSTF reg_def(29, 1)
|
||||
#define RCC_CSR_WWDGRSTF reg_def(30, 1)
|
||||
#define RCC_CSR_LPWRSTF reg_def(31, 1)
|
||||
|
||||
struct __attribute__((packed)) RCC {
|
||||
struct RCC {
|
||||
union RCC_CR CR;
|
||||
union RCC_CFGR CFGR;
|
||||
union RCC_CIR CIR;
|
||||
@ -457,7 +251,7 @@ struct __attribute__((packed)) RCC {
|
||||
union RCC_AHBENR AHBENR;
|
||||
union RCC_APB2ENR APB2ENR;
|
||||
union RCC_APB1ENR APB1ENR;
|
||||
union RCC_BDCR BDCR;
|
||||
uint32_t reserved1;
|
||||
union RCC_CSR CSR;
|
||||
};
|
||||
|
||||
|
||||
15
drv/reg.h
15
drv/reg.h
@ -1,15 +0,0 @@
|
||||
|
||||
#define reg_def(pos, size) pos, (((0x1 << size) - 1) << pos)
|
||||
|
||||
#define reg_set(reg, field) _reg_set(reg, field)
|
||||
#define _reg_set(reg, pos, mask) do { reg.word |= mask; } while (false)
|
||||
|
||||
#define reg_reset(reg, field) _reg_reset(reg, field)
|
||||
#define _reg_reset(reg, pos, mask) do { reg.word &= ~mask; } while (false)
|
||||
|
||||
#define reg_write(reg, field, value) _reg_write(reg, field, (value))
|
||||
#define _reg_write(reg, pos, mask, value) \
|
||||
do { \
|
||||
reg.word |= value << pos; \
|
||||
} while (false) \
|
||||
|
||||
64
drv/scb.c
Normal file
64
drv/scb.c
Normal file
@ -0,0 +1,64 @@
|
||||
/** @file scb.c
|
||||
* Module handling the System Control Block
|
||||
*
|
||||
* The module provides functions to configure miscelaneous options of the cortex
|
||||
* m3, including sleep behavior, event handler priorities, resets and fault
|
||||
* handlers
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "scb.h"
|
||||
#include "scb_regs.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct SCB* regs = (struct SCB*)SCB_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
uint16_t scb_pending_exception(void)
|
||||
{
|
||||
return regs->ICSR.VECTPENDING;
|
||||
}
|
||||
|
||||
uint16_t scb_active_exception(void)
|
||||
{
|
||||
return regs->ICSR.VECTACTIVE;
|
||||
}
|
||||
|
||||
void scb_configure_vector_table(uint32_t offset)
|
||||
{
|
||||
//TODO check that last LSB is 0 (alignement restrictions)
|
||||
regs->VTOR.TABLEOFF = offset & 0x1FFFFF;
|
||||
}
|
||||
|
||||
void scb_reset_system(void)
|
||||
{
|
||||
regs->AIRCR.SYSRESETREQ = 1;
|
||||
}
|
||||
|
||||
void scb_configure_deepsleep(bool enable)
|
||||
{
|
||||
regs->SCR.SLEEPDEEP = enable;
|
||||
}
|
||||
|
||||
void scb_configure_div0_fault(bool enable)
|
||||
{
|
||||
regs->CCR.DIV_0_TRP = enable;
|
||||
}
|
||||
|
||||
void scb_configure_unalign_fault(bool enable)
|
||||
{
|
||||
regs->CCR.UNALIGN_TRP = enable;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
32
drv/scb.h
Normal file
32
drv/scb.h
Normal file
@ -0,0 +1,32 @@
|
||||
/** @file scb.h
|
||||
* Module handling the System Control Block
|
||||
*
|
||||
* The module provides functions to configure miscelaneous options of the cortex
|
||||
* m3, including sleep behavior, event handler priorities, resets and fault
|
||||
* handlers
|
||||
*/
|
||||
|
||||
#ifndef _SCB_H_
|
||||
#define _SCB_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
uint16_t scb_pending_exception(void);
|
||||
uint16_t scb_active_exception(void);
|
||||
|
||||
void scb_configure_vector_table(uint32_t offset);
|
||||
void scb_reset_system(void);
|
||||
void scb_configure_deepsleep(bool enable);
|
||||
void scb_configure_div0_fault(bool enable);
|
||||
void scb_configure_unalign_fault(bool enable);
|
||||
|
||||
|
||||
#endif //_SCB_H_
|
||||
|
||||
192
drv/scb_regs.h
Normal file
192
drv/scb_regs.h
Normal file
@ -0,0 +1,192 @@
|
||||
/** @file scb_regs.h
|
||||
* Module defining System Control Block (SCB) registers.
|
||||
*
|
||||
* Mainly made to be used by the scb module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _SCB_REGS_H_
|
||||
#define _SCB_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define SCB_BASE_ADDRESS 0xE000ED00
|
||||
|
||||
union SCB_CPUID {
|
||||
struct {
|
||||
uint32_t revision:4;
|
||||
uint32_t part_no:12;
|
||||
uint32_t constant:4;
|
||||
uint32_t variant:4;
|
||||
uint32_t implementer:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_ICSR {
|
||||
struct {
|
||||
uint32_t VECTACTIVE:9;
|
||||
uint32_t reserved1:2;
|
||||
uint32_t RETOBASE:1;
|
||||
uint32_t VECTPENDING:10;
|
||||
uint32_t ISRPENDING:1;
|
||||
uint32_t reserved2:2;
|
||||
uint32_t PENDSTCLR:1;
|
||||
uint32_t PENDSTSET:1;
|
||||
uint32_t PENDSVCRL:1;
|
||||
uint32_t PENDSVSET:1;
|
||||
uint32_t reserved3:2;
|
||||
uint32_t NMIPENDSET:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_VTOR {
|
||||
struct {
|
||||
uint32_t reserved1:9;
|
||||
uint32_t TABLEOFF:21;
|
||||
uint32_t reserved2:2;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_AIRCR {
|
||||
struct {
|
||||
uint32_t VECTRESET:1;
|
||||
uint32_t VECTCRLACTIVE:1;
|
||||
uint32_t SYSRESETREQ:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t PRIGROUP:3;
|
||||
uint32_t reserved2:4;
|
||||
uint32_t ENDIANESS:1;
|
||||
uint32_t VECTKEY:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SCR {
|
||||
struct {
|
||||
uint32_t reserved1:1;
|
||||
uint32_t SLEEPONEXIT:1;
|
||||
uint32_t SLEEPDEEP:1;
|
||||
uint32_t reserved2:1;
|
||||
uint32_t SEVONPEND:1;
|
||||
uint32_t reserved3:27;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_CCR {
|
||||
struct {
|
||||
uint32_t NONBASETHRDEN:1;
|
||||
uint32_t USERSETMPEND:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t UNALIGN_TRP:1;
|
||||
uint32_t DIV_0_TRP:1;
|
||||
uint32_t reserved2:3;
|
||||
uint32_t BFHFNIGN:1;
|
||||
uint32_t STKALIGN:1;
|
||||
uint32_t reserved3:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHPR1 {
|
||||
struct {
|
||||
uint32_t PRI4:8;
|
||||
uint32_t PRI5:8;
|
||||
uint32_t PRI6:8;
|
||||
uint32_t reserved1:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHPR2 {
|
||||
struct {
|
||||
uint32_t reserved1:24;
|
||||
uint32_t PRI11:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHPR3 {
|
||||
struct {
|
||||
uint32_t reserved1:16;
|
||||
uint32_t PRI14:8;
|
||||
uint32_t PRI15:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHCRS {
|
||||
struct {
|
||||
uint32_t MEMFAULTACT:1;
|
||||
uint32_t BUSFAULTACT:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t USGFAULTACT:1;
|
||||
uint32_t reserved2:3;
|
||||
uint32_t SVCALLACT:1;
|
||||
uint32_t MONITORACT:1;
|
||||
uint32_t reserved3:1;
|
||||
uint32_t PENDSVACT:1;
|
||||
uint32_t SYSTICKACT:1;
|
||||
uint32_t USGFAULTPENDED:1;
|
||||
uint32_t MEMFAULTPENDED:1;
|
||||
uint32_t BUSFAULTPENDED:1;
|
||||
uint32_t SVCALLPENDED:1;
|
||||
uint32_t MEMFAULTENA:1;
|
||||
uint32_t BUSFAULTENA:1;
|
||||
uint32_t USGFAULTENA:1;
|
||||
uint32_t reserved4:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_CFSR {
|
||||
struct {
|
||||
uint32_t MMFSR:8;
|
||||
uint32_t BFSR:8;
|
||||
uint32_t UFSR:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_HFSR {
|
||||
struct {
|
||||
uint32_t reserved1:1;
|
||||
uint32_t VECTTBL:1;
|
||||
uint32_t reserved2:28;
|
||||
uint32_t FORCED:1;
|
||||
uint32_t DEBUG_VT:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct SCB {
|
||||
union SCB_CPUID CPUID;
|
||||
union SCB_ICSR ICSR;
|
||||
union SCB_VTOR VTOR;
|
||||
union SCB_AIRCR AIRCR;
|
||||
union SCB_SCR SCR;
|
||||
union SCB_CCR CCR;
|
||||
union SCB_SHPR1 SHPR1;
|
||||
union SCB_SHPR2 SHPR2;
|
||||
union SCB_SHPR3 SHPR3;
|
||||
union SCB_SHCRS SHCRS;
|
||||
union SCB_CFSR CFSR;
|
||||
union SCB_HFSR HFSR;
|
||||
uint32_t MMAR;
|
||||
uint32_t BFAR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_PWR_REGS_H_
|
||||
|
||||
90
drv/stk.c
Normal file
90
drv/stk.c
Normal file
@ -0,0 +1,90 @@
|
||||
/** @file stk.c
|
||||
* Module handling the system timer (systick or STK for short)
|
||||
*
|
||||
* The module provides functions to configure and use the system timer embedded
|
||||
* in the cortex m core
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stk.h"
|
||||
#include "stk_regs.h"
|
||||
|
||||
#include "rcc.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static volatile struct STK* regs = (struct STK*)STK_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static StkCallback callback;
|
||||
static uint32_t prescaler;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
uint32_t stk_configure(uint32_t period_us, StkCallback cb)
|
||||
{
|
||||
stk_reset();
|
||||
|
||||
struct RccClocks clocks;
|
||||
rcc_get_clocks(&clocks);
|
||||
|
||||
uint32_t prescaler = (clocks.ahb_freq / 1000000 / 8);
|
||||
uint32_t reload = period_us * prescaler;
|
||||
if (reload < 1) {
|
||||
//period is too small, try using the non-prescaled clock
|
||||
prescaler *= 8;
|
||||
reload = period_us * prescaler;
|
||||
if (reload < 1) {
|
||||
//period is still too small
|
||||
return 1;
|
||||
}
|
||||
regs->CTRL.CLKSOURCE = 1;
|
||||
}
|
||||
regs->LOAD.RELOAD = reload;
|
||||
regs->CTRL.TICKINT = 1;
|
||||
|
||||
callback = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stk_reset(void)
|
||||
{
|
||||
regs->CTRL.ENABLE = 0;
|
||||
regs->CTRL.TICKINT = 0;
|
||||
regs->CTRL.CLKSOURCE = 0;
|
||||
regs->CTRL.COUNTFLAG = 0;
|
||||
|
||||
regs->LOAD.RELOAD = 0;
|
||||
regs->VAL.CURRENT = 0;
|
||||
}
|
||||
|
||||
void stk_start(void)
|
||||
{
|
||||
regs->CTRL.ENABLE = 1;
|
||||
}
|
||||
|
||||
void stk_stop(void)
|
||||
{
|
||||
regs->CTRL.ENABLE = 0;
|
||||
}
|
||||
|
||||
uint32_t stk_read_us(void)
|
||||
{
|
||||
return (regs->VAL.word & 0x00FFFFFF) / prescaler;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
void hdr_sys_tick(void)
|
||||
{
|
||||
//clearing the pending bit in SCB_ICSR isn't needed, though I don't know why
|
||||
callback();
|
||||
}
|
||||
|
||||
55
drv/stk.h
Normal file
55
drv/stk.h
Normal file
@ -0,0 +1,55 @@
|
||||
/** @file stk.h
|
||||
* Module handling the system timer (systick or STK for short)
|
||||
*
|
||||
* The module provides functions to configure and use the system timer embedded
|
||||
* in the cortex m core
|
||||
*/
|
||||
|
||||
#ifndef _STK_H_
|
||||
#define _STK_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
typedef void (*StkCallback)(void);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the system timer to run at the specified period in µs and call the
|
||||
* given callback when said period is reached. Due to the limited configuration
|
||||
* options, 1.8s is the maximum period when running in speed preset (see rcc
|
||||
* module). The maximum period can be substantially increased by reducing the
|
||||
* core clock
|
||||
*/
|
||||
uint32_t stk_configure(uint32_t period_us, StkCallback cb);
|
||||
|
||||
/**
|
||||
* Resets the system timer configuration, restoring the default configuration
|
||||
* and stopping it
|
||||
*/
|
||||
void stk_reset(void);
|
||||
|
||||
/**
|
||||
* Starts the system timer. The timer will run until stopped
|
||||
*/
|
||||
void stk_start(void);
|
||||
|
||||
/**
|
||||
* Stops the system timer
|
||||
*/
|
||||
void stk_stop(void);
|
||||
|
||||
/**
|
||||
* Read the current value of the timer's counter in µs
|
||||
*/
|
||||
uint32_t stk_read_us(void);
|
||||
|
||||
|
||||
#endif //_STK_H_
|
||||
|
||||
70
drv/stk_regs.h
Normal file
70
drv/stk_regs.h
Normal file
@ -0,0 +1,70 @@
|
||||
/** @file stk_regs.h
|
||||
* Module defining systick (STK) registers.
|
||||
*
|
||||
* Mainly made to be used by the stk module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _STK_REGS_H_
|
||||
#define _STK_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define STK_BASE_ADDRESS 0xE000E010
|
||||
|
||||
union STK_CTRL {
|
||||
struct {
|
||||
uint32_t ENABLE:1;
|
||||
uint32_t TICKINT:1;
|
||||
uint32_t CLKSOURCE:1;
|
||||
uint32_t reserved1:13;
|
||||
uint32_t COUNTFLAG:1;
|
||||
uint32_t reserved2:15;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union STK_LOAD {
|
||||
struct {
|
||||
uint32_t RELOAD:24;
|
||||
uint32_t reserved1:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union STK_VAL {
|
||||
struct {
|
||||
uint32_t CURRENT:24;
|
||||
uint32_t reserved1:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union STK_CALIB {
|
||||
struct {
|
||||
uint32_t TENMS:24;
|
||||
uint32_t reserved1:6;
|
||||
uint32_t SKEW:1;
|
||||
uint32_t NOREF:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct STK {
|
||||
union STK_CTRL CTRL;
|
||||
union STK_LOAD LOAD;
|
||||
union STK_VAL VAL;
|
||||
union STK_CALIB CALIB;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_STK_REGS_H_
|
||||
|
||||
38
drv/usart.c
38
drv/usart.c
@ -9,7 +9,6 @@
|
||||
|
||||
#include "usart.h"
|
||||
#include "usart_regs.h"
|
||||
#include "reg.h"
|
||||
|
||||
#include "rcc.h"
|
||||
#include "dma.h"
|
||||
@ -132,7 +131,7 @@ uint32_t usart_write_byte(enum UsartPeriph periph, uint8_t byte)
|
||||
|
||||
//only write data if the tx register it empty, give up otherwise
|
||||
if (usarts[periph]->SR.TXE) {
|
||||
reg_write(usarts[periph]->DR, USART_DR_DR, byte);
|
||||
usarts[periph]->DR.DR = byte;
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
@ -145,7 +144,7 @@ const struct DmaParam* usart_configure_rx_dma(enum UsartPeriph periph)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
reg_set(usarts[periph]->CR3, USART_CR3_DMAR);
|
||||
usarts[periph]->CR3.DMAR = 1;
|
||||
return &usarts_rx_param[periph];
|
||||
}
|
||||
|
||||
@ -155,7 +154,7 @@ const struct DmaParam* usart_configure_tx_dma(enum UsartPeriph periph)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
reg_set(usarts[periph]->CR3, USART_CR3_DMAT);
|
||||
usarts[periph]->CR3.DMAT = 1;
|
||||
return &usarts_tx_param[periph];
|
||||
}
|
||||
|
||||
@ -176,19 +175,19 @@ static void configure_usart(volatile struct USART* regs,
|
||||
case USART_CONFIG_8E1:
|
||||
case USART_CONFIG_7E2:
|
||||
case USART_CONFIG_8E2:
|
||||
reg_set(regs->CR1, USART_CR1_PCE);
|
||||
reg_reset(regs->CR1, USART_CR1_PS);
|
||||
regs->CR1.PCE = 1;
|
||||
regs->CR1.PS = 0;
|
||||
break;
|
||||
case USART_CONFIG_7O1:
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8O1:
|
||||
case USART_CONFIG_8O2:
|
||||
reg_set(regs->CR1, USART_CR1_PCE);
|
||||
reg_set(regs->CR1, USART_CR1_PS);
|
||||
regs->CR1.PCE = 1;
|
||||
regs->CR1.PS = 1;
|
||||
break;
|
||||
case USART_CONFIG_8N1:
|
||||
case USART_CONFIG_8N2:
|
||||
reg_reset(regs->CR1, USART_CR1_PCE);
|
||||
regs->CR1.PCE = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -203,13 +202,13 @@ static void configure_usart(volatile struct USART* regs,
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8N1:
|
||||
case USART_CONFIG_8N2:
|
||||
reg_reset(regs->CR1, USART_CR1_M);
|
||||
regs->CR1.M = 0;
|
||||
break;
|
||||
case USART_CONFIG_8E2:
|
||||
case USART_CONFIG_8E1:
|
||||
case USART_CONFIG_8O1:
|
||||
case USART_CONFIG_8O2:
|
||||
reg_set(regs->CR1, USART_CR1_M);
|
||||
regs->CR1.M = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -223,24 +222,23 @@ static void configure_usart(volatile struct USART* regs,
|
||||
case USART_CONFIG_8N1:
|
||||
case USART_CONFIG_8E1:
|
||||
case USART_CONFIG_8O1:
|
||||
reg_reset(regs->CR2, USART_CR2_STOP);
|
||||
regs->CR2.STOP = 0;
|
||||
break;
|
||||
case USART_CONFIG_7E2:
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8N2:
|
||||
case USART_CONFIG_8E2:
|
||||
case USART_CONFIG_8O2:
|
||||
reg_reset(regs->CR2, USART_CR2_STOP);
|
||||
reg_write(regs->CR2, USART_CR2_STOP, 2);
|
||||
regs->CR2.STOP = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//enable Rx/Tx
|
||||
reg_set(regs->CR1, USART_CR1_TE);
|
||||
reg_set(regs->CR1, USART_CR1_RE);
|
||||
reg_set(regs->CR1, USART_CR1_UE);
|
||||
regs->CR1.TE = 1;
|
||||
regs->CR1.RE = 1;
|
||||
regs->CR1.UE = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -255,9 +253,7 @@ static void configure_baudrate(volatile struct USART* regs, uint32_t clock,
|
||||
uint32_t factor = clock / baudrate;
|
||||
volatile uint32_t divider = factor - (mantissa * 16);
|
||||
|
||||
reg_reset(regs->BRR, USART_BRR_DIV_Mantissa);
|
||||
reg_write(regs->BRR, USART_BRR_DIV_Mantissa, mantissa & 0xFFF);
|
||||
reg_reset(regs->BRR, USART_BRR_DIV_Fraction);
|
||||
reg_write(regs->BRR, USART_BRR_DIV_Fraction, divider & 0xF);
|
||||
regs->BRR.DIV_Mantissa = mantissa & 0xFFF;
|
||||
regs->BRR.DIV_Fraction = divider & 0xF;
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,6 @@
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
@ -23,7 +21,7 @@
|
||||
#define USART3_BASE_ADDRESS 0x40004800
|
||||
|
||||
union USART_SR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t PE:1;
|
||||
uint32_t FE:1;
|
||||
uint32_t NE:1;
|
||||
@ -39,31 +37,16 @@ union USART_SR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_SR_PE reg_def( 0, 1)
|
||||
#define USART_SR_FE reg_def( 1, 1)
|
||||
#define USART_SR_NE reg_def( 2, 1)
|
||||
#define USART_SR_ORE reg_def( 3, 1)
|
||||
#define USART_SR_IDLE reg_def( 4, 1)
|
||||
#define USART_SR_RXNE reg_def( 5, 1)
|
||||
#define USART_SR_TC reg_def( 6, 1)
|
||||
#define USART_SR_TXE reg_def( 7, 1)
|
||||
#define USART_SR_LBD reg_def( 8, 1)
|
||||
#define USART_SR_CTS reg_def( 9, 1)
|
||||
#define USART_SR_reserved1 reg_def(10, 22)
|
||||
|
||||
union USART_DR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t DR:9;
|
||||
uint32_t reserved1:23;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_DR_DR reg_def( 0, 9)
|
||||
#define USART_DR_reserved1 reg_def( 9, 23)
|
||||
|
||||
union USART_BRR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t DIV_Fraction:4;
|
||||
uint32_t DIV_Mantissa:12;
|
||||
uint32_t reserved1:16;
|
||||
@ -71,12 +54,8 @@ union USART_BRR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_BRR_DIV_Fraction reg_def( 0, 4)
|
||||
#define USART_BRR_DIV_Mantissa reg_def( 4, 12)
|
||||
#define USART_BRR_reserved1 reg_def(16, 16)
|
||||
|
||||
union USART_CR1 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t SBK:1;
|
||||
uint32_t RWU:1;
|
||||
uint32_t RE:1;
|
||||
@ -96,24 +75,8 @@ union USART_CR1 {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_CR1_SBK reg_def( 0, 1)
|
||||
#define USART_CR1_RWU reg_def( 1, 1)
|
||||
#define USART_CR1_RE reg_def( 2, 1)
|
||||
#define USART_CR1_TE reg_def( 3, 1)
|
||||
#define USART_CR1_IDLEIE reg_def( 4, 1)
|
||||
#define USART_CR1_RXNEIE reg_def( 5, 1)
|
||||
#define USART_CR1_TCIE reg_def( 6, 1)
|
||||
#define USART_CR1_TXEIE reg_def( 7, 1)
|
||||
#define USART_CR1_PEI reg_def( 8, 1)
|
||||
#define USART_CR1_PS reg_def( 9, 1)
|
||||
#define USART_CR1_PCE reg_def(10, 1)
|
||||
#define USART_CR1_WAKE reg_def(11, 1)
|
||||
#define USART_CR1_M reg_def(12, 1)
|
||||
#define USART_CR1_UE reg_def(13, 1)
|
||||
#define USART_CR1_reserved1 reg_def(14, 18)
|
||||
|
||||
union USART_CR2 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t ADD:4;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t LBDL:1;
|
||||
@ -130,21 +93,8 @@ union USART_CR2 {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_CR2_ADD reg_def( 0, 4)
|
||||
#define USART_CR2_reserved1 reg_def( 4, 1)
|
||||
#define USART_CR2_LBDL reg_def( 5, 1)
|
||||
#define USART_CR2_LBDIE reg_def( 6, 1)
|
||||
#define USART_CR2_reserved2 reg_def( 7, 1)
|
||||
#define USART_CR2_LBCL reg_def( 8, 1)
|
||||
#define USART_CR2_CPHA reg_def( 9, 1)
|
||||
#define USART_CR2_CPOL reg_def(10, 1)
|
||||
#define USART_CR2_CLKEN reg_def(11, 1)
|
||||
#define USART_CR2_STOP reg_def(12, 2)
|
||||
#define USART_CR2_LINEN reg_def(14, 1)
|
||||
#define USART_CR2_reserved3 reg_def(15, 17)
|
||||
|
||||
union USART_CR3 {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t EIE:1;
|
||||
uint32_t IREN:1;
|
||||
uint32_t IRLP:1;
|
||||
@ -161,21 +111,8 @@ union USART_CR3 {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_CR3_EIE reg_def( 0, 1)
|
||||
#define USART_CR3_IREN reg_def( 1, 1)
|
||||
#define USART_CR3_IRLP reg_def( 2, 1)
|
||||
#define USART_CR3_HDSEL reg_def( 3, 1)
|
||||
#define USART_CR3_NACK reg_def( 4, 1)
|
||||
#define USART_CR3_SCEN reg_def( 5, 1)
|
||||
#define USART_CR3_DMAR reg_def( 6, 1)
|
||||
#define USART_CR3_DMAT reg_def( 7, 1)
|
||||
#define USART_CR3_RTSE reg_def( 8, 1)
|
||||
#define USART_CR3_CTSE reg_def( 9, 1)
|
||||
#define USART_CR3_CTSIE reg_def(10, 1)
|
||||
#define USART_CR3_reserved3 reg_def(11, 21)
|
||||
|
||||
union USART_GTPR {
|
||||
struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t PSC:8;
|
||||
uint32_t GT:8;
|
||||
uint32_t reserved1:16;
|
||||
@ -183,10 +120,6 @@ union USART_GTPR {
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_GTPR_PSC reg_def( 0, 8)
|
||||
#define USART_GTPR_GT reg_def( 8, 8)
|
||||
#define USART_GTPR_reserved1 reg_def(16, 16)
|
||||
|
||||
struct USART {
|
||||
union USART_SR SR;
|
||||
union USART_DR DR;
|
||||
|
||||
25
openocd.cfg
Normal file
25
openocd.cfg
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
# using a STM32f103CB wich has 128kB of flash instead of the more common 64KB
|
||||
set CHIPNAME stm32f103CB
|
||||
set FLASH_SIZE 0x20000
|
||||
|
||||
# load default configurations
|
||||
source [find interface/stlink.cfg]
|
||||
source [find target/stm32f1x.cfg]
|
||||
|
||||
# override examine-end event
|
||||
$CHIPNAME.cpu configure -event examine-end {
|
||||
# write DBGMCU_CR, disable all peripherals (timers, dmas, watchdogs while
|
||||
# halted by debug. Trace is not affected
|
||||
mmw 0xE0042004 0x7E3FFF07 0
|
||||
}
|
||||
|
||||
|
||||
reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
# inits debugging, from that point, commands can be used
|
||||
init
|
||||
# resets the target and halt it immediately afterward. Stops debug from being
|
||||
# inacessible due to low-power states
|
||||
reset halt
|
||||
|
||||
23
srv/delay.c
Normal file
23
srv/delay.c
Normal file
@ -0,0 +1,23 @@
|
||||
/** @file delay.c
|
||||
* Module handling delays definitions and operations
|
||||
*
|
||||
* The module provides an API to delay the code execution with the most
|
||||
* accuraccy possible, putting the system in sleep whenever possible. The RTC is
|
||||
* required when using delays superior to a 1.5s. Accuraccy is only garenteed up
|
||||
* to the unit being used (to the millisecond when delaying in ms, to the second
|
||||
* when delaying in seconds)
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "delay.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
23
srv/delay.h
Normal file
23
srv/delay.h
Normal file
@ -0,0 +1,23 @@
|
||||
/** @file delay.h
|
||||
* Module handling delays definitions and operations
|
||||
*
|
||||
* The module provides an API to delay the code execution with the most
|
||||
* accuraccy possible, putting the system in sleep whenever possible. The RTC is
|
||||
* required when using delays superior to a 1.5s. Accuraccy is only garenteed up
|
||||
* to the unit being used (to the millisecond when delaying in ms, to the second
|
||||
* when delaying in seconds)
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H_
|
||||
#define _DELAY_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
//--internal_functions----------------------------------------------------------
|
||||
|
||||
#endif //_DELAY_H_
|
||||
|
||||
175
srv/task.c
Normal file
175
srv/task.c
Normal file
@ -0,0 +1,175 @@
|
||||
/** @file task.h
|
||||
* Module handling the task creation and management
|
||||
*
|
||||
* The module provides an API to create, run and manage lightweight, stack-less
|
||||
* threads (tasks). This system is based on protothreads,
|
||||
* see https://dunkels.com/adam/pt/index.html
|
||||
*
|
||||
* Task can be viewed as a lightweight, somewhat restricted, cooperative OS.
|
||||
* Tasks are runned on every events. Since the RTC is enabled by the scheduler,
|
||||
* every task should be run at least once per second. If at least one task is
|
||||
* currently paused, the systick is enabled and all tasks are updated every
|
||||
* millisecond
|
||||
*
|
||||
* State machine should mainly yield (see TASK_YIELD) while time sensitive
|
||||
* applications should pause (see TASK_PAUSE) instead. This configuration allows
|
||||
* state machines to be updated every time something changes in the system while
|
||||
* allowing the cpu to enter low power mode when possible. When time sensitive
|
||||
* applications are paused, they cause the systick to start which stops the cpu
|
||||
* from entering low power but making sure that the task is polled quickly
|
||||
* enough. Tasks requiring longer delay and less sensitive to timings can sleep
|
||||
* (see TASK_SLEEP) instead, which relies on the RTC rather than the systick
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "task.h"
|
||||
#include "error.h"
|
||||
#include "../drv/stk.h"
|
||||
#include "../drv/pwr.h"
|
||||
#include "../drv/rcc.h"
|
||||
#include "../drv/bkp.h"
|
||||
#include "../drv/exti.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
#define MAX_TASK_NB 10
|
||||
|
||||
static bool execute_task(struct Task* restrict task, uint8_t triggers);
|
||||
static void callback_stk(void);
|
||||
static void callback_rtc(void);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static struct Task task_list[MAX_TASK_NB];
|
||||
static uint8_t task_nb;
|
||||
static volatile bool stk_irq;
|
||||
static volatile bool rtc_irq;
|
||||
static volatile uint32_t timestamp;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void task_start_scheduler(void)
|
||||
{
|
||||
stk_configure(1000, callback_stk);
|
||||
|
||||
rcc_configure_lsi(true);
|
||||
pwr_configure_bkp_write(true);
|
||||
bkp_reset();
|
||||
bkp_configure_rtc(1000, BKP_RTC_CLOCK_SRC_LSI, BKP_RTC_IRQ_NONE, nullptr);
|
||||
pwr_configure_bkp_write(false);
|
||||
exti_configure(EXTI_LINE_RTC, EXTI_CONFIG_RISING_EDGE, callback_rtc);
|
||||
|
||||
while (true) {
|
||||
uint8_t triggers = stk_irq << 0 | rtc_irq << 1;
|
||||
stk_irq = false;
|
||||
rtc_irq = false;
|
||||
bool stk_needed = false;
|
||||
|
||||
for (uint8_t i = 0; i < task_nb; ++i) {
|
||||
stk_needed |= execute_task(&task_list[i], triggers);
|
||||
}
|
||||
|
||||
if (stk_needed) {
|
||||
stk_start();
|
||||
pwr_sleep();
|
||||
} else {
|
||||
pwr_configure_bkp_write(true);
|
||||
bkp_set_rtc_alam(1);
|
||||
pwr_configure_bkp_write(false);
|
||||
stk_stop();
|
||||
pwr_sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t task_current_time(void)
|
||||
{
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
void task_start(TaskFunction function)
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_TASK_NB; ++i) {
|
||||
if (task_list[i].function == nullptr) {
|
||||
|
||||
task_list[i].function = function;
|
||||
task_list[i].state.timestamp = 0;
|
||||
task_list[i].state.count = 0;
|
||||
|
||||
++task_nb;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error_trigger("task list is full");
|
||||
}
|
||||
|
||||
void task_stop(TaskFunction function)
|
||||
{
|
||||
for (uint8_t i = 0; i < task_nb; ++i) {
|
||||
if (task_list[i].function == function) {
|
||||
task_list[i].state.count = _TASK_COUNT_CLEANUP & 0x1F;
|
||||
task_list[i].function(&task_list[i].state, timestamp);
|
||||
task_list[i].function = nullptr;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error_trigger("task does not exist");
|
||||
}
|
||||
|
||||
bool task_is_running(TaskFunction function)
|
||||
{
|
||||
for (uint8_t i = 0; i < task_nb; ++i) {
|
||||
if (task_list[i].function == function) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
static bool execute_task(struct Task* restrict task, uint8_t triggers)
|
||||
{
|
||||
if (task->function != nullptr) {
|
||||
if (task->state.trigger == TASK_TRIGGER_ANY) {
|
||||
task->function(&task->state, timestamp);
|
||||
} else {
|
||||
if ((task->state.trigger & triggers) != 0) {
|
||||
|
||||
if (task->state.timestamp <= timestamp) {
|
||||
task->state.timestamp = 0;
|
||||
}
|
||||
|
||||
if ((task->state.timestamp == 0) ||
|
||||
task->state.timeout_mode) {
|
||||
task->function(&task->state,
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (task->state.trigger & TASK_TRIGGER_STK) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void callback_stk(void)
|
||||
{
|
||||
stk_irq = true;
|
||||
++timestamp;
|
||||
}
|
||||
|
||||
static void callback_rtc(void)
|
||||
{
|
||||
rtc_irq = true;
|
||||
timestamp = bkp_read_rtc() * 1000;
|
||||
}
|
||||
287
srv/task.h
Normal file
287
srv/task.h
Normal file
@ -0,0 +1,287 @@
|
||||
/** @file task.h
|
||||
* Module handling the task creation and management
|
||||
*
|
||||
* The module provides an API to create, run and manage lightweight, stack-less
|
||||
* threads (tasks). This system is based on protothreads,
|
||||
* see https://dunkels.com/adam/pt/index.html
|
||||
*
|
||||
* Task can be viewed as a lightweight, somewhat restricted, cooperative OS.
|
||||
* Tasks are runned on every events. Since the RTC is enabled by the scheduler,
|
||||
* every task should be run at least once per second. If at least one task is
|
||||
* currently paused, the systick is enabled and all tasks are updated every
|
||||
* millisecond
|
||||
*
|
||||
* State machine should mainly yield (see TASK_YIELD) while time sensitive
|
||||
* applications should pause (see TASK_PAUSE) instead. This configuration allows
|
||||
* state machines to be updated every time something changes in the system while
|
||||
* allowing the cpu to enter low power mode when possible. When time sensitive
|
||||
* applications are paused, they cause the systick to start which stops the cpu
|
||||
* from entering low power but making sure that the task is polled quickly
|
||||
* enough. Tasks requiring longer delay and less sensitive to timings can sleep
|
||||
* (see TASK_SLEEP) instead, which relies on the RTC rather than the systick
|
||||
*/
|
||||
|
||||
#ifndef _task_h_
|
||||
#define _task_h_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available triggers for a task
|
||||
*/
|
||||
enum TaskTrigger {
|
||||
TASK_TRIGGER_ANY,
|
||||
TASK_TRIGGER_STK,
|
||||
TASK_TRIGGER_RTC,
|
||||
TASK_TRIGGER_BOTH,
|
||||
};
|
||||
|
||||
/**
|
||||
* State of a task at any given time. Every single task is described by such a
|
||||
* struct
|
||||
*/
|
||||
struct TaskState {
|
||||
uint32_t timestamp; //timestamp at wich to wakeup the task, if any
|
||||
uint8_t count:5; //task counter: active step of task
|
||||
enum TaskTrigger trigger:2; //triggers on wich to execute the task
|
||||
uint8_t timeout_mode:1; //whether the timestamp is a timeout or a delay
|
||||
};
|
||||
|
||||
/**
|
||||
* Function prototype of tasks
|
||||
*/
|
||||
typedef void(*TaskFunction)(struct TaskState*, uint32_t);
|
||||
|
||||
/**
|
||||
* Full definition of a task. Contains the function supporting the task as well
|
||||
* as the state of said task
|
||||
*/
|
||||
struct Task {
|
||||
TaskFunction function;
|
||||
struct TaskState state;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Task declaration macro, to be used to declare and define a task instead of a
|
||||
* regular function declaration/defintion
|
||||
*/
|
||||
#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state, \
|
||||
uint32_t __task_time)
|
||||
|
||||
/**
|
||||
* Task entry macro, must be present at the begin of every task. Setup code to
|
||||
* be run indepently of the task state may be put before that (static variables,
|
||||
* init code, ...)
|
||||
*/
|
||||
#define TASK_ENTRY \
|
||||
_TASK_COUNT_INIT; \
|
||||
(void) __task_time; \
|
||||
switch (__task_state->count) {
|
||||
|
||||
/**
|
||||
* Task cleanup macro. Option, can be use right before TASK_EXIT. This step
|
||||
* will be executed before exiting the task when task_stop() is called. As the
|
||||
* name suggest, this is mainly usefull to implement cleanup code and allow for
|
||||
* gracefull shutdowns
|
||||
*/
|
||||
#define TASK_CLEANUP \
|
||||
case (_TASK_COUNT_CLEANUP): \
|
||||
/* fall through */
|
||||
|
||||
/**
|
||||
* Tasks exit macro, must be present at the end of every task. Any code written
|
||||
* after that will never be executed
|
||||
*/
|
||||
#define TASK_EXIT \
|
||||
} \
|
||||
__task_state->count = _TASK_COUNT_EXIT & 0x1F; \
|
||||
return;
|
||||
|
||||
/**
|
||||
* Returns whether the task was timed-out or not. This macro can be used after
|
||||
* TASK_PAUSE_UNTIL and TASK_SLEEP_UNTIL to know if the task resumed because of
|
||||
* the condition or because of the timeout. Does not correspond to anything
|
||||
* when called after any other step
|
||||
*/
|
||||
#define TASK_TIMEOUT (__task_state->timeout == 0)
|
||||
|
||||
/**
|
||||
* Give up the cpu, allowing the other tasks to run. The task will resume at the
|
||||
* next event. Between events, the cpu can enter various power saving states
|
||||
* depending on the other tasks running
|
||||
*/
|
||||
#define TASK_YIELD() _TASK_YIELD(_TASK_COUNT_INCR)
|
||||
|
||||
/**
|
||||
* Suspend the task for the specified amount of milliseconds. The systick will
|
||||
* remain active while the task is suspended to provide milliseconds counting,
|
||||
* limiting the ability of the cpu to save power
|
||||
*/
|
||||
#define TASK_PAUSE(delay_ms) _TASK_PAUSE(delay_ms, _TASK_COUNT_INCR)
|
||||
|
||||
/**
|
||||
* Suspend the task for the specified amount of seconds. The RTC will be used to
|
||||
* provide seconds counting. If no other tasks requires it, the systick is
|
||||
* disabled to save more power
|
||||
*/
|
||||
#define TASK_SLEEP(delay_s) _TASK_SLEEP(delay_s, _TASK_COUNT_INCR)
|
||||
|
||||
/**
|
||||
* Execute TASK_YIELD until the provided condition is reached. The condition
|
||||
* will be checked on every event
|
||||
*/
|
||||
#define TASK_YIELD_UNTIL(cond) _TASK_YIELD_UNTIL(cond, _TASK_COUNT_INCR)
|
||||
|
||||
/**
|
||||
* Execute TASK_PAUSE until either the condition or the delay is reached.
|
||||
* TASK_TIMEOUT can be used to know what cause the task to resume. The condition
|
||||
* will be checked every millisecond
|
||||
*/
|
||||
#define TASK_PAUSE_UNTIL(cond, delay_ms) \
|
||||
_TASK_PAUSE_UNTIL(cond, delay_ms, _TASK_COUNT_INCR)
|
||||
|
||||
/**
|
||||
* Execute TASK_SLEEP until either the condition or the delay is reached.
|
||||
* TASK_TIMEOUT can be used to know what cause the task to resume. The condition
|
||||
* will be checked every seconds
|
||||
*/
|
||||
#define TASK_SLEEP_UNTIL(cond, delay_s) \
|
||||
_TASK_SLEEP_UNTIL(cond, delay_s, _TASK_COUNT_INCR)
|
||||
|
||||
/**
|
||||
* Execute the specified task, suspending the current one until the task exits
|
||||
*/
|
||||
#define TASK_EXECUTE(task) _TASK_EXECUTE(task, _TASK_COUNT_INCR)
|
||||
|
||||
/**
|
||||
* Starts the task scheduler and run it until the system is shutdown. This
|
||||
* function never returns.
|
||||
*
|
||||
* All tasks started using task_start() are run according to their current
|
||||
* state (see TASK_* macros). Since this system is cooperative, the scheduler
|
||||
* does not preempt the tasks when running. The RTC is automatically configured
|
||||
* and started to provide events every seconds. The systick is automatically
|
||||
* started and stop to provide events every milliseconds when needed
|
||||
*/
|
||||
void task_start_scheduler(void);
|
||||
|
||||
/**
|
||||
* Returns the current system time. The epoc is undefined. The time is provided
|
||||
* in milliseconds, though the millisecond precision is only available while the
|
||||
* systick is running (at least one task paused)
|
||||
*/
|
||||
uint32_t task_current_time(void);
|
||||
|
||||
/**
|
||||
* Starts the specified task. The task will only trully be runned after
|
||||
* task_start_scheduler() is called.
|
||||
* A task already started will be left as-is
|
||||
*/
|
||||
void task_start(TaskFunction task);
|
||||
|
||||
/**
|
||||
* Stops the specified task. The task's cleanup state will be executed before
|
||||
* it exits
|
||||
*/
|
||||
void task_stop(TaskFunction task);
|
||||
|
||||
/**
|
||||
* Returns whether the specified task is currently running or not
|
||||
*/
|
||||
bool task_is_running(TaskFunction task);
|
||||
|
||||
|
||||
//--internal_functions----------------------------------------------------------
|
||||
|
||||
#define _TASK_COUNT_INIT enum { TASK_COUNTER_BASE = __COUNTER__ }
|
||||
#define _TASK_COUNT_INCR (uint8_t)(__COUNTER__ - TASK_COUNTER_BASE - 1)
|
||||
#define _TASK_COUNT_EXIT (UINT8_MAX & 0x3F)
|
||||
#define _TASK_COUNT_CLEANUP (UINT8_MAX - 1)
|
||||
|
||||
#define _TASK_YIELD(count_val) do { \
|
||||
__task_state->count = count_val; \
|
||||
__task_state->trigger = TASK_TRIGGER_ANY; \
|
||||
return; \
|
||||
case (count_val): \
|
||||
/* fall through */ \
|
||||
} while (0)
|
||||
|
||||
#define _TASK_PAUSE(delay_ms, count_val) do { \
|
||||
__task_state->count = count_val; \
|
||||
__task_state->timestamp = __task_time + delay_ms; \
|
||||
__task_state->trigger = TASK_TRIGGER_STK; \
|
||||
return; \
|
||||
case (count_val): \
|
||||
/* fall through */ \
|
||||
} while (0)
|
||||
|
||||
#define _TASK_SLEEP(delay_s, count_val) do { \
|
||||
__task_state->count = count_val; \
|
||||
__task_state->timestamp = __task_time + delay_s * 1000; \
|
||||
__task_state->trigger = TASK_TRIGGER_RTC; \
|
||||
return; \
|
||||
case (count_val): \
|
||||
/* fall through */ \
|
||||
} while (0)
|
||||
|
||||
#define _TASK_YIELD_UNTIL(cond, count_val) do { \
|
||||
__task_state->count = count_val; \
|
||||
__task_state->trigger = TASK_TRIGGER_ANY; \
|
||||
case (count_val): \
|
||||
if (!(cond)) { \
|
||||
return; \
|
||||
} \
|
||||
/* fall through */ \
|
||||
} while (0)
|
||||
|
||||
#define _TASK_PAUSE_UNTIL(cond, delay_ms, count_val) do { \
|
||||
__task_state->count = count_val; \
|
||||
__task_state->timestamp = __task_time + delay_ms; \
|
||||
__task_state->trigger = TASK_TRIGGER_STK; \
|
||||
__task_state->timeout_mode = true; \
|
||||
case (count_val): \
|
||||
if (!(cond) && __task_state->timestamp != 0) { \
|
||||
return; \
|
||||
} else { \
|
||||
__task_state->timeout_mode = false; \
|
||||
} \
|
||||
/* fall through */ \
|
||||
} while (0)
|
||||
|
||||
#define _TASK_SLEEP_UNTIL(cond, delay_s, count_val) do { \
|
||||
__task_state->count = count_val; \
|
||||
__task_state->timestamp = __taks_time + delay_s * 1000; \
|
||||
__task_state->trigger = TASK_TRIGGER_RTC; \
|
||||
__task_state->timeout_mode = true; \
|
||||
case (count_val): \
|
||||
if (!(cond) && __task_state->timestamp != 0) { \
|
||||
return; \
|
||||
} else { \
|
||||
__task_state->timeout_mode = false; \
|
||||
} \
|
||||
/* fall through */ \
|
||||
} while (0)
|
||||
|
||||
#define _TASK_EXECUTE(task, count_val) do { \
|
||||
__task_state->count = count_val; \
|
||||
__task_state->trigger = TASK_TRIGGER_ANY; \
|
||||
task_start(Task task); \
|
||||
return; \
|
||||
case (count_val): \
|
||||
if (task_is_running(task)) { \
|
||||
return; \
|
||||
} \
|
||||
/* fall through */ \
|
||||
} while (0)
|
||||
|
||||
#endif //_task_h_
|
||||
|
||||
Loading…
Reference in New Issue
Block a user