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=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=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 | ||||
|   test-linux: | ||||
|     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 | ||||
| 	portF | ||||
| 	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