Improvements for stm32wle targets :

- board/stm32: Add STM32 Nucleo WL55JC board
- stm32/stm32wl: Set 48Mhz HSE32/PLL as default Clock, SPI implementation
Этот коммит содержится в:
Olivier Fauchon 2021-11-20 21:08:42 +01:00 коммит произвёл Ron Evans
родитель 718746dd21
коммит b0fce80b50
9 изменённых файлов: 249 добавлений и 15 удалений

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

@ -435,6 +435,8 @@ ifneq ($(STM32), 0)
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-l552ze examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-wl55jc examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=stm32f4disco examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=stm32f4disco examples/blinky2

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

@ -43,7 +43,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
The following 72 microcontroller boards are currently supported:
The following 74 microcontroller boards are currently supported:
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
@ -115,6 +115,7 @@ The following 72 microcontroller boards are currently supported:
* [ST Micro "Nucleo" L031K6](https://www.st.com/ja/evaluation-tools/nucleo-l031k6.html)
* [ST Micro "Nucleo" L432KC](https://www.st.com/ja/evaluation-tools/nucleo-l432kc.html)
* [ST Micro "Nucleo" L552ZE](https://www.st.com/en/evaluation-tools/nucleo-l552ze-q.html)
* [ST Micro "Nucleo" WL55JC](https://www.st.com/en/evaluation-tools/nucleo-wl55jc.html)
* [ST Micro STM32F103XX "Bluepill"](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill)
* [ST Micro STM32F407 "Discovery"](https://www.st.com/en/evaluation-tools/stm32f4discovery.html)
* [X9 Pro smartwatch](https://github.com/curtpw/nRF5x-device-reverse-engineering/tree/master/X9-nrf52832-activity-tracker/)

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

@ -9,8 +9,8 @@ import (
)
const (
LED1 = PB5
LED = LED1 // Default LED
// We assume a LED is connected on PB5
LED = PB5 // Default LED
)
// SubGhz (SPI3)
@ -46,6 +46,11 @@ var (
RxAltFuncSelector: AF7_USART1_2,
}
DefaultUART = UART0
// SPI
SPI3 = SPI{
Bus: stm32.SPI3,
}
)
func init() {

72
src/machine/board_nucleowl55jc.go Обычный файл
Просмотреть файл

@ -0,0 +1,72 @@
//go:build nucleowl55jc
// +build nucleowl55jc
package machine
import (
"device/stm32"
"runtime/interrupt"
)
const (
LED_BLUE = PB15
LED_GREEN = PB9
LED_RED = PB11
LED = LED_RED
BTN1 = PA0
BTN2 = PA1
BTN3 = PC6
BUTTON = BTN1
// SubGhz (SPI3)
SPI0_NSS_PIN = PA4
SPI0_SCK_PIN = PA5
SPI0_SDO_PIN = PA6
SPI0_SDI_PIN = PA7
//MCU USART1
UART1_TX_PIN = PB6
UART1_RX_PIN = PB7
//MCU USART2
UART2_RX_PIN = PA3
UART2_TX_PIN = PA2
// DEFAULT USART
UART_RX_PIN = UART2_RX_PIN
UART_TX_PIN = UART2_TX_PIN
)
var (
// STM32 UART2 is connected to the embedded STLINKV3 Virtual Com Port
UART0 = &_UART0
_UART0 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.USART2,
TxAltFuncSelector: 7,
RxAltFuncSelector: 7,
}
// UART1 is free
UART1 = &_UART1
_UART1 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.USART1,
TxAltFuncSelector: 7,
RxAltFuncSelector: 7,
}
DefaultUART = UART0
// SPI
SPI3 = SPI{
Bus: stm32.SPI3,
}
)
func init() {
// Enable UARTs Interrupts
UART0.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART0.handleInterrupt)
UART1.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART1.handleInterrupt)
}

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

@ -1,5 +1,5 @@
//go:build stm32 && !stm32f7x2 && !stm32l5x2 && !stm32wle5
// +build stm32,!stm32f7x2,!stm32l5x2,!stm32wle5
//go:build stm32 && !stm32f7x2 && !stm32l5x2
// +build stm32,!stm32f7x2,!stm32l5x2
package machine

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

@ -7,6 +7,7 @@ package machine
import (
"device/stm32"
"math/bits"
"runtime/interrupt"
"runtime/volatile"
"unsafe"
@ -28,12 +29,15 @@ const (
AF15_EVENTOUT = 15
)
func CPUFrequency() uint32 {
return 4e6
}
const (
SYSCLK = 48e6
APB1_TIM_FREQ = SYSCLK
APB2_TIM_FREQ = SYSCLK
)
const APB1_TIM_FREQ = 4e6
const APB2_TIM_FREQ = 4e6
func CPUFrequency() uint32 {
return SYSCLK
}
const (
PA0 = portA + 0
@ -221,6 +225,64 @@ func (p Pin) registerInterrupt() interrupt.Interrupt {
return interrupt.Interrupt{}
}
// -- SPI ----------------------------------------------------------------------
type SPI struct {
Bus *stm32.SPI_Type
AltFuncSelector uint8
}
func (spi SPI) config8Bits() {
// Set rx threshold to 8-bits, so RXNE flag is set for 1 byte
// (common STM32 SPI implementation does 8-bit transfers only)
spi.Bus.CR2.SetBits(stm32.SPI_CR2_FRXTH)
}
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)
}
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
var clock uint32
// We keep this switch and separate management of SPI Clocks
// for future improvement of system/bus clocks and prescalers
switch spi.Bus {
case stm32.SPI1:
clock = CPUFrequency()
case stm32.SPI2, stm32.SPI3:
clock = CPUFrequency()
}
// limit requested frequency to bus frequency and min frequency (DIV256)
freq := config.Frequency
if min := clock / 256; freq < min {
freq = min
} else if freq > clock {
freq = clock
}
// calculate the exact clock divisor (freq=clock/div -> div=clock/freq).
// truncation is fine, since it produces a less-than-or-equal divisor, and
// thus a greater-than-or-equal frequency.
// divisors only come in consecutive powers of 2, so we can use log2 (or,
// equivalently, bits.Len - 1) to convert to respective enum value.
div := bits.Len32(clock/freq) - 1
// but DIV1 (2^0) is not permitted, as the least divisor is DIV2 (2^1), so
// subtract 1 from the log2 value, keeping a lower bound of 0
if div < 0 {
div = 0
} else if div > 0 {
div--
}
// finally, shift the enumerated value into position for SPI CR1
return uint32(div) << stm32.SPI_CR1_BR_Pos
}
//---------- UART related code
// Configure the UART.

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

@ -1,5 +1,5 @@
//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2 && !stm32wle5) || fe310 || k210 || atmega
// +build !baremetal stm32,!stm32f7x2,!stm32l5x2,!stm32wle5 fe310 k210 atmega
//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2) || fe310 || k210 || atmega
// +build !baremetal stm32,!stm32f7x2,!stm32l5x2 fe310 k210 atmega
package machine

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

@ -4,21 +4,100 @@
package runtime
import (
"device/stm32"
"machine"
)
type arrtype = uint32
const (
/* PLL Options RMN0461.p247 */
PLL_M = 2
PLL_N = 6
PLL_R = 2
PLL_P = 2
PLL_Q = 2
)
func init() {
// Currently the clock is not configured, which means
// the MCU runs at default reset clock speed (4Mhz).
// Code to initialize RCC and PLL can go here.
// Configure 48Mhz clock
initCLK()
// UART init
machine.Serial.Configure(machine.UARTConfig{})
// Timers init
initTickTimer(&machine.TIM1)
}
func initCLK() {
// Enable HSE32 VDDTCXO output on package pin PB0-VDDTCXO
stm32.RCC.CR.ReplaceBits(stm32.RCC_CR_HSEBYPPWR_VDDTCXO, stm32.RCC_CR_HSEBYPPWR_Msk, 0)
// SYSCLOCK from HSE32 clock division factor (SYSCLOCK=HSE32)
stm32.RCC.CR.ReplaceBits(stm32.RCC_CR_HSEPRE_Div1, stm32.RCC_CR_HSEPRE_Msk, 0)
// enable external Clock HSE32 TXCO (RM0461p226)
stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEBYPPWR)
stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON)
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {
}
// Disable PLL
stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)
for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
}
// Configure the PLL
stm32.RCC.PLLCFGR.Set((PLL_M-1)<<stm32.RCC_PLLCFGR_PLLM_Pos |
((PLL_N) << stm32.RCC_PLLCFGR_PLLN_Pos) |
((PLL_Q - 1) << stm32.RCC_PLLCFGR_PLLQ_Pos) |
((PLL_R - 1) << stm32.RCC_PLLCFGR_PLLR_Pos) |
((PLL_P - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) |
stm32.RCC_PLLCFGR_PLLSRC_HSE32 | stm32.RCC_PLLCFGR_PLLPEN)
// Enable PLL
stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
}
// Enable PLL System Clock output.
stm32.RCC.PLLCFGR.SetBits(stm32.RCC_PLLCFGR_PLLREN)
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
}
// Set Flash Latency of 2
stm32.FLASH.ACR.ReplaceBits(stm32.Flash_ACR_LATENCY_WS2, stm32.Flash_ACR_LATENCY_Msk, 0)
for (stm32.FLASH.ACR.Get() & stm32.Flash_ACR_LATENCY_Msk) != stm32.Flash_ACR_LATENCY_WS2 {
}
// HCLK1 clock division factor
stm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_HPRE_Div1, stm32.RCC_CFGR_HPRE_Msk, 0)
for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_HPREF) {
}
// HCLK3 clock division factor
stm32.RCC.EXTCFGR.ReplaceBits(stm32.RCC_EXTCFGR_SHDHPRE_Div1, stm32.RCC_EXTCFGR_SHDHPRE_Msk, 0)
for !stm32.RCC.EXTCFGR.HasBits(stm32.RCC_EXTCFGR_SHDHPREF) {
}
// PCLK1 clock division factor
stm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_PPRE1_Div1, stm32.RCC_CFGR_PPRE1_Msk, 0)
for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_PPRE1F) {
}
// PCLK2 clock division factor
stm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_PPRE2_Div1, stm32.RCC_CFGR_PPRE2_Msk, 0)
for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_PPRE2F) {
}
// Set clock source to PLL
stm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_SW_PLLR, stm32.RCC_CFGR_SW_Msk, 0)
for (stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk) != (stm32.RCC_CFGR_SWS_PLLR << stm32.RCC_CFGR_SWS_Pos) {
}
}
func putchar(c byte) {

13
targets/nucleo-wl55jc.json Обычный файл
Просмотреть файл

@ -0,0 +1,13 @@
{
"inherits": [
"stm32wle5"
],
"build-tags": [
"nucleowl55jc"
],
"serial": "uart",
"linkerscript": "targets/stm32wle5.ld",
"flash-method": "openocd",
"openocd-interface": "stlink",
"openocd-target": "stm32wlx"
}