Harmonize stm32 ticks and sleep (#1673)

machine/stm32f*: move to harmonized tick / sleep logic code
Этот коммит содержится в:
kenbell 2021-03-18 03:54:15 -07:00 коммит произвёл GitHub
родитель 5a4dcfb367
коммит b0b84c48ec
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 446 добавлений и 792 удалений

201
src/runtime/runtime_stm32_timers.go Обычный файл
Просмотреть файл

@ -0,0 +1,201 @@
// +build stm32
package runtime
// This file implements a common implementation of implementing 'ticks' and 'sleep' for STM32 devices. The
// implementation uses two 'basic' timers, so should be compatible with a broad range of STM32 MCUs.
//
// This implementation is of 'sleep' is for running in a normal power mode. Use of the RTC to enter and
// resume from low-power states is out of scope.
//
// Interface
// ---------
// For each MCU, the following constants should be defined:
// TICK_RATE The desired frequency of ticks, e.g. 1000 for 1KHz ticks
// TICK_TIMER_IRQ Which timer to use for counting ticks (e.g. stm32.IRQ_TIM7)
// TICK_TIMER_FREQ The frequency the clock feeding the sleep timer is set to (e.g. 84MHz)
// SLEEP_TIMER_IRQ Which timer to use for sleeping (e.g. stm32.IRQ_TIM3)
// SLEEP_TIMER_FREQ The frequency the clock feeding the sleep timer is set to (e.g. 84MHz)
//
// The type alias `arrtype` should be defined to either uint32 or uint16 depending on the
// size of that register in the MCU's TIM_Type structure
import (
"device/stm32"
"runtime/interrupt"
"runtime/volatile"
)
type timerInfo struct {
EnableRegister *volatile.Register32
EnableFlag uint32
Device *stm32.TIM_Type
}
const (
TICKS_PER_NS = 1000000000 / TICK_RATE
)
var (
// Tick count since boot
tickCount volatile.Register64
// The timer used for counting ticks
tickTimer *timerInfo
// The timer used for sleeping
sleepTimer *timerInfo
)
func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * TICKS_PER_NS
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns / TICKS_PER_NS)
}
// number of ticks (microseconds) since start.
func ticks() timeUnit {
return timeUnit(tickCount.Get())
}
//
// -- Ticks ---
//
// Enable the timer used to count ticks
func initTickTimer(ti *timerInfo) {
tickTimer = ti
ti.EnableRegister.SetBits(ti.EnableFlag)
psc := uint32(TICK_TIMER_FREQ / TICK_RATE)
period := uint32(1)
// Get the pre-scale into range, with interrupt firing
// once per tick.
for psc > 0x10000 || period == 1 {
psc >>= 1
period <<= 1
}
// Clamp overflow
if period > 0x10000 {
period = 0x10000
}
ti.Device.PSC.Set(psc - 1)
ti.Device.ARR.Set(arrtype(period - 1))
// Auto-repeat
ti.Device.EGR.SetBits(stm32.TIM_EGR_UG)
// Register the interrupt handler
intr := interrupt.New(TICK_TIMER_IRQ, handleTick)
intr.SetPriority(0xc1)
intr.Enable()
// Clear update flag
ti.Device.SR.ClearBits(stm32.TIM_SR_UIF)
// Enable the hardware interrupt
ti.Device.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer
ti.Device.CR1.SetBits(stm32.TIM_CR1_CEN)
}
func handleTick(interrupt.Interrupt) {
if tickTimer.Device.SR.HasBits(stm32.TIM_SR_UIF) {
// clear the update flag
tickTimer.Device.SR.ClearBits(stm32.TIM_SR_UIF)
// increment tick count
tickCount.Set(tickCount.Get() + 1)
}
}
//
// --- Sleep ---
//
func sleepTicks(d timeUnit) {
// If there is a scheduler, we sleep until any kind of CPU event up to
// a maximum of the requested sleep duration.
//
// The scheduler will call again if there is nothing to do and a further
// sleep is required.
if hasScheduler {
timerSleep(ticksToNanoseconds(d))
return
}
// There's no scheduler, so we sleep until at least the requested number
// of ticks has passed.
end := ticks() + d
for ticks() < end {
timerSleep(ticksToNanoseconds(d))
}
}
// Enable the Sleep clock
func initSleepTimer(ti *timerInfo) {
sleepTimer = ti
ti.EnableRegister.SetBits(ti.EnableFlag)
// No auto-repeat
ti.Device.EGR.SetBits(stm32.TIM_EGR_UG)
// Enable the hardware interrupt.
ti.Device.DIER.SetBits(stm32.TIM_DIER_UIE)
intr := interrupt.New(SLEEP_TIMER_IRQ, handleSleep)
intr.SetPriority(0xc3)
intr.Enable()
}
// timerSleep sleeps for 'at most' ns nanoseconds, but possibly less.
func timerSleep(ns int64) {
// Calculate initial pre-scale value.
// delay (in ns) and clock freq are both large values, so do the nanosecs
// conversion (divide by 1G) by pre-dividing each by 1000 to avoid overflow
// in any meaningful time period.
psc := ((ns / 1000) * (SLEEP_TIMER_FREQ / 1000)) / 1000
period := int64(1)
// Get the pre-scale into range, with interrupt firing
// once per tick.
for psc > 0x10000 || period == 1 {
psc >>= 1
period <<= 1
}
// Clamp overflow
if period > 0x10000 {
period = 0x10000
}
// Set the desired duration and enable
sleepTimer.Device.PSC.Set(uint32(psc) - 1)
sleepTimer.Device.ARR.Set(arrtype(period) - 1)
sleepTimer.Device.CR1.SetBits(stm32.TIM_CR1_CEN)
// Wait till either the timer or some other event wakes
// up the CPU
waitForEvents()
// In case it was not the sleep timer that woke the
// CPU, disable the timer now.
disableSleepTimer()
}
func handleSleep(interrupt.Interrupt) {
disableSleepTimer()
}
func disableSleepTimer() {
// Disable and clear the update flag.
sleepTimer.Device.CR1.ClearBits(stm32.TIM_CR1_CEN)
sleepTimer.Device.SR.ClearBits(stm32.TIM_SR_UIF)
}

Просмотреть файл

@ -3,18 +3,45 @@
package runtime package runtime
import ( import (
"device/arm"
"device/stm32" "device/stm32"
"machine" "machine"
"runtime/interrupt"
"runtime/volatile"
) )
/*
timer settings used for tick and sleep.
note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
settings configured in initCLK, so must be kept in sync if the clock settings
are changed.
*/
const (
TICK_RATE = 1000 // 1 KHz
SLEEP_TIMER_IRQ = stm32.IRQ_TIM3
SLEEP_TIMER_FREQ = 72000000 // 72 MHz
TICK_TIMER_IRQ = stm32.IRQ_TIM4
TICK_TIMER_FREQ = 72000000 // 72 MHz
)
type arrtype = uint32
const asyncScheduler = false
func init() { func init() {
initCLK() initCLK()
initRTC()
initTIM() initSleepTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM3EN,
Device: stm32.TIM3,
})
machine.UART0.Configure(machine.UARTConfig{}) machine.UART0.Configure(machine.UARTConfig{})
initTickTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM4EN,
Device: stm32.TIM4,
})
} }
func putchar(c byte) { func putchar(c byte) {
@ -52,157 +79,3 @@ func initCLK() {
for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) { for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) {
} }
} }
var (
timestamp timeUnit // microseconds since boottime
timerLastCounter uint64
)
var timerWakeup volatile.Register8
func initRTC() {
// Enable the PWR and BKP.
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN | stm32.RCC_APB1ENR_BKPEN)
// access to backup register
stm32.PWR.CR.SetBits(stm32.PWR_CR_DBP)
// Enable LSE
stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_LSEON)
// wait until LSE is ready
for !stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSERDY) {
}
// Select LSE
stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_RTCSEL_LSE << stm32.RCC_BDCR_RTCSEL_Pos)
// set prescaler to "max" per datasheet
stm32.RTC.PRLH.Set(stm32.RTC_PRLH_PRLH_Msk)
stm32.RTC.PRLL.Set(stm32.RTC_PRLL_PRLL_Msk)
// set count to zero
stm32.RTC.CNTH.Set(0x0)
stm32.RTC.CNTL.Set(0x0)
// Enable RTC
stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_RTCEN)
// Clear RSF
stm32.RTC.CRL.ClearBits(stm32.RTC_CRL_RSF)
// Wait till flag is set
for !stm32.RTC.CRL.HasBits(stm32.RTC_CRL_RSF) {
}
}
// Enable the TIM3 clock.
func initTIM() {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
intr := interrupt.New(stm32.IRQ_TIM3, handleTIM3)
intr.SetPriority(0xc3)
intr.Enable()
}
const asyncScheduler = false
func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * 1000
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns / 1000)
}
// sleepTicks should sleep for specific number of microseconds.
func sleepTicks(d timeUnit) {
for d != 0 {
ticks() // update timestamp
ticks := uint32(d) // current scaling only supports 100 usec to 6553 msec
timerSleep(ticks)
d -= timeUnit(ticks)
}
}
// number of ticks (microseconds) since start.
func ticks() timeUnit {
// convert RTC counter from seconds to microseconds
timerCounter := uint64(stm32.RTC.CNTH.Get()<<16|stm32.RTC.CNTL.Get()) * 1000 * 1000
// add the fractional part of current time using DIV register
timerCounter += uint64(0x8000-stm32.RTC.DIVL.Get()) * 31
// change since last measurement
offset := (timerCounter - timerLastCounter)
timerLastCounter = timerCounter
timestamp += timeUnit(offset)
return timestamp
}
// ticks are in microseconds
func timerSleep(ticks uint32) {
timerWakeup.Set(0)
// STM32 timer update event period is calculated as follows:
//
// Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)*(RCR + 1))
//
// Where:
//
// TIM_CLK = timer clock input
// PSC = 16-bit prescaler register
// ARR = 16/32-bit Autoreload register
// RCR = 16-bit repetition counter
//
// Example:
//
// TIM_CLK = 72 MHz
// Prescaler = 1
// Auto reload = 65535
// No repetition counter RCR = 0
// Update_event = 72*(10^6)/((1 + 1)*(65535 + 1)*(1))
// Update_event = 549.3 Hz
//
// Set the timer prescaler/autoreload timing registers.
// TODO: support smaller or larger scales (autoscaling) based
// on the length of sleep time requested.
// The current scaling only supports a range of 200 usec to 6553 msec.
// prescale counter down from 72mhz to 10khz aka 0.1 ms frequency.
stm32.TIM3.PSC.Set(machine.CPUFrequency()/10000 - 1) // 7199
// Set duty aka duration.
// STM32 dividers use n-1, i.e. n counts from 0 to n-1.
// As a result, with these prescaler settings,
// the minimum allowed duration is 200 microseconds.
if ticks < 200 {
ticks = 200
}
stm32.TIM3.ARR.Set(ticks/100 - 1) // convert from microseconds to 0.1 ms
// Enable the hardware interrupt.
stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN)
// wait till timer wakes up
for timerWakeup.Get() == 0 {
arm.Asm("wfi")
}
}
func handleTIM3(interrupt.Interrupt) {
if stm32.TIM3.SR.HasBits(stm32.TIM_SR_UIF) {
// Disable the timer.
stm32.TIM3.CR1.ClearBits(stm32.TIM_CR1_CEN)
// clear the update flag
stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF)
// timer was triggered
timerWakeup.Set(1)
}
}

Просмотреть файл

@ -3,20 +3,10 @@
package runtime package runtime
import ( import (
"device/arm"
"device/stm32" "device/stm32"
"machine" "machine"
"runtime/interrupt"
"runtime/volatile"
) )
func init() {
initOSC() // configure oscillators
initCLK() // configure CPU, AHB, and APB bus clocks
initTIM() // configure timers
initCOM() // configure serial comm interfaces
}
const ( const (
// +----------------------+ // +----------------------+
// | Clock Settings | // | Clock Settings |
@ -74,6 +64,43 @@ const (
FLASH_OPTIONS = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | stm32.FLASH_ACR_PRFTEN FLASH_OPTIONS = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | stm32.FLASH_ACR_PRFTEN
) )
/*
timer settings used for tick and sleep.
note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
settings above, so must be kept in sync if the clock settings are changed.
*/
const (
TICK_RATE = 1000 // 1 KHz
SLEEP_TIMER_IRQ = stm32.IRQ_TIM3
SLEEP_TIMER_FREQ = PCLK1_FREQ_HZ * 2
TICK_TIMER_IRQ = stm32.IRQ_TIM7
TICK_TIMER_FREQ = PCLK1_FREQ_HZ * 2
)
type arrtype = uint32
const asyncScheduler = false
func init() {
initOSC() // configure oscillators
initCLK()
initSleepTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM3EN,
Device: stm32.TIM3,
})
initCOM()
initTickTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM7EN,
Device: stm32.TIM7,
})
}
func initOSC() { func initOSC() {
// enable voltage regulator // enable voltage regulator
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
@ -154,95 +181,12 @@ func initCLK() {
stm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM) stm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM)
} }
func initTIM() {
// enable sleep counter (TIM3)
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
tim3 := interrupt.New(stm32.IRQ_TIM3, handleTIM3)
tim3.SetPriority(0xC3)
tim3.Enable()
// enable tick counter (TIM7)
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)
stm32.TIM7.PSC.Set((PCLK1_FREQ_HZ*2)/10000 - 1) // 84mhz to 10khz(0.1ms)
stm32.TIM7.ARR.Set(10 - 1) // interrupt per 1ms
stm32.TIM7.DIER.SetBits(stm32.TIM_DIER_UIE) // enable interrupt
stm32.TIM7.CR1.SetBits(stm32.TIM_CR1_CEN) // enable timer
tim7 := interrupt.New(stm32.IRQ_TIM7, handleTIM7)
tim7.SetPriority(0xC1)
tim7.Enable()
}
func initCOM() { func initCOM() {
if machine.NUM_UART_INTERFACES > 0 { if machine.NUM_UART_INTERFACES > 0 {
machine.UART0.Configure(machine.UARTConfig{}) machine.UART0.Configure(machine.UARTConfig{})
} }
} }
var (
// tick in milliseconds
tickCount timeUnit
timerWakeup volatile.Register8
)
const asyncScheduler = false
func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * 1000
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns / 1000)
}
// sleepTicks should sleep for specific number of microseconds.
func sleepTicks(d timeUnit) {
timerSleep(uint32(d))
}
// number of ticks (microseconds) since start.
func ticks() timeUnit {
return tickCount * 1000 // milliseconds to microseconds
}
// ticks are in microseconds
func timerSleep(ticks uint32) {
timerWakeup.Set(0)
stm32.TIM3.PSC.Set((PCLK1_FREQ_HZ*2)/10000 - 1) // 8399
arr := (ticks / 100) - 1 // microseconds to 0.1 ms
if arr == 0 {
arr = 1 // avoid blocking
}
stm32.TIM3.ARR.Set(arr)
stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE) // enable interrupt
stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN) // enable the timer
// wait for timer
for timerWakeup.Get() == 0 {
arm.Asm("wfi")
}
}
func handleTIM3(interrupt.Interrupt) {
if stm32.TIM3.SR.HasBits(stm32.TIM_SR_UIF) {
stm32.TIM3.CR1.ClearBits(stm32.TIM_CR1_CEN) // disable the timer
stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF) // clear the update flag
timerWakeup.Set(1) // flag timer ISR
}
}
func handleTIM7(interrupt.Interrupt) {
if stm32.TIM7.SR.HasBits(stm32.TIM_SR_UIF) {
stm32.TIM7.SR.ClearBits(stm32.TIM_SR_UIF) // clear the update flag
tickCount++
}
}
func putchar(c byte) { func putchar(c byte) {
machine.UART0.WriteByte(c) machine.UART0.WriteByte(c)
} }

Просмотреть файл

@ -3,31 +3,8 @@
package runtime package runtime
import ( import (
"device/arm"
"device/stm32" "device/stm32"
"machine" "machine"
"runtime/interrupt"
"runtime/volatile"
)
func init() {
initCLK()
initTIM3()
machine.UART0.Configure(machine.UARTConfig{})
initTIM7()
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
const (
HSE_STARTUP_TIMEOUT = 0x0500
/* PLL Options - See RM0090 Reference Manual pg. 95 */
PLL_M = 8 /* PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N */
PLL_N = 336
PLL_P = 2 /* SYSCLK = PLL_VCO / PLL_P */
PLL_Q = 7 /* USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q */
) )
/* /*
@ -40,8 +17,56 @@ const (
| APB1(PCLK1) | 42mhz | | APB1(PCLK1) | 42mhz |
+-------------+--------+ +-------------+--------+
*/ */
func initCLK() { const (
HSE_STARTUP_TIMEOUT = 0x0500
// PLL Options - See RM0090 Reference Manual pg. 95
PLL_M = 8 // PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N
PLL_N = 336
PLL_P = 2 // SYSCLK = PLL_VCO / PLL_P
PLL_Q = 7 // USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q
)
/*
timer settings used for tick and sleep.
note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
settings above, so must be kept in sync if the clock settings are changed.
*/
const (
TICK_RATE = 1000 // 1 KHz
TICK_TIMER_IRQ = stm32.IRQ_TIM7
TICK_TIMER_FREQ = 84000000 // 84 MHz
SLEEP_TIMER_IRQ = stm32.IRQ_TIM3
SLEEP_TIMER_FREQ = 84000000 // 84 MHz
)
type arrtype = uint32
const asyncScheduler = false
func init() {
initCLK()
initSleepTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM3EN,
Device: stm32.TIM3,
})
machine.UART0.Configure(machine.UARTConfig{})
initTickTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM7EN,
Device: stm32.TIM7,
})
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
func initCLK() {
// Reset clock registers // Reset clock registers
// Set HSION // Set HSION
stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION)
@ -104,111 +129,7 @@ func initCLK() {
for { for {
} }
} }
// Enable the CCM RAM clock // Enable the CCM RAM clock
stm32.RCC.AHB1ENR.SetBits(1 << 20) stm32.RCC.AHB1ENR.SetBits(1 << 20)
}
var (
// tick in milliseconds
tickCount timeUnit
)
var timerWakeup volatile.Register8
func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * 1000
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns / 1000)
}
// Enable the TIM3 clock.(sleep count)
func initTIM3() {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
intr := interrupt.New(stm32.IRQ_TIM3, handleTIM3)
intr.SetPriority(0xc3)
intr.Enable()
}
// Enable the TIM7 clock.(tick count)
func initTIM7() {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)
// CK_INT = APB1 x2 = 84mhz
stm32.TIM7.PSC.Set(84000000/10000 - 1) // 84mhz to 10khz(0.1ms)
stm32.TIM7.ARR.Set(10 - 1) // interrupt per 1ms
// Enable the hardware interrupt.
stm32.TIM7.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM7.CR1.SetBits(stm32.TIM_CR1_CEN)
intr := interrupt.New(stm32.IRQ_TIM7, handleTIM7)
intr.SetPriority(0xc1)
intr.Enable()
}
const asyncScheduler = false
// sleepTicks should sleep for specific number of microseconds.
func sleepTicks(d timeUnit) {
timerSleep(uint32(d))
}
// number of ticks (microseconds) since start.
func ticks() timeUnit {
// milliseconds to microseconds
return tickCount * 1000
}
// ticks are in microseconds
func timerSleep(ticks uint32) {
timerWakeup.Set(0)
// CK_INT = APB1 x2 = 84mhz
// prescale counter down from 84mhz to 10khz aka 0.1 ms frequency.
stm32.TIM3.PSC.Set(84000000/10000 - 1) // 8399
// set duty aka duration
arr := (ticks / 100) - 1 // convert from microseconds to 0.1 ms
if arr == 0 {
arr = 1 // avoid blocking
}
stm32.TIM3.ARR.Set(arr)
// Enable the hardware interrupt.
stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN)
// wait till timer wakes up
for timerWakeup.Get() == 0 {
arm.Asm("wfi")
}
}
func handleTIM3(interrupt.Interrupt) {
if stm32.TIM3.SR.HasBits(stm32.TIM_SR_UIF) {
// Disable the timer.
stm32.TIM3.CR1.ClearBits(stm32.TIM_CR1_CEN)
// clear the update flag
stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF)
// timer was triggered
timerWakeup.Set(1)
}
}
func handleTIM7(interrupt.Interrupt) {
if stm32.TIM7.SR.HasBits(stm32.TIM_SR_UIF) {
// clear the update flag
stm32.TIM7.SR.ClearBits(stm32.TIM_SR_UIF)
tickCount++
}
} }

Просмотреть файл

@ -3,30 +3,8 @@
package runtime package runtime
import ( import (
"device/arm"
"device/stm32" "device/stm32"
"machine" "machine"
"runtime/interrupt"
"runtime/volatile"
)
func init() {
initCLK()
initTIM3()
machine.UART0.Configure(machine.UARTConfig{})
initTIM7()
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
const (
HSE_STARTUP_TIMEOUT = 0x0500
PLL_M = 4
PLL_N = 216
PLL_P = 2
PLL_Q = 2
) )
/* /*
@ -39,6 +17,54 @@ const (
| APB2(PCLK2) | 108mhz | | APB2(PCLK2) | 108mhz |
+-------------+--------+ +-------------+--------+
*/ */
const (
HSE_STARTUP_TIMEOUT = 0x0500
PLL_M = 4
PLL_N = 216
PLL_P = 2
PLL_Q = 2
)
/*
timer settings used for tick and sleep.
note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
settings above, so must be kept in sync if the clock settings are changed.
*/
const (
TICK_RATE = 1000 // 1 KHz
SLEEP_TIMER_IRQ = stm32.IRQ_TIM3
SLEEP_TIMER_FREQ = 54000000 // 54 MHz (2x APB1)
TICK_TIMER_IRQ = stm32.IRQ_TIM7
TICK_TIMER_FREQ = 54000000 // 54 MHz (2x APB1)
)
type arrtype = uint32
const asyncScheduler = false
func init() {
initCLK()
initSleepTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM3EN,
Device: stm32.TIM3,
})
machine.UART0.Configure(machine.UARTConfig{})
initTickTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM7EN,
Device: stm32.TIM7,
})
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
func initCLK() { func initCLK() {
// PWR_CLK_ENABLE // PWR_CLK_ENABLE
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
@ -102,107 +128,3 @@ func initOsc() {
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
} }
} }
var (
// tick in milliseconds
tickCount timeUnit
)
var timerWakeup volatile.Register8
func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * 1000
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns / 1000)
}
// Enable the TIM3 clock.(sleep count)
func initTIM3() {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
intr := interrupt.New(stm32.IRQ_TIM3, handleTIM3)
intr.SetPriority(0xc3)
intr.Enable()
}
// Enable the TIM7 clock.(tick count)
func initTIM7() {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)
// CK_INT = APB1 x2 = 54mhz
stm32.TIM7.PSC.Set(54000000/10000 - 1) // 54mhz to 10khz(0.1ms)
stm32.TIM7.ARR.Set(10 - 1) // interrupt per 1ms
// Enable the hardware interrupt.
stm32.TIM7.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM7.CR1.SetBits(stm32.TIM_CR1_CEN)
intr := interrupt.New(stm32.IRQ_TIM7, handleTIM7)
intr.SetPriority(0xc1)
intr.Enable()
}
const asyncScheduler = false
// sleepTicks should sleep for specific number of microseconds.
func sleepTicks(d timeUnit) {
timerSleep(uint32(d))
}
// number of ticks (microseconds) since start.
func ticks() timeUnit {
// milliseconds to microseconds
return tickCount * 1000
}
// ticks are in microseconds
func timerSleep(ticks uint32) {
timerWakeup.Set(0)
// CK_INT = APB1 x2 = 54mhz
// prescale counter down from 54mhz to 10khz aka 0.1 ms frequency.
stm32.TIM3.PSC.Set(54000000/10000 - 1)
// set duty aka duration
arr := (ticks / 100) - 1 // convert from microseconds to 0.1 ms
if arr == 0 {
arr = 1 // avoid blocking
}
stm32.TIM3.ARR.Set(arr)
// Enable the hardware interrupt.
stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN)
// wait till timer wakes up
for timerWakeup.Get() == 0 {
arm.Asm("wfi")
}
}
func handleTIM3(interrupt.Interrupt) {
if stm32.TIM3.SR.HasBits(stm32.TIM_SR_UIF) {
// Disable the timer.
stm32.TIM3.CR1.ClearBits(stm32.TIM_CR1_CEN)
// clear the update flag
stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF)
// timer was triggered
timerWakeup.Set(1)
}
}
func handleTIM7(interrupt.Interrupt) {
if stm32.TIM7.SR.HasBits(stm32.TIM_SR_UIF) {
// clear the update flag
stm32.TIM7.SR.ClearBits(stm32.TIM_SR_UIF)
tickCount++
}
}

Просмотреть файл

@ -3,18 +3,42 @@
package runtime package runtime
import ( import (
"device/arm"
"device/stm32" "device/stm32"
"machine" "machine"
"runtime/interrupt"
"runtime/volatile"
) )
/*
timer settings used for tick and sleep.
note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
settings above, so must be kept in sync if the clock settings are changed.
*/
const (
TICK_RATE = 1000 // 1 KHz
TICK_TIMER_IRQ = stm32.IRQ_TIM7
TICK_TIMER_FREQ = 32000000 // 32 MHz
SLEEP_TIMER_IRQ = stm32.IRQ_TIM3
SLEEP_TIMER_FREQ = 32000000 // 32 MHz
)
type arrtype = uint16
func init() { func init() {
initCLK() initCLK()
initRTC()
initTIM() initSleepTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM3EN,
Device: stm32.TIM3,
})
machine.UART0.Configure(machine.UARTConfig{}) machine.UART0.Configure(machine.UARTConfig{})
initTickTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM7EN,
Device: stm32.TIM7,
})
} }
func putchar(c byte) { func putchar(c byte) {
@ -58,157 +82,4 @@ func initCLK() {
} }
var (
timestamp timeUnit // microseconds since boottime
timerLastCounter uint64
)
var timerWakeup volatile.Register8
func initRTC() {
// Enable power
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
// access to backup register
stm32.PWR.CR.SetBits(stm32.PWR_CR_DBP)
// Enable LSE
stm32.RCC.CSR.SetBits(stm32.RCC_CSR_LSEON)
// wait until LSE is ready
for !stm32.RCC.CSR.HasBits(stm32.RCC_CSR_LSERDY) {
}
// Select Clock Source LSE
stm32.RCC.CSR.SetBits(0x01 << stm32.RCC_CSR_RTCSEL_Pos)
stm32.RCC.CSR.ClearBits(0x02 << stm32.RCC_CSR_RTCSEL_Pos)
// Enable clock
stm32.RCC.CSR.SetBits(stm32.RCC_CSR_RTCEN)
stm32.RTC.WPR.Set(0xCA) // Enable Write Access for RTC Registers
stm32.RTC.WPR.Set(0x53) // Enable Write Access for RTC Registers
stm32.RTC.ISR.SetBits(stm32.RTC_ISR_INIT) // Enable init phase
// Wait for initialization state
for !stm32.RTC.ISR.HasBits(stm32.RTC_ISR_INITF) {
}
stm32.RTC.PRER.Set(0x003F0270) // set prescaler, 40kHz/64 => 625Hz, 625Hz/625 => 1Hz
// Set initial date
//RTC->TR = RTC_TR_PM | 0;
stm32.RTC.ISR.ClearBits(stm32.RTC_ISR_INIT) // Disable init phase
stm32.RTC.WPR.Set(0xFE) // Disable Write Access for RTC Registers
stm32.RTC.WPR.Set(0x64) // Disable Write Access for RTC Registers
}
// Enable the TIM3 clock.
func initTIM() {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
intr := interrupt.New(stm32.IRQ_TIM3, handleTIM3)
intr.SetPriority(0xc3)
intr.Enable()
}
const asyncScheduler = false const asyncScheduler = false
func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * 1000
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns / 1000)
}
// sleepTicks should sleep for specific number of microseconds.
func sleepTicks(d timeUnit) {
for d != 0 {
ticks() // update timestamp
ticks := uint32(d) // current scaling only supports 100 usec to 6553 msec
timerSleep(ticks)
d -= timeUnit(ticks)
}
}
// number of ticks (microseconds) since start.
func ticks() timeUnit {
// Read twice to force shadow register cache update
rSubSec := stm32.RTC.SSR.Get() & stm32.RTC_SSR_SS_Msk
rSubSec = stm32.RTC.SSR.Get() & stm32.RTC_SSR_SS_Msk
rDate := stm32.RTC.DR.Get()
rDate = stm32.RTC.DR.Get()
rDate++
rTime := stm32.RTC.TR.Get()
rTime = stm32.RTC.TR.Get()
prediv := stm32.RTC.PRER.Get() & stm32.RTC_PRER_PREDIV_S_Msk
var tsec uint64
// Timestamp in seconds
tsec = uint64(((rTime & 0x300000) >> 20) * 36000) // Hours Tens
tsec += uint64(((rTime & 0xf0000) >> 16) * 3600) // Hours Units
tsec += uint64(((rTime & 0x7000) >> 12) * 600) // Minutes Tens
tsec += uint64(((rTime & 0xf00) >> 8) * 60) // Minutes Units
tsec += uint64(((rTime & 0x70) >> 4) * 10) // Second Tens
tsec += uint64(rTime & 0xf) // Seconds Units
//Second fraction in milliseconds
ssec := uint64((1000 * (prediv - rSubSec)) / (prediv + 1))
timerCounter := uint64(tsec * 1000) // Timestamp in millis
timerCounter += ssec // Add sub-seconds
timerCounter *= 1000 // Convert to micros
// change since last measurement
offset := (timerCounter - timerLastCounter)
timerLastCounter = timerCounter
timestamp += timeUnit(offset)
return timestamp
}
// ticks are in microseconds
func timerSleep(ticks uint32) {
timerWakeup.Set(0)
// prescale counter down from 32mhz to 10khz aka 0.1 ms frequency.
clk := machine.CPUFrequency() / 2
stm32.TIM3.PSC.Set(clk/10000 - 1)
// Set duty aka duration.
// STM32 dividers use n-1, i.e. n counts from 0 to n-1.
// As a result, with these prescaler settings,
// the minimum allowed duration is 200 microseconds.
if ticks < 200 {
ticks = 200
}
stm32.TIM3.ARR.Set(uint16(ticks/100 - 1)) // convert from microseconds to 0.1 ms
// Enable the hardware interrupt.
stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN)
// wait till timer wakes up
for timerWakeup.Get() == 0 {
arm.Asm("wfi")
}
}
func handleTIM3(interrupt.Interrupt) {
if stm32.TIM3.SR.HasBits(stm32.TIM_SR_UIF) {
// Disable the timer.
stm32.TIM3.CR1.ClearBits(stm32.TIM_CR1_CEN)
// clear the update flag
stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF)
// timer was triggered
timerWakeup.Set(1)
}
}

Просмотреть файл

@ -3,31 +3,8 @@
package runtime package runtime
import ( import (
"device/arm"
"device/stm32" "device/stm32"
"machine" "machine"
"runtime/interrupt"
"runtime/volatile"
)
func init() {
initCLK()
initTIM15()
machine.UART0.Configure(machine.UARTConfig{})
initTIM16()
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
const (
HSE_STARTUP_TIMEOUT = 0x0500
PLL_M = 1
PLL_N = 55
PLL_P = 7 // RCC_PLLP_DIV7
PLL_Q = 2 // RCC_PLLQ_DIV2
PLL_R = 2 // RCC_PLLR_DIV2
) )
/* /*
@ -40,6 +17,55 @@ const (
| APB2(PCLK2) | 110mhz | | APB2(PCLK2) | 110mhz |
+-------------+-----------+ +-------------+-----------+
*/ */
const (
HSE_STARTUP_TIMEOUT = 0x0500
PLL_M = 1
PLL_N = 55
PLL_P = 7 // RCC_PLLP_DIV7
PLL_Q = 2 // RCC_PLLQ_DIV2
PLL_R = 2 // RCC_PLLR_DIV2
)
/*
timer settings used for tick and sleep.
note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
settings above, so must be kept in sync if the clock settings are changed.
*/
const (
TICK_RATE = 1000 // 1 KHz
SLEEP_TIMER_IRQ = stm32.IRQ_TIM15
SLEEP_TIMER_FREQ = 110000000 // 110 MHz
TICK_TIMER_IRQ = stm32.IRQ_TIM16
TICK_TIMER_FREQ = 110000000 // 110 MHz
)
type arrtype = uint32
const asyncScheduler = false
func init() {
initCLK()
initSleepTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB2ENR,
EnableFlag: stm32.RCC_APB2ENR_TIM15EN,
Device: stm32.TIM15,
})
machine.UART0.Configure(machine.UARTConfig{})
initTickTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB2ENR,
EnableFlag: stm32.RCC_APB2ENR_TIM16EN,
Device: stm32.TIM16,
})
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
func initCLK() { func initCLK() {
// PWR_CLK_ENABLE // PWR_CLK_ENABLE
@ -137,107 +163,3 @@ func initOsc() {
} }
} }
var (
// tick in milliseconds
tickCount timeUnit
)
var timerWakeup volatile.Register8
func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * 1000
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns / 1000)
}
// Enable the TIM15 clock.(sleep count)
func initTIM15() {
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM15EN)
intr := interrupt.New(stm32.IRQ_TIM15, handleTIM15)
intr.SetPriority(0xc3)
intr.Enable()
}
// Enable the TIM16 clock.(tick count)
func initTIM16() {
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM16EN)
// CK_INT = APB1 = 110mhz
stm32.TIM16.PSC.Set(110000000/10000 - 1) // 110mhz to 10khz(0.1ms)
stm32.TIM16.ARR.Set(10 - 1) // interrupt per 1ms
// Enable the hardware interrupt.
stm32.TIM16.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM16.CR1.SetBits(stm32.TIM_CR1_CEN)
intr := interrupt.New(stm32.IRQ_TIM16, handleTIM16)
intr.SetPriority(0xc1)
intr.Enable()
}
const asyncScheduler = false
// sleepTicks should sleep for specific number of microseconds.
func sleepTicks(d timeUnit) {
timerSleep(uint32(d))
}
// number of ticks (microseconds) since start.
func ticks() timeUnit {
// milliseconds to microseconds
return tickCount * 1000
}
// ticks are in microseconds
func timerSleep(ticks uint32) {
timerWakeup.Set(0)
// CK_INT = APB1 = 110mhz
// prescale counter down from 110mhz to 10khz aka 0.1 ms frequency.
stm32.TIM15.PSC.Set(110000000/10000 - 1)
// set duty aka duration
arr := (ticks / 100) - 1 // convert from microseconds to 0.1 ms
if arr == 0 {
arr = 1 // avoid blocking
}
stm32.TIM15.ARR.Set(arr)
// Enable the hardware interrupt.
stm32.TIM15.DIER.SetBits(stm32.TIM_DIER_UIE)
// Enable the timer.
stm32.TIM15.CR1.SetBits(stm32.TIM_CR1_CEN)
// wait till timer wakes up
for timerWakeup.Get() == 0 {
arm.Asm("wfi")
}
}
func handleTIM15(interrupt.Interrupt) {
if stm32.TIM15.SR.HasBits(stm32.TIM_SR_UIF) {
// Disable the timer.
stm32.TIM15.CR1.ClearBits(stm32.TIM_CR1_CEN)
// clear the update flag
stm32.TIM15.SR.ClearBits(stm32.TIM_SR_UIF)
// timer was triggered
timerWakeup.Set(1)
}
}
func handleTIM16(interrupt.Interrupt) {
if stm32.TIM16.SR.HasBits(stm32.TIM_SR_UIF) {
// clear the update flag
stm32.TIM16.SR.ClearBits(stm32.TIM_SR_UIF)
tickCount++
}
}