From a9a6d0ee6310669fa8fd81849ccd7dd9aa469b22 Mon Sep 17 00:00:00 2001 From: ardnew Date: Sat, 29 Aug 2020 14:32:24 -0500 Subject: [PATCH] add basic UART handler --- src/machine/board_feather-stm32f405.go | 30 +++++++++++++- src/machine/machine_stm32f405.go | 18 ++++++++- src/runtime/runtime_stm32f405.go | 56 ++++++++++++++++---------- 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/src/machine/board_feather-stm32f405.go b/src/machine/board_feather-stm32f405.go index 69fa80ff..14c7d063 100644 --- a/src/machine/board_feather-stm32f405.go +++ b/src/machine/board_feather-stm32f405.go @@ -2,6 +2,11 @@ package machine +import ( + "device/stm32" + "runtime/interrupt" +) + const ( NUM_DIGITAL_IO_PINS = 39 NUM_ANALOG_IO_PINS = 7 @@ -113,7 +118,30 @@ const ( UART_TX_PIN = UART0_TX_PIN // ) -func initUART() {} +var ( + UART1 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.USART3, + AltFuncSelector: stm32.AF7_USART1_2_3, + } + UART2 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.USART6, + AltFuncSelector: stm32.AF8_USART4_5_6, + } + UART3 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.USART1, + AltFuncSelector: stm32.AF7_USART1_2_3, + } + UART0 = UART1 +) + +func initUART() { + UART1.Interrupt = interrupt.New(stm32.IRQ_USART3, UART1.handleInterrupt) + UART2.Interrupt = interrupt.New(stm32.IRQ_USART6, UART2.handleInterrupt) + UART3.Interrupt = interrupt.New(stm32.IRQ_USART1, UART3.handleInterrupt) +} // -- SPI ---------------------------------------------------------------------- diff --git a/src/machine/machine_stm32f405.go b/src/machine/machine_stm32f405.go index 9413a977..e5994171 100644 --- a/src/machine/machine_stm32f405.go +++ b/src/machine/machine_stm32f405.go @@ -22,8 +22,22 @@ type UART struct { AltFuncSelector stm32.AltFunc } -func (uart UART) configurePins(config UARTConfig) {} -func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 { return 0 } +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) +} + +func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 { + var clock uint32 + switch uart.Bus { + case stm32.USART1, stm32.USART6: + clock = CPUFrequency() / 2 // APB2 Frequency + case stm32.USART2, stm32.USART3, stm32.UART4, stm32.UART5: + clock = CPUFrequency() / 4 // APB1 Frequency + } + return clock / baudRate +} // -- SPI ---------------------------------------------------------------------- diff --git a/src/runtime/runtime_stm32f405.go b/src/runtime/runtime_stm32f405.go index a7c451f9..8e542fff 100644 --- a/src/runtime/runtime_stm32f405.go +++ b/src/runtime/runtime_stm32f405.go @@ -1,10 +1,11 @@ -// +build stm32,stm32f4,stm32f405 +// +build stm32f405 package runtime import ( "device/arm" "device/stm32" + "machine" "runtime/interrupt" "runtime/volatile" ) @@ -13,6 +14,7 @@ func init() { initOSC() // configure oscillators initCLK() // configure CPU, AHB, and APB bus clocks initTIM() // configure timers + initCOM() // configure serial comm interfaces } const ( @@ -42,7 +44,8 @@ const ( PLL_DIV_P = ((2 >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP0_Pos PLL_DIV_Q = 7 << stm32.RCC_PLLCFGR_PLLQ0_Pos - SYSCLK_SRC_PLL = 2 << stm32.RCC_CFGR_SW0_Pos + SYSCLK_SRC_PLL = 2 << stm32.RCC_CFGR_SW0_Pos + SYSCLK_STAT_PLL = 2 << stm32.RCC_CFGR_SWS0_Pos RCC_DIV_PCLK1 = 5 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4 RCC_DIV_PCLK2 = 4 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2 @@ -52,22 +55,19 @@ const ( ) const ( - // +---------------------+---------------------------------------------------------------------------+ - // | | HCLK (MHz) | - // | +------------------+------------------+------------------+------------------+ - // | Wait states (WS) | Voltage range | Voltage range | Voltage range | Voltage range | - // | (LATENCY) | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | - // | | | | | Prefetch OFF | - // +---------------------+------------------+------------------+------------------+------------------+ - // | 0 WS (1 CPU cycle) | 0 < HCLK ≤ 30 | 0 < HCLK ≤ 24 | 0 < HCLK ≤ 22 | 0 < HCLK ≤ 20 | - // | 1 WS (2 CPU cycles) | 30 < HCLK ≤ 60 | 24 < HCLK ≤ 48 | 22 < HCLK ≤ 44 | 20 < HCLK ≤ 40 | - // | 2 WS (3 CPU cycles) | 60 < HCLK ≤ 90 | 48 < HCLK ≤ 72 | 44 < HCLK ≤ 66 | 40 < HCLK ≤ 60 | - // | 3 WS (4 CPU cycles) | 90 < HCLK ≤ 120 | 72 < HCLK ≤ 96 | 66 < HCLK ≤ 88 | 60 < HCLK ≤ 80 | - // | 4 WS (5 CPU cycles) | 120 < HCLK ≤ 150 | 96 < HCLK ≤ 120 | 88 < HCLK ≤ 110 | 80 < HCLK ≤ 100 | - // | 5 WS (6 CPU cycles) | 150 < HCLK ≤ 168 | 120 < HCLK ≤ 144 | 110 < HCLK ≤ 132 | 100 < HCLK ≤ 120 | - // | 6 WS (7 CPU cycles) | | 144 < HCLK ≤ 168 | 132 < HCLK ≤ 154 | 120 < HCLK ≤ 140 | - // | 7 WS (8 CPU cycles) | | | 154 < HCLK ≤ 168 | 140 < HCLK ≤ 160 | - // +---------------------+------------------+------------------+------------------+------------------+ + // +-----------------------------------+ + // | Voltage range = 2.7V - 3.6V | + // +----------------+------------------+ + // | Wait states | System Bus | + // | (WS, LATENCY) | HCLK (MHz) | + // +----------------+------------------+ + // | 0 WS, 1 cycle | 0 < HCLK ≤ 30 | + // | 1 WS, 2 cycles | 30 < HCLK ≤ 60 | + // | 2 WS, 3 cycles | 60 < HCLK ≤ 90 | + // | 3 WS, 4 cycles | 90 < HCLK ≤ 120 | + // | 4 WS, 5 cycles | 120 < HCLK ≤ 150 | + // | 5 WS, 6 cycles | 150 < HCLK ≤ 168 | + // +----------------+------------------+ FLASH_LATENCY = 5 << stm32.FLASH_ACR_LATENCY_Pos // 5 WS (6 CPU cycles) // instruction cache, data cache, and prefetch @@ -126,6 +126,8 @@ func initCLK() { // configure instruction/data caching, prefetch, and flash access wait states stm32.FLASH.ACR.Set(FLASH_OPTIONS | FLASH_LATENCY) + for !stm32.FLASH.ACR.HasBits(FLASH_LATENCY) { // verify new wait states + } // After a system reset, the HSI oscillator is selected as the system clock. // When a clock source is used directly or through PLL as the system clock, it @@ -140,12 +142,14 @@ func initCLK() { // set CPU clock source to PLL stm32.RCC.CFGR.SetBits(SYSCLK_SRC_PLL) - for !stm32.RCC.CFGR.HasBits(SYSCLK_SRC_PLL) { - } // update PCKL1/2 and HCLK divisors stm32.RCC.CFGR.SetBits(RCC_DIV_PCLK1 | RCC_DIV_PCLK2 | RCC_DIV_HCLK) + // verify system clock source is ready + for !stm32.RCC.CFGR.HasBits(SYSCLK_STAT_PLL) { + } + // enable the CCM RAM clock stm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM) } @@ -172,6 +176,12 @@ func initTIM() { tim7.Enable() } +func initCOM() { + if machine.NUM_UART_INTERFACES > 0 { + machine.UART0.Configure(machine.UARTConfig{}) + } +} + var ( // tick in milliseconds tickCount timeUnit @@ -203,7 +213,7 @@ func timerSleep(ticks uint32) { timerWakeup.Set(0) stm32.TIM3.PSC.Set((PCLK1_FREQ_HZ*2)/10000 - 1) // 8399 - arr := (ticks / 100) - 1 // convert from microseconds to 0.1 ms + arr := (ticks / 100) - 1 // microseconds to 0.1 ms if arr == 0 { arr = 1 // avoid blocking } @@ -233,4 +243,6 @@ func handleTIM7(interrupt.Interrupt) { } } -func putchar(c byte) {} +func putchar(c byte) { + machine.UART0.WriteByte(c) +}