Compare commits
6 Commits
80c027370b
...
a4ca0d30c3
| Author | SHA1 | Date | |
|---|---|---|---|
| a4ca0d30c3 | |||
| 89c81b8c42 | |||
| 24e412446d | |||
| 7ab6622908 | |||
| ba9bc57a49 | |||
| 947df53ecb |
30
drv/bkp.c
30
drv/bkp.c
@ -1,6 +1,11 @@
|
||||
/** @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--------------------------------------------------------------------
|
||||
@ -28,7 +33,7 @@ static BkpRtcCallback rtc_callback;
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
|
||||
enum BkpRtcIrq irq_mask, uint32_t alarm_tick, BkpRtcCallback callback)
|
||||
enum BkpRtcIrq irq_mask, BkpRtcCallback callback)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE);
|
||||
|
||||
@ -50,8 +55,6 @@ void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
|
||||
//configure core registers
|
||||
rtc_regs->PRLH.PRL = prescaler >> 16;
|
||||
rtc_regs->PRLL.PRL = prescaler;
|
||||
rtc_regs->ALRH.RTC_ALR = alarm_tick >> 16;
|
||||
rtc_regs->ALRL.RTC_ALR = alarm_tick;
|
||||
|
||||
//apply irq config
|
||||
rtc_regs->CRH.word |= irq_mask & 0x7;
|
||||
@ -68,6 +71,27 @@ void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
23
drv/bkp.h
23
drv/bkp.h
@ -1,6 +1,11 @@
|
||||
/** @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_
|
||||
@ -58,11 +63,23 @@ typedef void (*BkpRtcCallback)(enum BkpRtcIrq src);
|
||||
* 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 specified tick value can be rerouted to an exti line
|
||||
* for wakeup from stanby, in wich case it doesn't need to be enabled here.
|
||||
* 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, uint32_t alarm_tick, BkpRtcCallback callback);
|
||||
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
|
||||
|
||||
71
drv/exti.c
71
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-------------------------------------------------------------
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
20
srv/task.c
20
srv/task.c
@ -26,6 +26,10 @@
|
||||
#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-----------------------------------------------------------
|
||||
@ -51,7 +55,13 @@ static volatile uint32_t timestamp;
|
||||
void task_start_scheduler(void)
|
||||
{
|
||||
stk_configure(1000, callback_stk);
|
||||
//TODO: configure RTC
|
||||
|
||||
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;
|
||||
@ -65,10 +75,13 @@ void task_start_scheduler(void)
|
||||
|
||||
if (stk_needed) {
|
||||
stk_start();
|
||||
__asm("wfi");
|
||||
pwr_sleep();
|
||||
} else {
|
||||
pwr_configure_bkp_write(true);
|
||||
bkp_set_rtc_alam(1);
|
||||
pwr_configure_bkp_write(false);
|
||||
stk_stop();
|
||||
//TODO: enter deep sleep
|
||||
pwr_sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,4 +171,5 @@ static void callback_stk(void)
|
||||
static void callback_rtc(void)
|
||||
{
|
||||
rtc_irq = true;
|
||||
timestamp = bkp_read_rtc() * 1000;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user