diff --git a/src/examples/pwm/nucleo-l031k6.go b/src/examples/pwm/nucleo-l031k6.go new file mode 100644 index 00000000..59f32c17 --- /dev/null +++ b/src/examples/pwm/nucleo-l031k6.go @@ -0,0 +1,11 @@ +// +build stm32l0 + +package main + +import "machine" + +var ( + pwm = &machine.TIM2 + pinA = machine.PA0 + pinB = machine.PB3 +) diff --git a/src/machine/machine_stm32_tim.go b/src/machine/machine_stm32_tim.go index 89c006eb..f27cd64d 100644 --- a/src/machine/machine_stm32_tim.go +++ b/src/machine/machine_stm32_tim.go @@ -1,4 +1,4 @@ -// +build stm32f4 stm32l5 +// +build stm32f4 stm32l5 stm32l0 package machine diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go index 8dab461b..a25d6c9f 100644 --- a/src/machine/machine_stm32l0.go +++ b/src/machine/machine_stm32l0.go @@ -12,6 +12,12 @@ func CPUFrequency() uint32 { return 32000000 } +// Internal use: configured speed of the APB1 and APB2 timers, this should be kept +// in sync with any changes to runtime package which configures the oscillators +// and clock frequencies +const APB1_TIM_FREQ = 32e6 // 32MHz +const APB2_TIM_FREQ = 32e6 // 32MHz + const ( PA0 = portA + 0 PA1 = portA + 1 diff --git a/src/machine/machine_stm32l0x1.go b/src/machine/machine_stm32l0x1.go index 3fad050a..033718c5 100644 --- a/src/machine/machine_stm32l0x1.go +++ b/src/machine/machine_stm32l0x1.go @@ -6,9 +6,22 @@ package machine import ( "device/stm32" + "runtime/interrupt" + "runtime/volatile" "unsafe" ) +const ( + AF0_SYSTEM_SPI1_USART2_LPTIM_TIM21 = 0 + AF1_SPI1_I2C1_LPTIM = 1 + AF2_LPTIM_TIM2 = 2 + AF3_I2C1 = 3 + AF4_I2C1_USART2_LPUART1_TIM22 = 4 + AF5_TIM2_21_22 = 5 + AF6_LPUART1 = 6 + AF7_COMP1_2 = 7 +) + // Enable peripheral clock func enableAltFuncClock(bus unsafe.Pointer) { switch bus { @@ -50,3 +63,135 @@ func enableAltFuncClock(bus unsafe.Pointer) { stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) } } + +//---------- Timer related code + +var ( + TIM2 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM2EN, + Device: stm32.TIM2, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{{PA0, AF2_LPTIM_TIM2}, {PA5, AF5_TIM2_21_22}, {PA8, AF5_TIM2_21_22}, {PA15, AF5_TIM2_21_22}}}, + TimerChannel{Pins: []PinFunction{{PA1, AF2_LPTIM_TIM2}, {PB3, AF2_LPTIM_TIM2}}}, + TimerChannel{Pins: []PinFunction{{PA2, AF2_LPTIM_TIM2}, {PB0, AF5_TIM2_21_22}, {PB10, AF2_LPTIM_TIM2}}}, + TimerChannel{Pins: []PinFunction{{PA3, AF2_LPTIM_TIM2}, {PB1, AF5_TIM2_21_22}, {PB11, AF2_LPTIM_TIM2}}}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM3 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM3EN, + Device: stm32.TIM3, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM6 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM6EN, + Device: stm32.TIM6, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM7 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM7EN, + Device: stm32.TIM7, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM21 = TIM{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM21EN, + Device: stm32.TIM21, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB2_TIM_FREQ, + } + + TIM22 = TIM{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM22EN, + Device: stm32.TIM2, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB2_TIM_FREQ, + } +) + +func (t *TIM) registerUPInterrupt() interrupt.Interrupt { + switch t { + case &TIM2: + return interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt) + case &TIM3: + return interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt) + case &TIM6: + return interrupt.New(stm32.IRQ_TIM6, TIM6.handleUPInterrupt) + case &TIM7: + return interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt) + case &TIM21: + return interrupt.New(stm32.IRQ_TIM21, TIM21.handleUPInterrupt) + case &TIM22: + return interrupt.New(stm32.IRQ_TIM22, TIM22.handleUPInterrupt) + } + + return interrupt.Interrupt{} +} + +func (t *TIM) registerOCInterrupt() interrupt.Interrupt { + switch t { + case &TIM2: + return interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt) + case &TIM3: + return interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt) + case &TIM6: + return interrupt.New(stm32.IRQ_TIM6, TIM6.handleOCInterrupt) + case &TIM7: + return interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt) + case &TIM21: + return interrupt.New(stm32.IRQ_TIM21, TIM21.handleOCInterrupt) + case &TIM22: + return interrupt.New(stm32.IRQ_TIM22, TIM22.handleOCInterrupt) + } + + return interrupt.Interrupt{} +} + +func (t *TIM) enableMainOutput() { + // nothing to do - no BDTR register +} + +type arrtype = uint16 +type arrRegType = volatile.Register16 + +const ( + ARR_MAX = 0x10000 + PSC_MAX = 0x10000 +) diff --git a/src/machine/machine_stm32l0x2.go b/src/machine/machine_stm32l0x2.go index 71c7cd4a..3394f429 100644 --- a/src/machine/machine_stm32l0x2.go +++ b/src/machine/machine_stm32l0x2.go @@ -6,9 +6,22 @@ package machine import ( "device/stm32" + "runtime/interrupt" + "runtime/volatile" "unsafe" ) +const ( + AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22 = 0 + AF1_SPI1_2_I2S2_I2C1_TIM2_21 = 1 + AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3 = 2 + AF3_I2C1_TSC = 3 + AF4_I2C1_USART1_2_LPUART1_TIM3_22 = 4 + AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22 = 5 + AF6_I2C1_2_LPUART1_USART4_5_TIM21 = 6 + AF7_I2C3_LPUART1_COMP1_2_TIM3 = 7 +) + // Enable peripheral clock func enableAltFuncClock(bus unsafe.Pointer) { switch bus { @@ -52,3 +65,190 @@ func enableAltFuncClock(bus unsafe.Pointer) { stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) } } + +//---------- Timer related code + +var ( + TIM2 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM2EN, + Device: stm32.TIM2, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{ + {PA0, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PA5, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22}, + {PA15, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22}, + {PE9, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + TimerChannel{Pins: []PinFunction{ + {PA1, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PB3, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PE10, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + TimerChannel{Pins: []PinFunction{ + {PA2, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PB10, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PE11, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + TimerChannel{Pins: []PinFunction{ + {PA3, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PB11, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PE12, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM3 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM3EN, + Device: stm32.TIM3, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{ + {PA6, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PB4, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PC6, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PE3, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + }}, + TimerChannel{Pins: []PinFunction{ + {PA7, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PB5, AF4_I2C1_USART1_2_LPUART1_TIM3_22}, + {PC7, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PE4, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + }}, + TimerChannel{Pins: []PinFunction{ + {PB0, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PC8, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PE5, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + }}, + TimerChannel{Pins: []PinFunction{ + {PB1, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PC9, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + {PE6, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3}, + }}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM6 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM6EN, + Device: stm32.TIM6, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM7 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM7EN, + Device: stm32.TIM7, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB1_TIM_FREQ, + } + + TIM21 = TIM{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM21EN, + Device: stm32.TIM21, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{ + {PA2, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + {PB13, AF6_I2C1_2_LPUART1_USART4_5_TIM21}, + {PD0, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + {PE5, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + TimerChannel{Pins: []PinFunction{ + {PA3, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + {PB14, AF6_I2C1_2_LPUART1_USART4_5_TIM21}, + {PD7, AF1_SPI1_2_I2S2_I2C1_TIM2_21}, + {PE6, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB2_TIM_FREQ, + } + + TIM22 = TIM{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM22EN, + Device: stm32.TIM2, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{ + {PA6, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22}, + {PB4, AF4_I2C1_USART1_2_LPUART1_TIM3_22}, + {PC6, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + {PE3, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + TimerChannel{Pins: []PinFunction{ + {PA7, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22}, + {PB5, AF4_I2C1_USART1_2_LPUART1_TIM3_22}, + {PC7, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + {PE4, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22}, + }}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB2_TIM_FREQ, + } +) + +func (t *TIM) registerUPInterrupt() interrupt.Interrupt { + switch t { + case &TIM2: + return interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt) + case &TIM3: + return interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt) + case &TIM6: + return interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleUPInterrupt) + case &TIM7: + return interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt) + case &TIM21: + return interrupt.New(stm32.IRQ_TIM21, TIM21.handleUPInterrupt) + case &TIM22: + return interrupt.New(stm32.IRQ_TIM22, TIM22.handleUPInterrupt) + } + + return interrupt.Interrupt{} +} + +func (t *TIM) registerOCInterrupt() interrupt.Interrupt { + switch t { + case &TIM2: + return interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt) + case &TIM3: + return interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt) + case &TIM6: + return interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleOCInterrupt) + case &TIM7: + return interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt) + case &TIM21: + return interrupt.New(stm32.IRQ_TIM21, TIM21.handleOCInterrupt) + case &TIM22: + return interrupt.New(stm32.IRQ_TIM22, TIM22.handleOCInterrupt) + } + + return interrupt.Interrupt{} +} + +func (t *TIM) enableMainOutput() { + // nothing to do - no BDTR register +} + +type arrtype = uint16 +type arrRegType = volatile.Register16 + +const ( + ARR_MAX = 0x10000 + PSC_MAX = 0x10000 +)