add STM32F405 machine/runtime, and new board/target feather-stm32f405
Этот коммит содержится в:
		
							родитель
							
								
									04f65f1189
								
							
						
					
					
						коммит
						20a1c730a1
					
				
					 5 изменённых файлов: 529 добавлений и 0 удалений
				
			
		
							
								
								
									
										167
									
								
								src/machine/board_feather-stm32f405.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										167
									
								
								src/machine/board_feather-stm32f405.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,167 @@
 | 
				
			||||||
 | 
					// +build feather_stm32f405
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package machine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"device/stm32"
 | 
				
			||||||
 | 
						"runtime/interrupt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						NUM_DIGITAL_IO_PINS = 39
 | 
				
			||||||
 | 
						NUM_ANALOG_IO_PINS  = 7
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Pinout
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// Arduino pin = MCU port pin // primary functions (alternate functions)
 | 
				
			||||||
 | 
						D0  = PB11 // USART3 RX, PWM TIM2_CH4 (I2C2 SDA)
 | 
				
			||||||
 | 
						D1  = PB10 // USART3 TX, PWM TIM2_CH3 (I2C2 SCL, I2S2 BCK)
 | 
				
			||||||
 | 
						D2  = PB3  // GPIO, SPI3 FLASH SCK
 | 
				
			||||||
 | 
						D3  = PB4  // GPIO, SPI3 FLASH MISO
 | 
				
			||||||
 | 
						D4  = PB5  // GPIO, SPI3 FLASH MOSI
 | 
				
			||||||
 | 
						D5  = PC7  // GPIO, PWM TIM3_CH2 (USART6 RX, I2S3 MCK)
 | 
				
			||||||
 | 
						D6  = PC6  // GPIO, PWM TIM3_CH1 (USART6 TX, I2S2 MCK)
 | 
				
			||||||
 | 
						D7  = PA15 // GPIO, SPI3 FLASH CS
 | 
				
			||||||
 | 
						D8  = PC0  // GPIO, Neopixel
 | 
				
			||||||
 | 
						D9  = PB8  // GPIO, PWM TIM4_CH3 (CAN1 RX, I2C1 SCL)
 | 
				
			||||||
 | 
						D10 = PB9  // GPIO, PWM TIM4_CH4 (CAN1 TX, I2C1 SDA, I2S2 WSL)
 | 
				
			||||||
 | 
						D11 = PC3  // GPIO (I2S2 SD, SPI2 MOSI)
 | 
				
			||||||
 | 
						D12 = PC2  // GPIO (I2S2ext SD, SPI2 MISO)
 | 
				
			||||||
 | 
						D13 = PC1  // GPIO, Builtin LED
 | 
				
			||||||
 | 
						D14 = PB7  // I2C1 SDA, PWM TIM4_CH2 (USART1 RX)
 | 
				
			||||||
 | 
						D15 = PB6  // I2C1 SCL, PWM TIM4_CH1 (USART1 TX, CAN2 TX)
 | 
				
			||||||
 | 
						D16 = PA4  // A0 (DAC OUT1)
 | 
				
			||||||
 | 
						D17 = PA5  // A1 (DAC OUT2, SPI1 SCK)
 | 
				
			||||||
 | 
						D18 = PA6  // A2, PWM TIM3_CH1 (SPI1 MISO)
 | 
				
			||||||
 | 
						D19 = PA7  // A3, PWM TIM3_CH2 (SPI1 MOSI)
 | 
				
			||||||
 | 
						D20 = PC4  // A4
 | 
				
			||||||
 | 
						D21 = PC5  // A5
 | 
				
			||||||
 | 
						D22 = PA3  // A6
 | 
				
			||||||
 | 
						D23 = PB13 // SPI2 SCK, PWM TIM1_CH1N (I2S2 BCK, CAN2 TX)
 | 
				
			||||||
 | 
						D24 = PB14 // SPI2 MISO, PWM TIM1_CH2N (I2S2ext SD)
 | 
				
			||||||
 | 
						D25 = PB15 // SPI2 MOSI, PWM TIM1_CH3N (I2S2 SD)
 | 
				
			||||||
 | 
						D26 = PC8  // SDIO
 | 
				
			||||||
 | 
						D27 = PC9  // SDIO
 | 
				
			||||||
 | 
						D28 = PC10 // SDIO
 | 
				
			||||||
 | 
						D29 = PC11 // SDIO
 | 
				
			||||||
 | 
						D30 = PC12 // SDIO
 | 
				
			||||||
 | 
						D31 = PD2  // SDIO
 | 
				
			||||||
 | 
						D32 = PB12 // SD Detect
 | 
				
			||||||
 | 
						D33 = PC14 // OSC32
 | 
				
			||||||
 | 
						D34 = PC15 // OSC32
 | 
				
			||||||
 | 
						D35 = PA11 // USB D+
 | 
				
			||||||
 | 
						D36 = PA12 // USB D-
 | 
				
			||||||
 | 
						D37 = PA13 // SWDIO
 | 
				
			||||||
 | 
						D38 = PA14 // SWCLK
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Analog pins
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						A0 = D16 // ADC12 IN4
 | 
				
			||||||
 | 
						A1 = D17 // ADC12 IN5
 | 
				
			||||||
 | 
						A2 = D18 // ADC12 IN6
 | 
				
			||||||
 | 
						A3 = D19 // ADC12 IN7
 | 
				
			||||||
 | 
						A4 = D20 // ADC12 IN14
 | 
				
			||||||
 | 
						A5 = D21 // ADC12 IN15
 | 
				
			||||||
 | 
						A6 = D22 // VBAT
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Pretty lights
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						LED          = LED_BUILTIN
 | 
				
			||||||
 | 
						LED_BUILTIN  = LED_RED
 | 
				
			||||||
 | 
						LED_RED      = D13
 | 
				
			||||||
 | 
						LED_NEOPIXEL = D8
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UART pins
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						NUM_UART_INTERFACES = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UART_RX_PIN = UART1_RX_PIN
 | 
				
			||||||
 | 
						UART_TX_PIN = UART1_TX_PIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UART0_RX_PIN = D0
 | 
				
			||||||
 | 
						UART0_TX_PIN = D1
 | 
				
			||||||
 | 
						UART1_RX_PIN = UART0_RX_PIN
 | 
				
			||||||
 | 
						UART1_TX_PIN = UART0_TX_PIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UART2_RX_PIN = D5
 | 
				
			||||||
 | 
						UART2_TX_PIN = D6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UART3_RX_PIN = D14
 | 
				
			||||||
 | 
						UART3_TX_PIN = D15
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// TBD: why do UART0 and UART1 have different types (struct vs reference)?
 | 
				
			||||||
 | 
						UART0 = UART{
 | 
				
			||||||
 | 
							Buffer:          NewRingBuffer(),
 | 
				
			||||||
 | 
							Bus:             stm32.USART3,
 | 
				
			||||||
 | 
							AltFuncSelector: stm32.AF7_USART1_2_3,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						UART1 = &UART0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  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,
 | 
				
			||||||
 | 
					//  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// set up RX IRQ handler. Follow similar pattern for other UARTx instances
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						UART0.Interrupt = interrupt.New(stm32.IRQ_USART3, UART0.handleInterrupt)
 | 
				
			||||||
 | 
						//UART2.Interrupt = interrupt.New(stm32.IRQ_USART6, UART2.handleInterrupt)
 | 
				
			||||||
 | 
						//UART3.Interrupt = interrupt.New(stm32.IRQ_USART1, UART3.handleInterrupt)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SPI pins
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						NUM_SPI_INTERFACES = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SPI_SCK_PIN = SPI1_SCK_PIN
 | 
				
			||||||
 | 
						SPI_SDI_PIN = SPI1_SDI_PIN
 | 
				
			||||||
 | 
						SPI_SDO_PIN = SPI1_SDO_PIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SPI0_SCK_PIN = D23
 | 
				
			||||||
 | 
						SPI0_SDI_PIN = D24
 | 
				
			||||||
 | 
						SPI0_SDO_PIN = D25
 | 
				
			||||||
 | 
						SPI1_SCK_PIN = SPI0_SCK_PIN
 | 
				
			||||||
 | 
						SPI1_SDI_PIN = SPI0_SDI_PIN
 | 
				
			||||||
 | 
						SPI1_SDO_PIN = SPI0_SDO_PIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SPI2_SCK_PIN = D2
 | 
				
			||||||
 | 
						SPI2_SDI_PIN = D3
 | 
				
			||||||
 | 
						SPI2_SDO_PIN = D4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SPI3_SCK_PIN = D17
 | 
				
			||||||
 | 
						SPI3_SDI_PIN = D18
 | 
				
			||||||
 | 
						SPI3_SDO_PIN = D19
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1.
 | 
				
			||||||
 | 
					// TODO: implement SPI2 and SPI3.
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// TBD: why do SPI0 and SPI1 have different types (struct vs reference)?
 | 
				
			||||||
 | 
						SPI0 = SPI{
 | 
				
			||||||
 | 
							Bus:             stm32.SPI2,
 | 
				
			||||||
 | 
							AltFuncSelector: stm32.AF5_SPI1_SPI2,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						SPI1 = &SPI0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  SPI2 = &SPI{
 | 
				
			||||||
 | 
					//    Bus:             stm32.SPI3,
 | 
				
			||||||
 | 
					//    AltFuncSelector: stm32.AF6_SPI3,
 | 
				
			||||||
 | 
					//  }
 | 
				
			||||||
 | 
					//  SPI3 = &SPI{
 | 
				
			||||||
 | 
					//    Bus:             stm32.SPI1,
 | 
				
			||||||
 | 
					//    AltFuncSelector: stm32.AF5_SPI1_SPI2,
 | 
				
			||||||
 | 
					//  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										103
									
								
								src/machine/machine_stm32f405.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										103
									
								
								src/machine/machine_stm32f405.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,103 @@
 | 
				
			||||||
 | 
					// +build stm32f405
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package machine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Peripheral abstraction layer for the stm32f405
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"device/stm32"
 | 
				
			||||||
 | 
						"runtime/interrupt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func CPUFrequency() uint32 {
 | 
				
			||||||
 | 
						return 168000000
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//---------- 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, 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 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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										237
									
								
								src/runtime/runtime_stm32f405.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										237
									
								
								src/runtime/runtime_stm32f405.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,237 @@
 | 
				
			||||||
 | 
					// +build stm32,stm32f4,stm32f405
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package runtime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"device/arm"
 | 
				
			||||||
 | 
						"device/stm32"
 | 
				
			||||||
 | 
						"runtime/interrupt"
 | 
				
			||||||
 | 
						"runtime/volatile"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						initOSC() // configure oscillators
 | 
				
			||||||
 | 
						initCLK() // configure CPU, AHB, and APB bus clocks
 | 
				
			||||||
 | 
						initTIM() // configure timers
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						HCLK_FREQ_HZ  = 168000000
 | 
				
			||||||
 | 
						PCLK1_FREQ_HZ = HCLK_FREQ_HZ / 4
 | 
				
			||||||
 | 
						PCLK2_FREQ_HZ = HCLK_FREQ_HZ / 2
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						PWR_SCALE1 = 1 << stm32.PWR_CSR_VOSRDY_Pos // max value of HCLK = 168 MHz
 | 
				
			||||||
 | 
						PWR_SCALE2 = 0                             // max value of HCLK = 144 MHz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PLL_SRC_HSE = 1 << stm32.RCC_PLLCFGR_PLLSRC_Pos // use HSE for PLL and PLLI2S
 | 
				
			||||||
 | 
						PLL_SRC_HSI = 0                                 // use HSI for PLL and PLLI2S
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PLL_DIV_M = 6 << stm32.RCC_PLLCFGR_PLLM0_Pos
 | 
				
			||||||
 | 
						PLL_MLT_N = 168 << stm32.RCC_PLLCFGR_PLLN0_Pos
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RCC_DIV_PCLK1 = 5 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4
 | 
				
			||||||
 | 
						RCC_DIV_PCLK2 = 4 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2
 | 
				
			||||||
 | 
						RCC_DIV_HCLK  = 0 << stm32.RCC_CFGR_HPRE_Pos  // SYSCLK / 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CLK_CCM_RAM = 1 << 20
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 |
 | 
				
			||||||
 | 
						// +---------------------+------------------+------------------+------------------+------------------+
 | 
				
			||||||
 | 
						FLASH_LATENCY = 5 << stm32.FLASH_ACR_LATENCY_Pos // 5 WS (6 CPU cycles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// instruction cache, data cache, and prefetch
 | 
				
			||||||
 | 
						FLASH_OPTIONS = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | stm32.FLASH_ACR_PRFTEN
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					   clock settings
 | 
				
			||||||
 | 
					   +-------------+--------+
 | 
				
			||||||
 | 
					   | HSE         | 12mhz  |
 | 
				
			||||||
 | 
					   | SYSCLK      | 168mhz |
 | 
				
			||||||
 | 
					   | HCLK        | 168mhz |
 | 
				
			||||||
 | 
					   | APB1(PCLK1) | 42mhz  |
 | 
				
			||||||
 | 
					   | APB2(PCLK2) | 84mhz  |
 | 
				
			||||||
 | 
					   +-------------+--------+
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func initOSC() {
 | 
				
			||||||
 | 
						// enable voltage regulator
 | 
				
			||||||
 | 
						stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
 | 
				
			||||||
 | 
						stm32.PWR.CR.SetBits(PWR_SCALE1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// enable HSE
 | 
				
			||||||
 | 
						stm32.RCC.CR.Set(stm32.RCC_CR_HSEON)
 | 
				
			||||||
 | 
						for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Since the main-PLL configuration parameters cannot be changed once PLL is
 | 
				
			||||||
 | 
						// enabled, it is recommended to configure PLL before enabling it (selection
 | 
				
			||||||
 | 
						// of the HSI or HSE oscillator as PLL clock source, and configuration of
 | 
				
			||||||
 | 
						// division factors M, N, P, and Q).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// disable PLL and wait for it to reset
 | 
				
			||||||
 | 
						stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)
 | 
				
			||||||
 | 
						for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// set HSE as PLL source and configure clock divisors
 | 
				
			||||||
 | 
						stm32.RCC.PLLCFGR.Set(PLL_SRC_HSE | PLL_DIV_M | PLL_MLT_N | PLL_DIV_P | PLL_DIV_Q)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// enable PLL and wait for it to sync
 | 
				
			||||||
 | 
						stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)
 | 
				
			||||||
 | 
						for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initCLK() {
 | 
				
			||||||
 | 
						// After reset, the CPU clock frequency is 16 MHz and 0 wait state (WS) is
 | 
				
			||||||
 | 
						// configured in the FLASH_ACR register.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// It is highly recommended to use the following software sequences to tune
 | 
				
			||||||
 | 
						// the number of wait states needed to access the Flash memory with the CPU
 | 
				
			||||||
 | 
						// frequency.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 1. Program the new number of wait states to the LATENCY bits in the
 | 
				
			||||||
 | 
						//    FLASH_ACR register
 | 
				
			||||||
 | 
						// 2. Check that the new number of wait states is taken into account to access
 | 
				
			||||||
 | 
						//    the Flash memory by reading the FLASH_ACR register
 | 
				
			||||||
 | 
						// 3. Modify the CPU clock source by writing the SW bits in the RCC_CFGR
 | 
				
			||||||
 | 
						//    register
 | 
				
			||||||
 | 
						// 4. If needed, modify the CPU clock prescaler by writing the HPRE bits in
 | 
				
			||||||
 | 
						//    RCC_CFGR
 | 
				
			||||||
 | 
						// 5. Check that the new CPU clock source or/and the new CPU clock prescaler
 | 
				
			||||||
 | 
						//    value is/are taken into account by reading the clock source status (SWS
 | 
				
			||||||
 | 
						//    bits) or/and the AHB prescaler value (HPRE bits), respectively, in the
 | 
				
			||||||
 | 
						//    RCC_CFGR register.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// configure instruction/data caching, prefetch, and flash access wait states
 | 
				
			||||||
 | 
						stm32.FLASH.ACR.Set(FLASH_OPTIONS | FLASH_LATENCY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 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
 | 
				
			||||||
 | 
						// is not possible to stop it.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// A switch from one clock source to another occurs only if the target clock
 | 
				
			||||||
 | 
						// source is ready (clock stable after startup delay or PLL locked). If a
 | 
				
			||||||
 | 
						// clock source that is not yet ready is selected, the switch occurs when the
 | 
				
			||||||
 | 
						// clock source is ready. Status bits in the RCC clock control register
 | 
				
			||||||
 | 
						// (RCC_CR) indicate which clock(s) is (are) ready and which clock is
 | 
				
			||||||
 | 
						// currently used as the system clock.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// enable the CCM RAM clock
 | 
				
			||||||
 | 
						stm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initTIM() {
 | 
				
			||||||
 | 
						// enable sleep counter (TIM3)
 | 
				
			||||||
 | 
						stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tim3 := interrupt.New(stm32.IRQ_TIM3, handleTIM3)
 | 
				
			||||||
 | 
						tim3.SetPriority(0xC3)
 | 
				
			||||||
 | 
						tim3.Enable()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// enable tick counter (TIM7)
 | 
				
			||||||
 | 
						stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stm32.TIM7.PSC.Set((PCLK1_FREQ_HZ*2)/10000 - 1) // 84mhz to 10khz(0.1ms)
 | 
				
			||||||
 | 
						stm32.TIM7.ARR.Set(10 - 1)                      // interrupt per 1ms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stm32.TIM7.DIER.SetBits(stm32.TIM_DIER_UIE) // enable interrupt
 | 
				
			||||||
 | 
						stm32.TIM7.CR1.SetBits(stm32.TIM_CR1_CEN)   // enable timer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tim7 := interrupt.New(stm32.IRQ_TIM7, handleTIM7)
 | 
				
			||||||
 | 
						tim7.SetPriority(0xC1)
 | 
				
			||||||
 | 
						tim7.Enable()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// tick in milliseconds
 | 
				
			||||||
 | 
						tickCount   timeUnit
 | 
				
			||||||
 | 
						timerWakeup volatile.Register8
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const asyncScheduler = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ticksToNanoseconds(ticks timeUnit) int64 {
 | 
				
			||||||
 | 
						return int64(ticks) * 1000
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nanosecondsToTicks(ns int64) timeUnit {
 | 
				
			||||||
 | 
						return timeUnit(ns / 1000)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// sleepTicks should sleep for specific number of microseconds.
 | 
				
			||||||
 | 
					func sleepTicks(d timeUnit) {
 | 
				
			||||||
 | 
						timerSleep(uint32(d))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// number of ticks (microseconds) since start.
 | 
				
			||||||
 | 
					func ticks() timeUnit {
 | 
				
			||||||
 | 
						return tickCount * 1000 // milliseconds to microseconds
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ticks are in microseconds
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
						if arr == 0 {
 | 
				
			||||||
 | 
							arr = 1 // avoid blocking
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stm32.TIM3.ARR.Set(arr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE) // enable interrupt
 | 
				
			||||||
 | 
						stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN)   // enable the timer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// wait for timer
 | 
				
			||||||
 | 
						for timerWakeup.Get() == 0 {
 | 
				
			||||||
 | 
							arm.Asm("wfi")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func handleTIM3(interrupt.Interrupt) {
 | 
				
			||||||
 | 
						if stm32.TIM3.SR.HasBits(stm32.TIM_SR_UIF) {
 | 
				
			||||||
 | 
							stm32.TIM3.CR1.ClearBits(stm32.TIM_CR1_CEN) // disable the timer
 | 
				
			||||||
 | 
							stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF)   // clear the update flag
 | 
				
			||||||
 | 
							timerWakeup.Set(1)                          // flag timer ISR
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func handleTIM7(interrupt.Interrupt) {
 | 
				
			||||||
 | 
						if stm32.TIM7.SR.HasBits(stm32.TIM_SR_UIF) {
 | 
				
			||||||
 | 
							stm32.TIM7.SR.ClearBits(stm32.TIM_SR_UIF) // clear the update flag
 | 
				
			||||||
 | 
							tickCount++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func putchar(c byte) {}
 | 
				
			||||||
							
								
								
									
										13
									
								
								targets/feather-stm32f405.json
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										13
									
								
								targets/feather-stm32f405.json
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "inherits": ["cortex-m4"],
 | 
				
			||||||
 | 
					  "build-tags": ["feather_stm32f405", "stm32f405", "stm32f4", "stm32"],
 | 
				
			||||||
 | 
					  "cflags": [
 | 
				
			||||||
 | 
					    "-Qunused-arguments"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "linkerscript": "targets/stm32f405.ld",
 | 
				
			||||||
 | 
					  "extra-files": [
 | 
				
			||||||
 | 
					    "src/device/stm32/stm32f405.s"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "flash-method": "command",
 | 
				
			||||||
 | 
					  "flash-command": "dfu-util -a 0 --dfuse-address 0x08000000 -D {hex}"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								targets/stm32f405.ld
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										9
									
								
								targets/stm32f405.ld
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					MEMORY
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 1M
 | 
				
			||||||
 | 
					    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_stack_size = 4K;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INCLUDE "targets/arm.ld"
 | 
				
			||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче