aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKenneth Bell <[email protected]>2021-03-22 18:14:28 -0700
committerRon Evans <[email protected]>2021-04-07 17:20:19 +0200
commita30671751faabf29a5658c90b01a84500b9ade5d (patch)
treeb72727cc666cb57cb93154c80bcaf27a51b6a159
parentc246978dd7844192c414c0d95428d1d7e9a6f6a6 (diff)
downloadtinygo-a30671751faabf29a5658c90b01a84500b9ade5d.tar.gz
tinygo-a30671751faabf29a5658c90b01a84500b9ade5d.zip
stm32: add nucleo-l031k6 support
Adds i2c for all L0 series UART, Blinky (LED) and i2c tested
-rw-r--r--Makefile2
-rw-r--r--src/machine/board_lgt92.go15
-rw-r--r--src/machine/board_nucleol031k6.go92
-rw-r--r--src/machine/i2c.go2
-rw-r--r--src/machine/machine_stm32_i2c_revb.go2
-rw-r--r--src/machine/machine_stm32l0.go55
-rw-r--r--src/machine/machine_stm32l0x1.go52
-rw-r--r--src/machine/machine_stm32l0x2.go54
-rw-r--r--src/runtime/runtime_stm32l0.go91
-rw-r--r--src/runtime/runtime_stm32l0x1.go44
-rw-r--r--src/runtime/runtime_stm32l0x2.go44
-rw-r--r--targets/cortex-m0.json8
-rw-r--r--targets/nucleo-l031k6.json11
-rw-r--r--targets/stm32l031k6.ld10
14 files changed, 388 insertions, 94 deletions
diff --git a/Makefile b/Makefile
index 6c7f142e3..bcaf50559 100644
--- a/Makefile
+++ b/Makefile
@@ -352,6 +352,8 @@ ifneq ($(STM32), 0)
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-f722ze examples/blinky1
@$(MD5SUM) test.hex
+ $(TINYGO) build -size short -o test.hex -target=nucleo-l031k6 examples/blinky1
+ @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-l432kc examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-l552ze examples/blinky1
diff --git a/src/machine/board_lgt92.go b/src/machine/board_lgt92.go
index ee6129b7f..c95de360b 100644
--- a/src/machine/board_lgt92.go
+++ b/src/machine/board_lgt92.go
@@ -41,13 +41,17 @@ const (
// LORA RFM95 Radio
RFM95_DIO0_PIN = PC13
- //TinyGo UART is MCU LPUSART1
+ // TinyGo UART is MCU LPUSART1
UART_RX_PIN = PA13
UART_TX_PIN = PA14
- //TinyGo UART1 is MCU USART1
+ // TinyGo UART1 is MCU USART1
UART1_RX_PIN = PB6
UART1_TX_PIN = PB7
+
+ // MPU9250 Nine-Axis (Gyro + Accelerometer + Compass)
+ I2C0_SCL_PIN = PA9
+ I2C0_SDA_PIN = PA10
)
var (
@@ -68,6 +72,13 @@ var (
RxAltFuncSelector: 0,
}
+ // MPU9250 Nine-Axis (Gyro + Accelerometer + Compass)
+ I2C1 = &I2C{
+ Bus: stm32.I2C1,
+ AltFuncSelector: 6,
+ }
+ I2C0 = I2C1
+
// SPI
SPI0 = SPI{
Bus: stm32.SPI1,
diff --git a/src/machine/board_nucleol031k6.go b/src/machine/board_nucleol031k6.go
new file mode 100644
index 000000000..d5fddebf4
--- /dev/null
+++ b/src/machine/board_nucleol031k6.go
@@ -0,0 +1,92 @@
+// +build nucleol031k6
+
+package machine
+
+import (
+ "device/stm32"
+ "runtime/interrupt"
+)
+
+const (
+ LED = LED_BUILTIN
+ LED_BUILTIN = LED_GREEN
+ LED_GREEN = PB3
+)
+
+const (
+ // Arduino Pins
+ A0 = PA0 // ADC_IN0
+ A1 = PA1 // ADC_IN1
+ A2 = PA3 // ADC_IN3
+ A3 = PA4 // ADC_IN4
+ A4 = PA5 // ADC_IN5 || I2C1_SDA
+ A5 = PA6 // ADC_IN6 || I2C1_SCL
+ A6 = PA7 // ADC_IN7
+ A7 = PA2 // ADC_IN2
+
+ D0 = PA10 // USART1_TX
+ D1 = PA9 // USART1_RX
+ D2 = PA12
+ D3 = PB0 // TIM2_CH3
+ D4 = PB7
+ D5 = PB6 // TIM16_CH1N
+ D6 = PB1 // TIM14_CH1
+ D9 = PA8 // TIM1_CH1
+ D10 = PA11 // SPI_CS || TIM1_CH4
+ D11 = PB5 // SPI1_MOSI || TIM3_CH2
+ D12 = PB4 // SPI1_MISO
+ D13 = PB3 // SPI1_SCK
+)
+
+const (
+ // UART pins
+ // PA2 and PA15 are connected to the ST-Link Virtual Com Port (VCP)
+ UART_TX_PIN = PA2
+ UART_RX_PIN = PA15
+
+ // SPI
+ SPI1_SCK_PIN = PB3
+ SPI1_SDI_PIN = PB5
+ SPI1_SDO_PIN = PB4
+ SPI0_SCK_PIN = SPI1_SCK_PIN
+ SPI0_SDI_PIN = SPI1_SDI_PIN
+ SPI0_SDO_PIN = SPI1_SDO_PIN
+
+ // I2C pins
+ // PB6 and PB7 are mapped to CN4 pin 7 and CN4 pin 8 respectively with the
+ // default solder bridge settings
+ I2C0_SCL_PIN = PB7
+ I2C0_SDA_PIN = PB6
+ I2C0_ALT_FUNC = 1
+)
+
+var (
+ // USART2 is the hardware serial port connected to the onboard ST-LINK
+ // debugger to be exposed as virtual COM port over USB on Nucleo boards.
+ // Both UART0 and UART1 refer to USART2.
+ UART0 = UART{
+ Buffer: NewRingBuffer(),
+ Bus: stm32.USART2,
+ TxAltFuncSelector: 4,
+ RxAltFuncSelector: 4,
+ }
+ UART1 = &UART0
+
+ // I2C1 is documented, alias to I2C0 as well
+ I2C1 = &I2C{
+ Bus: stm32.I2C1,
+ AltFuncSelector: 1,
+ }
+ I2C0 = I2C1
+
+ // SPI
+ SPI0 = SPI{
+ Bus: stm32.SPI1,
+ AltFuncSelector: 0,
+ }
+ SPI1 = &SPI0
+)
+
+func init() {
+ UART0.Interrupt = interrupt.New(stm32.IRQ_USART2, UART0.handleInterrupt)
+}
diff --git a/src/machine/i2c.go b/src/machine/i2c.go
index 310173614..60204f48d 100644
--- a/src/machine/i2c.go
+++ b/src/machine/i2c.go
@@ -1,4 +1,4 @@
-// +build atmega nrf sam stm32,!stm32l0 fe310 k210
+// +build atmega nrf sam stm32 fe310 k210
package machine
diff --git a/src/machine/machine_stm32_i2c_revb.go b/src/machine/machine_stm32_i2c_revb.go
index 63e9205f1..aca962400 100644
--- a/src/machine/machine_stm32_i2c_revb.go
+++ b/src/machine/machine_stm32_i2c_revb.go
@@ -1,4 +1,4 @@
-// +build stm32l5 stm32f7 stm32l4
+// +build stm32l5 stm32f7 stm32l4 stm32l0
package machine
diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go
index c37d6a027..886c3985a 100644
--- a/src/machine/machine_stm32l0.go
+++ b/src/machine/machine_stm32l0.go
@@ -6,7 +6,6 @@ package machine
import (
"device/stm32"
- "unsafe"
)
func CPUFrequency() uint32 {
@@ -142,50 +141,6 @@ func (p Pin) enableClock() {
}
}
-// Enable peripheral clock
-func enableAltFuncClock(bus unsafe.Pointer) {
- switch bus {
- case unsafe.Pointer(stm32.DAC): // DAC interface clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_DACEN)
- case unsafe.Pointer(stm32.PWR): // Power interface clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
- case unsafe.Pointer(stm32.I2C3): // I2C3 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN)
- case unsafe.Pointer(stm32.I2C2): // I2C2 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN)
- case unsafe.Pointer(stm32.I2C1): // I2C1 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
- case unsafe.Pointer(stm32.USART5): // UART5 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART5EN)
- case unsafe.Pointer(stm32.USART4): // UART4 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART4EN)
- case unsafe.Pointer(stm32.USART2): // USART2 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
- case unsafe.Pointer(stm32.SPI2): // SPI2 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)
- case unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_LPUART1EN)
- case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)
- case unsafe.Pointer(stm32.TIM7): // TIM7 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)
- case unsafe.Pointer(stm32.TIM6): // TIM6 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN)
- case unsafe.Pointer(stm32.TIM3): // TIM3 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
- case unsafe.Pointer(stm32.TIM2): // TIM2 clock enable
- stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)
- case unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable
- stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)
- case unsafe.Pointer(stm32.SPI1): // SPI1 clock enable
- stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
- case unsafe.Pointer(stm32.ADC): // ADC clock enable
- stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN)
- case unsafe.Pointer(stm32.USART1): // USART1 clock enable
- stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
- }
-}
-
//---------- UART related types and code
// Configure the UART.
@@ -285,3 +240,13 @@ func (spi SPI) configurePins(config SPIConfig) {
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
}
+
+//---------- I2C related types and code
+
+// Gets the value for TIMINGR register
+func (i2c I2C) getFreqRange() uint32 {
+ // This is a 'magic' value calculated by STM32CubeMX
+ // for 80MHz PCLK1.
+ // TODO: Do calculations based on PCLK1
+ return 0x00303D5B
+}
diff --git a/src/machine/machine_stm32l0x1.go b/src/machine/machine_stm32l0x1.go
new file mode 100644
index 000000000..3fad050a6
--- /dev/null
+++ b/src/machine/machine_stm32l0x1.go
@@ -0,0 +1,52 @@
+// +build stm32l0x1
+
+package machine
+
+// Peripheral abstraction layer for the stm32l0
+
+import (
+ "device/stm32"
+ "unsafe"
+)
+
+// Enable peripheral clock
+func enableAltFuncClock(bus unsafe.Pointer) {
+ switch bus {
+ case unsafe.Pointer(stm32.PWR): // Power interface clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
+ case unsafe.Pointer(stm32.I2C3): // I2C3 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN)
+ case unsafe.Pointer(stm32.I2C2): // I2C2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN)
+ case unsafe.Pointer(stm32.I2C1): // I2C1 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
+ case unsafe.Pointer(stm32.USART5): // UART5 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART5EN)
+ case unsafe.Pointer(stm32.USART4): // UART4 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART4EN)
+ case unsafe.Pointer(stm32.USART2): // USART2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
+ case unsafe.Pointer(stm32.SPI2): // SPI2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)
+ case unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_LPUART1EN)
+ case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)
+ case unsafe.Pointer(stm32.TIM7): // TIM7 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)
+ case unsafe.Pointer(stm32.TIM6): // TIM6 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN)
+ case unsafe.Pointer(stm32.TIM3): // TIM3 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
+ case unsafe.Pointer(stm32.TIM2): // TIM2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)
+ case unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)
+ case unsafe.Pointer(stm32.SPI1): // SPI1 clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
+ case unsafe.Pointer(stm32.ADC): // ADC clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN)
+ case unsafe.Pointer(stm32.USART1): // USART1 clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
+ }
+}
diff --git a/src/machine/machine_stm32l0x2.go b/src/machine/machine_stm32l0x2.go
new file mode 100644
index 000000000..71c7cd4a0
--- /dev/null
+++ b/src/machine/machine_stm32l0x2.go
@@ -0,0 +1,54 @@
+// +build stm32l0x2
+
+package machine
+
+// Peripheral abstraction layer for the stm32l0
+
+import (
+ "device/stm32"
+ "unsafe"
+)
+
+// Enable peripheral clock
+func enableAltFuncClock(bus unsafe.Pointer) {
+ switch bus {
+ case unsafe.Pointer(stm32.DAC): // DAC interface clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_DACEN)
+ case unsafe.Pointer(stm32.PWR): // Power interface clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
+ case unsafe.Pointer(stm32.I2C3): // I2C3 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN)
+ case unsafe.Pointer(stm32.I2C2): // I2C2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN)
+ case unsafe.Pointer(stm32.I2C1): // I2C1 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
+ case unsafe.Pointer(stm32.USART5): // UART5 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART5EN)
+ case unsafe.Pointer(stm32.USART4): // UART4 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART4EN)
+ case unsafe.Pointer(stm32.USART2): // USART2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
+ case unsafe.Pointer(stm32.SPI2): // SPI2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)
+ case unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_LPUART1EN)
+ case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)
+ case unsafe.Pointer(stm32.TIM7): // TIM7 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)
+ case unsafe.Pointer(stm32.TIM6): // TIM6 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN)
+ case unsafe.Pointer(stm32.TIM3): // TIM3 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
+ case unsafe.Pointer(stm32.TIM2): // TIM2 clock enable
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)
+ case unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)
+ case unsafe.Pointer(stm32.SPI1): // SPI1 clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
+ case unsafe.Pointer(stm32.ADC): // ADC clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN)
+ case unsafe.Pointer(stm32.USART1): // USART1 clock enable
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
+ }
+}
diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go
index db14a520f..c7045087b 100644
--- a/src/runtime/runtime_stm32l0.go
+++ b/src/runtime/runtime_stm32l0.go
@@ -1,4 +1,4 @@
-// +build stm32,stm32l0
+// +build stm32l0
package runtime
@@ -7,68 +7,48 @@ import (
"machine"
)
-/*
- 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
+ RCC_SYSCLK_DIV1 = 0 // Needs SVD update (should be stm32.RCC_SYSCLK_DIV1)
)
type arrtype = uint16
-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,
- })
-}
+const asyncScheduler = false
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
-// initCLK sets clock to 32MHz
-// SEE: https://github.com/WRansohoff/STM32x0_timer_example/blob/master/src/main.c
-
func initCLK() {
+ // Set Power Regulator to enable max performance (1.8V)
+ stm32.PWR.CR.ReplaceBits(1<<stm32.PWR_CR_VOS_Pos, stm32.PWR_CR_VOS_Msk, 0)
- // Set the Flash ACR to use 1 wait-state
- // enable the prefetch buffer and pre-read for performance
- stm32.FLASH.ACR.SetBits(stm32.Flash_ACR_LATENCY | stm32.Flash_ACR_PRFTEN | stm32.Flash_ACR_PRE_READ)
-
- // Set presaclers so half system clock (PCLKx = HCLK/2)
- stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos)
- stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos)
+ // Calibration (default 0x10)
+ stm32.RCC.ICSCR.ReplaceBits(0x10<<stm32.RCC_ICSCR_HSI16TRIM_Pos, stm32.RCC_ICSCR_HSI16TRIM_Msk, 0)
// Enable the HSI16 oscillator, since the L0 series boots to the MSI one.
- stm32.RCC.CR.SetBits(stm32.RCC_CR_HSI16ON)
+ stm32.RCC.CR.ReplaceBits(stm32.RCC_CR_HSI16ON, stm32.RCC_CR_HSI16ON_Msk|stm32.RCC_CR_HSI16DIVEN_Msk, 0)
// Wait for HSI16 to be ready
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSI16RDYF) {
}
+ // Disable PLL
+ stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)
+
+ // Wait for PLL to be disabled
+ for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
+ }
+
// Configure the PLL to use HSI16 with a PLLDIV of 2 and PLLMUL of 4.
- stm32.RCC.CFGR.SetBits(0x01<<stm32.RCC_CFGR_PLLDIV_Pos | 0x01<<stm32.RCC_CFGR_PLLMUL_Pos)
- stm32.RCC.CFGR.ClearBits(0x02<<stm32.RCC_CFGR_PLLDIV_Pos | 0x0E<<stm32.RCC_CFGR_PLLMUL_Pos)
- stm32.RCC.CFGR.ClearBits(stm32.RCC_CFGR_PLLSRC)
+ stm32.RCC.CFGR.ReplaceBits(
+ (stm32.RCC_CFGR_PLLSRC_HSI16<<stm32.RCC_CFGR_PLLSRC_Pos)|
+ (stm32.RCC_CFGR_PLLMUL_Mul4<<stm32.RCC_CFGR_PLLMUL_Pos)|
+ (stm32.RCC_CFGR_PLLDIV_Div2<<stm32.RCC_CFGR_PLLDIV_Pos),
+ stm32.RCC_CFGR_PLLSRC_Msk|
+ stm32.RCC_CFGR_PLLMUL_Msk|
+ stm32.RCC_CFGR_PLLDIV_Msk,
+ 0)
// Enable PLL
stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)
@@ -77,9 +57,30 @@ func initCLK() {
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
}
+ // Adjust flash latency
+ if FlashLatency > getFlashLatency() {
+ setFlashLatency(FlashLatency)
+ for getFlashLatency() != FlashLatency {
+ }
+ }
+
+ // HCLK
+ stm32.RCC.CFGR.ReplaceBits(RCC_SYSCLK_DIV1, stm32.RCC_CFGR_HPRE_Msk, 0)
+
// Use PLL As System clock
- stm32.RCC.CFGR.SetBits(0x3)
+ stm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_SWS_PLL, stm32.RCC_CFGR_SW_Msk, 0)
+ for stm32.RCC.CFGR.Get()&stm32.RCC_CFGR_SW_Msk != stm32.RCC_CFGR_SWS_PLL {
+ }
+ // Set prescalers so half system clock (PCLKx = HCLK/2)
+ stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos)
+ stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos)
}
-const asyncScheduler = false
+func getFlashLatency() uint32 {
+ return stm32.FLASH.ACR.Get() & stm32.Flash_ACR_LATENCY_Msk
+}
+
+func setFlashLatency(l uint32) {
+ stm32.FLASH.ACR.ReplaceBits(l, stm32.Flash_ACR_LATENCY_Msk, 0)
+}
diff --git a/src/runtime/runtime_stm32l0x1.go b/src/runtime/runtime_stm32l0x1.go
new file mode 100644
index 000000000..1d48388e8
--- /dev/null
+++ b/src/runtime/runtime_stm32l0x1.go
@@ -0,0 +1,44 @@
+// +build stm32l0x1
+
+package runtime
+
+import (
+ "device/stm32"
+ "machine"
+)
+
+/*
+ timer settings used for tick and sleep.
+
+ note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
+ settings, so must be kept in sync if the clock settings are changed.
+*/
+const (
+ TICK_RATE = 1000 // 1 KHz
+ TICK_TIMER_IRQ = stm32.IRQ_TIM21
+ TICK_TIMER_FREQ = 32000000 // 32 MHz
+ SLEEP_TIMER_IRQ = stm32.IRQ_TIM22
+ SLEEP_TIMER_FREQ = 32000000 // 32 MHz
+)
+
+const (
+ FlashLatency = stm32.Flash_ACR_LATENCY_WS1
+)
+
+func init() {
+ initCLK()
+
+ initSleepTimer(&timerInfo{
+ EnableRegister: &stm32.RCC.APB2ENR,
+ EnableFlag: stm32.RCC_APB2ENR_TIM22EN,
+ Device: stm32.TIM22,
+ })
+
+ machine.UART0.Configure(machine.UARTConfig{})
+
+ initTickTimer(&timerInfo{
+ EnableRegister: &stm32.RCC.APB2ENR,
+ EnableFlag: stm32.RCC_APB2ENR_TIM21EN,
+ Device: stm32.TIM21,
+ })
+}
diff --git a/src/runtime/runtime_stm32l0x2.go b/src/runtime/runtime_stm32l0x2.go
new file mode 100644
index 000000000..6eccf0eb6
--- /dev/null
+++ b/src/runtime/runtime_stm32l0x2.go
@@ -0,0 +1,44 @@
+// +build stm32l0x2
+
+package runtime
+
+import (
+ "device/stm32"
+ "machine"
+)
+
+/*
+ timer settings used for tick and sleep.
+
+ note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock
+ settings, 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
+)
+
+const (
+ FlashLatency = stm32.Flash_ACR_LATENCY_WS1
+)
+
+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,
+ })
+}
diff --git a/targets/cortex-m0.json b/targets/cortex-m0.json
new file mode 100644
index 000000000..8cbbe2850
--- /dev/null
+++ b/targets/cortex-m0.json
@@ -0,0 +1,8 @@
+{
+ "inherits": ["cortex-m"],
+ "llvm-target": "armv6m-none-eabi",
+ "cflags": [
+ "--target=armv6m-none-eabi",
+ "-Qunused-arguments"
+ ]
+}
diff --git a/targets/nucleo-l031k6.json b/targets/nucleo-l031k6.json
new file mode 100644
index 000000000..928dd43dc
--- /dev/null
+++ b/targets/nucleo-l031k6.json
@@ -0,0 +1,11 @@
+{
+ "inherits": ["cortex-m0"],
+ "build-tags": ["nucleol031k6", "stm32l031", "stm32l0x1", "stm32l0", "stm32"],
+ "linkerscript": "targets/stm32l031k6.ld",
+ "extra-files": [
+ "src/device/stm32/stm32l0x1.s"
+ ],
+ "flash-method": "openocd",
+ "openocd-interface": "stlink",
+ "openocd-target": "stm32l0"
+} \ No newline at end of file
diff --git a/targets/stm32l031k6.ld b/targets/stm32l031k6.ld
new file mode 100644
index 000000000..f9995bc02
--- /dev/null
+++ b/targets/stm32l031k6.ld
@@ -0,0 +1,10 @@
+
+MEMORY
+{
+ FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
+}
+
+_stack_size = 2K;
+
+INCLUDE "targets/arm.ld" \ No newline at end of file