stm32: add support for the STM32F4Discovery
Signed-off-by: Yusuke Mitsuki <mickey.happygolucky@gmail.com>
Этот коммит содержится в:
		
							родитель
							
								
									315cd4059f
								
							
						
					
					
						коммит
						1322f404a6
					
				
					 7 изменённых файлов: 571 добавлений и 0 удалений
				
			
		|  | @ -68,6 +68,8 @@ commands: | ||||||
|       - run: tinygo build -size short -o test.elf -target=pca10056            examples/blinky2 |       - run: tinygo build -size short -o test.elf -target=pca10056            examples/blinky2 | ||||||
|       - run: tinygo build -size short -o test.elf -target=itsybitsy-m0        examples/blinky1 |       - run: tinygo build -size short -o test.elf -target=itsybitsy-m0        examples/blinky1 | ||||||
|       - run: tinygo build -size short -o test.elf -target=circuitplay-express examples/blinky1 |       - run: tinygo build -size short -o test.elf -target=circuitplay-express examples/blinky1 | ||||||
|  |       - run: tinygo build -size short -o test.elf -target=stm32f4disco        examples/blinky1 | ||||||
|  |       - run: tinygo build -size short -o test.elf -target=stm32f4disco        examples/blinky2 | ||||||
|       - run: tinygo build             -o wasm.wasm -target=wasm               examples/wasm |       - run: tinygo build             -o wasm.wasm -target=wasm               examples/wasm | ||||||
|   test-linux: |   test-linux: | ||||||
|     parameters: |     parameters: | ||||||
|  |  | ||||||
							
								
								
									
										112
									
								
								src/machine/board_stm32f4disco.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										112
									
								
								src/machine/board_stm32f4disco.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,112 @@ | ||||||
|  | // +build stm32,stm32f4disco | ||||||
|  | 
 | ||||||
|  | package machine | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
|  | 
 | ||||||
|  | 	PD0  = portD + 0 | ||||||
|  | 	PD1  = portD + 1 | ||||||
|  | 	PD2  = portD + 2 | ||||||
|  | 	PD3  = portD + 3 | ||||||
|  | 	PD4  = portD + 4 | ||||||
|  | 	PD5  = portD + 5 | ||||||
|  | 	PD6  = portD + 6 | ||||||
|  | 	PD7  = portD + 7 | ||||||
|  | 	PD8  = portD + 8 | ||||||
|  | 	PD9  = portD + 9 | ||||||
|  | 	PD10 = portD + 10 | ||||||
|  | 	PD11 = portD + 11 | ||||||
|  | 	PD12 = portD + 12 | ||||||
|  | 	PD13 = portD + 13 | ||||||
|  | 	PD14 = portD + 14 | ||||||
|  | 	PD15 = portD + 15 | ||||||
|  | 
 | ||||||
|  | 	PE0  = portE + 0 | ||||||
|  | 	PE1  = portE + 1 | ||||||
|  | 	PE2  = portE + 2 | ||||||
|  | 	PE3  = portE + 3 | ||||||
|  | 	PE4  = portE + 4 | ||||||
|  | 	PE5  = portE + 5 | ||||||
|  | 	PE6  = portE + 6 | ||||||
|  | 	PE7  = portE + 7 | ||||||
|  | 	PE8  = portE + 8 | ||||||
|  | 	PE9  = portE + 9 | ||||||
|  | 	PE10 = portE + 10 | ||||||
|  | 	PE11 = portE + 11 | ||||||
|  | 	PE12 = portE + 12 | ||||||
|  | 	PE13 = portE + 13 | ||||||
|  | 	PE14 = portE + 14 | ||||||
|  | 	PE15 = portE + 15 | ||||||
|  | 
 | ||||||
|  | 	PH0 = portH + 0 | ||||||
|  | 	PH1 = portH + 1 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	LED         = LED_BUILTIN | ||||||
|  | 	LED1        = LED_GREEN | ||||||
|  | 	LED2        = LED_ORANGE | ||||||
|  | 	LED3        = LED_RED | ||||||
|  | 	LED4        = LED_BLUE | ||||||
|  | 	LED_BUILTIN = LED_GREEN | ||||||
|  | 	LED_GREEN   = PD12 | ||||||
|  | 	LED_ORANGE  = PD13 | ||||||
|  | 	LED_RED     = PD14 | ||||||
|  | 	LED_BLUE    = PD15 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // UART pins | ||||||
|  | const ( | ||||||
|  | 	UART_TX_PIN = PA2 | ||||||
|  | 	UART_RX_PIN = PA3 | ||||||
|  | ) | ||||||
|  | @ -14,4 +14,5 @@ const ( | ||||||
| 	portE | 	portE | ||||||
| 	portF | 	portF | ||||||
| 	portG | 	portG | ||||||
|  | 	portH | ||||||
| ) | ) | ||||||
|  |  | ||||||
							
								
								
									
										220
									
								
								src/machine/machine_stm32f407.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										220
									
								
								src/machine/machine_stm32f407.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,220 @@ | ||||||
|  | // +build stm32,stm32f407 | ||||||
|  | 
 | ||||||
|  | package machine | ||||||
|  | 
 | ||||||
|  | // Peripheral abstraction layer for the stm32. | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"device/arm" | ||||||
|  | 	"device/stm32" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const CPU_FREQUENCY = 168000000 | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	// Mode Flag | ||||||
|  | 	GPIO_OUTPUT         = 0 | ||||||
|  | 	GPIO_INPUT          = GPIO_INPUT_PULLDOWN | ||||||
|  | 	GPIO_INPUT_FLOATING = 1 | ||||||
|  | 	GPIO_INPUT_PULLDOWN = 2 | ||||||
|  | 	GPIO_INPUT_PULLUP   = 3 | ||||||
|  | 
 | ||||||
|  | 	// for UART | ||||||
|  | 	GPIO_UART_TX = 4 | ||||||
|  | 	GPIO_UART_RX = 5 | ||||||
|  | 
 | ||||||
|  | 	//GPIOx_MODER | ||||||
|  | 	GPIO_MODE_INPUT          = 0 | ||||||
|  | 	GPIO_MODE_GENERAL_OUTPUT = 1 | ||||||
|  | 	GPIO_MODE_ALTERNABTIVE   = 2 | ||||||
|  | 	GPIO_MODE_ANALOG         = 3 | ||||||
|  | 
 | ||||||
|  | 	//GPIOx_OTYPER | ||||||
|  | 	GPIO_OUTPUT_MODE_PUSH_PULL  = 0 | ||||||
|  | 	GPIO_OUTPUT_MODE_OPEN_DRAIN = 1 | ||||||
|  | 
 | ||||||
|  | 	// GPIOx_OSPEEDR | ||||||
|  | 	GPIO_SPEED_LOW     = 0 | ||||||
|  | 	GPIO_SPEED_MID     = 1 | ||||||
|  | 	GPIO_SPEED_HI      = 2 | ||||||
|  | 	GPIO_SPEED_VERY_HI = 3 | ||||||
|  | 
 | ||||||
|  | 	// GPIOx_PUPDR | ||||||
|  | 	GPIO_FLOATING  = 0 | ||||||
|  | 	GPIO_PULL_UP   = 1 | ||||||
|  | 	GPIO_PULL_DOWN = 2 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
|  | 	case 7: | ||||||
|  | 		return stm32.GPIOH | ||||||
|  | 	case 8: | ||||||
|  | 		return stm32.GPIOI | ||||||
|  | 	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.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOAEN | ||||||
|  | 	case 1: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOBEN | ||||||
|  | 	case 2: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOCEN | ||||||
|  | 	case 3: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIODEN | ||||||
|  | 	case 4: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOEEN | ||||||
|  | 	case 5: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOFEN | ||||||
|  | 	case 6: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOGEN | ||||||
|  | 	case 7: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOHEN | ||||||
|  | 	case 8: | ||||||
|  | 		stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOIEN | ||||||
|  | 	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 := pin * 2 | ||||||
|  | 
 | ||||||
|  | 	if config.Mode == GPIO_INPUT_FLOATING { | ||||||
|  | 		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos))) | ||||||
|  | 		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos))) | ||||||
|  | 	} else if config.Mode == GPIO_INPUT_PULLDOWN { | ||||||
|  | 		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos))) | ||||||
|  | 		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_DOWN) << pos))) | ||||||
|  | 	} else if config.Mode == GPIO_INPUT_PULLUP { | ||||||
|  | 		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos))) | ||||||
|  | 		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos))) | ||||||
|  | 	} else if config.Mode == GPIO_OUTPUT { | ||||||
|  | 		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_GENERAL_OUTPUT) << pos))) | ||||||
|  | 		port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos))) | ||||||
|  | 	} else if config.Mode == GPIO_UART_TX { | ||||||
|  | 		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos))) | ||||||
|  | 		port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos))) | ||||||
|  | 		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos))) | ||||||
|  | 		p.setAltFunc(0x7) | ||||||
|  | 	} else if config.Mode == GPIO_UART_RX { | ||||||
|  | 		port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos))) | ||||||
|  | 		port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos))) | ||||||
|  | 		p.setAltFunc(0x7) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p GPIO) setAltFunc(af uint32) { | ||||||
|  | 	port := p.getPort() | ||||||
|  | 	pin := p.Pin % 16 | ||||||
|  | 	pos := pin * 4 | ||||||
|  | 	if pin >= 8 { | ||||||
|  | 		port.AFRH = stm32.RegValue(uint32(port.AFRH)&^(0xF<<pos) | ((af & 0xF) << pos)) | ||||||
|  | 	} else { | ||||||
|  | 		port.AFRL = stm32.RegValue(uint32(port.AFRL)&^(0xF<<pos) | ((af & 0xF) << 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 | ||||||
|  | type UART struct { | ||||||
|  | 	Buffer *RingBuffer | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	// Both UART0 and UART1 refer to USART2. | ||||||
|  | 	UART0 = UART{Buffer: NewRingBuffer()} | ||||||
|  | 	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 { | ||||||
|  | 	default: | ||||||
|  | 		// use standard TX/RX pins PA2 and PA3 | ||||||
|  | 		GPIO{UART_TX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_TX}) | ||||||
|  | 		GPIO{UART_RX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_RX}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Enable USART2 clock | ||||||
|  | 	stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_USART2EN | ||||||
|  | 
 | ||||||
|  | 	/* | ||||||
|  | 	  Set baud rate(115200) | ||||||
|  | 	  OVER8 = 0, APB2 = 42mhz | ||||||
|  | 	  +----------+--------+ | ||||||
|  | 	  | baudrate | BRR    | | ||||||
|  | 	  +----------+--------+ | ||||||
|  | 	  | 1200     | 0x88B8 | | ||||||
|  | 	  | 2400     | 0x445C | | ||||||
|  | 	  | 9600     | 0x1117 | | ||||||
|  | 	  | 19200    | 0x88C  | | ||||||
|  | 	  | 38400    | 0x446  | | ||||||
|  | 	  | 57600    | 0x2D9  | | ||||||
|  | 	  | 115200   | 0x16D  | | ||||||
|  | 	  +----------+--------+ | ||||||
|  | 	*/ | ||||||
|  | 	stm32.USART2.BRR = 0x16c | ||||||
|  | 
 | ||||||
|  | 	// Enable USART2 port. | ||||||
|  | 	stm32.USART2.CR1 = stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE | ||||||
|  | 
 | ||||||
|  | 	// Enable RX IRQ. | ||||||
|  | 	arm.SetPriority(stm32.IRQ_USART2, 0xc0) | ||||||
|  | 	arm.EnableIRQ(stm32.IRQ_USART2) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // WriteByte writes a byte of data to the UART. | ||||||
|  | func (uart UART) WriteByte(c byte) error { | ||||||
|  | 	stm32.USART2.DR = stm32.RegValue(c) | ||||||
|  | 
 | ||||||
|  | 	for (stm32.USART2.SR & stm32.USART_SR_TXE) == 0 { | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //go:export USART2_IRQHandler | ||||||
|  | func handleUSART2() { | ||||||
|  | 	UART1.Receive(byte((stm32.USART2.DR & 0xFF))) | ||||||
|  | } | ||||||
							
								
								
									
										208
									
								
								src/runtime/runtime_stm32f407.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										208
									
								
								src/runtime/runtime_stm32f407.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,208 @@ | ||||||
|  | // +build stm32,stm32f407 | ||||||
|  | 
 | ||||||
|  | package runtime | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"device/arm" | ||||||
|  | 	"device/stm32" | ||||||
|  | 	"machine" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	initCLK() | ||||||
|  | 	initTIM3() | ||||||
|  | 	machine.UART0.Configure(machine.UARTConfig{}) | ||||||
|  | 	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 |= stm32.RCC_CR_HSION | ||||||
|  | 	for (stm32.RCC.CR & stm32.RCC_CR_HSIRDY) == 0 { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Reset CFGR | ||||||
|  | 	stm32.RCC.CFGR = 0x00000000 | ||||||
|  | 	// Reset HSEON, CSSON and PLLON | ||||||
|  | 	stm32.RCC.CR &= 0xFEF6FFFF | ||||||
|  | 	// Reset PLLCFGR | ||||||
|  | 	stm32.RCC.PLLCFGR = 0x24003010 | ||||||
|  | 	// Reset HSEBYP | ||||||
|  | 	stm32.RCC.CR &= 0xFFFBFFFF | ||||||
|  | 	// Disable all interrupts | ||||||
|  | 	stm32.RCC.CIR = 0x00000000 | ||||||
|  | 
 | ||||||
|  | 	// Set up the clock | ||||||
|  | 	var startupCounter uint32 = 0 | ||||||
|  | 
 | ||||||
|  | 	// Enable HSE | ||||||
|  | 	stm32.RCC.CR = stm32.RCC_CR_HSEON | ||||||
|  | 	// Wait till HSE is ready and if timeout is reached exit | ||||||
|  | 	for { | ||||||
|  | 		startupCounter++ | ||||||
|  | 		if (stm32.RCC.CR&stm32.RCC_CR_HSERDY != 0) || (startupCounter == HSE_STARTUP_TIMEOUT) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (stm32.RCC.CR & stm32.RCC_CR_HSERDY) != 0 { | ||||||
|  | 		// Enable high performance mode, System frequency up to 168MHz | ||||||
|  | 		stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_PWREN | ||||||
|  | 		stm32.PWR.CR |= 0x4000 // PWR_CR_VOS | ||||||
|  | 		// HCLK = SYSCLK / 1 | ||||||
|  | 		stm32.RCC.CFGR |= (0x0 << stm32.RCC_CFGR_HPRE_Pos) | ||||||
|  | 		// PCLK2 = HCLK / 2 | ||||||
|  | 		stm32.RCC.CFGR |= (0x4 << stm32.RCC_CFGR_PPRE2_Pos) | ||||||
|  | 		// PCLK1 = HCLK / 4 | ||||||
|  | 		stm32.RCC.CFGR |= (0x5 << stm32.RCC_CFGR_PPRE1_Pos) | ||||||
|  | 		// Configure the main PLL | ||||||
|  | 		// PLL Options - See RM0090 Reference Manual pg. 95 | ||||||
|  | 		stm32.RCC.PLLCFGR = 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 |= stm32.RCC_CR_PLLON | ||||||
|  | 		// Wait till the main PLL is ready | ||||||
|  | 		for (stm32.RCC.CR & stm32.RCC_CR_PLLRDY) == 0 { | ||||||
|  | 		} | ||||||
|  | 		// Configure Flash prefetch, Instruction cache, Data cache and wait state | ||||||
|  | 		stm32.FLASH.ACR = 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 &^= stm32.RCC_CFGR_SW0 | stm32.RCC_CFGR_SW1 | ||||||
|  | 		stm32.RCC.CFGR |= (0x2 << stm32.RCC_CFGR_SW0_Pos) | ||||||
|  | 		for (stm32.RCC.CFGR & (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 |= (1 << 20) | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const tickMicros = 1000 | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	// tick in milliseconds | ||||||
|  | 	tickCount timeUnit | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | //go:volatile | ||||||
|  | type isrFlag bool | ||||||
|  | 
 | ||||||
|  | var timerWakeup isrFlag | ||||||
|  | 
 | ||||||
|  | // Enable the TIM3 clock.(sleep count) | ||||||
|  | func initTIM3() { | ||||||
|  | 	stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_TIM3EN | ||||||
|  | 
 | ||||||
|  | 	arm.SetPriority(stm32.IRQ_TIM3, 0xc3) | ||||||
|  | 	arm.EnableIRQ(stm32.IRQ_TIM3) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Enable the TIM7 clock.(tick count) | ||||||
|  | func initTIM7() { | ||||||
|  | 	stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_TIM7EN | ||||||
|  | 
 | ||||||
|  | 	// CK_INT = APB1 x2 = 84mhz | ||||||
|  | 	stm32.TIM7.PSC = 84000000/10000 - 1     // 84mhz to 10khz(0.1ms) | ||||||
|  | 	stm32.TIM7.ARR = stm32.RegValue(10) - 1 // interrupt per 1ms | ||||||
|  | 
 | ||||||
|  | 	// Enable the hardware interrupt. | ||||||
|  | 	stm32.TIM7.DIER |= stm32.TIM_DIER_UIE | ||||||
|  | 
 | ||||||
|  | 	// Enable the timer. | ||||||
|  | 	stm32.TIM7.CR1 |= stm32.TIM_CR1_CEN | ||||||
|  | 
 | ||||||
|  | 	arm.SetPriority(stm32.IRQ_TIM7, 0xc1) | ||||||
|  | 	arm.EnableIRQ(stm32.IRQ_TIM7) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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 = false | ||||||
|  | 
 | ||||||
|  | 	// CK_INT = APB1 x2 = 84mhz | ||||||
|  | 	// prescale counter down from 84mhz to 10khz aka 0.1 ms frequency. | ||||||
|  | 	stm32.TIM3.PSC = 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 = stm32.RegValue(arr) | ||||||
|  | 
 | ||||||
|  | 	// Enable the hardware interrupt. | ||||||
|  | 	stm32.TIM3.DIER |= stm32.TIM_DIER_UIE | ||||||
|  | 
 | ||||||
|  | 	// Enable the timer. | ||||||
|  | 	stm32.TIM3.CR1 |= stm32.TIM_CR1_CEN | ||||||
|  | 
 | ||||||
|  | 	// wait till timer wakes up | ||||||
|  | 	for !timerWakeup { | ||||||
|  | 		arm.Asm("wfi") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //go:export TIM3_IRQHandler | ||||||
|  | func handleTIM3() { | ||||||
|  | 	if (stm32.TIM3.SR & stm32.TIM_SR_UIF) > 0 { | ||||||
|  | 		// Disable the timer. | ||||||
|  | 		stm32.TIM3.CR1 &^= stm32.TIM_CR1_CEN | ||||||
|  | 
 | ||||||
|  | 		// clear the update flag | ||||||
|  | 		stm32.TIM3.SR &^= stm32.TIM_SR_UIF | ||||||
|  | 
 | ||||||
|  | 		// timer was triggered | ||||||
|  | 		timerWakeup = true | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //go:export TIM7_IRQHandler | ||||||
|  | func handleTIM7() { | ||||||
|  | 	if (stm32.TIM7.SR & stm32.TIM_SR_UIF) > 0 { | ||||||
|  | 		// clear the update flag | ||||||
|  | 		stm32.TIM7.SR &^= stm32.TIM_SR_UIF | ||||||
|  | 		tickCount++ | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								targets/stm32f407.ld
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										10
									
								
								targets/stm32f407.ld
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | 
 | ||||||
|  | MEMORY | ||||||
|  | { | ||||||
|  |     FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 1M | ||||||
|  |     RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | _stack_size = 4K; | ||||||
|  | 
 | ||||||
|  | INCLUDE "targets/arm.ld" | ||||||
							
								
								
									
										18
									
								
								targets/stm32f4disco.json
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										18
									
								
								targets/stm32f4disco.json
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | { | ||||||
|  |   "inherits": ["cortex-m"], | ||||||
|  |   "llvm-target": "armv7em-none-eabi", | ||||||
|  |   "build-tags": ["stm32f4disco", "stm32f407", "stm32"], | ||||||
|  |   "cflags": [ | ||||||
|  |     "--target=armv7em-none-eabi", | ||||||
|  |     "-Qunused-arguments" | ||||||
|  |   ], | ||||||
|  |   "ldflags": [ | ||||||
|  |     "-T", "targets/stm32f407.ld" | ||||||
|  |   ], | ||||||
|  |   "extra-files": [ | ||||||
|  |     "src/device/stm32/stm32f407.s" | ||||||
|  |   ], | ||||||
|  |   "flash": "openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c 'program {hex} reset exit'", | ||||||
|  |   "ocd-daemon": ["openocd", "-f", "interface/stlink.cfg", "-f", "target/stm32f4x.cfg"], | ||||||
|  |   "gdb-initial-cmds": ["target remote :3333", "monitor halt", "load", "monitor reset", "c"] | ||||||
|  | } | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Yusuke Mitsuki
						Yusuke Mitsuki