Created
October 12, 2020 20:17
-
-
Save paulc/10a9e618fbb5b185324f01e41afbf34a to your computer and use it in GitHub Desktop.
WeAct stm32f411
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/machine/board_weact_stm32f411.go b/src/machine/board_weact_stm32f411.go | |
new file mode 100644 | |
index 0000000..bdb1e97 | |
--- /dev/null | |
+++ b/src/machine/board_weact_stm32f411.go | |
@@ -0,0 +1,49 @@ | |
+// +build weact_stm32f411 | |
+ | |
+package machine | |
+ | |
+import ( | |
+ "device/stm32" | |
+) | |
+ | |
+const ( | |
+ LED = PC13 | |
+) | |
+ | |
+// UART pins | |
+const ( | |
+ UART_TX_PIN = PA2 | |
+ UART_RX_PIN = PA3 | |
+) | |
+ | |
+var ( | |
+ UART0 = UART{ | |
+ Buffer: NewRingBuffer(), | |
+ Bus: stm32.USART2, | |
+ } | |
+ UART1 = &UART0 | |
+) | |
+ | |
+// set up RX IRQ handler. Follow similar pattern for other UARTx instances | |
+func init() { | |
+ // UART0.Interrupt = interrupt.New(stm32.IRQ_USART2, UART0.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 | |
+) | |
+ | |
+// 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, | |
+ } | |
+ SPI1 = &SPI0 | |
+) | |
diff --git a/src/machine/i2c.go b/src/machine/i2c.go | |
index b465060..3ab7b0d 100644 | |
--- a/src/machine/i2c.go | |
+++ b/src/machine/i2c.go | |
@@ -1,4 +1,4 @@ | |
-// +build avr nrf sam stm32,!stm32f4 fe310 k210 | |
+// +build avr nrf sam stm32,!stm32f4,!stm32f411 fe310 k210 | |
package machine | |
diff --git a/src/machine/machine_stm32f411.go b/src/machine/machine_stm32f411.go | |
new file mode 100644 | |
index 0000000..8ba69b4 | |
--- /dev/null | |
+++ b/src/machine/machine_stm32f411.go | |
@@ -0,0 +1,240 @@ | |
+// +build stm32f411 | |
+ | |
+package machine | |
+ | |
+// Peripheral abstraction layer for the stm32f411 | |
+ | |
+import ( | |
+ "device/stm32" | |
+ "runtime/interrupt" | |
+ "unsafe" | |
+) | |
+ | |
+func CPUFrequency() uint32 { | |
+ return 100000000 | |
+} | |
+ | |
+// --- From machine_stm32f4.go | |
+ | |
+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 | |
+) | |
+ | |
+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 | |
+ 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.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOAEN) | |
+ case 1: | |
+ stm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOBEN) | |
+ case 2: | |
+ stm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOCEN) | |
+ case 3: | |
+ stm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIODEN) | |
+ default: | |
+ panic("machine: unknown port") | |
+ } | |
+} | |
+ | |
+// Enable peripheral clock | |
+func enableAltFuncClock(bus unsafe.Pointer) { | |
+ switch bus { | |
+ 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.USART2): // USART2 clock enable | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN) | |
+ case unsafe.Pointer(stm32.SPI3): // SPI3 clock enable | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI3EN) | |
+ case unsafe.Pointer(stm32.SPI2): // SPI2 clock enable | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN) | |
+ case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN) | |
+ case unsafe.Pointer(stm32.TIM5): // TIM5 clock enable | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM5EN) | |
+ case unsafe.Pointer(stm32.TIM4): // TIM4 clock enable | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM4EN) | |
+ 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.TIM11): // TIM11 clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM11EN) | |
+ case unsafe.Pointer(stm32.TIM10): // TIM10 clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM10EN) | |
+ case unsafe.Pointer(stm32.TIM9): // TIM9 clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM9EN) | |
+ case unsafe.Pointer(stm32.SYSCFG): // 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.SDIO): // SDIO clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SDIOEN) | |
+ case unsafe.Pointer(stm32.ADC1): // ADC1 clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC1EN) | |
+ case unsafe.Pointer(stm32.USART6): // USART6 clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART6EN) | |
+ case unsafe.Pointer(stm32.USART1): // USART1 clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) | |
+ case unsafe.Pointer(stm32.TIM1): // TIM1 clock enable | |
+ stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN) | |
+ } | |
+} | |
+ | |
+//---------- 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 | |
+// NOTE: keep this in sync with the runtime/runtime_stm32f407.go clock init code | |
+func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 { | |
+ var clock uint32 | |
+ switch uart.Bus { | |
+ case stm32.USART1: | |
+ clock = CPUFrequency() / 2 // APB2 Frequency | |
+ case stm32.USART2: | |
+ clock = CPUFrequency() / 4 // APB1 Frequency | |
+ } | |
+ return clock / baudRate | |
+} | |
+ | |
+//---------- 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_stm32f411.go b/src/runtime/runtime_stm32f411.go | |
new file mode 100644 | |
index 0000000..073f13b | |
--- /dev/null | |
+++ b/src/runtime/runtime_stm32f411.go | |
@@ -0,0 +1,219 @@ | |
+// +build stm32,stm32f411 | |
+ | |
+package runtime | |
+ | |
+import ( | |
+ "device/arm" | |
+ "device/stm32" | |
+ "machine" | |
+ "runtime/interrupt" | |
+ "runtime/volatile" | |
+) | |
+ | |
+func init() { | |
+ initCLK() | |
+ initTIM3() | |
+ machine.UART0.Configure(machine.UARTConfig{}) | |
+ // XXX Disable for stm32f411 | |
+ // 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.SetBits(stm32.RCC_CR_HSION) | |
+ for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) { | |
+ } | |
+ | |
+ // Reset CFGR | |
+ stm32.RCC.CFGR.Set(0x00000000) | |
+ // Reset HSEON, CSSON and PLLON | |
+ stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEON | stm32.RCC_CR_CSSON | stm32.RCC_CR_PLLON) | |
+ // Reset PLLCFGR | |
+ stm32.RCC.PLLCFGR.Set(0x24003010) | |
+ // Reset HSEBYP | |
+ stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEBYP) | |
+ // Disable all interrupts | |
+ stm32.RCC.CIR.Set(0x00000000) | |
+ | |
+ // Set up the clock | |
+ var startupCounter uint32 = 0 | |
+ | |
+ // Enable HSE | |
+ stm32.RCC.CR.Set(stm32.RCC_CR_HSEON) | |
+ | |
+ // Wait till HSE is ready and if timeout is reached exit | |
+ for { | |
+ startupCounter++ | |
+ if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) || (startupCounter == HSE_STARTUP_TIMEOUT) { | |
+ break | |
+ } | |
+ } | |
+ if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { | |
+ // Enable high performance mode, System frequency up to 168MHz | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) | |
+ stm32.PWR.CR.SetBits(0x4000) // PWR_CR_VOS | |
+ // HCLK = SYSCLK / 1 | |
+ stm32.RCC.CFGR.SetBits(0x0 << stm32.RCC_CFGR_HPRE_Pos) | |
+ // PCLK2 = HCLK / 2 | |
+ stm32.RCC.CFGR.SetBits(0x4 << stm32.RCC_CFGR_PPRE2_Pos) | |
+ // PCLK1 = HCLK / 4 | |
+ stm32.RCC.CFGR.SetBits(0x5 << stm32.RCC_CFGR_PPRE1_Pos) | |
+ // Configure the main PLL | |
+ // PLL Options - See RM0090 Reference Manual pg. 95 | |
+ stm32.RCC.PLLCFGR.Set(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.SetBits(stm32.RCC_CR_PLLON) | |
+ // Wait till the main PLL is ready | |
+ for (stm32.RCC.CR.Get() & stm32.RCC_CR_PLLRDY) == 0 { | |
+ } | |
+ // Configure Flash prefetch, Instruction cache, Data cache and wait state | |
+ stm32.FLASH.ACR.Set(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.ClearBits(stm32.RCC_CFGR_SW0 | stm32.RCC_CFGR_SW1) | |
+ stm32.RCC.CFGR.SetBits(0x2 << stm32.RCC_CFGR_SW0_Pos) | |
+ for (stm32.RCC.CFGR.Get() & (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.SetBits(1 << 20) | |
+ | |
+} | |
+ | |
+var ( | |
+ // tick in milliseconds | |
+ tickCount timeUnit | |
+) | |
+ | |
+var timerWakeup volatile.Register8 | |
+ | |
+func ticksToNanoseconds(ticks timeUnit) int64 { | |
+ return int64(ticks) * 1000 | |
+} | |
+ | |
+func nanosecondsToTicks(ns int64) timeUnit { | |
+ return timeUnit(ns / 1000) | |
+} | |
+ | |
+// Enable the TIM3 clock.(sleep count) | |
+func initTIM3() { | |
+ stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN) | |
+ | |
+ intr := interrupt.New(stm32.IRQ_TIM3, handleTIM3) | |
+ intr.SetPriority(0xc3) | |
+ intr.Enable() | |
+} | |
+ | |
+// XXX Disable for smt32f411 (no TIM7) | |
+// | |
+// // Enable the TIM7 clock.(tick count) | |
+// func initTIM7() { | |
+// stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN) | |
+// | |
+// // CK_INT = APB1 x2 = 84mhz | |
+// stm32.TIM7.PSC.Set(84000000/10000 - 1) // 84mhz to 10khz(0.1ms) | |
+// stm32.TIM7.ARR.Set(10 - 1) // interrupt per 1ms | |
+// | |
+// // Enable the hardware interrupt. | |
+// stm32.TIM7.DIER.SetBits(stm32.TIM_DIER_UIE) | |
+// | |
+// // Enable the timer. | |
+// stm32.TIM7.CR1.SetBits(stm32.TIM_CR1_CEN) | |
+// | |
+// intr := interrupt.New(stm32.IRQ_TIM7, handleTIM7) | |
+// intr.SetPriority(0xc1) | |
+// intr.Enable() | |
+// } | |
+ | |
+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.Set(0) | |
+ | |
+ // CK_INT = APB1 x2 = 84mhz | |
+ // prescale counter down from 84mhz to 10khz aka 0.1 ms frequency. | |
+ stm32.TIM3.PSC.Set(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.Set(arr) | |
+ | |
+ // 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) | |
+ | |
+ // timer was triggered | |
+ timerWakeup.Set(1) | |
+ } | |
+} | |
+ | |
+// XXX Disable for stm32f411 | |
+// | |
+// func handleTIM7(interrupt.Interrupt) { | |
+// if stm32.TIM7.SR.HasBits(stm32.TIM_SR_UIF) { | |
+// // clear the update flag | |
+// stm32.TIM7.SR.ClearBits(stm32.TIM_SR_UIF) | |
+// tickCount++ | |
+// } | |
+// } | |
diff --git a/targets/stm32f411.ld b/targets/stm32f411.ld | |
new file mode 100644 | |
index 0000000..664cc8b | |
--- /dev/null | |
+++ b/targets/stm32f411.ld | |
@@ -0,0 +1,10 @@ | |
+ | |
+MEMORY | |
+{ | |
+ FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 512K | |
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K | |
+} | |
+ | |
+_stack_size = 4K; | |
+ | |
+INCLUDE "targets/arm.ld" | |
diff --git a/targets/weact_stm32f411.json b/targets/weact_stm32f411.json | |
new file mode 100644 | |
index 0000000..cc7215c | |
--- /dev/null | |
+++ b/targets/weact_stm32f411.json | |
@@ -0,0 +1,13 @@ | |
+{ | |
+ "inherits": ["cortex-m4"], | |
+ "build-tags": ["weact_stm32f411", "stm32f411", "stm32"], | |
+ "cflags": [ | |
+ "-Qunused-arguments" | |
+ ], | |
+ "linkerscript": "targets/stm32f411.ld", | |
+ "extra-files": [ | |
+ "src/device/stm32/stm32f411.s" | |
+ ], | |
+ "flash-method": "command", | |
+ "flash-command": "dfu-util --alt 0 --dfuse-address 0x08000000 --download {bin}" | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment