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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/device/stm32/stm32f103xx-bitfields.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Hand created file. DO NOT DELETE.
// STM32F103XX bitfield definitions that are not auto-generated by gen-device-svd.py

// +build stm32,stm32f103xx

package stm32

const (
// Flash Access Control Register flag values.
FLASH_ACR_LATENCY_0 = 0x00000001
FLASH_ACR_LATENCY_1 = 0x00000002
FLASH_ACR_LATENCY_2 = 0x00000004

// Reset and Clock Control Control Register flag values.
RCC_CFGR_SW_HSI = 0
RCC_CFGR_SW_HSE = 1
RCC_CFGR_SW_PLL = 2

RCC_CFGR_SWS_HSI = 0x00000000
RCC_CFGR_SWS_HSE = 0x00000004
RCC_CFGR_SWS_PLL = 0x00000008

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

RCC_CFGR_PLLMUL_2 = 0x00000000
RCC_CFGR_PLLMUL_3 = 0x00040000
RCC_CFGR_PLLMUL_4 = 0x00080000
RCC_CFGR_PLLMUL_5 = 0x000C0000
RCC_CFGR_PLLMUL_6 = 0x00100000
RCC_CFGR_PLLMUL_7 = 0x00140000
RCC_CFGR_PLLMUL_8 = 0x00180000
RCC_CFGR_PLLMUL_9 = 0x001C0000
RCC_CFGR_PLLMUL_10 = 0x00200000
RCC_CFGR_PLLMUL_11 = 0x00240000
RCC_CFGR_PLLMUL_12 = 0x00280000
RCC_CFGR_PLLMUL_13 = 0x002C0000
RCC_CFGR_PLLMUL_14 = 0x00300000
RCC_CFGR_PLLMUL_15 = 0x00340000
RCC_CFGR_PLLMUL_16 = 0x00380000
)
60 changes: 0 additions & 60 deletions src/machine/machine_stm32.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,8 @@ package machine

// Peripheral abstraction layer for the stm32.

import (
"device/stm32"
)

type GPIOMode uint8

const (
GPIO_INPUT = 0 // Input mode
GPIO_OUTPUT = 2 // Output mode, max speed 2MHz
)

const (
portA = iota * 16
portB
Expand All @@ -24,54 +15,3 @@ const (
portF
portG
)

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
default:
panic("machine: unknown port")
}
}

// Configure this pin with the given configuration.
func (p GPIO) Configure(config GPIOConfig) {
// Enable clock.
// Do this always, as it isn't known whether the clock has already been
// enabled.
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_IOPCEN

// Configure the GPIO pin.
port := p.getPort()
pin := p.Pin % 16
pos := p.Pin % 8 * 4
if pin < 8 {
port.CRL = stm32.RegValue((uint32(port.CRL) &^ (0xf << pos)) | (uint32(config.Mode) << pos))
} else {
port.CRH = stm32.RegValue((uint32(port.CRH) &^ (0xf << pos)) | (uint32(config.Mode) << 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)
}
}
161 changes: 161 additions & 0 deletions src/machine/machine_stm32f103xx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// +build stm32,stm32f103xx

package machine

// Peripheral abstraction layer for the stm32.

import (
"device/arm"
"device/stm32"
)

const CPU_FREQUENCY = 72000000

const (
GPIO_INPUT = 0 // Input mode
GPIO_OUTPUT_10MHz = 1 // Output mode, max speed 10MHz
GPIO_OUTPUT_2MHz = 2 // Output mode, max speed 2MHz
GPIO_OUTPUT_50MHz = 3 // Output mode, max speed 50MHz
GPIO_OUTPUT = GPIO_OUTPUT_2MHz

GPIO_INPUT_MODE_ANALOG = 0 // Input analog mode
GPIO_INPUT_MODE_FLOATING = 4 // Input floating mode
GPIO_INPUT_MODE_PULL_UP_DOWN = 8 // Input pull up/down mode
GPIO_INPUT_MODE_RESERVED = 12 // Input mode (reserved)

GPIO_OUTPUT_MODE_GP_PUSH_PULL = 0 // Output mode general purpose push/pull
GPIO_OUTPUT_MODE_GP_OPEN_DRAIN = 4 // Output mode general purpose open drain
GPIO_OUTPUT_MODE_ALT_PUSH_PULL = 8 // Output mode alt. purpose push/pull
GPIO_OUTPUT_MODE_ALT_OPEN_DRAIN = 12 // Output mode alt. purpose open drain
)

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
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.APB2ENR |= stm32.RCC_APB2ENR_IOPAEN
case 1:
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_IOPBEN
case 2:
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_IOPCEN
case 3:
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_IOPDEN
case 4:
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_IOPEEN
case 5:
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_IOPFEN
case 6:
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_IOPGEN
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 := p.Pin % 8 * 4
if pin < 8 {
port.CRL = stm32.RegValue((uint32(port.CRL) &^ (0xf << pos)) | (uint32(config.Mode) << pos))
} else {
port.CRH = stm32.RegValue((uint32(port.CRH) &^ (0xf << pos)) | (uint32(config.Mode) << 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
var (
// USART1 is the first hardware serial port on the STM32.
// Both UART0 and UART1 refers to USART1.
UART0 = &UART{}
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 {
case PB6:
// use alternate TX/RX pins PB6/PB7 via AFIO mapping
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_AFIOEN
stm32.AFIO.MAPR |= stm32.AFIO_MAPR_USART1_REMAP
GPIO{PB6}.Configure(GPIOConfig{Mode: GPIO_OUTPUT_50MHz + GPIO_OUTPUT_MODE_ALT_PUSH_PULL})
GPIO{PB7}.Configure(GPIOConfig{Mode: GPIO_INPUT_MODE_FLOATING})
default:
// use standard TX/RX pins PA9 and PA10
GPIO{PA9}.Configure(GPIOConfig{Mode: GPIO_OUTPUT_50MHz + GPIO_OUTPUT_MODE_ALT_PUSH_PULL})
GPIO{PA10}.Configure(GPIOConfig{Mode: GPIO_INPUT_MODE_FLOATING})
}

// Enable USART1 clock
stm32.RCC.APB2ENR |= stm32.RCC_APB2ENR_USART1EN

// Set baud rate
uart.SetBaudRate(config.BaudRate)

// Enable USART1 port.
stm32.USART1.CR1 = stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE

// Enable RX IRQ.
arm.EnableIRQ(stm32.IRQ_USART1)
}

// SetBaudRate sets the communication speed for the UART.
func (uart UART) SetBaudRate(br uint32) {
divider := CPU_FREQUENCY / br
stm32.USART1.BRR = stm32.RegValue(divider)
}

// WriteByte writes a byte of data to the UART.
func (uart UART) WriteByte(c byte) error {
stm32.USART1.DR = stm32.RegValue(c)

for (stm32.USART1.SR & stm32.USART_SR_TXE) == 0 {
}
return nil
}

//go:export USART1_IRQHandler
func handleUART1() {
bufferPut(byte((stm32.USART1.DR & 0xFF)))
}
4 changes: 3 additions & 1 deletion src/machine/uart.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// +build avr nrf
// +build avr nrf stm32

package machine

import "errors"

type UARTConfig struct {
BaudRate uint32
TX uint8
RX uint8
}

type UART struct {
Expand Down
21 changes: 0 additions & 21 deletions src/runtime/runtime_stm32.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,12 @@

package runtime

import (
"device/arm"
)

type timeUnit int64

const tickMicros = 1 // TODO

//go:export Reset_Handler
func main() {
preinit()
initAll()
mainWrapper()
abort()
}

func putchar(c byte) {
// TODO
}

func sleepTicks(d timeUnit) {
// TODO: use a real timer here
for i := 0; i < int(d/535); i++ {
arm.Asm("")
}
}

func ticks() timeUnit {
return 0 // TODO
}
56 changes: 56 additions & 0 deletions src/runtime/runtime_stm32f103xx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// +build stm32,stm32f103xx

package runtime

import (
"device/arm"
"device/stm32"
"machine"
)

const tickMicros = 1 // TODO

func init() {
initCLK()
machine.UART0.Configure(machine.UARTConfig{})
}

func putchar(c byte) {
machine.UART0.WriteByte(c)
}

// initCLK sets clock to 72MHz using HSE 8MHz crystal w/ PLL X 9 (8MHz x 9 = 72MHz).
func initCLK() {
stm32.FLASH.ACR |= stm32.FLASH_ACR_LATENCY_2 // Two wait states, per datasheet
stm32.RCC.CFGR |= stm32.RCC_CFGR_PPRE1_DIV_2 // prescale AHB1 = HCLK/2
stm32.RCC.CR |= stm32.RCC_CR_HSEON // enable HSE clock

// wait for the HSEREADY flag
for (stm32.RCC.CR & stm32.RCC_CR_HSERDY) == 0 {
}

stm32.RCC.CFGR |= stm32.RCC_CFGR_PLLSRC // set PLL source to HSE
stm32.RCC.CFGR |= stm32.RCC_CFGR_PLLMUL_9 // multiply by 9
stm32.RCC.CR |= stm32.RCC_CR_PLLON // enable the PLL

// wait for the PLLRDY flag
for (stm32.RCC.CR & stm32.RCC_CR_PLLRDY) == 0 {
}

stm32.RCC.CFGR |= stm32.RCC_CFGR_SW_PLL // set clock source to pll

// wait for PLL to be CLK
for (stm32.RCC.CFGR & stm32.RCC_CFGR_SWS_PLL) == 0 {
}
}

func sleepTicks(d timeUnit) {
// TODO: use a real timer here
for i := 0; i < int(d/535); i++ {
arm.Asm("")
}
}

func ticks() timeUnit {
return 0 // TODO
}