Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/machine/machine_stm32.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

package machine

import (
"device/arm"
)

// Peripheral abstraction layer for the stm32.

const (
Expand Down Expand Up @@ -53,3 +57,8 @@ func (p Pin) Get() bool {
val := port.IDR.Get() & (1 << pin)
return (val > 0)
}

// Wait for interrupt or event
func waitForEvents() {
arm.Asm("wfe")
}
27 changes: 12 additions & 15 deletions src/machine/machine_stm32_i2c_revb.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import (
"unsafe"
)

//go:linkname ticks runtime.ticks
func ticks() int64

// I2C implementation for 'newer' STM32 MCUs, including the F7, L5 and L4
// series of MCUs.
//
Expand Down Expand Up @@ -103,7 +100,7 @@ func (i2c *I2C) configurePins(config I2CConfig) {
}

func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {
start := ticks()
start := Ticks()

if !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) {
return errI2CBusReadyTimeout
Expand Down Expand Up @@ -162,7 +159,7 @@ func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {
}

func (i2c *I2C) controllerReceive(addr uint16, r []byte) error {
start := ticks()
start := Ticks()

if !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) {
return errI2CBusReadyTimeout
Expand Down Expand Up @@ -220,16 +217,16 @@ func (i2c *I2C) controllerReceive(addr uint16, r []byte) error {
return nil
}

func (i2c *I2C) waitOnFlagUntilTimeout(flag uint32, set bool, startTicks int64) bool {
func (i2c *I2C) waitOnFlagUntilTimeout(flag uint32, set bool, startTicks uint64) bool {
for i2c.hasFlag(flag) != set {
if (ticks() - startTicks) > TIMEOUT_TICKS {
if (Ticks() - startTicks) > TIMEOUT_TICKS {
return false
}
}
return true
}

func (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks int64) bool {
func (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks uint64) bool {
for !i2c.hasFlag(flagRXNE) {
if i2c.isAcknowledgeFailed(startTicks) {
return false
Expand All @@ -241,48 +238,48 @@ func (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks int64) bool {
return false
}

if (ticks() - startTicks) > TIMEOUT_TICKS {
if (Ticks() - startTicks) > TIMEOUT_TICKS {
return false
}
}

return true
}

func (i2c *I2C) waitOnTXISFlagUntilTimeout(startTicks int64) bool {
func (i2c *I2C) waitOnTXISFlagUntilTimeout(startTicks uint64) bool {
for !i2c.hasFlag(flagTXIS) {
if i2c.isAcknowledgeFailed(startTicks) {
return false
}

if (ticks() - startTicks) > TIMEOUT_TICKS {
if (Ticks() - startTicks) > TIMEOUT_TICKS {
return false
}
}

return true
}

func (i2c *I2C) waitOnStopFlagUntilTimeout(startTicks int64) bool {
func (i2c *I2C) waitOnStopFlagUntilTimeout(startTicks uint64) bool {
for !i2c.hasFlag(flagSTOPF) {
if i2c.isAcknowledgeFailed(startTicks) {
return false
}

if (ticks() - startTicks) > TIMEOUT_TICKS {
if (Ticks() - startTicks) > TIMEOUT_TICKS {
return false
}
}

return true
}

func (i2c *I2C) isAcknowledgeFailed(startTicks int64) bool {
func (i2c *I2C) isAcknowledgeFailed(startTicks uint64) bool {
if i2c.hasFlag(flagAF) {
// Wait until STOP Flag is reset
// AutoEnd should be initiate after AF
for !i2c.hasFlag(flagSTOPF) {
if (ticks() - startTicks) > TIMEOUT_TICKS {
if (Ticks() - startTicks) > TIMEOUT_TICKS {
return true
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build stm32

package runtime
package machine

// 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.
Expand Down Expand Up @@ -47,24 +47,14 @@ var (
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.
//go:linkname ticks runtime.ticks
func ticks() timeUnit {
return timeUnit(tickCount.Get())
}

//
// -- Ticks ---
//

func Ticks() uint64 {
return tickCount.Get()
}

// Enable the timer used to count ticks
func initTickTimer(ti *timerInfo) {
tickTimer = ti
Expand Down Expand Up @@ -120,25 +110,6 @@ func handleTick(interrupt.Interrupt) {
// --- 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
Expand All @@ -157,7 +128,7 @@ func initSleepTimer(ti *timerInfo) {
}

// timerSleep sleeps for 'at most' ns nanoseconds, but possibly less.
func timerSleep(ns int64) {
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
Expand Down
60 changes: 60 additions & 0 deletions src/machine/machine_stm32f103.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,66 @@ func enableAltFuncClock(bus unsafe.Pointer) {
}
}

//---------- Clock and Oscillator related code

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

func InitializeClocks() {
initPLL()

initSleepTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM3EN,
Device: stm32.TIM3,
})

initTickTimer(&timerInfo{
EnableRegister: &stm32.RCC.APB1ENR,
EnableFlag: stm32.RCC_APB1ENR_TIM4EN,
Device: stm32.TIM4,
})
}

// InitializeClocks sets clock to 72MHz using HSE 8MHz crystal w/ PLL X 9 (8MHz x 9 = 72MHz).
func initPLL() {
stm32.FLASH.ACR.SetBits(stm32.FLASH_ACR_LATENCY_WS2) // Two wait states, per datasheet
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos) // prescale PCLK1 = HCLK/2
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div1 << stm32.RCC_CFGR_PPRE2_Pos) // prescale PCLK2 = HCLK/1
stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON) // enable HSE clock

// wait for the HSEREADY flag
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {
}

stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) // enable HSI clock

// wait for the HSIREADY flag
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) {
}

stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLSRC) // set PLL source to HSE
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLMUL_Mul9 << stm32.RCC_CFGR_PLLMUL_Pos) // multiply by 9
stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) // enable the PLL

// wait for the PLLRDY flag
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
}

stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL) // set clock source to pll

// wait for PLL to be CLK
for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) {
}
}

//---------- UART related code

// Configure the TX and RX pins
Expand Down
Loading