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"
 | 
			
		||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче