A while back, macros had to be put in place to avoid letting the compiler directly use the bitfields. This was necessary because the compiler used strb instruction which only write bytes. On the AHB bus, byte writes are transformed into word writes by repeating the byte, which caused mayhem in the registers. After a lot of research, turns out the packed attribute stops the compiler from does optimal (word) writes and isn't needed anyway. Removing them fixes the issue
91 lines
1.8 KiB
C
91 lines
1.8 KiB
C
/** @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();
|
|
}
|
|
|