github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_stm32wlx.go (about)

     1  //go:build stm32wlx
     2  
     3  package machine
     4  
     5  // Peripheral abstraction layer for the stm32wle5
     6  
     7  import (
     8  	"device/stm32"
     9  	"encoding/binary"
    10  	"errors"
    11  	"math/bits"
    12  	"runtime/interrupt"
    13  	"runtime/volatile"
    14  	"unsafe"
    15  )
    16  
    17  var deviceIDAddr = []uintptr{0x1FFF7590, 0x1FFF7594, 0x1FFF7598}
    18  
    19  const (
    20  	AF0_SYSTEM             = 0
    21  	AF1_TIM1_2_LPTIM1      = 1
    22  	AF2_TIM1_2             = 2
    23  	AF3_SPIS2_TIM1_LPTIM3  = 3
    24  	AF4_I2C1_2_3           = 4
    25  	AF5_SPI1_SPI2S2        = 5
    26  	AF6_RF                 = 6
    27  	AF7_USART1_2           = 7
    28  	AF8_LPUART1            = 8
    29  	AF12_COMP1_2_TIM1      = 12
    30  	AF13_DEBUG             = 13
    31  	AF14_TIM2_16_17_LPTIM2 = 14
    32  	AF15_EVENTOUT          = 15
    33  )
    34  
    35  const (
    36  	SYSCLK        = 48e6
    37  	APB1_TIM_FREQ = SYSCLK
    38  	APB2_TIM_FREQ = SYSCLK
    39  )
    40  
    41  func CPUFrequency() uint32 {
    42  	return SYSCLK
    43  }
    44  
    45  const (
    46  	PA0  = portA + 0
    47  	PA1  = portA + 1
    48  	PA2  = portA + 2
    49  	PA3  = portA + 3
    50  	PA4  = portA + 4
    51  	PA5  = portA + 5
    52  	PA6  = portA + 6
    53  	PA7  = portA + 7
    54  	PA8  = portA + 8
    55  	PA9  = portA + 9
    56  	PA10 = portA + 10
    57  	PA11 = portA + 11
    58  	PA12 = portA + 12
    59  	PA13 = portA + 13
    60  	PA14 = portA + 14
    61  	PA15 = portA + 15
    62  
    63  	PB0  = portB + 0
    64  	PB1  = portB + 1
    65  	PB2  = portB + 2
    66  	PB3  = portB + 3
    67  	PB4  = portB + 4
    68  	PB5  = portB + 5
    69  	PB6  = portB + 6
    70  	PB7  = portB + 7
    71  	PB8  = portB + 8
    72  	PB9  = portB + 9
    73  	PB10 = portB + 10
    74  	PB11 = portB + 11
    75  	PB12 = portB + 12
    76  	PB13 = portB + 13
    77  	PB14 = portB + 14
    78  	PB15 = portB + 15
    79  
    80  	PC0  = portC + 0
    81  	PC1  = portC + 1
    82  	PC2  = portC + 2
    83  	PC3  = portC + 3
    84  	PC4  = portC + 4
    85  	PC5  = portC + 5
    86  	PC6  = portC + 6
    87  	PC7  = portC + 7
    88  	PC8  = portC + 8
    89  	PC9  = portC + 9
    90  	PC10 = portC + 10
    91  	PC11 = portC + 11
    92  	PC12 = portC + 12
    93  	PC13 = portC + 13
    94  	PC14 = portC + 14
    95  	PC15 = portC + 15
    96  
    97  	PH3 = portH + 3
    98  )
    99  
   100  func (p Pin) getPort() *stm32.GPIO_Type {
   101  	switch p / 16 {
   102  	case 0:
   103  		return stm32.GPIOA
   104  	case 1:
   105  		return stm32.GPIOB
   106  	case 2:
   107  		return stm32.GPIOC
   108  	case 7:
   109  		return stm32.GPIOH
   110  	default:
   111  		panic("machine: unknown port")
   112  	}
   113  }
   114  
   115  // enableClock enables the clock for this desired GPIO port.
   116  func (p Pin) enableClock() {
   117  	switch p / 16 {
   118  	case 0:
   119  		stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOAEN)
   120  	case 1:
   121  		stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOBEN)
   122  	case 2:
   123  		stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOCEN)
   124  	case 7:
   125  		stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOHEN)
   126  	default:
   127  		panic("machine: unknown port")
   128  	}
   129  }
   130  
   131  // Enable peripheral clock
   132  func enableAltFuncClock(bus unsafe.Pointer) {
   133  	switch bus {
   134  	// APB1ENR1
   135  	case unsafe.Pointer(stm32.LPTIM1): // LPTIM1 clock enable
   136  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_LPTIM1EN)
   137  	case unsafe.Pointer(stm32.DAC): // DAC clock enable
   138  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_DAC1EN)
   139  	case unsafe.Pointer(stm32.I2C3): // I2C3 clock enable
   140  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C3EN)
   141  	case unsafe.Pointer(stm32.I2C2): // I2C2 clock enable
   142  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C2EN)
   143  	case unsafe.Pointer(stm32.I2C1): // I2C1 clock enable
   144  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C1EN)
   145  	case unsafe.Pointer(stm32.USART2): // USART2 clock enable
   146  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_USART2EN)
   147  	case unsafe.Pointer(stm32.SPI2): // SPI2S2 clock enable
   148  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_SPI2S2EN)
   149  	case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable
   150  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_WWDGEN)
   151  	case unsafe.Pointer(stm32.TIM2): // TIM2 clock enable
   152  		stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM2EN)
   153  	// APB1ENR2
   154  	case unsafe.Pointer(stm32.LPTIM3): // LPTIM3 clock enable
   155  		stm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM3EN)
   156  	case unsafe.Pointer(stm32.LPTIM2): // LPTIM2 clock enable
   157  		stm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM2EN)
   158  	case unsafe.Pointer(stm32.LPUART): // LPUART clock enable
   159  		stm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPUART1EN)
   160  	//APB2ENR
   161  	case unsafe.Pointer(stm32.TIM17): // TIM17 clock enable
   162  		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM17EN)
   163  	case unsafe.Pointer(stm32.TIM16): // TIM16 clock enable
   164  		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM16EN)
   165  	case unsafe.Pointer(stm32.USART1): // USART1 clock enable
   166  		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
   167  	case unsafe.Pointer(stm32.SPI1): // SPI1 clock enable
   168  		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
   169  	case unsafe.Pointer(stm32.TIM1): // TIM1 clock enable
   170  		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN)
   171  	case unsafe.Pointer(stm32.ADC): // ADC clock enable
   172  		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN)
   173  
   174  	}
   175  }
   176  
   177  func handlePinInterrupt(pin uint8) {
   178  	if stm32.EXTI.PR1.HasBits(1 << pin) {
   179  		// Writing 1 to the pending register clears the
   180  		// pending flag for that bit
   181  		stm32.EXTI.PR1.Set(1 << pin)
   182  
   183  		callback := pinCallbacks[pin]
   184  		if callback != nil {
   185  			callback(interruptPins[pin])
   186  		}
   187  	}
   188  }
   189  
   190  func (p Pin) registerInterrupt() interrupt.Interrupt {
   191  	pin := uint8(p) % 16
   192  
   193  	switch pin {
   194  	case 0:
   195  		return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
   196  	case 1:
   197  		return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
   198  	case 2:
   199  		return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
   200  	case 3:
   201  		return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
   202  	case 4:
   203  		return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
   204  	case 5:
   205  		return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
   206  	case 6:
   207  		return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
   208  	case 7:
   209  		return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
   210  	case 8:
   211  		return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
   212  	case 9:
   213  		return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
   214  	case 10:
   215  		return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
   216  	case 11:
   217  		return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
   218  	case 12:
   219  		return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
   220  	case 13:
   221  		return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
   222  	case 14:
   223  		return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
   224  	case 15:
   225  		return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
   226  	}
   227  
   228  	return interrupt.Interrupt{}
   229  }
   230  
   231  // -- SPI ----------------------------------------------------------------------
   232  
   233  type SPI struct {
   234  	Bus             *stm32.SPI_Type
   235  	AltFuncSelector uint8
   236  }
   237  
   238  func (spi SPI) config8Bits() {
   239  	// Set rx threshold to 8-bits, so RXNE flag is set for 1 byte
   240  	// (common STM32 SPI implementation does 8-bit transfers only)
   241  	spi.Bus.CR2.SetBits(stm32.SPI_CR2_FRXTH)
   242  }
   243  
   244  func (spi SPI) configurePins(config SPIConfig) {
   245  	config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
   246  	config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
   247  	config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
   248  }
   249  
   250  func (spi SPI) getBaudRate(config SPIConfig) uint32 {
   251  	var clock uint32
   252  
   253  	// We keep this switch and separate management of SPI Clocks
   254  	// for future improvement of system/bus clocks and prescalers
   255  	switch spi.Bus {
   256  	case stm32.SPI1:
   257  		clock = CPUFrequency()
   258  	case stm32.SPI2, stm32.SPI3:
   259  		clock = CPUFrequency()
   260  	}
   261  
   262  	// limit requested frequency to bus frequency and min frequency (DIV256)
   263  	freq := config.Frequency
   264  	if min := clock / 256; freq < min {
   265  		freq = min
   266  	} else if freq > clock {
   267  		freq = clock
   268  	}
   269  
   270  	// calculate the exact clock divisor (freq=clock/div -> div=clock/freq).
   271  	// truncation is fine, since it produces a less-than-or-equal divisor, and
   272  	// thus a greater-than-or-equal frequency.
   273  	// divisors only come in consecutive powers of 2, so we can use log2 (or,
   274  	// equivalently, bits.Len - 1) to convert to respective enum value.
   275  	div := bits.Len32(clock/freq) - 1
   276  
   277  	// but DIV1 (2^0) is not permitted, as the least divisor is DIV2 (2^1), so
   278  	// subtract 1 from the log2 value, keeping a lower bound of 0
   279  	if div < 0 {
   280  		div = 0
   281  	} else if div > 0 {
   282  		div--
   283  	}
   284  
   285  	// finally, shift the enumerated value into position for SPI CR1
   286  	return uint32(div) << stm32.SPI_CR1_BR_Pos
   287  }
   288  
   289  //---------- I2C related code
   290  
   291  // Gets the value for TIMINGR register
   292  func (i2c *I2C) getFreqRange() uint32 {
   293  	// This is a 'magic' value calculated by STM32CubeMX
   294  	// for 48Mhz PCLK1.
   295  	// TODO: Do calculations based on PCLK1
   296  	return 0x20303E5D
   297  }
   298  
   299  //---------- UART related code
   300  
   301  // Configure the UART.
   302  func (uart UART) configurePins(config UARTConfig) {
   303  	// enable the alternate functions on the TX and RX pins
   304  	config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)
   305  	config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
   306  }
   307  
   308  // UART baudrate calc based on the bus and clockspeed
   309  // NOTE: keep this in sync with the runtime/runtime_stm32wle5.go clock init code
   310  func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {
   311  	var br uint32
   312  	uartClock := CPUFrequency() // No Prescaler configuration
   313  	br = uint32((uartClock + baudRate/2) / baudRate)
   314  	return (br)
   315  }
   316  
   317  // Register names vary by ST processor, these are for STM L5
   318  func (uart *UART) setRegisters() {
   319  	uart.rxReg = &uart.Bus.RDR
   320  	uart.txReg = &uart.Bus.TDR
   321  	uart.statusReg = &uart.Bus.ISR
   322  	uart.txEmptyFlag = stm32.USART_ISR_TXFNF //(TXFNF == TXE == bit 7, but depends alternate RM0461/1094)
   323  }
   324  
   325  //---------- Timer related code
   326  
   327  var (
   328  	TIM1 = TIM{
   329  		EnableRegister: &stm32.RCC.APB2ENR,
   330  		EnableFlag:     stm32.RCC_APB2ENR_TIM1EN,
   331  		Device:         stm32.TIM1,
   332  		Channels: [4]TimerChannel{
   333  			TimerChannel{Pins: []PinFunction{{PA8, AF1_TIM1_2_LPTIM1}}},
   334  			TimerChannel{Pins: []PinFunction{{PA9, AF1_TIM1_2_LPTIM1}}},
   335  			TimerChannel{Pins: []PinFunction{{PA10, AF1_TIM1_2_LPTIM1}}},
   336  			TimerChannel{Pins: []PinFunction{{PA11, AF1_TIM1_2_LPTIM1}}},
   337  		},
   338  		busFreq: APB2_TIM_FREQ,
   339  	}
   340  	TIM2 = TIM{
   341  		EnableRegister: &stm32.RCC.APB1ENR1,
   342  		EnableFlag:     stm32.RCC_APB1ENR1_TIM2EN,
   343  		Device:         stm32.TIM2,
   344  		Channels: [4]TimerChannel{
   345  			TimerChannel{Pins: []PinFunction{{PA0, AF1_TIM1_2_LPTIM1}, {PA5, AF1_TIM1_2_LPTIM1}, {PA15, AF1_TIM1_2_LPTIM1}}},
   346  			TimerChannel{Pins: []PinFunction{{PA1, AF1_TIM1_2_LPTIM1}, {PB3, AF1_TIM1_2_LPTIM1}}},
   347  			TimerChannel{Pins: []PinFunction{{PA2, AF1_TIM1_2_LPTIM1}, {PB10, AF1_TIM1_2_LPTIM1}}},
   348  			TimerChannel{Pins: []PinFunction{{PA3, AF1_TIM1_2_LPTIM1}, {PB11, AF1_TIM1_2_LPTIM1}}},
   349  		},
   350  		busFreq: APB1_TIM_FREQ,
   351  	}
   352  	TIM16 = TIM{
   353  		EnableRegister: &stm32.RCC.APB2ENR,
   354  		EnableFlag:     stm32.RCC_APB2ENR_TIM16EN,
   355  		Device:         stm32.TIM16,
   356  		Channels: [4]TimerChannel{
   357  			TimerChannel{Pins: []PinFunction{{PA6, AF14_TIM2_16_17_LPTIM2}}},
   358  			TimerChannel{Pins: []PinFunction{}},
   359  			TimerChannel{Pins: []PinFunction{}},
   360  			TimerChannel{Pins: []PinFunction{}},
   361  		},
   362  		busFreq: APB2_TIM_FREQ,
   363  	}
   364  	TIM17 = TIM{
   365  		EnableRegister: &stm32.RCC.APB2ENR,
   366  		EnableFlag:     stm32.RCC_APB2ENR_TIM17EN,
   367  		Device:         stm32.TIM17,
   368  		Channels: [4]TimerChannel{
   369  			TimerChannel{Pins: []PinFunction{{PA7, AF1_TIM1_2_LPTIM1}, {PB9, AF1_TIM1_2_LPTIM1}}},
   370  			TimerChannel{Pins: []PinFunction{}},
   371  			TimerChannel{Pins: []PinFunction{}},
   372  			TimerChannel{Pins: []PinFunction{}},
   373  		},
   374  		busFreq: APB2_TIM_FREQ,
   375  	}
   376  )
   377  
   378  func (t *TIM) registerUPInterrupt() interrupt.Interrupt {
   379  	switch t {
   380  	case &TIM1:
   381  		return interrupt.New(stm32.IRQ_TIM1_UP, TIM1.handleUPInterrupt)
   382  	case &TIM2:
   383  		return interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)
   384  	case &TIM16:
   385  		return interrupt.New(stm32.IRQ_TIM16, TIM16.handleUPInterrupt)
   386  	case &TIM17:
   387  		return interrupt.New(stm32.IRQ_TIM17, TIM17.handleUPInterrupt)
   388  	}
   389  
   390  	return interrupt.Interrupt{}
   391  }
   392  
   393  func (t *TIM) registerOCInterrupt() interrupt.Interrupt {
   394  	switch t {
   395  	case &TIM1:
   396  		return interrupt.New(stm32.IRQ_TIM1_CC, TIM1.handleOCInterrupt)
   397  	case &TIM2:
   398  		return interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)
   399  	case &TIM16:
   400  		return interrupt.New(stm32.IRQ_TIM16, TIM16.handleOCInterrupt)
   401  	case &TIM17:
   402  		return interrupt.New(stm32.IRQ_TIM17, TIM17.handleOCInterrupt)
   403  	}
   404  
   405  	return interrupt.Interrupt{}
   406  }
   407  
   408  func (t *TIM) enableMainOutput() {
   409  	t.Device.BDTR.SetBits(stm32.TIM_BDTR_MOE)
   410  }
   411  
   412  func initRNG() {
   413  	stm32.RCC.AHB3ENR.SetBits(stm32.RCC_AHB3ENR_RNGEN)
   414  
   415  	// Enable RNG with config.A  (See RM0453 22.6.2)
   416  	stm32.RNG.CR.Set(0x40F00D40)   // RNG Config. A
   417  	stm32.RNG.HTCR.Set(0x17590ABC) // MAGIC NUMBER
   418  	stm32.RNG.HTCR.Set(0x0000AA74) // HTCR VALUE
   419  	stm32.RNG.CR.Set(0x00F00D4C)   // CONFIG A  + RNG_EN=1 + IE=1
   420  }
   421  
   422  //----------
   423  
   424  type arrtype = uint32
   425  type arrRegType = volatile.Register32
   426  
   427  const (
   428  	ARR_MAX = 0x10000
   429  	PSC_MAX = 0x10000
   430  )
   431  
   432  //---------- Flash related code
   433  
   434  const eraseBlockSizeValue = 2048
   435  
   436  // eraseBlock of the passed in block number
   437  func eraseBlock(block uint32) error {
   438  	waitUntilFlashDone()
   439  
   440  	// check if operation is allowed.
   441  	if stm32.FLASH.GetSR_PESD() != 0 {
   442  		return errFlashCannotErasePage
   443  	}
   444  
   445  	// clear any previous errors
   446  	stm32.FLASH.SR.SetBits(0x3FA)
   447  
   448  	// page erase operation
   449  	stm32.FLASH.SetCR_PER(1)
   450  	defer stm32.FLASH.SetCR_PER(0)
   451  
   452  	// set the address to the page to be written
   453  	stm32.FLASH.SetCR_PNB(block)
   454  	defer stm32.FLASH.SetCR_PNB(0)
   455  
   456  	// start the page erase
   457  	stm32.FLASH.SetCR_STRT(1)
   458  
   459  	waitUntilFlashDone()
   460  
   461  	if err := checkError(); err != nil {
   462  		return err
   463  	}
   464  
   465  	return nil
   466  }
   467  
   468  const writeBlockSize = 8
   469  
   470  func writeFlashData(address uintptr, data []byte) (int, error) {
   471  	if len(data)%writeBlockSize != 0 {
   472  		return 0, errFlashInvalidWriteLength
   473  	}
   474  
   475  	waitUntilFlashDone()
   476  
   477  	// check if operation is allowed
   478  	if stm32.FLASH.GetSR_PESD() != 0 {
   479  		return 0, errFlashNotAllowedWriteData
   480  	}
   481  
   482  	// clear any previous errors
   483  	stm32.FLASH.SR.SetBits(0x3FA)
   484  
   485  	for j := 0; j < len(data); j += writeBlockSize {
   486  		// start page write operation
   487  		stm32.FLASH.SetCR_PG(1)
   488  
   489  		// write first word using double-word high order word
   490  		*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(data[j : j+writeBlockSize/2])
   491  
   492  		address += writeBlockSize / 2
   493  
   494  		// write second word using double-word low order word
   495  		*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(data[j+writeBlockSize/2 : j+writeBlockSize])
   496  
   497  		waitUntilFlashDone()
   498  
   499  		if err := checkError(); err != nil {
   500  			return j, err
   501  		}
   502  
   503  		// end flash write
   504  		stm32.FLASH.SetCR_PG(0)
   505  		address += writeBlockSize / 2
   506  	}
   507  
   508  	return len(data), nil
   509  }
   510  
   511  func waitUntilFlashDone() {
   512  	for stm32.FLASH.GetSR_BSY() != 0 {
   513  	}
   514  
   515  	for stm32.FLASH.GetSR_CFGBSY() != 0 {
   516  	}
   517  }
   518  
   519  var (
   520  	errFlashPGS  = errors.New("errFlashPGS")
   521  	errFlashSIZE = errors.New("errFlashSIZE")
   522  	errFlashPGA  = errors.New("errFlashPGA")
   523  	errFlashWRP  = errors.New("errFlashWRP")
   524  	errFlashPROG = errors.New("errFlashPROG")
   525  )
   526  
   527  func checkError() error {
   528  	switch {
   529  	case stm32.FLASH.GetSR_PGSERR() != 0:
   530  		return errFlashPGS
   531  	case stm32.FLASH.GetSR_SIZERR() != 0:
   532  		return errFlashSIZE
   533  	case stm32.FLASH.GetSR_PGAERR() != 0:
   534  		return errFlashPGA
   535  	case stm32.FLASH.GetSR_WRPERR() != 0:
   536  		return errFlashWRP
   537  	case stm32.FLASH.GetSR_PROGERR() != 0:
   538  		return errFlashPROG
   539  	}
   540  
   541  	return nil
   542  }