From a32792317651148fab130b724e10400bbea95ed3 Mon Sep 17 00:00:00 2001 From: Olivier Fauchon Date: Tue, 5 Jan 2021 09:13:38 +0100 Subject: [PATCH 1/8] Add support for stm32l0 familly, and Dragino LGT92 Board --- src/machine/board_lgt92.go | 107 +++++++++++ src/machine/i2c.go | 2 +- src/machine/machine_stm32_i2c.go | 2 +- src/machine/machine_stm32_uart.go | 2 +- src/machine/machine_stm32l0.go | 193 +++++++++++++++++++ src/machine/machine_stm32l0_uart.go | 64 +++++++ src/machine/machine_stm32l0x2.go | 108 +++++++++++ src/runtime/runtime_stm32l0x2.go | 281 ++++++++++++++++++++++++++++ targets/lgt92.json | 23 +++ targets/stm32l072czt6.ld | 10 + 10 files changed, 789 insertions(+), 3 deletions(-) create mode 100644 src/machine/board_lgt92.go create mode 100644 src/machine/machine_stm32l0.go create mode 100644 src/machine/machine_stm32l0_uart.go create mode 100644 src/machine/machine_stm32l0x2.go create mode 100644 src/runtime/runtime_stm32l0x2.go create mode 100644 targets/lgt92.json create mode 100644 targets/stm32l072czt6.ld diff --git a/src/machine/board_lgt92.go b/src/machine/board_lgt92.go new file mode 100644 index 0000000000..321731c37a --- /dev/null +++ b/src/machine/board_lgt92.go @@ -0,0 +1,107 @@ +// +build lgt92 + +package machine + +import ( + "device/stm32" + "runtime/interrupt" +) + +const ( + LED1 = PA12 + LED2 = PA8 + LED3 = PA11 + + LED_RED = LED1 + LED_BLUE = LED2 + LED_GREEN = LED3 + + BUTTON = PB14 + + // LG GPS module + GPS_STANDBY_PIN = PB3 + GPS_RESET_PIN = PB4 + GPS_POWER_PIN = PB5 + + // LORA + RFM95_DIO0_PIN = PC13 + + //TinyGo UART is MCU LPUSART1 + UART_RX_PIN = PA13 + UART_TX_PIN = PA14 + + //TinyGo UART1 is MCU USART1 + UART1_RX_PIN = PB6 + UART1_TX_PIN = PB7 +) + +var ( + + // Console UART (LPUSART1) + UART0 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.LPUSART1, + AltFuncSelector: 6, + } + + // Gps UART + UART1 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.USART1, + AltFuncSelector: 0, + } +) + +// set up RX IRQ handler. Follow similar pattern for other UARTx instances +func init() { + + // Enable GPIOs + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPAEN) + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPBEN) + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPCEN) + + // Enable NVM (eeprom) + stm32.RCC.AHBENR.SetBits(stm32.RCC_AHBENR_MIFEN) + + // Enable Leds GPIO output + LED_RED.Configure(PinConfig{Mode: PinOutput}) + LED_GREEN.Configure(PinConfig{Mode: PinOutput}) + LED_BLUE.Configure(PinConfig{Mode: PinOutput}) + + LED_RED.Low() + LED_GREEN.Low() + LED_BLUE.Low() + + // Enable UART0 (MCU LPUART1) Interrupt + // Enable UART1 (MCU UART1) Interrupt + UART0.Interrupt = interrupt.New(stm32.IRQ_AES_RNG_LPUART1, UART0.handleInterrupt) + UART1.Interrupt = interrupt.New(stm32.IRQ_USART1, UART1.handleInterrupt) + +} + +// SPI pins +const ( + SPI1_SCK_PIN = PA5 + SPI1_SDI_PIN = PA6 + SPI1_SDO_PIN = PA7 + SPI0_SCK_PIN = SPI1_SCK_PIN + SPI0_SDI_PIN = SPI1_SDI_PIN + SPI0_SDO_PIN = SPI1_SDO_PIN +) + +// MEMs accelerometer +const ( + MEMS_ACCEL_CS = PE3 + MEMS_ACCEL_INT1 = PE0 + MEMS_ACCEL_INT2 = PE1 +) + +// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1. +// TODO: implement SPI2 and SPI3. +var ( + SPI0 = SPI{ + Bus: stm32.SPI1, + // AltFuncSelector: stm32.AF5_SPI1_SPI2, + } + SPI1 = &SPI0 +) diff --git a/src/machine/i2c.go b/src/machine/i2c.go index 9a461d0283..aa804f6b92 100644 --- a/src/machine/i2c.go +++ b/src/machine/i2c.go @@ -1,4 +1,4 @@ -// +build avr nrf sam stm32,!stm32f407,!stm32f7x2 fe310 k210 +// +build avr nrf sam stm32,!stm32f407,!stm32f7x2,!stm32l0 fe310 k210 package machine diff --git a/src/machine/machine_stm32_i2c.go b/src/machine/machine_stm32_i2c.go index 899e55a744..b502582eec 100644 --- a/src/machine/machine_stm32_i2c.go +++ b/src/machine/machine_stm32_i2c.go @@ -1,4 +1,4 @@ -// +build stm32,!stm32f103xx,!stm32f407,!stm32f7x2 +// +build stm32,!stm32f103xx,!stm32f407,!stm32f7x2,!stm32l0 package machine diff --git a/src/machine/machine_stm32_uart.go b/src/machine/machine_stm32_uart.go index 9d2bab9cec..e4fa470821 100644 --- a/src/machine/machine_stm32_uart.go +++ b/src/machine/machine_stm32_uart.go @@ -1,4 +1,4 @@ -// +build stm32,!stm32f7 +// +build stm32,!stm32f7,!stm32l0 package machine diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go new file mode 100644 index 0000000000..6a9d14f123 --- /dev/null +++ b/src/machine/machine_stm32l0.go @@ -0,0 +1,193 @@ +// +build stm32l0 + +package machine + +// Peripheral abstraction layer for the stm32l0 + +import ( + "device/stm32" + "unsafe" +) + +const ( + PA0 = portA + 0 + PA1 = portA + 1 + PA2 = portA + 2 + PA3 = portA + 3 + PA4 = portA + 4 + PA5 = portA + 5 + PA6 = portA + 6 + PA7 = portA + 7 + PA8 = portA + 8 + PA9 = portA + 9 + PA10 = portA + 10 + PA11 = portA + 11 + PA12 = portA + 12 + PA13 = portA + 13 + PA14 = portA + 14 + PA15 = portA + 15 + + PB0 = portB + 0 + PB1 = portB + 1 + PB2 = portB + 2 + PB3 = portB + 3 + PB4 = portB + 4 + PB5 = portB + 5 + PB6 = portB + 6 + PB7 = portB + 7 + PB8 = portB + 8 + PB9 = portB + 9 + PB10 = portB + 10 + PB11 = portB + 11 + PB12 = portB + 12 + PB13 = portB + 13 + PB14 = portB + 14 + PB15 = portB + 15 + + PC0 = portC + 0 + PC1 = portC + 1 + PC2 = portC + 2 + PC3 = portC + 3 + PC4 = portC + 4 + PC5 = portC + 5 + PC6 = portC + 6 + PC7 = portC + 7 + PC8 = portC + 8 + PC9 = portC + 9 + PC10 = portC + 10 + PC11 = portC + 11 + PC12 = portC + 12 + PC13 = portC + 13 + PC14 = portC + 14 + PC15 = portC + 15 + + PD0 = portD + 0 + PD1 = portD + 1 + PD2 = portD + 2 + PD3 = portD + 3 + PD4 = portD + 4 + PD5 = portD + 5 + PD6 = portD + 6 + PD7 = portD + 7 + PD8 = portD + 8 + PD9 = portD + 9 + PD10 = portD + 10 + PD11 = portD + 11 + PD12 = portD + 12 + PD13 = portD + 13 + PD14 = portD + 14 + PD15 = portD + 15 + + PE0 = portE + 0 + PE1 = portE + 1 + PE2 = portE + 2 + PE3 = portE + 3 + PE4 = portE + 4 + PE5 = portE + 5 + PE6 = portE + 6 + PE7 = portE + 7 + PE8 = portE + 8 + PE9 = portE + 9 + PE10 = portE + 10 + PE11 = portE + 11 + PE12 = portE + 12 + PE13 = portE + 13 + PE14 = portE + 14 + PE15 = portE + 15 + + PH0 = portH + 0 + PH1 = portH + 1 +) + +func (p Pin) getPort() *stm32.GPIO_Type { + switch p / 16 { + case 0: + return stm32.GPIOA + case 1: + return stm32.GPIOB + case 2: + return stm32.GPIOC + case 3: + return stm32.GPIOD + case 4: + return stm32.GPIOE + // case 5: + // return stm32.GPIOF + // case 6: + // return stm32.GPIOG + case 7: + return stm32.GPIOH + // case 8: + // return stm32.GPIOI + default: + panic("machine: unknown port") + } +} + +// enableClock enables the clock for this desired GPIO port. +func (p Pin) enableClock() { + switch p / 16 { + case 0: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPAEN) + case 1: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPBEN) + case 2: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPCEN) + case 3: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPDEN) + case 4: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPEEN) + case 7: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPHEN) + default: + panic("machine: unknown port") + } +} + +// 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.LPUSART1): // LPUSART1 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_COMP): // 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) + // case unsafe.Pointer(stm32.TIM8): // TIM8 clock enable + // stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM8EN) + // case unsafe.Pointer(stm32.TIM1): // TIM1 clock enable + // stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB) + } +} diff --git a/src/machine/machine_stm32l0_uart.go b/src/machine/machine_stm32l0_uart.go new file mode 100644 index 0000000000..80285937bb --- /dev/null +++ b/src/machine/machine_stm32l0_uart.go @@ -0,0 +1,64 @@ +// +build stm32,stm32l0 + +package machine + +// Peripheral abstraction layer for UARTs on the stm32 family. + +import ( + "device/stm32" + "runtime/interrupt" + "unsafe" +) + +// Configure the UART. +func (uart UART) Configure(config UARTConfig) { + // Default baud rate to 115200. + if config.BaudRate == 0 { + config.BaudRate = 115200 + } + + // Set the GPIO pins to defaults if they're not set + if config.TX == 0 && config.RX == 0 { + config.TX = UART_TX_PIN + config.RX = UART_RX_PIN + } + + // Enable USART clock + enableAltFuncClock(unsafe.Pointer(uart.Bus)) + + uart.configurePins(config) + + // Set baud rate + uart.SetBaudRate(config.BaudRate) + + // Enable USART port, tx, rx and rx interrupts + uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE) + + // Enable RX IRQ + uart.Interrupt.SetPriority(0xc0) + uart.Interrupt.Enable() +} + +// handleInterrupt should be called from the appropriate interrupt handler for +// this UART instance. +func (uart *UART) handleInterrupt(interrupt.Interrupt) { + uart.Receive(byte((uart.Bus.RDR.Get() & 0xFF))) +} + +// SetBaudRate sets the communication speed for the UART. Defer to chip-specific +// routines for calculation +func (uart UART) SetBaudRate(br uint32) { + divider := uart.getBaudRateDivisor(br) + uart.Bus.BRR.Set(divider) +} + +// WriteByte writes a byte of data to the UART. +func (uart UART) WriteByte(c byte) error { + + uart.Bus.TDR.Set(uint32(c)) + + for !uart.Bus.ISR.HasBits(stm32.USART_ISR_TXE) { + } + + return nil +} diff --git a/src/machine/machine_stm32l0x2.go b/src/machine/machine_stm32l0x2.go new file mode 100644 index 0000000000..88bb9e30d3 --- /dev/null +++ b/src/machine/machine_stm32l0x2.go @@ -0,0 +1,108 @@ +// +build stm32l0x2 + +package machine + +// Peripheral abstraction layer for the stm32l0x2 + +import ( + "device/stm32" + "runtime/interrupt" +) + +func CPUFrequency() uint32 { + return 32000000 +} + +//---------- UART related types and code + +// UART representation +type UART struct { + Buffer *RingBuffer + Bus *stm32.USART_Type + Interrupt interrupt.Interrupt + AltFuncSelector stm32.AltFunc +} + +// Configure the UART. +func (uart UART) configurePins(config UARTConfig) { + // enable the alternate functions on the TX and RX pins + config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.AltFuncSelector) + config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.AltFuncSelector) +} + +// UART baudrate calc based on the bus and clockspeed +func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 { + var clock, rate uint32 + switch uart.Bus { + case stm32.LPUSART1: + clock = CPUFrequency() / 2 // APB1 Frequency + rate = uint32((256 * clock) / baudRate) + case stm32.USART1: + clock = CPUFrequency() / 2 // APB2 Frequency + rate = uint32(clock / baudRate) + case stm32.USART2: + clock = CPUFrequency() / 2 // APB1 Frequency + rate = uint32(clock / baudRate) + } + + return rate +} + +//---------- SPI related types and code + +// SPI on the STM32Fxxx using MODER / alternate function pins +type SPI struct { + Bus *stm32.SPI_Type + AltFuncSelector stm32.AltFunc +} + +// Set baud rate for SPI +func (spi SPI) getBaudRate(config SPIConfig) uint32 { + var conf uint32 + + localFrequency := config.Frequency + if spi.Bus != stm32.SPI1 { + // Assume it's SPI2 or SPI3 on APB1 at 1/2 the clock frequency of APB2, so + // we want to pretend to request 2x the baudrate asked for + localFrequency = localFrequency * 2 + } + + // set frequency dependent on PCLK prescaler. Since these are rather weird + // speeds due to the CPU freqency, pick a range up to that frquency for + // clients to use more human-understandable numbers, e.g. nearest 100KHz + + // These are based on APB2 clock frquency (84MHz on the discovery board) + // TODO: also include the MCU/APB clock setting in the equation + switch true { + case localFrequency < 328125: + conf = stm32.SPI_PCLK_256 + case localFrequency < 656250: + conf = stm32.SPI_PCLK_128 + case localFrequency < 1312500: + conf = stm32.SPI_PCLK_64 + case localFrequency < 2625000: + conf = stm32.SPI_PCLK_32 + case localFrequency < 5250000: + conf = stm32.SPI_PCLK_16 + case localFrequency < 10500000: + conf = stm32.SPI_PCLK_8 + // NOTE: many SPI components won't operate reliably (or at all) above 10MHz + // Check the datasheet of the part + case localFrequency < 21000000: + conf = stm32.SPI_PCLK_4 + case localFrequency < 42000000: + conf = stm32.SPI_PCLK_2 + default: + // None of the specific baudrates were selected; choose the lowest speed + conf = stm32.SPI_PCLK_256 + } + + return conf << stm32.SPI_CR1_BR_Pos +} + +// Configure SPI pins for input output and clock +func (spi SPI) configurePins(config SPIConfig) { + config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector) + config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector) + config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector) +} diff --git a/src/runtime/runtime_stm32l0x2.go b/src/runtime/runtime_stm32l0x2.go new file mode 100644 index 0000000000..f2c9b3ee75 --- /dev/null +++ b/src/runtime/runtime_stm32l0x2.go @@ -0,0 +1,281 @@ +// +build stm32,stm32l0x2 + +package runtime + +import ( + "device/arm" + "device/stm32" + "machine" + "runtime/interrupt" + "runtime/volatile" +) + +func init() { + initCLK() + initRTC() + initTIM() + machine.UART0.Configure(machine.UARTConfig{}) +} + +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 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_DIV_2) + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_DIV_2) + + // Enable the HSI16 oscillator, since the L0 series boots to the MSI one. + stm32.RCC.CR.SetBits(stm32.RCC_CR_HSI16ON) + + // Wait for HSI16 to be ready + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSI16RDYF) { + } + + // Configure the PLL to use HSI16 with a PLLDIV of 2 and PLLMUL of 4. + stm32.RCC.CFGR.SetBits(0b01< 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 + +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)) + /* + if subsec > prediv { + tsec-- + } + */ + + timerCounter := uint64(tsec * 1000) // Timestamp in millis + timerCounter += ssec // Add sub-seconds + timerCounter *= 1000 // Convert to micros + + //println("RTC:") + //println(" rTime:", rTime) + //println(" rDate:", rDate) + //println(" tsec:", tsec) + //println(" subsec:", rSubSec) + //println(" prediv:", prediv) + //println(ssec, "/", prediv) + + // 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 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(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) + + //machine.LED_BLUE.High() + + // timer was triggered + timerWakeup.Set(1) + } +} + +/* +func toggleLed() { + if machine.LED_BLUE.Get() { + machine.LED_BLUE.Low() + } else { + machine.LED_BLUE.High() + } +} +*/ + +// Helper function to connect SYSCLK to a PA8 +// (To ensure clock configuration is OK) +/* +func sysclt_clockout() { + // Configure SysClk with Prescaler 16 as Clockout + stm32.RCC.CFGR.ReplaceBits(0b01000001, 0xff, 24) + + // Set alternate function PA8 AF0 (MCO) + stm32.GPIOA.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, 8*2) + stm32.GPIOA.AFRH.ReplaceBits(0b0000, 0xf, 0) +} +*/ diff --git a/targets/lgt92.json b/targets/lgt92.json new file mode 100644 index 0000000000..5089126bad --- /dev/null +++ b/targets/lgt92.json @@ -0,0 +1,23 @@ +{ + "inherits": [ + "cortex-m" + ], + "llvm-target": "armv6m-none-eabi", + "build-tags": [ + "lgt92", + "stm32l0", + "stm32l0x2", + "stm32" + ], + "cflags": [ + "--target=armv6m-none-eabi", + "-Qunused-arguments" + ], + "linkerscript": "targets/stm32l072czt6.ld", + "extra-files": [ + "src/device/stm32/stm32l0x2.s" + ], + "flash-method": "openocd", + "openocd-interface": "stlink-v2", + "openocd-target": "stm32f0x" +} diff --git a/targets/stm32l072czt6.ld b/targets/stm32l072czt6.ld new file mode 100644 index 0000000000..358f87bc8a --- /dev/null +++ b/targets/stm32l072czt6.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 128K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +} + +_stack_size = 2K; + +INCLUDE "targets/arm.ld" From 931cbcb7aa1232266565a18f45fb9b249c8684a0 Mon Sep 17 00:00:00 2001 From: Olivier Fauchon Date: Tue, 5 Jan 2021 15:11:35 +0100 Subject: [PATCH 2/8] - Dead code removed - lgt92.json now inherits stm32l0x2.json --- src/runtime/runtime_stm32l0x2.go | 67 -------------------------------- targets/lgt92.json | 17 ++------ targets/stm32l0x2.json | 23 +++++++++++ 3 files changed, 26 insertions(+), 81 deletions(-) create mode 100644 targets/stm32l0x2.json diff --git a/src/runtime/runtime_stm32l0x2.go b/src/runtime/runtime_stm32l0x2.go index f2c9b3ee75..94c7b1f322 100644 --- a/src/runtime/runtime_stm32l0x2.go +++ b/src/runtime/runtime_stm32l0x2.go @@ -56,9 +56,6 @@ func initCLK() { // Use PLL As System clock stm32.RCC.CFGR.SetBits(0b11) - // sysclt_clockout will clock out systemclck to PA8 to control - // the clock with logic analtzer - //sysclt_clockout() } var ( @@ -162,24 +159,11 @@ func ticks() timeUnit { //Second fraction in milliseconds ssec := uint64((1000 * (prediv - rSubSec)) / (prediv + 1)) - /* - if subsec > prediv { - tsec-- - } - */ timerCounter := uint64(tsec * 1000) // Timestamp in millis timerCounter += ssec // Add sub-seconds timerCounter *= 1000 // Convert to micros - //println("RTC:") - //println(" rTime:", rTime) - //println(" rDate:", rDate) - //println(" tsec:", tsec) - //println(" subsec:", rSubSec) - //println(" prediv:", prediv) - //println(ssec, "/", prediv) - // change since last measurement offset := (timerCounter - timerLastCounter) timerLastCounter = timerCounter @@ -191,32 +175,6 @@ func ticks() timeUnit { 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 32mhz to 10khz aka 0.1 ms frequency. clk := machine.CPUFrequency() / 2 stm32.TIM3.PSC.Set(clk/10000 - 1) @@ -250,32 +208,7 @@ func handleTIM3(interrupt.Interrupt) { // clear the update flag stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF) - //machine.LED_BLUE.High() - // timer was triggered timerWakeup.Set(1) } } - -/* -func toggleLed() { - if machine.LED_BLUE.Get() { - machine.LED_BLUE.Low() - } else { - machine.LED_BLUE.High() - } -} -*/ - -// Helper function to connect SYSCLK to a PA8 -// (To ensure clock configuration is OK) -/* -func sysclt_clockout() { - // Configure SysClk with Prescaler 16 as Clockout - stm32.RCC.CFGR.ReplaceBits(0b01000001, 0xff, 24) - - // Set alternate function PA8 AF0 (MCO) - stm32.GPIOA.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, 8*2) - stm32.GPIOA.AFRH.ReplaceBits(0b0000, 0xf, 0) -} -*/ diff --git a/targets/lgt92.json b/targets/lgt92.json index 5089126bad..82c603a9b3 100644 --- a/targets/lgt92.json +++ b/targets/lgt92.json @@ -1,23 +1,12 @@ { "inherits": [ - "cortex-m" + "stm32l0x2" ], - "llvm-target": "armv6m-none-eabi", "build-tags": [ - "lgt92", - "stm32l0", - "stm32l0x2", - "stm32" - ], - "cflags": [ - "--target=armv6m-none-eabi", - "-Qunused-arguments" + "lgt92" ], "linkerscript": "targets/stm32l072czt6.ld", - "extra-files": [ - "src/device/stm32/stm32l0x2.s" - ], "flash-method": "openocd", "openocd-interface": "stlink-v2", "openocd-target": "stm32f0x" -} +} \ No newline at end of file diff --git a/targets/stm32l0x2.json b/targets/stm32l0x2.json new file mode 100644 index 0000000000..a24e75078b --- /dev/null +++ b/targets/stm32l0x2.json @@ -0,0 +1,23 @@ +{ + "inherits": [ + "cortex-m" + ], + "llvm-target": "armv6m-none-eabi", + "build-tags": [ + "lgt92", + "stm32l0", + "stm32l0x2", + "stm32" + ], + "cflags": [ + "--target=armv6m-none-eabi", + "-Qunused-arguments" + ], + "linkerscript": "targets/stm32l072czt6.ld", + "extra-files": [ + "src/device/stm32/stm32l0x2.s" + ], + "flash-method": "openocd", + "openocd-interface": "stlink-v2", + "openocd-target": "stm32f0x" +} \ No newline at end of file From b57d0f16a2d6b2aeb0abe6cb42ee90c16cacb0d2 Mon Sep 17 00:00:00 2001 From: Olivier Fauchon Date: Tue, 5 Jan 2021 15:18:08 +0100 Subject: [PATCH 3/8] removed lgt92 build tag in stm32l0x2.json --- targets/stm32l0x2.json | 1 - 1 file changed, 1 deletion(-) diff --git a/targets/stm32l0x2.json b/targets/stm32l0x2.json index a24e75078b..9aacdb2360 100644 --- a/targets/stm32l0x2.json +++ b/targets/stm32l0x2.json @@ -4,7 +4,6 @@ ], "llvm-target": "armv6m-none-eabi", "build-tags": [ - "lgt92", "stm32l0", "stm32l0x2", "stm32" From 14eb657aa4b7d5d0c81c782fa218f9fffacc66f8 Mon Sep 17 00:00:00 2001 From: Olivier Fauchon Date: Wed, 6 Jan 2021 17:15:41 +0100 Subject: [PATCH 4/8] Add smoketest for lgt92 Add default LED declaration so example compiles Remove useless hardware init and comments Move all machine_stm32l0x2 code back to machine_stm32l0 as it'll probably work for stm32l0x1 Move Flash-method,linkerscript... from chip target to board target json --- Makefile | 2 + src/machine/board_lgt92.go | 73 +++++++------------- src/machine/machine_stm32l0.go | 115 ++++++++++++++++++++++++++++--- src/machine/machine_stm32l0x2.go | 108 ----------------------------- targets/stm32l0x2.json | 6 +- 5 files changed, 131 insertions(+), 173 deletions(-) delete mode 100644 src/machine/machine_stm32l0x2.go diff --git a/Makefile b/Makefile index ac9284bacb..20bb409bd1 100644 --- a/Makefile +++ b/Makefile @@ -295,6 +295,8 @@ smoketest: @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=pinetime-devkit0 examples/blinky1 @$(MD5SUM) test.hex + $(TINYGO) build -size short -o test.hex -target=lgt92 examples/blinky1 + @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=x9pro examples/blinky1 @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=pca10056-s140v7 examples/blinky1 diff --git a/src/machine/board_lgt92.go b/src/machine/board_lgt92.go index 321731c37a..ed2e6b5e52 100644 --- a/src/machine/board_lgt92.go +++ b/src/machine/board_lgt92.go @@ -16,6 +16,9 @@ const ( LED_BLUE = LED2 LED_GREEN = LED3 + // Default led + LED = LED1 + BUTTON = PB14 // LG GPS module @@ -23,7 +26,19 @@ const ( GPS_RESET_PIN = PB4 GPS_POWER_PIN = PB5 - // LORA + MEMS_ACCEL_CS = PE3 + MEMS_ACCEL_INT1 = PE0 + MEMS_ACCEL_INT2 = PE1 + + // SPI + SPI1_SCK_PIN = PA5 + SPI1_SDI_PIN = PA6 + SPI1_SDO_PIN = PA7 + SPI0_SCK_PIN = SPI1_SCK_PIN + SPI0_SDI_PIN = SPI1_SDI_PIN + SPI0_SDO_PIN = SPI1_SDO_PIN + + // LORA RFM95 Radio RFM95_DIO0_PIN = PC13 //TinyGo UART is MCU LPUSART1 @@ -50,58 +65,16 @@ var ( Bus: stm32.USART1, AltFuncSelector: 0, } -) - -// set up RX IRQ handler. Follow similar pattern for other UARTx instances -func init() { - - // Enable GPIOs - stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPAEN) - stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPBEN) - stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPCEN) - - // Enable NVM (eeprom) - stm32.RCC.AHBENR.SetBits(stm32.RCC_AHBENR_MIFEN) - - // Enable Leds GPIO output - LED_RED.Configure(PinConfig{Mode: PinOutput}) - LED_GREEN.Configure(PinConfig{Mode: PinOutput}) - LED_BLUE.Configure(PinConfig{Mode: PinOutput}) - LED_RED.Low() - LED_GREEN.Low() - LED_BLUE.Low() - - // Enable UART0 (MCU LPUART1) Interrupt - // Enable UART1 (MCU UART1) Interrupt - UART0.Interrupt = interrupt.New(stm32.IRQ_AES_RNG_LPUART1, UART0.handleInterrupt) - UART1.Interrupt = interrupt.New(stm32.IRQ_USART1, UART1.handleInterrupt) - -} - -// SPI pins -const ( - SPI1_SCK_PIN = PA5 - SPI1_SDI_PIN = PA6 - SPI1_SDO_PIN = PA7 - SPI0_SCK_PIN = SPI1_SCK_PIN - SPI0_SDI_PIN = SPI1_SDI_PIN - SPI0_SDO_PIN = SPI1_SDO_PIN -) - -// MEMs accelerometer -const ( - MEMS_ACCEL_CS = PE3 - MEMS_ACCEL_INT1 = PE0 - MEMS_ACCEL_INT2 = PE1 -) - -// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1. -// TODO: implement SPI2 and SPI3. -var ( + // SPI SPI0 = SPI{ Bus: stm32.SPI1, - // AltFuncSelector: stm32.AF5_SPI1_SPI2, } SPI1 = &SPI0 ) + +func init() { + // Enable UARTs Interrupts + UART0.Interrupt = interrupt.New(stm32.IRQ_AES_RNG_LPUART1, UART0.handleInterrupt) + UART1.Interrupt = interrupt.New(stm32.IRQ_USART1, UART1.handleInterrupt) +} diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go index 6a9d14f123..115e0ec450 100644 --- a/src/machine/machine_stm32l0.go +++ b/src/machine/machine_stm32l0.go @@ -6,9 +6,14 @@ package machine import ( "device/stm32" + "runtime/interrupt" "unsafe" ) +func CPUFrequency() uint32 { + return 32000000 +} + const ( PA0 = portA + 0 PA1 = portA + 1 @@ -111,14 +116,8 @@ func (p Pin) getPort() *stm32.GPIO_Type { return stm32.GPIOD case 4: return stm32.GPIOE - // case 5: - // return stm32.GPIOF - // case 6: - // return stm32.GPIOG case 7: return stm32.GPIOH - // case 8: - // return stm32.GPIOI default: panic("machine: unknown port") } @@ -185,9 +184,105 @@ func enableAltFuncClock(bus unsafe.Pointer) { stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN) case unsafe.Pointer(stm32.USART1): // USART1 clock enable stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) - // case unsafe.Pointer(stm32.TIM8): // TIM8 clock enable - // stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM8EN) - // case unsafe.Pointer(stm32.TIM1): // TIM1 clock enable - // stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB) } } + +//---------- UART related types and code + +// UART representation +type UART struct { + Buffer *RingBuffer + Bus *stm32.USART_Type + Interrupt interrupt.Interrupt + AltFuncSelector stm32.AltFunc +} + +// Configure the UART. +func (uart UART) configurePins(config UARTConfig) { + // enable the alternate functions on the TX and RX pins + config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.AltFuncSelector) + config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.AltFuncSelector) +} + +// UART baudrate calc based on the bus and clockspeed +func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 { + var clock, rate uint32 + switch uart.Bus { + case stm32.LPUSART1: + clock = CPUFrequency() / 2 // APB1 Frequency + rate = uint32((256 * clock) / baudRate) + case stm32.USART1: + clock = CPUFrequency() / 2 // APB2 Frequency + rate = uint32(clock / baudRate) + case stm32.USART2: + clock = CPUFrequency() / 2 // APB1 Frequency + rate = uint32(clock / baudRate) + } + + return rate +} + +//---------- SPI related types and code + +// SPI on the STM32Fxxx using MODER / alternate function pins +type SPI struct { + Bus *stm32.SPI_Type + AltFuncSelector stm32.AltFunc +} + +// Set baud rate for SPI +func (spi SPI) getBaudRate(config SPIConfig) uint32 { + var conf uint32 + + localFrequency := config.Frequency + + // Default + if config.Frequency == 0 { + config.Frequency = 4e6 + } + + if spi.Bus != stm32.SPI1 { + // Assume it's SPI2 or SPI3 on APB1 at 1/2 the clock frequency of APB2, so + // we want to pretend to request 2x the baudrate asked for + localFrequency = localFrequency * 2 + } + + // set frequency dependent on PCLK prescaler. Since these are rather weird + // speeds due to the CPU freqency, pick a range up to that frquency for + // clients to use more human-understandable numbers, e.g. nearest 100KHz + + // These are based on APB2 clock frquency (84MHz on the discovery board) + // TODO: also include the MCU/APB clock setting in the equation + switch { + case localFrequency < 328125: + conf = stm32.SPI_PCLK_256 + case localFrequency < 656250: + conf = stm32.SPI_PCLK_128 + case localFrequency < 1312500: + conf = stm32.SPI_PCLK_64 + case localFrequency < 2625000: + conf = stm32.SPI_PCLK_32 + case localFrequency < 5250000: + conf = stm32.SPI_PCLK_16 + case localFrequency < 10500000: + conf = stm32.SPI_PCLK_8 + // NOTE: many SPI components won't operate reliably (or at all) above 10MHz + // Check the datasheet of the part + case localFrequency < 21000000: + conf = stm32.SPI_PCLK_4 + case localFrequency < 42000000: + conf = stm32.SPI_PCLK_2 + default: + // None of the specific baudrates were selected; choose the lowest speed + conf = stm32.SPI_PCLK_256 + } + + return conf << stm32.SPI_CR1_BR_Pos +} + +// Configure SPI pins for input output and clock +func (spi SPI) configurePins(config SPIConfig) { + config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector) + config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector) + config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector) +} diff --git a/src/machine/machine_stm32l0x2.go b/src/machine/machine_stm32l0x2.go deleted file mode 100644 index 88bb9e30d3..0000000000 --- a/src/machine/machine_stm32l0x2.go +++ /dev/null @@ -1,108 +0,0 @@ -// +build stm32l0x2 - -package machine - -// Peripheral abstraction layer for the stm32l0x2 - -import ( - "device/stm32" - "runtime/interrupt" -) - -func CPUFrequency() uint32 { - return 32000000 -} - -//---------- UART related types and code - -// UART representation -type UART struct { - Buffer *RingBuffer - Bus *stm32.USART_Type - Interrupt interrupt.Interrupt - AltFuncSelector stm32.AltFunc -} - -// Configure the UART. -func (uart UART) configurePins(config UARTConfig) { - // enable the alternate functions on the TX and RX pins - config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.AltFuncSelector) - config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.AltFuncSelector) -} - -// UART baudrate calc based on the bus and clockspeed -func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 { - var clock, rate uint32 - switch uart.Bus { - case stm32.LPUSART1: - clock = CPUFrequency() / 2 // APB1 Frequency - rate = uint32((256 * clock) / baudRate) - case stm32.USART1: - clock = CPUFrequency() / 2 // APB2 Frequency - rate = uint32(clock / baudRate) - case stm32.USART2: - clock = CPUFrequency() / 2 // APB1 Frequency - rate = uint32(clock / baudRate) - } - - return rate -} - -//---------- SPI related types and code - -// SPI on the STM32Fxxx using MODER / alternate function pins -type SPI struct { - Bus *stm32.SPI_Type - AltFuncSelector stm32.AltFunc -} - -// Set baud rate for SPI -func (spi SPI) getBaudRate(config SPIConfig) uint32 { - var conf uint32 - - localFrequency := config.Frequency - if spi.Bus != stm32.SPI1 { - // Assume it's SPI2 or SPI3 on APB1 at 1/2 the clock frequency of APB2, so - // we want to pretend to request 2x the baudrate asked for - localFrequency = localFrequency * 2 - } - - // set frequency dependent on PCLK prescaler. Since these are rather weird - // speeds due to the CPU freqency, pick a range up to that frquency for - // clients to use more human-understandable numbers, e.g. nearest 100KHz - - // These are based on APB2 clock frquency (84MHz on the discovery board) - // TODO: also include the MCU/APB clock setting in the equation - switch true { - case localFrequency < 328125: - conf = stm32.SPI_PCLK_256 - case localFrequency < 656250: - conf = stm32.SPI_PCLK_128 - case localFrequency < 1312500: - conf = stm32.SPI_PCLK_64 - case localFrequency < 2625000: - conf = stm32.SPI_PCLK_32 - case localFrequency < 5250000: - conf = stm32.SPI_PCLK_16 - case localFrequency < 10500000: - conf = stm32.SPI_PCLK_8 - // NOTE: many SPI components won't operate reliably (or at all) above 10MHz - // Check the datasheet of the part - case localFrequency < 21000000: - conf = stm32.SPI_PCLK_4 - case localFrequency < 42000000: - conf = stm32.SPI_PCLK_2 - default: - // None of the specific baudrates were selected; choose the lowest speed - conf = stm32.SPI_PCLK_256 - } - - return conf << stm32.SPI_CR1_BR_Pos -} - -// Configure SPI pins for input output and clock -func (spi SPI) configurePins(config SPIConfig) { - config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector) - config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector) - config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector) -} diff --git a/targets/stm32l0x2.json b/targets/stm32l0x2.json index 9aacdb2360..666441fb1d 100644 --- a/targets/stm32l0x2.json +++ b/targets/stm32l0x2.json @@ -12,11 +12,7 @@ "--target=armv6m-none-eabi", "-Qunused-arguments" ], - "linkerscript": "targets/stm32l072czt6.ld", "extra-files": [ "src/device/stm32/stm32l0x2.s" - ], - "flash-method": "openocd", - "openocd-interface": "stlink-v2", - "openocd-target": "stm32f0x" + ] } \ No newline at end of file From 7e7b8d14b83fa4ed7df4bfd5676a7bbc45951ee6 Mon Sep 17 00:00:00 2001 From: Olivier Fauchon Date: Wed, 6 Jan 2021 23:05:43 +0100 Subject: [PATCH 5/8] Moved runtime_stm32l0x2 in runtime_stm32l0 --- src/runtime/{runtime_stm32l0x2.go => runtime_stm32l0.go} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/runtime/{runtime_stm32l0x2.go => runtime_stm32l0.go} (99%) diff --git a/src/runtime/runtime_stm32l0x2.go b/src/runtime/runtime_stm32l0.go similarity index 99% rename from src/runtime/runtime_stm32l0x2.go rename to src/runtime/runtime_stm32l0.go index 94c7b1f322..bb043a3e4c 100644 --- a/src/runtime/runtime_stm32l0x2.go +++ b/src/runtime/runtime_stm32l0.go @@ -1,4 +1,4 @@ -// +build stm32,stm32l0x2 +// +build stm32,stm32l0 package runtime From 7e246d73a13c364f33915361e04cc374730a3be9 Mon Sep 17 00:00:00 2001 From: Olivier Fauchon Date: Thu, 7 Jan 2021 01:10:33 +0100 Subject: [PATCH 6/8] Add some registers const to avoid the use of an extra stm32l0x2-bitfields.go file. --- src/runtime/runtime_stm32l0.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go index bb043a3e4c..a42b025179 100644 --- a/src/runtime/runtime_stm32l0.go +++ b/src/runtime/runtime_stm32l0.go @@ -10,6 +10,23 @@ import ( "runtime/volatile" ) +const ( + // Sets PCLK1 + RCC_CFGR_PPRE1_DIV_NONE = 0x00000000 + RCC_CFGR_PPRE1_DIV_2 = 0x00000400 + RCC_CFGR_PPRE1_DIV_4 = 0x00000500 + RCC_CFGR_PPRE1_DIV_8 = 0x00000600 + RCC_CFGR_PPRE1_DIV_16 = 0x00000700 + + // Sets PCLK2 + RCC_CFGR_PPRE2_DIV_NONE = 0x00000000 + RCC_CFGR_PPRE2_DIV_2 = 0x00002000 + RCC_CFGR_PPRE2_DIV_4 = 0x00002800 + RCC_CFGR_PPRE2_DIV_8 = 0x00003000 + RCC_CFGR_PPRE2_DIV_16 = 0x00003800 + +) + func init() { initCLK() initRTC() @@ -31,8 +48,8 @@ func initCLK() { 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_DIV_2) - stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_DIV_2) + stm32.RCC.CFGR.SetBits(RCC_CFGR_PPRE1_DIV_2) + stm32.RCC.CFGR.SetBits(RCC_CFGR_PPRE2_DIV_2) // Enable the HSI16 oscillator, since the L0 series boots to the MSI one. stm32.RCC.CR.SetBits(stm32.RCC_CR_HSI16ON) From d644a9329f9305b3f1ab2a41091a1f43859d0e9f Mon Sep 17 00:00:00 2001 From: Olivier Fauchon Date: Thu, 7 Jan 2021 12:42:43 +0100 Subject: [PATCH 7/8] Remove binary integer prefix 0b, for Golang<1.13 backward compatibility --- src/runtime/runtime_stm32l0.go | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go index a42b025179..e6b0298a6e 100644 --- a/src/runtime/runtime_stm32l0.go +++ b/src/runtime/runtime_stm32l0.go @@ -11,20 +11,19 @@ import ( ) const ( - // Sets PCLK1 - RCC_CFGR_PPRE1_DIV_NONE = 0x00000000 - RCC_CFGR_PPRE1_DIV_2 = 0x00000400 - RCC_CFGR_PPRE1_DIV_4 = 0x00000500 - RCC_CFGR_PPRE1_DIV_8 = 0x00000600 - RCC_CFGR_PPRE1_DIV_16 = 0x00000700 - - // Sets PCLK2 - RCC_CFGR_PPRE2_DIV_NONE = 0x00000000 - RCC_CFGR_PPRE2_DIV_2 = 0x00002000 - RCC_CFGR_PPRE2_DIV_4 = 0x00002800 - RCC_CFGR_PPRE2_DIV_8 = 0x00003000 - RCC_CFGR_PPRE2_DIV_16 = 0x00003800 - + // Sets PCLK1 + RCC_CFGR_PPRE1_DIV_NONE = 0x00000000 + RCC_CFGR_PPRE1_DIV_2 = 0x00000400 + RCC_CFGR_PPRE1_DIV_4 = 0x00000500 + RCC_CFGR_PPRE1_DIV_8 = 0x00000600 + RCC_CFGR_PPRE1_DIV_16 = 0x00000700 + + // Sets PCLK2 + RCC_CFGR_PPRE2_DIV_NONE = 0x00000000 + RCC_CFGR_PPRE2_DIV_2 = 0x00002000 + RCC_CFGR_PPRE2_DIV_4 = 0x00002800 + RCC_CFGR_PPRE2_DIV_8 = 0x00003000 + RCC_CFGR_PPRE2_DIV_16 = 0x00003800 ) func init() { @@ -59,8 +58,8 @@ func initCLK() { } // Configure the PLL to use HSI16 with a PLLDIV of 2 and PLLMUL of 4. - stm32.RCC.CFGR.SetBits(0b01< Date: Thu, 7 Jan 2021 14:37:34 +0100 Subject: [PATCH 8/8] Remove more binary integer prefix 0b, for Golang<1.13 backward compatibility --- src/runtime/runtime_stm32l0.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go index e6b0298a6e..daab1276b7 100644 --- a/src/runtime/runtime_stm32l0.go +++ b/src/runtime/runtime_stm32l0.go @@ -70,7 +70,7 @@ func initCLK() { } // Use PLL As System clock - stm32.RCC.CFGR.SetBits(0b11) + stm32.RCC.CFGR.SetBits(0x3) } @@ -97,8 +97,8 @@ func initRTC() { } // Select Clock Source LSE - stm32.RCC.CSR.SetBits(0b01 << stm32.RCC_CSR_RTCSEL_Pos) - stm32.RCC.CSR.ClearBits(0b10 << stm32.RCC_CSR_RTCSEL_Pos) + 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)