Compare commits

..

No commits in common. "a4ca0d30c3cfc1668943adbebdf947d95de99848" and "80c027370b4102f876ae0a07cdcd8d2cb1a0dee4" have entirely different histories.

6 changed files with 110 additions and 122 deletions

View File

@ -1,11 +1,6 @@
/** @file bkp.c /** @file bkp.c
* Module handling the Backup (BKP) domain functionalities. * 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-------------------------------------------------------------------- //--includes--------------------------------------------------------------------
@ -33,7 +28,7 @@ static BkpRtcCallback rtc_callback;
//--public functions------------------------------------------------------------ //--public functions------------------------------------------------------------
void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src, void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
enum BkpRtcIrq irq_mask, BkpRtcCallback callback) enum BkpRtcIrq irq_mask, uint32_t alarm_tick, BkpRtcCallback callback)
{ {
rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE); rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE);
@ -55,6 +50,8 @@ void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
//configure core registers //configure core registers
rtc_regs->PRLH.PRL = prescaler >> 16; rtc_regs->PRLH.PRL = prescaler >> 16;
rtc_regs->PRLL.PRL = prescaler; rtc_regs->PRLL.PRL = prescaler;
rtc_regs->ALRH.RTC_ALR = alarm_tick >> 16;
rtc_regs->ALRL.RTC_ALR = alarm_tick;
//apply irq config //apply irq config
rtc_regs->CRH.word |= irq_mask & 0x7; rtc_regs->CRH.word |= irq_mask & 0x7;
@ -71,27 +68,6 @@ 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) uint32_t bkp_read_rtc(void)
{ {
//wait for core registers to be synchronized, immediate most of the time //wait for core registers to be synchronized, immediate most of the time

View File

@ -1,11 +1,6 @@
/** @file bkp.h /** @file bkp.h
* Module handling the Backup (BKP) domain functionalities. * 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_ #ifndef _BKP_H_
@ -63,23 +58,11 @@ typedef void (*BkpRtcCallback)(enum BkpRtcIrq src);
* Clocks must be enabled prior to calling this function * Clocks must be enabled prior to calling this function
* *
* Mulitple IRQs can be enabled and redirected to single callback. The alarm * 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 * IRQ, triggered at the specified tick value can be rerouted to an exti line
* rerouted to an exti line for wakeup from stop and standby, in wich case it * for wakeup from stanby, in wich case it doesn't need to be enabled here.
* 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, void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
enum BkpRtcIrq irq_mask, BkpRtcCallback callback); enum BkpRtcIrq irq_mask, uint32_t alarm_tick, 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 * Returns the current counter value of the RTC

View File

@ -11,6 +11,7 @@
#include "exti_regs.h" #include "exti_regs.h"
#include "nvic.h" #include "nvic.h"
#include "afio.h"
//--local definitions----------------------------------------------------------- //--local definitions-----------------------------------------------------------
@ -23,11 +24,13 @@ static ExtiCallback callbacks[19];
//--public functions------------------------------------------------------------ //--public functions------------------------------------------------------------
void exti_configure(enum ExtiLine line_mask, enum ExtiConfig config_mask, void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
ExtiCallback callback) enum ExtiConfig config_mask, ExtiCallback callback)
{ {
exti_reset(line_mask); exti_reset(line_mask);
afio_map_exti(line_mask, port);
//configure edge detections //configure edge detections
if (config_mask & EXTI_CONFIG_RISING_EDGE) { if (config_mask & EXTI_CONFIG_RISING_EDGE) {
regs->RTSR.word |= line_mask; regs->RTSR.word |= line_mask;
@ -45,7 +48,7 @@ void exti_configure(enum ExtiLine line_mask, enum ExtiConfig config_mask,
regs->EMR.word |= line_mask; regs->EMR.word |= line_mask;
if (callback) { if (callback) {
//register callbacks for each line selected //register callbacks for each line selected
for (uint8_t i = 0; i < 19; ++i) { for (uint8_t i = 0; i < 16; ++i) {
if (line_mask & (0x1 << i)) { if (line_mask & (0x1 << i)) {
callbacks[i] = callback; callbacks[i] = callback;
} }
@ -63,15 +66,6 @@ void exti_configure(enum ExtiLine line_mask, enum ExtiConfig config_mask,
if (line_mask & 0x7c00) { if (line_mask & 0x7c00) {
nvic_enable(NVIC_IRQ_EXTI15_10); 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 //enable irqs in last to avoid triggers during config
regs->IMR.word |= line_mask; regs->IMR.word |= line_mask;
@ -100,6 +94,56 @@ void exti_reset(enum ExtiLine line_mask)
nvic_disable(NVIC_IRQ_EXTI15_10); 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 //disable events/irqs
regs->IMR.word &= ~line_mask; regs->IMR.word &= ~line_mask;
regs->EMR.word &= ~line_mask; regs->EMR.word &= ~line_mask;
@ -119,7 +163,6 @@ void exti_reset(enum ExtiLine line_mask)
} }
} }
void exti_reset_peripheral(void) void exti_reset_peripheral(void)
{ {
//reset peripheral config //reset peripheral config
@ -139,6 +182,8 @@ void exti_reset_peripheral(void)
nvic_disable(NVIC_IRQ_PVD); nvic_disable(NVIC_IRQ_PVD);
nvic_disable(NVIC_IRQ_RTC_ALARM); nvic_disable(NVIC_IRQ_RTC_ALARM);
nvic_disable(NVIC_IRQ_USB_WAKEUP); nvic_disable(NVIC_IRQ_USB_WAKEUP);
afio_map_exti(0xFFFF, 0x0);
} }
//--local functions------------------------------------------------------------- //--local functions-------------------------------------------------------------

View File

@ -10,11 +10,16 @@
//--includes-------------------------------------------------------------------- //--includes--------------------------------------------------------------------
#include "stdint.h"
#include "stdbool.h"
#include "gpio.h"
//--type definitions------------------------------------------------------------ //--type definitions------------------------------------------------------------
/** /**
* Available exti lines. The numbered lines correspond to gpios while the * Available exti lines. These lines correspond to gpios
* remaining are directly mapped to peripherals
*/ */
enum ExtiLine { enum ExtiLine {
EXTI_LINE_0 = (0x1 << 0), EXTI_LINE_0 = (0x1 << 0),
@ -33,6 +38,12 @@ enum ExtiLine {
EXTI_LINE_13 = (0x1 << 13), EXTI_LINE_13 = (0x1 << 13),
EXTI_LINE_14 = (0x1 << 14), EXTI_LINE_14 = (0x1 << 14),
EXTI_LINE_15 = (0x1 << 15), EXTI_LINE_15 = (0x1 << 15),
};
/**
* Available exti lines. These lines correspond to specific peripherals
*/
enum ExtiLineSpecific {
EXTI_LINE_PVD = (0x1 << 16), EXTI_LINE_PVD = (0x1 << 16),
EXTI_LINE_RTC = (0x1 << 17), EXTI_LINE_RTC = (0x1 << 17),
EXTI_LINE_USB = (0x1 << 18), EXTI_LINE_USB = (0x1 << 18),
@ -53,31 +64,43 @@ typedef void (*ExtiCallback)(void);
//--functions------------------------------------------------------------------- //--functions-------------------------------------------------------------------
/** /**
* Configure lines to call a single callback. The ExtiLine enum can be used as a * Configure lines on a single GPIO port. The ExtiLine enum can be used as a
* mask to configure multiple lines at the same time. * 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.
* *
* Every numbered line must be linked to a gpio port using afio_map_exti(). Each * Note: wich port is linked to a line can be changed atfer the fact using
* line is linked to the pins of the same id (ex : pin 1 for exti 1). When * afio_map_exti()
* 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 ExtiConfig config_mask, void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
ExtiCallback callback); enum ExtiConfig config_mask, ExtiCallback callback);
/** /**
* Resets lines. The ExtiLine enum can be used as a mask to reset multiple lines * Resets lines. The ExtiLine enum can be used as a mask to configure multiple
* at the same time * lines at the same time
*/ */
void exti_reset(enum ExtiLine line_mask); 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 * Resets all lines. The exti peripheral is returned to its reset configuration
*/ */

View File

@ -1,25 +0,0 @@
# 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

View File

@ -26,10 +26,6 @@
#include "task.h" #include "task.h"
#include "error.h" #include "error.h"
#include "../drv/stk.h" #include "../drv/stk.h"
#include "../drv/pwr.h"
#include "../drv/rcc.h"
#include "../drv/bkp.h"
#include "../drv/exti.h"
//--local definitions----------------------------------------------------------- //--local definitions-----------------------------------------------------------
@ -55,13 +51,7 @@ static volatile uint32_t timestamp;
void task_start_scheduler(void) void task_start_scheduler(void)
{ {
stk_configure(1000, callback_stk); 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) { while (true) {
uint8_t triggers = stk_irq << 0 | rtc_irq << 1; uint8_t triggers = stk_irq << 0 | rtc_irq << 1;
@ -75,13 +65,10 @@ void task_start_scheduler(void)
if (stk_needed) { if (stk_needed) {
stk_start(); stk_start();
pwr_sleep(); __asm("wfi");
} else { } else {
pwr_configure_bkp_write(true);
bkp_set_rtc_alam(1);
pwr_configure_bkp_write(false);
stk_stop(); stk_stop();
pwr_sleep(); //TODO: enter deep sleep
} }
} }
} }
@ -171,5 +158,4 @@ static void callback_stk(void)
static void callback_rtc(void) static void callback_rtc(void)
{ {
rtc_irq = true; rtc_irq = true;
timestamp = bkp_read_rtc() * 1000;
} }