stm32: add support for the STM32F4Discovery
Signed-off-by: Yusuke Mitsuki <mickey.happygolucky@gmail.com>
Этот коммит содержится в:
родитель
315cd4059f
коммит
1322f404a6
7 изменённых файлов: 571 добавлений и 0 удалений
|
@ -68,6 +68,8 @@ commands:
|
||||||
- run: tinygo build -size short -o test.elf -target=pca10056 examples/blinky2
|
- run: tinygo build -size short -o test.elf -target=pca10056 examples/blinky2
|
||||||
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 examples/blinky1
|
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 examples/blinky1
|
||||||
- run: tinygo build -size short -o test.elf -target=circuitplay-express examples/blinky1
|
- run: tinygo build -size short -o test.elf -target=circuitplay-express examples/blinky1
|
||||||
|
- run: tinygo build -size short -o test.elf -target=stm32f4disco examples/blinky1
|
||||||
|
- run: tinygo build -size short -o test.elf -target=stm32f4disco examples/blinky2
|
||||||
- run: tinygo build -o wasm.wasm -target=wasm examples/wasm
|
- run: tinygo build -o wasm.wasm -target=wasm examples/wasm
|
||||||
test-linux:
|
test-linux:
|
||||||
parameters:
|
parameters:
|
||||||
|
|
112
src/machine/board_stm32f4disco.go
Обычный файл
112
src/machine/board_stm32f4disco.go
Обычный файл
|
@ -0,0 +1,112 @@
|
||||||
|
// +build stm32,stm32f4disco
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LED = LED_BUILTIN
|
||||||
|
LED1 = LED_GREEN
|
||||||
|
LED2 = LED_ORANGE
|
||||||
|
LED3 = LED_RED
|
||||||
|
LED4 = LED_BLUE
|
||||||
|
LED_BUILTIN = LED_GREEN
|
||||||
|
LED_GREEN = PD12
|
||||||
|
LED_ORANGE = PD13
|
||||||
|
LED_RED = PD14
|
||||||
|
LED_BLUE = PD15
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART pins
|
||||||
|
const (
|
||||||
|
UART_TX_PIN = PA2
|
||||||
|
UART_RX_PIN = PA3
|
||||||
|
)
|
|
@ -14,4 +14,5 @@ const (
|
||||||
portE
|
portE
|
||||||
portF
|
portF
|
||||||
portG
|
portG
|
||||||
|
portH
|
||||||
)
|
)
|
||||||
|
|
220
src/machine/machine_stm32f407.go
Обычный файл
220
src/machine/machine_stm32f407.go
Обычный файл
|
@ -0,0 +1,220 @@
|
||||||
|
// +build stm32,stm32f407
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Peripheral abstraction layer for the stm32.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/arm"
|
||||||
|
"device/stm32"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CPU_FREQUENCY = 168000000
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Mode Flag
|
||||||
|
GPIO_OUTPUT = 0
|
||||||
|
GPIO_INPUT = GPIO_INPUT_PULLDOWN
|
||||||
|
GPIO_INPUT_FLOATING = 1
|
||||||
|
GPIO_INPUT_PULLDOWN = 2
|
||||||
|
GPIO_INPUT_PULLUP = 3
|
||||||
|
|
||||||
|
// for UART
|
||||||
|
GPIO_UART_TX = 4
|
||||||
|
GPIO_UART_RX = 5
|
||||||
|
|
||||||
|
//GPIOx_MODER
|
||||||
|
GPIO_MODE_INPUT = 0
|
||||||
|
GPIO_MODE_GENERAL_OUTPUT = 1
|
||||||
|
GPIO_MODE_ALTERNABTIVE = 2
|
||||||
|
GPIO_MODE_ANALOG = 3
|
||||||
|
|
||||||
|
//GPIOx_OTYPER
|
||||||
|
GPIO_OUTPUT_MODE_PUSH_PULL = 0
|
||||||
|
GPIO_OUTPUT_MODE_OPEN_DRAIN = 1
|
||||||
|
|
||||||
|
// GPIOx_OSPEEDR
|
||||||
|
GPIO_SPEED_LOW = 0
|
||||||
|
GPIO_SPEED_MID = 1
|
||||||
|
GPIO_SPEED_HI = 2
|
||||||
|
GPIO_SPEED_VERY_HI = 3
|
||||||
|
|
||||||
|
// GPIOx_PUPDR
|
||||||
|
GPIO_FLOATING = 0
|
||||||
|
GPIO_PULL_UP = 1
|
||||||
|
GPIO_PULL_DOWN = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p GPIO) getPort() *stm32.GPIO_Type {
|
||||||
|
switch p.Pin / 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 GPIO) enableClock() {
|
||||||
|
switch p.Pin / 16 {
|
||||||
|
case 0:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOAEN
|
||||||
|
case 1:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOBEN
|
||||||
|
case 2:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOCEN
|
||||||
|
case 3:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIODEN
|
||||||
|
case 4:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOEEN
|
||||||
|
case 5:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOFEN
|
||||||
|
case 6:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOGEN
|
||||||
|
case 7:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOHEN
|
||||||
|
case 8:
|
||||||
|
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOIEN
|
||||||
|
default:
|
||||||
|
panic("machine: unknown port")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure this pin with the given configuration.
|
||||||
|
func (p GPIO) Configure(config GPIOConfig) {
|
||||||
|
// Configure the GPIO pin.
|
||||||
|
p.enableClock()
|
||||||
|
port := p.getPort()
|
||||||
|
pin := p.Pin % 16
|
||||||
|
pos := pin * 2
|
||||||
|
|
||||||
|
if config.Mode == GPIO_INPUT_FLOATING {
|
||||||
|
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
|
||||||
|
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
|
||||||
|
} else if config.Mode == GPIO_INPUT_PULLDOWN {
|
||||||
|
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
|
||||||
|
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_DOWN) << pos)))
|
||||||
|
} else if config.Mode == GPIO_INPUT_PULLUP {
|
||||||
|
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
|
||||||
|
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
|
||||||
|
} else if config.Mode == GPIO_OUTPUT {
|
||||||
|
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_GENERAL_OUTPUT) << pos)))
|
||||||
|
port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
|
||||||
|
} else if config.Mode == GPIO_UART_TX {
|
||||||
|
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
|
||||||
|
port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
|
||||||
|
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
|
||||||
|
p.setAltFunc(0x7)
|
||||||
|
} else if config.Mode == GPIO_UART_RX {
|
||||||
|
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
|
||||||
|
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
|
||||||
|
p.setAltFunc(0x7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p GPIO) setAltFunc(af uint32) {
|
||||||
|
port := p.getPort()
|
||||||
|
pin := p.Pin % 16
|
||||||
|
pos := pin * 4
|
||||||
|
if pin >= 8 {
|
||||||
|
port.AFRH = stm32.RegValue(uint32(port.AFRH)&^(0xF<<pos) | ((af & 0xF) << pos))
|
||||||
|
} else {
|
||||||
|
port.AFRL = stm32.RegValue(uint32(port.AFRL)&^(0xF<<pos) | ((af & 0xF) << pos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the pin to high or low.
|
||||||
|
// Warning: only use this on an output pin!
|
||||||
|
func (p GPIO) Set(high bool) {
|
||||||
|
port := p.getPort()
|
||||||
|
pin := p.Pin % 16
|
||||||
|
if high {
|
||||||
|
port.BSRR = 1 << pin
|
||||||
|
} else {
|
||||||
|
port.BSRR = 1 << (pin + 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UART
|
||||||
|
type UART struct {
|
||||||
|
Buffer *RingBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Both UART0 and UART1 refer to USART2.
|
||||||
|
UART0 = UART{Buffer: NewRingBuffer()}
|
||||||
|
UART1 = &UART0
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configure the UART.
|
||||||
|
func (uart UART) Configure(config UARTConfig) {
|
||||||
|
// Default baud rate to 115200.
|
||||||
|
if config.BaudRate == 0 {
|
||||||
|
config.BaudRate = 115200
|
||||||
|
}
|
||||||
|
|
||||||
|
// pins
|
||||||
|
switch config.TX {
|
||||||
|
default:
|
||||||
|
// use standard TX/RX pins PA2 and PA3
|
||||||
|
GPIO{UART_TX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_TX})
|
||||||
|
GPIO{UART_RX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_RX})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable USART2 clock
|
||||||
|
stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_USART2EN
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set baud rate(115200)
|
||||||
|
OVER8 = 0, APB2 = 42mhz
|
||||||
|
+----------+--------+
|
||||||
|
| baudrate | BRR |
|
||||||
|
+----------+--------+
|
||||||
|
| 1200 | 0x88B8 |
|
||||||
|
| 2400 | 0x445C |
|
||||||
|
| 9600 | 0x1117 |
|
||||||
|
| 19200 | 0x88C |
|
||||||
|
| 38400 | 0x446 |
|
||||||
|
| 57600 | 0x2D9 |
|
||||||
|
| 115200 | 0x16D |
|
||||||
|
+----------+--------+
|
||||||
|
*/
|
||||||
|
stm32.USART2.BRR = 0x16c
|
||||||
|
|
||||||
|
// Enable USART2 port.
|
||||||
|
stm32.USART2.CR1 = stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE
|
||||||
|
|
||||||
|
// Enable RX IRQ.
|
||||||
|
arm.SetPriority(stm32.IRQ_USART2, 0xc0)
|
||||||
|
arm.EnableIRQ(stm32.IRQ_USART2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteByte writes a byte of data to the UART.
|
||||||
|
func (uart UART) WriteByte(c byte) error {
|
||||||
|
stm32.USART2.DR = stm32.RegValue(c)
|
||||||
|
|
||||||
|
for (stm32.USART2.SR & stm32.USART_SR_TXE) == 0 {
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:export USART2_IRQHandler
|
||||||
|
func handleUSART2() {
|
||||||
|
UART1.Receive(byte((stm32.USART2.DR & 0xFF)))
|
||||||
|
}
|
208
src/runtime/runtime_stm32f407.go
Обычный файл
208
src/runtime/runtime_stm32f407.go
Обычный файл
|
@ -0,0 +1,208 @@
|
||||||
|
// +build stm32,stm32f407
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/arm"
|
||||||
|
"device/stm32"
|
||||||
|
"machine"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 */
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
clock settings
|
||||||
|
+-------------+--------+
|
||||||
|
| HSE | 8mhz |
|
||||||
|
| SYSCLK | 168mhz |
|
||||||
|
| HCLK | 168mhz |
|
||||||
|
| APB2(PCLK2) | 84mhz |
|
||||||
|
| APB1(PCLK1) | 42mhz |
|
||||||
|
+-------------+--------+
|
||||||
|
*/
|
||||||
|
func initCLK() {
|
||||||
|
|
||||||
|
// Reset clock registers
|
||||||
|
// Set HSION
|
||||||
|
stm32.RCC.CR |= stm32.RCC_CR_HSION
|
||||||
|
for (stm32.RCC.CR & stm32.RCC_CR_HSIRDY) == 0 {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset CFGR
|
||||||
|
stm32.RCC.CFGR = 0x00000000
|
||||||
|
// Reset HSEON, CSSON and PLLON
|
||||||
|
stm32.RCC.CR &= 0xFEF6FFFF
|
||||||
|
// Reset PLLCFGR
|
||||||
|
stm32.RCC.PLLCFGR = 0x24003010
|
||||||
|
// Reset HSEBYP
|
||||||
|
stm32.RCC.CR &= 0xFFFBFFFF
|
||||||
|
// Disable all interrupts
|
||||||
|
stm32.RCC.CIR = 0x00000000
|
||||||
|
|
||||||
|
// Set up the clock
|
||||||
|
var startupCounter uint32 = 0
|
||||||
|
|
||||||
|
// Enable HSE
|
||||||
|
stm32.RCC.CR = stm32.RCC_CR_HSEON
|
||||||
|
// Wait till HSE is ready and if timeout is reached exit
|
||||||
|
for {
|
||||||
|
startupCounter++
|
||||||
|
if (stm32.RCC.CR&stm32.RCC_CR_HSERDY != 0) || (startupCounter == HSE_STARTUP_TIMEOUT) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stm32.RCC.CR & stm32.RCC_CR_HSERDY) != 0 {
|
||||||
|
// Enable high performance mode, System frequency up to 168MHz
|
||||||
|
stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_PWREN
|
||||||
|
stm32.PWR.CR |= 0x4000 // PWR_CR_VOS
|
||||||
|
// HCLK = SYSCLK / 1
|
||||||
|
stm32.RCC.CFGR |= (0x0 << stm32.RCC_CFGR_HPRE_Pos)
|
||||||
|
// PCLK2 = HCLK / 2
|
||||||
|
stm32.RCC.CFGR |= (0x4 << stm32.RCC_CFGR_PPRE2_Pos)
|
||||||
|
// PCLK1 = HCLK / 4
|
||||||
|
stm32.RCC.CFGR |= (0x5 << stm32.RCC_CFGR_PPRE1_Pos)
|
||||||
|
// Configure the main PLL
|
||||||
|
// PLL Options - See RM0090 Reference Manual pg. 95
|
||||||
|
stm32.RCC.PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) |
|
||||||
|
(1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | (PLL_Q << 24)
|
||||||
|
// Enable main PLL
|
||||||
|
stm32.RCC.CR |= stm32.RCC_CR_PLLON
|
||||||
|
// Wait till the main PLL is ready
|
||||||
|
for (stm32.RCC.CR & stm32.RCC_CR_PLLRDY) == 0 {
|
||||||
|
}
|
||||||
|
// Configure Flash prefetch, Instruction cache, Data cache and wait state
|
||||||
|
stm32.FLASH.ACR = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | (5 << stm32.FLASH_ACR_LATENCY_Pos)
|
||||||
|
// Select the main PLL as system clock source
|
||||||
|
stm32.RCC.CFGR &^= stm32.RCC_CFGR_SW0 | stm32.RCC_CFGR_SW1
|
||||||
|
stm32.RCC.CFGR |= (0x2 << stm32.RCC_CFGR_SW0_Pos)
|
||||||
|
for (stm32.RCC.CFGR & (0x3 << stm32.RCC_CFGR_SWS0_Pos)) != (0x2 << stm32.RCC_CFGR_SWS0_Pos) {
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If HSE failed to start up, the application will have wrong clock configuration
|
||||||
|
for {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Enable the CCM RAM clock
|
||||||
|
stm32.RCC.AHB1ENR |= (1 << 20)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const tickMicros = 1000
|
||||||
|
|
||||||
|
var (
|
||||||
|
// tick in milliseconds
|
||||||
|
tickCount timeUnit
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:volatile
|
||||||
|
type isrFlag bool
|
||||||
|
|
||||||
|
var timerWakeup isrFlag
|
||||||
|
|
||||||
|
// Enable the TIM3 clock.(sleep count)
|
||||||
|
func initTIM3() {
|
||||||
|
stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_TIM3EN
|
||||||
|
|
||||||
|
arm.SetPriority(stm32.IRQ_TIM3, 0xc3)
|
||||||
|
arm.EnableIRQ(stm32.IRQ_TIM3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the TIM7 clock.(tick count)
|
||||||
|
func initTIM7() {
|
||||||
|
stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_TIM7EN
|
||||||
|
|
||||||
|
// CK_INT = APB1 x2 = 84mhz
|
||||||
|
stm32.TIM7.PSC = 84000000/10000 - 1 // 84mhz to 10khz(0.1ms)
|
||||||
|
stm32.TIM7.ARR = stm32.RegValue(10) - 1 // interrupt per 1ms
|
||||||
|
|
||||||
|
// Enable the hardware interrupt.
|
||||||
|
stm32.TIM7.DIER |= stm32.TIM_DIER_UIE
|
||||||
|
|
||||||
|
// Enable the timer.
|
||||||
|
stm32.TIM7.CR1 |= stm32.TIM_CR1_CEN
|
||||||
|
|
||||||
|
arm.SetPriority(stm32.IRQ_TIM7, 0xc1)
|
||||||
|
arm.EnableIRQ(stm32.IRQ_TIM7)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = false
|
||||||
|
|
||||||
|
// CK_INT = APB1 x2 = 84mhz
|
||||||
|
// prescale counter down from 84mhz to 10khz aka 0.1 ms frequency.
|
||||||
|
stm32.TIM3.PSC = 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 = stm32.RegValue(arr)
|
||||||
|
|
||||||
|
// Enable the hardware interrupt.
|
||||||
|
stm32.TIM3.DIER |= stm32.TIM_DIER_UIE
|
||||||
|
|
||||||
|
// Enable the timer.
|
||||||
|
stm32.TIM3.CR1 |= stm32.TIM_CR1_CEN
|
||||||
|
|
||||||
|
// wait till timer wakes up
|
||||||
|
for !timerWakeup {
|
||||||
|
arm.Asm("wfi")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:export TIM3_IRQHandler
|
||||||
|
func handleTIM3() {
|
||||||
|
if (stm32.TIM3.SR & stm32.TIM_SR_UIF) > 0 {
|
||||||
|
// Disable the timer.
|
||||||
|
stm32.TIM3.CR1 &^= stm32.TIM_CR1_CEN
|
||||||
|
|
||||||
|
// clear the update flag
|
||||||
|
stm32.TIM3.SR &^= stm32.TIM_SR_UIF
|
||||||
|
|
||||||
|
// timer was triggered
|
||||||
|
timerWakeup = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:export TIM7_IRQHandler
|
||||||
|
func handleTIM7() {
|
||||||
|
if (stm32.TIM7.SR & stm32.TIM_SR_UIF) > 0 {
|
||||||
|
// clear the update flag
|
||||||
|
stm32.TIM7.SR &^= stm32.TIM_SR_UIF
|
||||||
|
tickCount++
|
||||||
|
}
|
||||||
|
}
|
10
targets/stm32f407.ld
Обычный файл
10
targets/stm32f407.ld
Обычный файл
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 1M
|
||||||
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
|
||||||
|
}
|
||||||
|
|
||||||
|
_stack_size = 4K;
|
||||||
|
|
||||||
|
INCLUDE "targets/arm.ld"
|
18
targets/stm32f4disco.json
Обычный файл
18
targets/stm32f4disco.json
Обычный файл
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"inherits": ["cortex-m"],
|
||||||
|
"llvm-target": "armv7em-none-eabi",
|
||||||
|
"build-tags": ["stm32f4disco", "stm32f407", "stm32"],
|
||||||
|
"cflags": [
|
||||||
|
"--target=armv7em-none-eabi",
|
||||||
|
"-Qunused-arguments"
|
||||||
|
],
|
||||||
|
"ldflags": [
|
||||||
|
"-T", "targets/stm32f407.ld"
|
||||||
|
],
|
||||||
|
"extra-files": [
|
||||||
|
"src/device/stm32/stm32f407.s"
|
||||||
|
],
|
||||||
|
"flash": "openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c 'program {hex} reset exit'",
|
||||||
|
"ocd-daemon": ["openocd", "-f", "interface/stlink.cfg", "-f", "target/stm32f4x.cfg"],
|
||||||
|
"gdb-initial-cmds": ["target remote :3333", "monitor halt", "load", "monitor reset", "c"]
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче