mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-10 14:03:39 +00:00
Merge branch 'dev' into feature/usb-common
This commit is contained in:
@@ -47,8 +47,6 @@ const (
|
||||
LED = D6
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN Pin = PA24
|
||||
|
||||
@@ -35,8 +35,6 @@ const (
|
||||
LED3 Pin = PB03 // RX LED
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// ADC pins
|
||||
const (
|
||||
AREF Pin = PA03
|
||||
|
||||
@@ -74,5 +74,3 @@ const (
|
||||
PB30 Pin = 62
|
||||
PB31 Pin = 63
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
@@ -15,8 +15,6 @@ const (
|
||||
BUTTON = PB31
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
const (
|
||||
// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf
|
||||
|
||||
|
||||
@@ -11,7 +11,13 @@ const (
|
||||
LED = PC13
|
||||
)
|
||||
|
||||
var Serial = UART1
|
||||
const (
|
||||
// This board does not have a user button, so
|
||||
// use first GPIO pin by default
|
||||
BUTTON = PA0
|
||||
)
|
||||
|
||||
var DefaultUART = UART1
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
|
||||
@@ -38,6 +38,7 @@ const (
|
||||
const (
|
||||
LED = D13
|
||||
NEOPIXELS = D8
|
||||
WS2812 = D8
|
||||
|
||||
BUTTONA = D4
|
||||
BUTTONB = D5
|
||||
@@ -56,8 +57,6 @@ const (
|
||||
UART_RX_PIN = P0_30 // PORTB
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = P0_05 // I2C0 external
|
||||
|
||||
@@ -41,6 +41,7 @@ const (
|
||||
const (
|
||||
LED = D13
|
||||
NEOPIXELS = D8
|
||||
WS2812 = D8
|
||||
|
||||
BUTTONA = D4
|
||||
BUTTONB = D5
|
||||
|
||||
@@ -72,6 +72,7 @@ const (
|
||||
LED1 = LED
|
||||
LED2 = D43
|
||||
NEOPIXEL = D18
|
||||
WS2812 = D18
|
||||
|
||||
BUTTON_LEFT = D5
|
||||
BUTTON_RIGHT = D11
|
||||
@@ -103,11 +104,6 @@ const (
|
||||
UART_TX_PIN = D1
|
||||
)
|
||||
|
||||
// Serial is the USB device
|
||||
var (
|
||||
Serial = USB
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = D20 // I2C0 external
|
||||
|
||||
@@ -68,8 +68,6 @@ const (
|
||||
ADC3 Pin = IO39
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
|
||||
// UART0 pins
|
||||
const (
|
||||
UART_TX_PIN = IO1
|
||||
|
||||
@@ -44,10 +44,9 @@ const (
|
||||
const (
|
||||
LED = D13
|
||||
NEOPIXELS = D8
|
||||
WS2812 = D8
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
|
||||
@@ -36,11 +36,10 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
LED = D13
|
||||
LED = D13
|
||||
WS2812 = D8
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// +build feather_nrf52840_sense
|
||||
|
||||
package machine
|
||||
|
||||
const HasLowFrequencyCrystal = true
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
D0 = P0_25 // UART TX
|
||||
D1 = P0_24 // UART RX
|
||||
D2 = P0_10 // NFC2
|
||||
D3 = P1_11
|
||||
D4 = P1_10 // LED2
|
||||
D5 = P1_08
|
||||
D6 = P0_07
|
||||
D7 = P1_02 // Button
|
||||
D8 = P0_16 // NeoPixel
|
||||
D9 = P0_26
|
||||
D10 = P0_27
|
||||
D11 = P0_06
|
||||
D12 = P0_08
|
||||
D13 = P1_09 // LED1
|
||||
D14 = P0_04 // A0
|
||||
D15 = P0_05 // A1
|
||||
D16 = P0_30 // A2
|
||||
D17 = P0_28 // A3
|
||||
D18 = P0_02 // A4
|
||||
D19 = P0_03 // A5
|
||||
D20 = P0_29 // Battery
|
||||
D21 = P0_31 // AREF
|
||||
D22 = P0_12 // I2C SDA
|
||||
D23 = P0_11 // I2C SCL
|
||||
D24 = P0_15 // SPI MISO
|
||||
D25 = P0_13 // SPI MOSI
|
||||
D26 = P0_14 // SPI SCK
|
||||
D27 = P0_19 // QSPI CLK
|
||||
D28 = P0_20 // QSPI CS
|
||||
D29 = P0_17 // QSPI Data 0
|
||||
D30 = P0_22 // QSPI Data 1
|
||||
D31 = P0_23 // QSPI Data 2
|
||||
D32 = P0_21 // QSPI Data 3
|
||||
D33 = P0_09 // NFC1 (test point on bottom of board)
|
||||
)
|
||||
|
||||
// Analog Pins
|
||||
const (
|
||||
A0 = D14
|
||||
A1 = D15
|
||||
A2 = D16
|
||||
A3 = D17
|
||||
A4 = D18
|
||||
A5 = D19
|
||||
A6 = D20 // Battery
|
||||
A7 = D21 // ARef
|
||||
)
|
||||
|
||||
const (
|
||||
LED = D13
|
||||
LED1 = LED
|
||||
LED2 = D4
|
||||
NEOPIXEL = D8
|
||||
WS2812 = D8
|
||||
BUTTON = D7
|
||||
|
||||
QSPI_SCK = D27
|
||||
QSPI_CS = D28
|
||||
QSPI_DATA0 = D29
|
||||
QSPI_DATA1 = D30
|
||||
QSPI_DATA2 = D31
|
||||
QSPI_DATA3 = D32
|
||||
)
|
||||
|
||||
// UART0 pins (logical UART1)
|
||||
const (
|
||||
UART_RX_PIN = D1
|
||||
UART_TX_PIN = D0
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = D22 // I2C0 external
|
||||
SCL_PIN = D23 // I2C0 external
|
||||
)
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D26 // SCK
|
||||
SPI0_SDO_PIN = D25 // SDO
|
||||
SPI0_SDI_PIN = D24 // SDI
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
const (
|
||||
usb_STRING_PRODUCT = "Feather nRF52840 Express"
|
||||
usb_STRING_MANUFACTURER = "Adafruit Industries LLC"
|
||||
)
|
||||
|
||||
var (
|
||||
usb_VID uint16 = 0x239A
|
||||
usb_PID uint16 = 0x8088
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultUART = UART0
|
||||
)
|
||||
@@ -59,6 +59,7 @@ const (
|
||||
LED1 = LED
|
||||
LED2 = D4
|
||||
NEOPIXEL = D8
|
||||
WS2812 = D8
|
||||
BUTTON = D7
|
||||
|
||||
QSPI_SCK = D27
|
||||
@@ -71,13 +72,8 @@ const (
|
||||
|
||||
// UART0 pins (logical UART1)
|
||||
const (
|
||||
UART_RX_PIN = D0
|
||||
UART_TX_PIN = D1
|
||||
)
|
||||
|
||||
// Serial is the USB device
|
||||
var (
|
||||
Serial = USB
|
||||
UART_RX_PIN = D1
|
||||
UART_TX_PIN = D0
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
@@ -103,3 +99,7 @@ var (
|
||||
usb_VID uint16 = 0x239A
|
||||
usb_PID uint16 = 0x802A
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultUART = UART0
|
||||
)
|
||||
|
||||
@@ -84,6 +84,7 @@ const (
|
||||
LED_NEOPIXEL = D8
|
||||
LED_BUILTIN = LED_RED
|
||||
LED = LED_BUILTIN
|
||||
WS2812 = D8
|
||||
)
|
||||
|
||||
func initLED() {}
|
||||
@@ -140,7 +141,7 @@ var (
|
||||
TxAltFuncSelector: AF7_USART1_2_3,
|
||||
RxAltFuncSelector: AF7_USART1_2_3,
|
||||
}
|
||||
Serial = UART1
|
||||
DefaultUART = UART1
|
||||
)
|
||||
|
||||
func initUART() {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// +build feather_rp2040
|
||||
|
||||
package machine
|
||||
|
||||
const (
|
||||
LED = GPIO13
|
||||
|
||||
// Onboard crystal oscillator frequency, in MHz.
|
||||
xoscFreq = 12 // MHz
|
||||
)
|
||||
|
||||
// SPI default pins
|
||||
const (
|
||||
// Default Serial Clock Bus 0 for SPI communications
|
||||
SPI0_SCK_PIN = GPIO18
|
||||
// Default Serial Out Bus 0 for SPI communications
|
||||
SPI0_SDO_PIN = GPIO19 // Tx
|
||||
// Default Serial In Bus 0 for SPI communications
|
||||
SPI0_SDI_PIN = GPIO20 // Rx
|
||||
|
||||
// Default Serial Clock Bus 1 for SPI communications
|
||||
SPI1_SCK_PIN = GPIO10
|
||||
// Default Serial Out Bus 1 for SPI communications
|
||||
SPI1_SDO_PIN = GPIO11 // Tx
|
||||
// Default Serial In Bus 1 for SPI communications
|
||||
SPI1_SDI_PIN = GPIO12 // Rx
|
||||
)
|
||||
@@ -139,10 +139,9 @@ const (
|
||||
LED_RX = UART_RX_LED_PIN
|
||||
LED_TX = UART_TX_LED_PIN
|
||||
NEOPIXEL = NEOPIXEL_PIN
|
||||
WS2812 = NEOPIXEL_PIN
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
UART1_RX_PIN = D0 // (PB25)
|
||||
|
||||
@@ -35,7 +35,7 @@ const (
|
||||
LED_BLUE = P21
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
const (
|
||||
// TODO: figure out the pin numbers for these.
|
||||
|
||||
@@ -37,8 +37,6 @@ const (
|
||||
LED = D13
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
|
||||
@@ -70,11 +70,6 @@ const (
|
||||
UART_TX_PIN = D1
|
||||
)
|
||||
|
||||
// Serial is the USB device
|
||||
var (
|
||||
Serial = USB
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = D21 // I2C0 external
|
||||
|
||||
@@ -54,7 +54,7 @@ const (
|
||||
I2C0_SDA_PIN = PA10
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
var (
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ const (
|
||||
LED_BLUE = D14
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// Default pins for UARTHS.
|
||||
const (
|
||||
|
||||
@@ -75,6 +75,7 @@ const (
|
||||
const (
|
||||
LED = D13
|
||||
NEOPIXEL = D4
|
||||
WS2812 = D4
|
||||
)
|
||||
|
||||
// Button pins
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
// UART on the MatrixPortal M4
|
||||
var (
|
||||
Serial = UART1
|
||||
UART1 = &_UART1
|
||||
_UART1 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
|
||||
@@ -37,11 +37,10 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
LED = D13
|
||||
LED = D13
|
||||
WS2812 = D40
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
|
||||
@@ -12,7 +12,7 @@ const (
|
||||
BUTTONB Pin = P11
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
|
||||
@@ -12,7 +12,7 @@ const (
|
||||
BUTTONB Pin = 26
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// +build nano_33_ble
|
||||
|
||||
// This contains the pin mappings for the Arduino Nano 33 BLE [Sense] boards.
|
||||
//
|
||||
// Flashing the board requires special version of bossac.
|
||||
//
|
||||
// This executable can be obtained two ways:
|
||||
// 1) In Arduino IDE, install support for the board ("Arduino Mbed OS Nano Boards")
|
||||
// Search for "tools/bossac/1.9.1-arduino2/bossac" in Arduino IDEs directory
|
||||
// 2) Download https://downloads.arduino.cc/packages/package_index.json
|
||||
// Search for "bossac-1.9.1-arduino2" in that file
|
||||
// Download tarball for your OS and unpack it
|
||||
//
|
||||
// Once you have the executable, make it accessible in your PATH as "bossac_arduino2".
|
||||
//
|
||||
// It is possible to replace original bossac with this new one (this only adds support for nrf chip).
|
||||
// In that case make "bossac_arduino2" symlink on it, for the board target to be able to find it.
|
||||
//
|
||||
// For more information, see:
|
||||
// - https://store.arduino.cc/arduino-nano-33-ble
|
||||
// - https://store.arduino.cc/arduino-nano-33-ble-sense
|
||||
//
|
||||
package machine
|
||||
|
||||
const HasLowFrequencyCrystal = true
|
||||
|
||||
// Digital Pins
|
||||
const (
|
||||
D2 Pin = P1_11
|
||||
D3 Pin = P1_12
|
||||
D4 Pin = P1_15
|
||||
D5 Pin = P1_13
|
||||
D6 Pin = P1_14
|
||||
D7 Pin = P0_23
|
||||
D8 Pin = P0_21
|
||||
D9 Pin = P0_27
|
||||
D10 Pin = P1_02
|
||||
D11 Pin = P1_01
|
||||
D12 Pin = P1_08
|
||||
D13 Pin = P0_13
|
||||
)
|
||||
|
||||
// Analog pins
|
||||
const (
|
||||
A0 Pin = P0_04
|
||||
A1 Pin = P0_05
|
||||
A2 Pin = P0_30
|
||||
A3 Pin = P0_29
|
||||
A4 Pin = P0_31
|
||||
A5 Pin = P0_02
|
||||
A6 Pin = P0_28
|
||||
A7 Pin = P0_03
|
||||
)
|
||||
|
||||
// Onboard LEDs
|
||||
const (
|
||||
LED = LED_BUILTIN
|
||||
LED1 = LED_RED
|
||||
LED2 = LED_GREEN
|
||||
LED3 = LED_BLUE
|
||||
LED_BUILTIN = P0_13
|
||||
LED_RED = P0_24
|
||||
LED_GREEN = P0_16
|
||||
LED_BLUE = P0_06
|
||||
)
|
||||
|
||||
// UART0 pins
|
||||
const (
|
||||
UART_RX_PIN = P1_10
|
||||
UART_TX_PIN = P1_03
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = P0_31
|
||||
SCL_PIN = P0_02
|
||||
)
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = P0_13
|
||||
SPI0_SDO_PIN = P1_01
|
||||
SPI0_SDI_PIN = P1_08
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
const (
|
||||
usb_STRING_PRODUCT = "Nano 33 BLE"
|
||||
usb_STRING_MANUFACTURER = "Arduino"
|
||||
)
|
||||
|
||||
var (
|
||||
usb_VID uint16 = 0x2341
|
||||
usb_PID uint16 = 0x805a
|
||||
)
|
||||
@@ -0,0 +1,98 @@
|
||||
// +build nano_rp2040
|
||||
|
||||
// This contains the pin mappings for the Arduino Nano RP2040 Connect board.
|
||||
//
|
||||
// Sometimes the board is not detected even when the board is connected to your computer.
|
||||
// To solve this, place a jumper wire between the REC and GND pins, then connect the board to your computer.
|
||||
//
|
||||
// For more information, see: https://store.arduino.cc/nano-rp2040-connect
|
||||
// Also
|
||||
// - Datasheets: https://docs.arduino.cc/hardware/nano-rp2040-connect
|
||||
// - Nano RP2040 Connect technical reference: https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-01-technical-reference
|
||||
//
|
||||
package machine
|
||||
|
||||
// Digital Pins
|
||||
const (
|
||||
D2 Pin = GPIO25
|
||||
D3 Pin = GPIO15
|
||||
D4 Pin = GPIO16
|
||||
D5 Pin = GPIO17
|
||||
D6 Pin = GPIO18
|
||||
D7 Pin = GPIO19
|
||||
D8 Pin = GPIO20
|
||||
D9 Pin = GPIO21
|
||||
D10 Pin = GPIO5
|
||||
D11 Pin = GPIO7
|
||||
D12 Pin = GPIO4
|
||||
D13 Pin = GPIO6
|
||||
D14 Pin = GPIO26
|
||||
D15 Pin = GPIO27
|
||||
D16 Pin = GPIO28
|
||||
D17 Pin = GPIO29
|
||||
D18 Pin = GPIO12
|
||||
D19 Pin = GPIO13
|
||||
)
|
||||
|
||||
// Analog pins
|
||||
const (
|
||||
A0 Pin = ADC0
|
||||
A1 Pin = ADC1
|
||||
A2 Pin = ADC2
|
||||
A3 Pin = ADC3
|
||||
)
|
||||
|
||||
// Onboard LED
|
||||
const (
|
||||
LED = GPIO6
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN Pin = GPIO12
|
||||
SCL_PIN Pin = GPIO13
|
||||
)
|
||||
|
||||
// SPI pins. SPI1 not available on Nano RP2040 Connect.
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = GPIO6
|
||||
SPI0_SDO_PIN Pin = GPIO7
|
||||
SPI0_SDI_PIN Pin = GPIO4
|
||||
|
||||
// GPIO22 does not have SPI functionality so we set it to avoid interfering with NINA.
|
||||
SPI1_SCK_PIN Pin = GPIO22
|
||||
SPI1_SDO_PIN Pin = GPIO22
|
||||
SPI1_SDI_PIN Pin = GPIO22
|
||||
)
|
||||
|
||||
// NINA-W102 Pins
|
||||
const (
|
||||
NINA_SCK Pin = GPIO14
|
||||
NINA_SDO Pin = GPIO11
|
||||
NINA_SDI Pin = GPIO8
|
||||
|
||||
NINA_CS Pin = GPIO9
|
||||
NINA_ACK Pin = GPIO10
|
||||
NINA_GPIO0 Pin = GPIO0
|
||||
NINA_RESETN Pin = GPIO3
|
||||
|
||||
NINA_TX Pin = GPIO9
|
||||
NINA_RX Pin = GPIO8
|
||||
)
|
||||
|
||||
// Onboard crystal oscillator frequency, in MHz.
|
||||
const (
|
||||
xoscFreq = 12 // MHz
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
// https://github.com/arduino/ArduinoCore-mbed/blob/master/variants/NANO_RP2040_CONNECT/pins_arduino.h
|
||||
const (
|
||||
usb_STRING_PRODUCT = "Nano RP2040 Connect"
|
||||
usb_STRING_MANUFACTURER = "Arduino"
|
||||
)
|
||||
|
||||
var (
|
||||
usb_VID uint16 = 0x2341
|
||||
usb_PID uint16 = 0x005e
|
||||
)
|
||||
@@ -54,11 +54,6 @@ const (
|
||||
UART_TX_PIN = P0_08
|
||||
)
|
||||
|
||||
// Serial is the USB device
|
||||
var (
|
||||
Serial = USB
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = P0_17 // I2C0 external
|
||||
|
||||
@@ -20,8 +20,6 @@ const (
|
||||
// Onboard blue LED (on the AI-Thinker module).
|
||||
const LED = D4
|
||||
|
||||
var Serial = UART0
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D5
|
||||
|
||||
@@ -23,9 +23,6 @@ const (
|
||||
UART_RX_PIN Pin = NoPin
|
||||
)
|
||||
|
||||
// Serial is the USB device
|
||||
var Serial = USB
|
||||
|
||||
// I2C pins (unused)
|
||||
const (
|
||||
SDA_PIN = NoPin
|
||||
|
||||
@@ -18,9 +18,6 @@ const (
|
||||
UART_RX_PIN Pin = 19
|
||||
)
|
||||
|
||||
// Serial is the USB device
|
||||
var Serial = USB
|
||||
|
||||
// I2C pins (unused)
|
||||
const (
|
||||
SDA_PIN = NoPin
|
||||
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: stm32.USART2,
|
||||
}
|
||||
Serial = UART2
|
||||
DefaultUART = UART2
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -38,7 +38,7 @@ var (
|
||||
TxAltFuncSelector: UART_ALT_FN,
|
||||
RxAltFuncSelector: UART_ALT_FN,
|
||||
}
|
||||
Serial = UART1
|
||||
DefaultUART = UART1
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -13,6 +13,12 @@ const (
|
||||
LED_GREEN = PB3
|
||||
)
|
||||
|
||||
const (
|
||||
// This board does not have a user button, so
|
||||
// use first GPIO pin by default
|
||||
BUTTON = PA0
|
||||
)
|
||||
|
||||
const (
|
||||
// Arduino Pins
|
||||
A0 = PA0 // ADC_IN0
|
||||
@@ -70,7 +76,7 @@ var (
|
||||
TxAltFuncSelector: 4,
|
||||
RxAltFuncSelector: 4,
|
||||
}
|
||||
Serial = UART1
|
||||
DefaultUART = UART1
|
||||
|
||||
// I2C1 is documented, alias to I2C0 as well
|
||||
I2C1 = &I2C{
|
||||
|
||||
@@ -13,6 +13,12 @@ const (
|
||||
LED_GREEN = PB3
|
||||
)
|
||||
|
||||
const (
|
||||
// This board does not have a user button, so
|
||||
// use first GPIO pin by default
|
||||
BUTTON = PA0
|
||||
)
|
||||
|
||||
const (
|
||||
// Arduino Pins
|
||||
A0 = PA0
|
||||
@@ -72,7 +78,7 @@ var (
|
||||
TxAltFuncSelector: 7,
|
||||
RxAltFuncSelector: 3,
|
||||
}
|
||||
Serial = UART1
|
||||
DefaultUART = UART1
|
||||
|
||||
// I2C1 is documented, alias to I2C0 as well
|
||||
I2C1 = &I2C{
|
||||
|
||||
@@ -38,7 +38,7 @@ var (
|
||||
TxAltFuncSelector: UART_ALT_FN,
|
||||
RxAltFuncSelector: UART_ALT_FN,
|
||||
}
|
||||
Serial = UART1
|
||||
DefaultUART = UART1
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -41,7 +41,7 @@ const (
|
||||
|
||||
// UART
|
||||
var (
|
||||
Serial = UART0
|
||||
DefaultUART = UART0
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -41,7 +41,7 @@ const (
|
||||
|
||||
// UART
|
||||
var (
|
||||
Serial = UART0
|
||||
DefaultUART = UART0
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -41,7 +41,7 @@ const (
|
||||
|
||||
// UART
|
||||
var (
|
||||
Serial = UART0
|
||||
DefaultUART = UART0
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -19,7 +19,7 @@ const (
|
||||
LED_BLUE Pin = 23
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
BUTTON4 Pin = 16
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART pins for NRF52840-DK
|
||||
const (
|
||||
|
||||
@@ -22,7 +22,7 @@ const (
|
||||
BUTTON4 Pin = 25
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
|
||||
@@ -34,11 +34,6 @@ const (
|
||||
UART_RX_PIN Pin = NoPin
|
||||
)
|
||||
|
||||
// Serial is the USB device
|
||||
var (
|
||||
Serial = USB
|
||||
)
|
||||
|
||||
// I2C pins (unused)
|
||||
const (
|
||||
SDA_PIN = NoPin
|
||||
|
||||
+44
-31
@@ -4,40 +4,53 @@ package machine
|
||||
|
||||
// GPIO pins
|
||||
const (
|
||||
GP0 Pin = 0
|
||||
GP1 Pin = 1
|
||||
GP2 Pin = 2
|
||||
GP3 Pin = 3
|
||||
GP4 Pin = 4
|
||||
GP5 Pin = 5
|
||||
GP6 Pin = 6
|
||||
GP7 Pin = 7
|
||||
GP8 Pin = 8
|
||||
GP9 Pin = 9
|
||||
GP10 Pin = 10
|
||||
GP11 Pin = 11
|
||||
GP12 Pin = 12
|
||||
GP13 Pin = 13
|
||||
GP14 Pin = 14
|
||||
GP15 Pin = 15
|
||||
GP16 Pin = 16
|
||||
GP17 Pin = 17
|
||||
GP18 Pin = 18
|
||||
GP19 Pin = 19
|
||||
GP20 Pin = 20
|
||||
GP21 Pin = 21
|
||||
GP22 Pin = 22
|
||||
GP23 Pin = 23
|
||||
GP24 Pin = 24
|
||||
GP25 Pin = 25
|
||||
GP26 Pin = 26
|
||||
GP27 Pin = 27
|
||||
GP28 Pin = 28
|
||||
GP29 Pin = 29
|
||||
GP0 Pin = GPIO0
|
||||
GP1 Pin = GPIO1
|
||||
GP2 Pin = GPIO2
|
||||
GP3 Pin = GPIO3
|
||||
GP4 Pin = GPIO4
|
||||
GP5 Pin = GPIO5
|
||||
GP6 Pin = GPIO6
|
||||
GP7 Pin = GPIO7
|
||||
GP8 Pin = GPIO8
|
||||
GP9 Pin = GPIO9
|
||||
GP10 Pin = GPIO10
|
||||
GP11 Pin = GPIO11
|
||||
GP12 Pin = GPIO12
|
||||
GP13 Pin = GPIO13
|
||||
GP14 Pin = GPIO14
|
||||
GP15 Pin = GPIO15
|
||||
GP16 Pin = GPIO16
|
||||
GP17 Pin = GPIO17
|
||||
GP18 Pin = GPIO18
|
||||
GP19 Pin = GPIO19
|
||||
GP20 Pin = GPIO20
|
||||
GP21 Pin = GPIO21
|
||||
GP22 Pin = GPIO22
|
||||
GP26 Pin = GPIO26
|
||||
GP27 Pin = GPIO27
|
||||
GP28 Pin = GPIO28
|
||||
|
||||
// Onboard LED
|
||||
LED Pin = GP25
|
||||
LED Pin = GPIO25
|
||||
|
||||
// Onboard crystal oscillator frequency, in MHz.
|
||||
xoscFreq = 12 // MHz
|
||||
)
|
||||
|
||||
// SPI default pins
|
||||
const (
|
||||
// Default Serial Clock Bus 0 for SPI communications
|
||||
SPI0_SCK_PIN = GPIO18
|
||||
// Default Serial Out Bus 0 for SPI communications
|
||||
SPI0_SDO_PIN = GPIO19 // Tx
|
||||
// Default Serial In Bus 0 for SPI communications
|
||||
SPI0_SDI_PIN = GPIO16 // Rx
|
||||
|
||||
// Default Serial Clock Bus 1 for SPI communications
|
||||
SPI1_SCK_PIN = GPIO10
|
||||
// Default Serial Out Bus 1 for SPI communications
|
||||
SPI1_SDO_PIN = GPIO11 // Tx
|
||||
// Default Serial In Bus 1 for SPI communications
|
||||
SPI1_SDI_PIN = GPIO12 // Rx
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ const (
|
||||
LED3 = LCD_BACKLIGHT_LOW
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART pins for PineTime. Note that RX is set to NoPin as RXD is not listed in
|
||||
// the PineTime schematic 1.0:
|
||||
|
||||
@@ -40,6 +40,7 @@ const (
|
||||
const (
|
||||
LED = D13
|
||||
NEOPIXELS = D8
|
||||
WS2812 = D8
|
||||
|
||||
LIGHTSENSOR = A7
|
||||
|
||||
@@ -66,8 +67,6 @@ const (
|
||||
BUTTON_B_MASK = 128
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
|
||||
@@ -42,6 +42,7 @@ const (
|
||||
const (
|
||||
LED = D13
|
||||
NEOPIXELS = D8
|
||||
WS2812 = D8
|
||||
|
||||
SD_CS = D7
|
||||
|
||||
@@ -69,8 +70,6 @@ const (
|
||||
BUTTON_B_MASK = 128
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
|
||||
@@ -68,6 +68,7 @@ const (
|
||||
TFT_WR = D26
|
||||
|
||||
NEOPIXEL = D2
|
||||
WS2812 = D2
|
||||
SPK_SD = D50
|
||||
)
|
||||
|
||||
@@ -94,8 +95,6 @@ const (
|
||||
LED = D13
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
|
||||
@@ -42,7 +42,9 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
LED = D13
|
||||
NEOPIXELS = D11
|
||||
WS2812 = D11
|
||||
NEOPIXELS_POWER = D12
|
||||
)
|
||||
|
||||
// USBCDC pins
|
||||
|
||||
@@ -29,7 +29,7 @@ const (
|
||||
BUTTON Pin = 7
|
||||
)
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
|
||||
@@ -20,6 +20,10 @@ const (
|
||||
LED_BLUE = PD15
|
||||
)
|
||||
|
||||
const (
|
||||
BUTTON = PA0
|
||||
)
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
UART_TX_PIN = PA2
|
||||
@@ -34,7 +38,7 @@ var (
|
||||
TxAltFuncSelector: AF7_USART1_2_3,
|
||||
RxAltFuncSelector: AF7_USART1_2_3,
|
||||
}
|
||||
Serial = UART1
|
||||
DefaultUART = UART1
|
||||
)
|
||||
|
||||
// set up RX IRQ handler. Follow similar pattern for other UARTx instances
|
||||
|
||||
@@ -87,6 +87,8 @@ var (
|
||||
TeensyUART5 = UART4
|
||||
)
|
||||
|
||||
var DefaultUART = UART0
|
||||
|
||||
const (
|
||||
defaultUART0RX = D00
|
||||
defaultUART0TX = D01
|
||||
|
||||
@@ -146,9 +146,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
Serial = UART1
|
||||
UART1 = &_UART1
|
||||
_UART1 = UART{
|
||||
DefaultUART = UART1
|
||||
UART1 = &_UART1
|
||||
_UART1 = UART{
|
||||
Bus: nxp.LPUART6,
|
||||
Buffer: NewRingBuffer(),
|
||||
txBuffer: NewRingBuffer(),
|
||||
|
||||
@@ -325,8 +325,6 @@ const (
|
||||
OUTPUT_CTR_3V3 = PC15
|
||||
)
|
||||
|
||||
var Serial = USB
|
||||
|
||||
// USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PIN_USB_DM
|
||||
|
||||
@@ -27,4 +27,4 @@ const (
|
||||
|
||||
const HasLowFrequencyCrystal = true
|
||||
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
@@ -122,7 +122,7 @@ func (i2c *I2C) readByte() byte {
|
||||
}
|
||||
|
||||
// Always use UART0 as the serial output.
|
||||
var Serial = UART0
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART
|
||||
var (
|
||||
|
||||
@@ -251,6 +251,8 @@ func (p Pin) mux() *volatile.Register32 {
|
||||
}
|
||||
}
|
||||
|
||||
var DefaultUART = UART0
|
||||
|
||||
var (
|
||||
UART0 = &_UART0
|
||||
_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}
|
||||
|
||||
@@ -139,6 +139,8 @@ func (p Pin) PortMaskClear() (*uint32, uint32) {
|
||||
return &esp.GPIO.GPIO_OUT_W1TC.Reg, 1 << p
|
||||
}
|
||||
|
||||
var DefaultUART = UART0
|
||||
|
||||
// UART0 is a hardware UART that supports both TX and RX.
|
||||
var UART0 = &_UART0
|
||||
var _UART0 = UART{Buffer: NewRingBuffer()}
|
||||
|
||||
@@ -11,6 +11,12 @@ var (
|
||||
USB = &UART{100}
|
||||
)
|
||||
|
||||
// The Serial port always points to the default UART in a simulated environment.
|
||||
//
|
||||
// TODO: perhaps this should be a special serial object that outputs via WASI
|
||||
// stdout calls.
|
||||
var Serial = UART0
|
||||
|
||||
const (
|
||||
PinInput PinMode = iota
|
||||
PinOutput
|
||||
@@ -118,12 +124,6 @@ type UART struct {
|
||||
Bus uint8
|
||||
}
|
||||
|
||||
type UARTConfig struct {
|
||||
BaudRate uint32
|
||||
TX Pin
|
||||
RX Pin
|
||||
}
|
||||
|
||||
// Configure the UART.
|
||||
func (uart *UART) Configure(config UARTConfig) {
|
||||
uartConfigure(uart.Bus, config.TX, config.RX)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// +build nrf52840,nrf52840_reset_bossa
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"device/nrf"
|
||||
)
|
||||
|
||||
const DFU_MAGIC_SERIAL_ONLY_RESET = 0xb0
|
||||
|
||||
// checkShouldReset is called by the USB-CDC implementation to check whether to
|
||||
// reset into the bootloader/OTA and if so, resets the chip appropriately.
|
||||
func checkShouldReset() {
|
||||
if usbLineInfo.dwDTERate == 1200 && usbLineInfo.lineState&usb_CDC_LINESTATE_DTR == 0 {
|
||||
EnterSerialBootloader()
|
||||
}
|
||||
}
|
||||
|
||||
// EnterSerialBootloader resets the chip into the serial bootloader. After
|
||||
// reset, it can be flashed using serial/nrfutil.
|
||||
func EnterSerialBootloader() {
|
||||
arm.DisableInterrupts()
|
||||
nrf.POWER.GPREGRET.Set(DFU_MAGIC_SERIAL_ONLY_RESET)
|
||||
arm.SystemReset()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build nrf52840,!nrf52840_reset_uf2
|
||||
// +build nrf52840,!nrf52840_reset_uf2,!nrf52840_reset_bossa
|
||||
|
||||
package machine
|
||||
|
||||
|
||||
@@ -115,13 +115,14 @@ func (a ADC) Get() uint16 {
|
||||
// SPI on the NRF.
|
||||
type SPI struct {
|
||||
Bus *nrf.SPIM_Type
|
||||
buf *[1]byte // 1-byte buffer for the Transfer method
|
||||
}
|
||||
|
||||
// There are 3 SPI interfaces on the NRF528xx.
|
||||
var (
|
||||
SPI0 = SPI{Bus: nrf.SPIM0}
|
||||
SPI1 = SPI{Bus: nrf.SPIM1}
|
||||
SPI2 = SPI{Bus: nrf.SPIM2}
|
||||
SPI0 = SPI{Bus: nrf.SPIM0, buf: new([1]byte)}
|
||||
SPI1 = SPI{Bus: nrf.SPIM1, buf: new([1]byte)}
|
||||
SPI2 = SPI{Bus: nrf.SPIM2, buf: new([1]byte)}
|
||||
)
|
||||
|
||||
// SPIConfig is used to store config info for SPI.
|
||||
@@ -207,10 +208,10 @@ func (spi SPI) Configure(config SPIConfig) {
|
||||
|
||||
// Transfer writes/reads a single byte using the SPI interface.
|
||||
func (spi SPI) Transfer(w byte) (byte, error) {
|
||||
var wbuf, rbuf [1]byte
|
||||
wbuf[0] = w
|
||||
err := spi.Tx(wbuf[:], rbuf[:])
|
||||
return rbuf[0], err
|
||||
buf := spi.buf[:]
|
||||
buf[0] = w
|
||||
err := spi.Tx(buf[:], buf[:])
|
||||
return buf[0], err
|
||||
}
|
||||
|
||||
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous
|
||||
|
||||
@@ -4,7 +4,47 @@ package machine
|
||||
|
||||
import (
|
||||
"device/rp"
|
||||
_ "unsafe"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
const (
|
||||
// GPIO pins
|
||||
GPIO0 Pin = 0
|
||||
GPIO1 Pin = 1
|
||||
GPIO2 Pin = 2
|
||||
GPIO3 Pin = 3
|
||||
GPIO4 Pin = 4
|
||||
GPIO5 Pin = 5
|
||||
GPIO6 Pin = 6
|
||||
GPIO7 Pin = 7
|
||||
GPIO8 Pin = 8
|
||||
GPIO9 Pin = 9
|
||||
GPIO10 Pin = 10
|
||||
GPIO11 Pin = 11
|
||||
GPIO12 Pin = 12
|
||||
GPIO13 Pin = 13
|
||||
GPIO14 Pin = 14
|
||||
GPIO15 Pin = 15
|
||||
GPIO16 Pin = 16
|
||||
GPIO17 Pin = 17
|
||||
GPIO18 Pin = 18
|
||||
GPIO19 Pin = 19
|
||||
GPIO20 Pin = 20
|
||||
GPIO21 Pin = 21
|
||||
GPIO22 Pin = 22
|
||||
GPIO23 Pin = 23
|
||||
GPIO24 Pin = 24
|
||||
GPIO25 Pin = 25
|
||||
GPIO26 Pin = 26
|
||||
GPIO27 Pin = 27
|
||||
GPIO28 Pin = 28
|
||||
GPIO29 Pin = 29
|
||||
|
||||
// Analog pins
|
||||
ADC0 Pin = GPIO26
|
||||
ADC1 Pin = GPIO27
|
||||
ADC2 Pin = GPIO28
|
||||
ADC3 Pin = GPIO29
|
||||
)
|
||||
|
||||
//go:linkname machineInit runtime.machineInit
|
||||
@@ -42,3 +82,35 @@ func machineInit() {
|
||||
func ticks() uint64 {
|
||||
return timer.timeElapsed()
|
||||
}
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
UART_TX_PIN = UART0_TX_PIN
|
||||
UART_RX_PIN = UART0_RX_PIN
|
||||
UART0_TX_PIN = GPIO0
|
||||
UART0_RX_PIN = GPIO1
|
||||
UART1_TX_PIN = GPIO8
|
||||
UART1_RX_PIN = GPIO9
|
||||
)
|
||||
|
||||
// UART on the RP2040
|
||||
var (
|
||||
UART0 = &_UART0
|
||||
_UART0 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: rp.UART0,
|
||||
}
|
||||
|
||||
UART1 = &_UART1
|
||||
_UART1 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: rp.UART1,
|
||||
}
|
||||
)
|
||||
|
||||
var DefaultUART = UART0
|
||||
|
||||
func init() {
|
||||
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
|
||||
UART1.Interrupt = interrupt.New(rp.IRQ_UART1_IRQ, _UART1.handleInterrupt)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// +build rp2040
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/rp"
|
||||
)
|
||||
|
||||
func InitADC() {
|
||||
// reset ADC
|
||||
rp.RESETS.RESET.SetBits(rp.RESETS_RESET_ADC)
|
||||
rp.RESETS.RESET.ClearBits(rp.RESETS_RESET_ADC)
|
||||
for !rp.RESETS.RESET_DONE.HasBits(rp.RESETS_RESET_ADC) {
|
||||
}
|
||||
|
||||
// enable ADC
|
||||
rp.ADC.CS.Set(rp.ADC_CS_EN)
|
||||
|
||||
waitForReady()
|
||||
}
|
||||
|
||||
// Configure configures a ADC pin to be able to be used to read data.
|
||||
func (a ADC) Configure(config ADCConfig) {
|
||||
switch a.Pin {
|
||||
case ADC0, ADC1, ADC2, ADC3:
|
||||
a.Pin.Configure(PinConfig{Mode: PinAnalog})
|
||||
default:
|
||||
// invalid ADC
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (a ADC) Get() uint16 {
|
||||
rp.ADC.CS.SetBits(uint32(a.getADCChannel()) << rp.ADC_CS_AINSEL_Pos)
|
||||
rp.ADC.CS.SetBits(rp.ADC_CS_START_ONCE)
|
||||
|
||||
waitForReady()
|
||||
|
||||
// rp2040 uses 12-bit sampling, so scale to 16-bit
|
||||
return uint16(rp.ADC.RESULT.Get() << 4)
|
||||
}
|
||||
|
||||
func waitForReady() {
|
||||
for !rp.ADC.CS.HasBits(rp.ADC_CS_READY) {
|
||||
}
|
||||
}
|
||||
|
||||
func (a ADC) getADCChannel() uint8 {
|
||||
switch a.Pin {
|
||||
case ADC0:
|
||||
return 0
|
||||
case ADC1:
|
||||
return 1
|
||||
case ADC2:
|
||||
return 2
|
||||
case ADC3:
|
||||
return 3
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,12 @@ const (
|
||||
|
||||
const (
|
||||
PinOutput PinMode = iota
|
||||
PinInput
|
||||
PinInputPulldown
|
||||
PinInputPullup
|
||||
PinAnalog
|
||||
PinUART
|
||||
PinSPI
|
||||
)
|
||||
|
||||
// set drives the pin high
|
||||
@@ -83,6 +89,11 @@ func (p Pin) xor() {
|
||||
rp.SIO.GPIO_OUT_XOR.Set(mask)
|
||||
}
|
||||
|
||||
// get returns the pin value
|
||||
func (p Pin) get() bool {
|
||||
return rp.SIO.GPIO_IN.HasBits(uint32(1) << p)
|
||||
}
|
||||
|
||||
func (p Pin) ioCtrl() *volatile.Register32 {
|
||||
return &ioBank0.io[p].ctrl
|
||||
}
|
||||
@@ -91,6 +102,21 @@ func (p Pin) padCtrl() *volatile.Register32 {
|
||||
return &padsBank0.io[p]
|
||||
}
|
||||
|
||||
func (p Pin) pullup() {
|
||||
p.padCtrl().SetBits(rp.PADS_BANK0_GPIO0_PUE)
|
||||
p.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PDE)
|
||||
}
|
||||
|
||||
func (p Pin) pulldown() {
|
||||
p.padCtrl().SetBits(rp.PADS_BANK0_GPIO0_PDE)
|
||||
p.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PUE)
|
||||
}
|
||||
|
||||
func (p Pin) pulloff() {
|
||||
p.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PDE)
|
||||
p.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PUE)
|
||||
}
|
||||
|
||||
// setFunc will set pin function to fn.
|
||||
func (p Pin) setFunc(fn pinFunc) {
|
||||
// Set input enable, Clear output disable
|
||||
@@ -107,8 +133,6 @@ func (p Pin) init() {
|
||||
mask := uint32(1) << p
|
||||
rp.SIO.GPIO_OE_CLR.Set(mask)
|
||||
p.clr()
|
||||
p.setFunc(fnSIO)
|
||||
|
||||
}
|
||||
|
||||
// Configure configures the gpio pin as per mode.
|
||||
@@ -117,7 +141,23 @@ func (p Pin) Configure(config PinConfig) {
|
||||
mask := uint32(1) << p
|
||||
switch config.Mode {
|
||||
case PinOutput:
|
||||
p.setFunc(fnSIO)
|
||||
rp.SIO.GPIO_OE_SET.Set(mask)
|
||||
case PinInput:
|
||||
p.setFunc(fnSIO)
|
||||
case PinInputPulldown:
|
||||
p.setFunc(fnSIO)
|
||||
p.pulldown()
|
||||
case PinInputPullup:
|
||||
p.setFunc(fnSIO)
|
||||
p.pullup()
|
||||
case PinAnalog:
|
||||
p.setFunc(fnNULL)
|
||||
p.pulloff()
|
||||
case PinUART:
|
||||
p.setFunc(fnUART)
|
||||
case PinSPI:
|
||||
p.setFunc(fnSPI)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,3 +169,8 @@ func (p Pin) Set(value bool) {
|
||||
p.clr()
|
||||
}
|
||||
}
|
||||
|
||||
// Get reads the pin value.
|
||||
func (p Pin) Get() bool {
|
||||
return p.get()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
// +build rp2040
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/rp"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// SPI on the RP2040
|
||||
var (
|
||||
SPI0 = &_SPI0
|
||||
_SPI0 = SPI{
|
||||
Bus: rp.SPI0,
|
||||
}
|
||||
SPI1 = &_SPI1
|
||||
_SPI1 = SPI{
|
||||
Bus: rp.SPI1,
|
||||
}
|
||||
)
|
||||
|
||||
// SPIConfig is used to store config info for SPI.
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
// LSB not supported on rp2040.
|
||||
LSBFirst bool
|
||||
// Mode's two most LSB are CPOL and CPHA. i.e. Mode==2 (0b10) is CPOL=1, CPHA=0
|
||||
Mode uint8
|
||||
// Number of data bits per transfer. Valid values 4..16. Default and recommended is 8.
|
||||
DataBits uint8
|
||||
// Serial clock pin
|
||||
SCK Pin
|
||||
// TX or Serial Data Out (MOSI if rp2040 is master)
|
||||
SDO Pin
|
||||
// RX or Serial Data In (MISO if rp2040 is master)
|
||||
SDI Pin
|
||||
}
|
||||
|
||||
var (
|
||||
ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022")
|
||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
||||
ErrSPITimeout = errors.New("SPI timeout")
|
||||
ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
|
||||
)
|
||||
|
||||
type SPI struct {
|
||||
Bus *rp.SPI0_Type
|
||||
}
|
||||
|
||||
// time to wait on a transaction before dropping. Unit in Microseconds for compatibility with ticks().
|
||||
const _SPITimeout = 10 * 1000 // 10 ms
|
||||
|
||||
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
|
||||
// interface, there must always be the same number of bytes written as bytes read.
|
||||
// The Tx method knows about this, and offers a few different ways of calling it.
|
||||
//
|
||||
// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.
|
||||
// Note that the tx and rx buffers must be the same size:
|
||||
//
|
||||
// spi.Tx(tx, rx)
|
||||
//
|
||||
// This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros
|
||||
// until all the bytes in the command packet have been received:
|
||||
//
|
||||
// spi.Tx(tx, nil)
|
||||
//
|
||||
// This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet":
|
||||
//
|
||||
// spi.Tx(nil, rx)
|
||||
//
|
||||
// Remark: This implementation (RP2040) allows reading into buffer with a custom repeated
|
||||
// value on tx.
|
||||
//
|
||||
// spi.Tx([]byte{0xff}, rx) // may cause unwanted heap allocations.
|
||||
//
|
||||
// This form sends 0xff and puts the result into rx buffer. Useful for reading from SD cards
|
||||
// which require 0xff input on SI.
|
||||
func (spi SPI) Tx(w, r []byte) (err error) {
|
||||
switch {
|
||||
case w == nil:
|
||||
// read only, so write zero and read a result.
|
||||
err = spi.rx(r, 0)
|
||||
case r == nil:
|
||||
// write only
|
||||
err = spi.tx(w)
|
||||
case len(w) == 1 && len(r) > 1:
|
||||
// Read with custom repeated value.
|
||||
err = spi.rx(r, w[0])
|
||||
default:
|
||||
// write/read
|
||||
err = spi.txrx(w, r)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Write a single byte and read a single byte from TX/RX FIFO.
|
||||
func (spi SPI) Transfer(w byte) (byte, error) {
|
||||
var deadline = ticks() + _SPITimeout
|
||||
for !spi.isWritable() {
|
||||
if ticks() > deadline {
|
||||
return 0, ErrSPITimeout
|
||||
}
|
||||
}
|
||||
|
||||
spi.Bus.SSPDR.Set(uint32(w))
|
||||
|
||||
for !spi.isReadable() {
|
||||
if ticks() > deadline {
|
||||
return 0, ErrSPITimeout
|
||||
}
|
||||
}
|
||||
return uint8(spi.Bus.SSPDR.Get()), nil
|
||||
}
|
||||
|
||||
func (spi SPI) SetBaudRate(br uint32) error {
|
||||
const freqin uint32 = 125 * MHz
|
||||
const maxBaud uint32 = 66.5 * MHz // max output frequency is 66.5MHz on rp2040. see Note page 527.
|
||||
// Find smallest prescale value which puts output frequency in range of
|
||||
// post-divide. Prescale is an even number from 2 to 254 inclusive.
|
||||
var prescale, postdiv uint32
|
||||
for prescale = 2; prescale < 255; prescale += 2 {
|
||||
if freqin < (prescale+2)*256*br {
|
||||
break
|
||||
}
|
||||
}
|
||||
if prescale > 254 || br > maxBaud {
|
||||
return ErrSPIBaud
|
||||
}
|
||||
// Find largest post-divide which makes output <= baudrate. Post-divide is
|
||||
// an integer in the range 1 to 256 inclusive.
|
||||
for postdiv = 256; postdiv > 1; postdiv-- {
|
||||
if freqin/(prescale*(postdiv-1)) > br {
|
||||
break
|
||||
}
|
||||
}
|
||||
spi.Bus.SSPCPSR.Set(prescale)
|
||||
spi.Bus.SSPCR0.ReplaceBits((postdiv-1)<<rp.SPI0_SSPCR0_SCR_Pos, rp.SPI0_SSPCR0_SCR_Msk, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spi SPI) GetBaudRate() uint32 {
|
||||
const freqin uint32 = 125 * MHz
|
||||
prescale := spi.Bus.SSPCPSR.Get()
|
||||
postdiv := ((spi.Bus.SSPCR0.Get() & rp.SPI0_SSPCR0_SCR_Msk) >> rp.SPI0_SSPCR0_SCR_Pos) + 1
|
||||
return freqin / (prescale * postdiv)
|
||||
}
|
||||
|
||||
// Configure is intended to setup/initialize the SPI interface.
|
||||
// Default baudrate of 115200 is used if Frequency == 0. Default
|
||||
// word length (data bits) is 8.
|
||||
// Below is a list of GPIO pins corresponding to SPI0 bus on the rp2040:
|
||||
// SI : 0, 4, 17 a.k.a RX and MISO (if rp2040 is master)
|
||||
// SO : 3, 7, 19 a.k.a TX and MOSI (if rp2040 is master)
|
||||
// SCK: 2, 6, 18
|
||||
// SPI1 bus GPIO pins:
|
||||
// SI : 8, 12
|
||||
// SO : 11, 15
|
||||
// SCK: 10, 14
|
||||
// No pin configuration is needed of SCK, SDO and SDI needed after calling Configure.
|
||||
func (spi SPI) Configure(config SPIConfig) error {
|
||||
const defaultBaud uint32 = 115200
|
||||
if config.SCK == 0 {
|
||||
// set default pins if config zero valued or invalid clock pin supplied.
|
||||
switch spi.Bus {
|
||||
case rp.SPI0:
|
||||
config.SCK = SPI0_SCK_PIN
|
||||
config.SDO = SPI0_SDO_PIN
|
||||
config.SDI = SPI0_SDI_PIN
|
||||
case rp.SPI1:
|
||||
config.SCK = SPI1_SCK_PIN
|
||||
config.SDO = SPI1_SDO_PIN
|
||||
config.SDI = SPI1_SDI_PIN
|
||||
}
|
||||
}
|
||||
if config.DataBits < 4 || config.DataBits > 16 {
|
||||
config.DataBits = 8
|
||||
}
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = defaultBaud
|
||||
}
|
||||
// SPI pin configuration
|
||||
config.SCK.setFunc(fnSPI)
|
||||
config.SDO.setFunc(fnSPI)
|
||||
config.SDI.setFunc(fnSPI)
|
||||
|
||||
return spi.initSPI(config)
|
||||
}
|
||||
|
||||
func (spi SPI) initSPI(config SPIConfig) (err error) {
|
||||
spi.reset()
|
||||
// LSB-first not supported on PL022:
|
||||
if config.LSBFirst {
|
||||
return ErrLSBNotSupported
|
||||
}
|
||||
err = spi.SetBaudRate(config.Frequency)
|
||||
// Set SPI Format (CPHA and CPOL) and frame format (default is Motorola)
|
||||
spi.setFormat(config.DataBits, config.Mode, rp.XIP_SSI_CTRLR0_SPI_FRF_STD)
|
||||
|
||||
// Always enable DREQ signals -- harmless if DMA is not listening
|
||||
spi.Bus.SSPDMACR.SetBits(rp.SPI0_SSPDMACR_TXDMAE | rp.SPI0_SSPDMACR_RXDMAE)
|
||||
// Finally enable the SPI
|
||||
spi.Bus.SSPCR1.SetBits(rp.SPI0_SSPCR1_SSE)
|
||||
return err
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func (spi SPI) setFormat(databits, mode uint8, frameFormat uint32) {
|
||||
cpha := uint32(mode) & 1
|
||||
cpol := uint32(mode>>1) & 1
|
||||
spi.Bus.SSPCR0.ReplaceBits(
|
||||
(cpha<<rp.SPI0_SSPCR0_SPH_Pos)|
|
||||
(cpol<<rp.SPI0_SSPCR0_SPO_Pos)|
|
||||
(uint32(databits-1)<<rp.SPI0_SSPCR0_DSS_Pos)| // Set databits (SPI word length). Valid inputs are 4-16.
|
||||
(frameFormat&0b11)<<rp.SPI0_SSPCR0_FRF_Pos, // Frame format bits 4:5
|
||||
rp.SPI0_SSPCR0_SPH_Msk|rp.SPI0_SSPCR0_SPO_Msk|rp.SPI0_SSPCR0_DSS_Msk|rp.SPI0_SSPCR0_FRF_Msk, 0)
|
||||
}
|
||||
|
||||
// reset resets SPI and waits until reset is done.
|
||||
//go:inline
|
||||
func (spi SPI) reset() {
|
||||
resetVal := spi.deinit()
|
||||
rp.RESETS.RESET.ClearBits(resetVal)
|
||||
// Wait until reset is done.
|
||||
for !rp.RESETS.RESET_DONE.HasBits(resetVal) {
|
||||
}
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func (spi SPI) deinit() (resetVal uint32) {
|
||||
switch spi.Bus {
|
||||
case rp.SPI0:
|
||||
resetVal = rp.RESETS_RESET_SPI0
|
||||
case rp.SPI1:
|
||||
resetVal = rp.RESETS_RESET_SPI1
|
||||
}
|
||||
// Perform SPI reset.
|
||||
rp.RESETS.RESET.SetBits(resetVal)
|
||||
return resetVal
|
||||
}
|
||||
|
||||
// isWritable returns false if no space is available to write. True if a write is possible
|
||||
//go:inline
|
||||
func (spi SPI) isWritable() bool {
|
||||
return spi.Bus.SSPSR.HasBits(rp.SPI0_SSPSR_TNF)
|
||||
}
|
||||
|
||||
// isReadable returns true if a read is possible i.e. data is present
|
||||
//go:inline
|
||||
func (spi SPI) isReadable() bool {
|
||||
return spi.Bus.SSPSR.HasBits(rp.SPI0_SSPSR_RNE)
|
||||
}
|
||||
|
||||
// PrintRegs prints SPI's peripheral common registries current values
|
||||
func (spi SPI) PrintRegs() {
|
||||
cr0 := spi.Bus.SSPCR0.Get()
|
||||
cr1 := spi.Bus.SSPCR1.Get()
|
||||
dmacr := spi.Bus.SSPDMACR.Get()
|
||||
cpsr := spi.Bus.SSPCPSR.Get()
|
||||
dr := spi.Bus.SSPDR.Get()
|
||||
ris := spi.Bus.SSPRIS.Get()
|
||||
println("CR0:", cr0)
|
||||
println("CR1:", cr1)
|
||||
println("DMACR:", dmacr)
|
||||
println("CPSR:", cpsr)
|
||||
println("DR:", dr)
|
||||
println("RIS:", ris)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func (spi SPI) isBusy() bool {
|
||||
return spi.Bus.SSPSR.HasBits(rp.SPI0_SSPSR_BSY)
|
||||
}
|
||||
|
||||
// tx writes buffer to SPI ignoring Rx.
|
||||
func (spi SPI) tx(tx []byte) error {
|
||||
var deadline = ticks() + _SPITimeout
|
||||
// Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX
|
||||
// is full, PL022 inhibits RX pushes, and sets a sticky flag on
|
||||
// push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set.
|
||||
for i := range tx {
|
||||
for !spi.isWritable() {
|
||||
if ticks() > deadline {
|
||||
return ErrSPITimeout
|
||||
}
|
||||
}
|
||||
spi.Bus.SSPDR.Set(uint32(tx[i]))
|
||||
}
|
||||
// Drain RX FIFO, then wait for shifting to finish (which may be *after*
|
||||
// TX FIFO drains), then drain RX FIFO again
|
||||
for spi.isReadable() {
|
||||
spi.Bus.SSPDR.Get()
|
||||
}
|
||||
for spi.isBusy() {
|
||||
if ticks() > deadline {
|
||||
return ErrSPITimeout
|
||||
}
|
||||
}
|
||||
for spi.isReadable() {
|
||||
spi.Bus.SSPDR.Get()
|
||||
}
|
||||
// Don't leave overrun flag set
|
||||
spi.Bus.SSPICR.Set(rp.SPI0_SSPICR_RORIC)
|
||||
return nil
|
||||
}
|
||||
|
||||
// rx reads buffer to SPI ignoring x.
|
||||
// txrepeat is output repeatedly on SO as data is read in from SI.
|
||||
// Generally this can be 0, but some devices require a specific value here,
|
||||
// e.g. SD cards expect 0xff
|
||||
func (spi SPI) rx(rx []byte, txrepeat byte) error {
|
||||
var deadline = ticks() + _SPITimeout
|
||||
plen := len(rx)
|
||||
const fifoDepth = 8 // see txrx
|
||||
var rxleft, txleft = plen, plen
|
||||
for txleft != 0 || rxleft != 0 {
|
||||
if txleft != 0 && spi.isWritable() && rxleft < txleft+fifoDepth {
|
||||
spi.Bus.SSPDR.Set(uint32(txrepeat))
|
||||
txleft--
|
||||
}
|
||||
if rxleft != 0 && spi.isReadable() {
|
||||
rx[plen-rxleft] = uint8(spi.Bus.SSPDR.Get())
|
||||
rxleft--
|
||||
continue // if reading succesfully in rx there is no need to check deadline.
|
||||
}
|
||||
if ticks() > deadline {
|
||||
return ErrSPITimeout
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write len bytes from src to SPI. Simultaneously read len bytes from SPI to dst.
|
||||
// Note this function is guaranteed to exit in a known amount of time (bits sent * time per bit)
|
||||
func (spi SPI) txrx(tx, rx []byte) error {
|
||||
var deadline = ticks() + _SPITimeout
|
||||
plen := len(tx)
|
||||
if plen != len(rx) {
|
||||
return ErrTxInvalidSliceSize
|
||||
}
|
||||
// Never have more transfers in flight than will fit into the RX FIFO,
|
||||
// else FIFO will overflow if this code is heavily interrupted.
|
||||
const fifoDepth = 8
|
||||
var rxleft, txleft = plen, plen
|
||||
for (txleft != 0 || rxleft != 0) && ticks() <= deadline {
|
||||
if txleft != 0 && spi.isWritable() && rxleft < txleft+fifoDepth {
|
||||
spi.Bus.SSPDR.Set(uint32(tx[plen-txleft]))
|
||||
txleft--
|
||||
}
|
||||
if rxleft != 0 && spi.isReadable() {
|
||||
rx[plen-rxleft] = uint8(spi.Bus.SSPDR.Get())
|
||||
rxleft--
|
||||
}
|
||||
}
|
||||
|
||||
if txleft != 0 || rxleft != 0 {
|
||||
// Transaction ended early due to timeout
|
||||
return ErrSPITimeout
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// +build rp2040
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/rp"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// UART on the RP2040.
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
Bus *rp.UART0_Type
|
||||
Interrupt interrupt.Interrupt
|
||||
}
|
||||
|
||||
// Configure the UART.
|
||||
func (uart *UART) Configure(config UARTConfig) error {
|
||||
initUART(uart)
|
||||
|
||||
// Default baud rate to 115200.
|
||||
if config.BaudRate == 0 {
|
||||
config.BaudRate = 115200
|
||||
}
|
||||
|
||||
// Use default pins if pins are not set.
|
||||
if config.TX == 0 && config.RX == 0 {
|
||||
// use default pins
|
||||
config.TX = UART_TX_PIN
|
||||
config.RX = UART_RX_PIN
|
||||
}
|
||||
|
||||
uart.SetBaudRate(config.BaudRate)
|
||||
|
||||
// default to 8-1-N
|
||||
uart.SetFormat(8, 1, ParityNone)
|
||||
|
||||
// Enable the UART, both TX and RX
|
||||
uart.Bus.UARTCR.SetBits(rp.UART0_UARTCR_UARTEN |
|
||||
rp.UART0_UARTCR_RXE |
|
||||
rp.UART0_UARTCR_TXE)
|
||||
|
||||
// set GPIO mux to UART for the pins
|
||||
config.TX.Configure(PinConfig{Mode: PinUART})
|
||||
config.RX.Configure(PinConfig{Mode: PinUART})
|
||||
|
||||
// Enable RX IRQ.
|
||||
uart.Interrupt.SetPriority(0x80)
|
||||
uart.Interrupt.Enable()
|
||||
|
||||
// setup interrupt on receive
|
||||
uart.Bus.UARTIMSC.Set(rp.UART0_UARTIMSC_RXIM)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the baudrate to be used for the UART.
|
||||
func (uart *UART) SetBaudRate(br uint32) {
|
||||
div := 8 * 125 * MHz / br
|
||||
|
||||
ibrd := div >> 7
|
||||
var fbrd uint32
|
||||
|
||||
switch {
|
||||
case ibrd == 0:
|
||||
ibrd = 1
|
||||
fbrd = 0
|
||||
case ibrd >= 65535:
|
||||
ibrd = 65535
|
||||
fbrd = 0
|
||||
default:
|
||||
fbrd = ((div & 0x7f) + 1) / 2
|
||||
}
|
||||
|
||||
// set PL011 baud divisor registers
|
||||
uart.Bus.UARTIBRD.Set(ibrd)
|
||||
uart.Bus.UARTFBRD.Set(fbrd)
|
||||
|
||||
// PL011 needs a (dummy) line control register write.
|
||||
// See https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c#L93-L95
|
||||
uart.Bus.UARTLCR_H.SetBits(0)
|
||||
}
|
||||
|
||||
// WriteByte writes a byte of data to the UART.
|
||||
func (uart *UART) WriteByte(c byte) error {
|
||||
// wait until buffer is not full
|
||||
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_TXFF) {
|
||||
}
|
||||
|
||||
// write data
|
||||
uart.Bus.UARTDR.Set(uint32(c))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFormat for number of data bits, stop bits, and parity for the UART.
|
||||
func (uart *UART) SetFormat(databits, stopbits uint8, parity UARTParity) error {
|
||||
var pen, pev uint8
|
||||
if parity != ParityNone {
|
||||
pen = rp.UART0_UARTLCR_H_PEN
|
||||
}
|
||||
if parity == ParityEven {
|
||||
pev = rp.UART0_UARTLCR_H_EPS
|
||||
}
|
||||
uart.Bus.UARTLCR_H.SetBits(uint32((databits-5)<<rp.UART0_UARTLCR_H_WLEN_Pos |
|
||||
(stopbits-1)<<rp.UART0_UARTLCR_H_STP2_Pos |
|
||||
pen | pev))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initUART(uart *UART) {
|
||||
var resetVal uint32
|
||||
switch {
|
||||
case uart.Bus == rp.UART0:
|
||||
resetVal = rp.RESETS_RESET_UART0
|
||||
case uart.Bus == rp.UART1:
|
||||
resetVal = rp.RESETS_RESET_UART1
|
||||
}
|
||||
|
||||
// reset UART
|
||||
rp.RESETS.RESET.SetBits(resetVal)
|
||||
rp.RESETS.RESET.ClearBits(resetVal)
|
||||
for !rp.RESETS.RESET_DONE.HasBits(resetVal) {
|
||||
}
|
||||
}
|
||||
|
||||
// handleInterrupt should be called from the appropriate interrupt handler for
|
||||
// this UART instance.
|
||||
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
||||
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_RXFE) {
|
||||
}
|
||||
uart.Receive(byte((uart.Bus.UARTDR.Get() & 0xFF)))
|
||||
}
|
||||
@@ -31,6 +31,13 @@ const (
|
||||
// Also, the stm32f1xx series handles things differently from the stm32f0/2/3/4
|
||||
|
||||
// ---------- General pin operations ----------
|
||||
type PinChange uint8
|
||||
|
||||
const (
|
||||
PinRising PinChange = 1 << iota
|
||||
PinFalling
|
||||
PinToggle = PinRising | PinFalling
|
||||
)
|
||||
|
||||
// Set the pin to high or low.
|
||||
// Warning: only use this on an output pin!
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// +build stm32f1
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
func getEXTIConfigRegister(pin uint8) *volatile.Register32 {
|
||||
switch (pin & 0xf) / 4 {
|
||||
case 0:
|
||||
return &stm32.AFIO.EXTICR1
|
||||
case 1:
|
||||
return &stm32.AFIO.EXTICR2
|
||||
case 2:
|
||||
return &stm32.AFIO.EXTICR3
|
||||
case 3:
|
||||
return &stm32.AFIO.EXTICR4
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func enableEXTIConfigRegisters() {
|
||||
// Enable AFIO
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// +build stm32l5
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
func getEXTIConfigRegister(pin uint8) *volatile.Register32 {
|
||||
switch (pin & 0xf) / 4 {
|
||||
case 0:
|
||||
return &stm32.EXTI.EXTICR1
|
||||
case 1:
|
||||
return &stm32.EXTI.EXTICR2
|
||||
case 2:
|
||||
return &stm32.EXTI.EXTICR3
|
||||
case 3:
|
||||
return &stm32.EXTI.EXTICR4
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func enableEXTIConfigRegisters() {
|
||||
// No-op
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// +build stm32,!stm32f1,!stm32l5
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
func getEXTIConfigRegister(pin uint8) *volatile.Register32 {
|
||||
switch (pin & 0xf) / 4 {
|
||||
case 0:
|
||||
return &stm32.SYSCFG.EXTICR1
|
||||
case 1:
|
||||
return &stm32.SYSCFG.EXTICR2
|
||||
case 2:
|
||||
return &stm32.SYSCFG.EXTICR3
|
||||
case 3:
|
||||
return &stm32.SYSCFG.EXTICR4
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func enableEXTIConfigRegisters() {
|
||||
// Enable SYSCFG
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// +build stm32,!stm32l4,!stm32l5
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
)
|
||||
|
||||
// This variant of the GPIO input interrupt logic is for
|
||||
// chips with a smaller number of interrupt channels
|
||||
// (that fits in a single register).
|
||||
|
||||
//
|
||||
// STM32 allows one interrupt source per pin number, with
|
||||
// the same pin number in different ports sharing a single
|
||||
// interrupt source (so PA0, PB0, PC0 all share). Only a
|
||||
// single physical pin can be connected to each interrupt
|
||||
// line.
|
||||
//
|
||||
// To call interrupt callbacks, we record here for each
|
||||
// pin number the callback and the actual associated pin.
|
||||
//
|
||||
|
||||
// Callbacks for pin interrupt events
|
||||
var pinCallbacks [16]func(Pin)
|
||||
|
||||
// The pin currently associated with interrupt callback
|
||||
// for a given slot.
|
||||
var interruptPins [16]Pin
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state. The pin should already be configured as an input, including a pull up
|
||||
// or down if no external pull is provided.
|
||||
//
|
||||
// This call will replace a previously set callback on this pin. You can pass a
|
||||
// nil func to unset the pin change interrupt. If you do so, the change
|
||||
// parameter is ignored and can be set to any value (such as 0).
|
||||
func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
||||
port := uint32(uint8(p) / 16)
|
||||
pin := uint8(p) % 16
|
||||
|
||||
enableEXTIConfigRegisters()
|
||||
|
||||
if callback == nil {
|
||||
stm32.EXTI.IMR.ClearBits(1 << pin)
|
||||
pinCallbacks[pin] = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if pinCallbacks[pin] != nil {
|
||||
// The pin was already configured.
|
||||
// To properly re-configure a pin, unset it first and set a new
|
||||
// configuration.
|
||||
return ErrNoPinChangeChannel
|
||||
}
|
||||
|
||||
// Set the callback now (before the interrupt is enabled) to avoid
|
||||
// possible race condition
|
||||
pinCallbacks[pin] = callback
|
||||
interruptPins[pin] = p
|
||||
|
||||
crReg := getEXTIConfigRegister(pin)
|
||||
shift := (pin & 0x3) * 4
|
||||
crReg.ReplaceBits(port, 0xf, shift)
|
||||
|
||||
if (change & PinRising) != 0 {
|
||||
stm32.EXTI.RTSR.SetBits(1 << pin)
|
||||
}
|
||||
if (change & PinFalling) != 0 {
|
||||
stm32.EXTI.FTSR.SetBits(1 << pin)
|
||||
}
|
||||
stm32.EXTI.IMR.SetBits(1 << pin)
|
||||
|
||||
intr := p.registerInterrupt()
|
||||
intr.SetPriority(0)
|
||||
intr.Enable()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handlePinInterrupt(pin uint8) {
|
||||
if stm32.EXTI.PR.HasBits(1 << pin) {
|
||||
// Writing 1 to the pending register clears the
|
||||
// pending flag for that bit
|
||||
stm32.EXTI.PR.Set(1 << pin)
|
||||
|
||||
callback := pinCallbacks[pin]
|
||||
if callback != nil {
|
||||
callback(interruptPins[pin])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// +build stm32l4 stm32l5
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
)
|
||||
|
||||
// This variant of the GPIO input interrupt logic is for
|
||||
// chips with a larger number of interrupt channels (more
|
||||
// than fits in a single register).
|
||||
|
||||
//
|
||||
// STM32 allows one interrupt source per pin number, with
|
||||
// the same pin number in different ports sharing a single
|
||||
// interrupt source (so PA0, PB0, PC0 all share). Only a
|
||||
// single physical pin can be connected to each interrupt
|
||||
// line.
|
||||
//
|
||||
// To call interrupt callbacks, we record here for each
|
||||
// pin number the callback and the actual associated pin.
|
||||
//
|
||||
|
||||
// Callbacks for pin interrupt events
|
||||
var pinCallbacks [16]func(Pin)
|
||||
|
||||
// The pin currently associated with interrupt callback
|
||||
// for a given slot.
|
||||
var interruptPins [16]Pin
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state. The pin should already be configured as an input, including a pull up
|
||||
// or down if no external pull is provided.
|
||||
//
|
||||
// This call will replace a previously set callback on this pin. You can pass a
|
||||
// nil func to unset the pin change interrupt. If you do so, the change
|
||||
// parameter is ignored and can be set to any value (such as 0).
|
||||
func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
||||
port := uint32(uint8(p) / 16)
|
||||
pin := uint8(p) % 16
|
||||
|
||||
enableEXTIConfigRegisters()
|
||||
|
||||
if callback == nil {
|
||||
stm32.EXTI.IMR1.ClearBits(1 << pin)
|
||||
pinCallbacks[pin] = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if pinCallbacks[pin] != nil {
|
||||
// The pin was already configured.
|
||||
// To properly re-configure a pin, unset it first and set a new
|
||||
// configuration.
|
||||
return ErrNoPinChangeChannel
|
||||
}
|
||||
|
||||
// Set the callback now (before the interrupt is enabled) to avoid
|
||||
// possible race condition
|
||||
pinCallbacks[pin] = callback
|
||||
interruptPins[pin] = p
|
||||
|
||||
crReg := getEXTIConfigRegister(pin)
|
||||
shift := (pin & 0x3) * 4
|
||||
crReg.ReplaceBits(port, 0xf, shift)
|
||||
|
||||
if (change & PinRising) != 0 {
|
||||
stm32.EXTI.RTSR1.SetBits(1 << pin)
|
||||
}
|
||||
if (change & PinFalling) != 0 {
|
||||
stm32.EXTI.FTSR1.SetBits(1 << pin)
|
||||
}
|
||||
stm32.EXTI.IMR1.SetBits(1 << pin)
|
||||
|
||||
intr := p.registerInterrupt()
|
||||
intr.SetPriority(0)
|
||||
intr.Enable()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -37,6 +37,11 @@ const (
|
||||
PinOutputModeGPOpenDrain PinMode = 4 // Output mode general purpose open drain
|
||||
PinOutputModeAltPushPull PinMode = 8 // Output mode alt. purpose push/pull
|
||||
PinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain
|
||||
|
||||
// Pull-up vs Pull down is not part of the CNF0 / CNF1 bits, but is
|
||||
// controlled by PxODR. Encoded using the 'spare' bit 5.
|
||||
PinInputPulldown PinMode = PinInputModePullUpDown
|
||||
PinInputPullup PinMode = PinInputModePullUpDown | 0x10
|
||||
)
|
||||
|
||||
// Pin constants for all stm32f103 package sizes
|
||||
@@ -157,6 +162,16 @@ func (p Pin) Configure(config PinConfig) {
|
||||
} else {
|
||||
port.CRH.ReplaceBits(uint32(config.Mode), 0xf, pos)
|
||||
}
|
||||
|
||||
// If configured for input pull-up or pull-down, set ODR
|
||||
// for desired pull-up or pull-down.
|
||||
if (config.Mode & 0xf) == PinInputModePullUpDown {
|
||||
var pullup uint32
|
||||
if config.Mode == PinInputPullup {
|
||||
pullup = 1
|
||||
}
|
||||
port.ODR.ReplaceBits(pullup, 0x1, pin)
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) getPort() *stm32.GPIO_Type {
|
||||
@@ -215,6 +230,47 @@ func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) registerInterrupt() interrupt.Interrupt {
|
||||
pin := uint8(p) % 16
|
||||
|
||||
switch pin {
|
||||
case 0:
|
||||
return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
|
||||
case 1:
|
||||
return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
|
||||
case 2:
|
||||
return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
|
||||
case 3:
|
||||
return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
|
||||
case 4:
|
||||
return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
|
||||
case 5:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
|
||||
case 6:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
|
||||
case 7:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
|
||||
case 8:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
|
||||
case 9:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
|
||||
case 10:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
|
||||
case 11:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
|
||||
case 12:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
|
||||
case 13:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
|
||||
case 14:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
|
||||
case 15:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
|
||||
}
|
||||
|
||||
return interrupt.Interrupt{}
|
||||
}
|
||||
|
||||
//---------- UART related code
|
||||
|
||||
// Configure the TX and RX pins
|
||||
|
||||
@@ -200,6 +200,47 @@ func (p Pin) enableClock() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) registerInterrupt() interrupt.Interrupt {
|
||||
pin := uint8(p) % 16
|
||||
|
||||
switch pin {
|
||||
case 0:
|
||||
return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
|
||||
case 1:
|
||||
return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
|
||||
case 2:
|
||||
return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
|
||||
case 3:
|
||||
return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
|
||||
case 4:
|
||||
return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
|
||||
case 5:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
|
||||
case 6:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
|
||||
case 7:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
|
||||
case 8:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
|
||||
case 9:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
|
||||
case 10:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
|
||||
case 11:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
|
||||
case 12:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
|
||||
case 13:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
|
||||
case 14:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
|
||||
case 15:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
|
||||
}
|
||||
|
||||
return interrupt.Interrupt{}
|
||||
}
|
||||
|
||||
// Enable peripheral clock
|
||||
func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
switch bus {
|
||||
|
||||
@@ -309,6 +309,47 @@ func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) registerInterrupt() interrupt.Interrupt {
|
||||
pin := uint8(p) % 16
|
||||
|
||||
switch pin {
|
||||
case 0:
|
||||
return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
|
||||
case 1:
|
||||
return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
|
||||
case 2:
|
||||
return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
|
||||
case 3:
|
||||
return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
|
||||
case 4:
|
||||
return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
|
||||
case 5:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
|
||||
case 6:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
|
||||
case 7:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
|
||||
case 8:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
|
||||
case 9:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
|
||||
case 10:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
|
||||
case 11:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
|
||||
case 12:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
|
||||
case 13:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
|
||||
case 14:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
|
||||
case 15:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
|
||||
}
|
||||
|
||||
return interrupt.Interrupt{}
|
||||
}
|
||||
|
||||
//---------- Timer related code
|
||||
|
||||
var (
|
||||
|
||||
@@ -6,6 +6,7 @@ package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
@@ -147,6 +148,47 @@ func (p Pin) enableClock() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) registerInterrupt() interrupt.Interrupt {
|
||||
pin := uint8(p) % 16
|
||||
|
||||
switch pin {
|
||||
case 0:
|
||||
return interrupt.New(stm32.IRQ_EXTI0_1, func(interrupt.Interrupt) { handlePinInterrupt(0) })
|
||||
case 1:
|
||||
return interrupt.New(stm32.IRQ_EXTI0_1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
|
||||
case 2:
|
||||
return interrupt.New(stm32.IRQ_EXTI2_3, func(interrupt.Interrupt) { handlePinInterrupt(2) })
|
||||
case 3:
|
||||
return interrupt.New(stm32.IRQ_EXTI2_3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
|
||||
case 4:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(4) })
|
||||
case 5:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(5) })
|
||||
case 6:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(6) })
|
||||
case 7:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(7) })
|
||||
case 8:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(8) })
|
||||
case 9:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(9) })
|
||||
case 10:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(10) })
|
||||
case 11:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(11) })
|
||||
case 12:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(12) })
|
||||
case 13:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(13) })
|
||||
case 14:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(14) })
|
||||
case 15:
|
||||
return interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(15) })
|
||||
}
|
||||
|
||||
return interrupt.Interrupt{}
|
||||
}
|
||||
|
||||
//---------- UART related types and code
|
||||
|
||||
// Configure the UART.
|
||||
|
||||
@@ -203,6 +203,60 @@ func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
}
|
||||
}
|
||||
|
||||
func handlePinInterrupt(pin uint8) {
|
||||
if stm32.EXTI.PR1.HasBits(1 << pin) {
|
||||
// Writing 1 to the pending register clears the
|
||||
// pending flag for that bit
|
||||
stm32.EXTI.PR1.Set(1 << pin)
|
||||
|
||||
callback := pinCallbacks[pin]
|
||||
if callback != nil {
|
||||
callback(interruptPins[pin])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) registerInterrupt() interrupt.Interrupt {
|
||||
pin := uint8(p) % 16
|
||||
|
||||
switch pin {
|
||||
case 0:
|
||||
return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
|
||||
case 1:
|
||||
return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
|
||||
case 2:
|
||||
return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
|
||||
case 3:
|
||||
return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
|
||||
case 4:
|
||||
return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
|
||||
case 5:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
|
||||
case 6:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })
|
||||
case 7:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })
|
||||
case 8:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })
|
||||
case 9:
|
||||
return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })
|
||||
case 10:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
|
||||
case 11:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })
|
||||
case 12:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })
|
||||
case 13:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })
|
||||
case 14:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })
|
||||
case 15:
|
||||
return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })
|
||||
}
|
||||
|
||||
return interrupt.Interrupt{}
|
||||
}
|
||||
|
||||
//---------- SPI related types and code
|
||||
|
||||
// SPI on the STM32Fxxx using MODER / alternate function pins
|
||||
|
||||
@@ -271,6 +271,65 @@ func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) registerInterrupt() interrupt.Interrupt {
|
||||
pin := uint8(p) % 16
|
||||
|
||||
switch pin {
|
||||
case 0:
|
||||
return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })
|
||||
case 1:
|
||||
return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })
|
||||
case 2:
|
||||
return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })
|
||||
case 3:
|
||||
return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })
|
||||
case 4:
|
||||
return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })
|
||||
case 5:
|
||||
return interrupt.New(stm32.IRQ_EXTI5, func(interrupt.Interrupt) { handlePinInterrupt(5) })
|
||||
case 6:
|
||||
return interrupt.New(stm32.IRQ_EXTI6, func(interrupt.Interrupt) { handlePinInterrupt(6) })
|
||||
case 7:
|
||||
return interrupt.New(stm32.IRQ_EXTI7, func(interrupt.Interrupt) { handlePinInterrupt(7) })
|
||||
case 8:
|
||||
return interrupt.New(stm32.IRQ_EXTI8, func(interrupt.Interrupt) { handlePinInterrupt(8) })
|
||||
case 9:
|
||||
return interrupt.New(stm32.IRQ_EXTI9, func(interrupt.Interrupt) { handlePinInterrupt(9) })
|
||||
case 10:
|
||||
return interrupt.New(stm32.IRQ_EXTI10, func(interrupt.Interrupt) { handlePinInterrupt(10) })
|
||||
case 11:
|
||||
return interrupt.New(stm32.IRQ_EXTI11, func(interrupt.Interrupt) { handlePinInterrupt(11) })
|
||||
case 12:
|
||||
return interrupt.New(stm32.IRQ_EXTI12, func(interrupt.Interrupt) { handlePinInterrupt(12) })
|
||||
case 13:
|
||||
return interrupt.New(stm32.IRQ_EXTI13, func(interrupt.Interrupt) { handlePinInterrupt(13) })
|
||||
case 14:
|
||||
return interrupt.New(stm32.IRQ_EXTI14, func(interrupt.Interrupt) { handlePinInterrupt(14) })
|
||||
case 15:
|
||||
return interrupt.New(stm32.IRQ_EXTI15, func(interrupt.Interrupt) { handlePinInterrupt(15) })
|
||||
}
|
||||
|
||||
return interrupt.Interrupt{}
|
||||
}
|
||||
|
||||
func handlePinInterrupt(pin uint8) {
|
||||
// The pin abstraction doesn't differentiate pull-up
|
||||
// events from pull-down events, so combine them to
|
||||
// a single call here.
|
||||
|
||||
if stm32.EXTI.RPR1.HasBits(1<<pin) || stm32.EXTI.FPR1.HasBits(1<<pin) {
|
||||
// Writing 1 to the pending register clears the
|
||||
// pending flag for that bit
|
||||
stm32.EXTI.RPR1.Set(1 << pin)
|
||||
stm32.EXTI.FPR1.Set(1 << pin)
|
||||
|
||||
callback := pinCallbacks[pin]
|
||||
if callback != nil {
|
||||
callback(interruptPins[pin])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------- Timer related code
|
||||
|
||||
var (
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// +build baremetal,serial.none
|
||||
|
||||
package machine
|
||||
|
||||
// Serial is a null device: writes to it are ignored.
|
||||
var Serial = NullSerial{}
|
||||
@@ -0,0 +1,6 @@
|
||||
// +build baremetal,serial.uart
|
||||
|
||||
package machine
|
||||
|
||||
// Serial is implemented via the default (usually the first) UART on the chip.
|
||||
var Serial = DefaultUART
|
||||
@@ -0,0 +1,6 @@
|
||||
// +build baremetal,serial.usb
|
||||
|
||||
package machine
|
||||
|
||||
// Serial is implemented via USB (USB-CDC).
|
||||
var Serial = USB
|
||||
@@ -0,0 +1,46 @@
|
||||
package machine
|
||||
|
||||
import "errors"
|
||||
|
||||
var errNoByte = errors.New("machine: no byte read")
|
||||
|
||||
// UARTConfig is a struct with which a UART (or similar object) can be
|
||||
// configured. The baud rate is usually respected, but TX and RX may be ignored
|
||||
// depending on the chip and the type of object.
|
||||
type UARTConfig struct {
|
||||
BaudRate uint32
|
||||
TX Pin
|
||||
RX Pin
|
||||
}
|
||||
|
||||
// NullSerial is a serial version of /dev/null (or null router): it drops
|
||||
// everything that is written to it.
|
||||
type NullSerial struct {
|
||||
}
|
||||
|
||||
// Configure does nothing: the null serial has no configuration.
|
||||
func (ns NullSerial) Configure(config UARTConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteByte is a no-op: the null serial doesn't write bytes.
|
||||
func (ns NullSerial) WriteByte(b byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadByte always returns an error because there aren't any bytes to read.
|
||||
func (ns NullSerial) ReadByte() (byte, error) {
|
||||
return 0, errNoByte
|
||||
}
|
||||
|
||||
// Buffered returns how many bytes are buffered in the UART. It always returns 0
|
||||
// as there are no bytes to read.
|
||||
func (ns NullSerial) Buffered() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Write is a no-op: none of the data is being written and it will not return an
|
||||
// error.
|
||||
func (ns NullSerial) Write(p []byte) (n int, err error) {
|
||||
return len(p), nil
|
||||
}
|
||||
+17
-6
@@ -1,4 +1,4 @@
|
||||
// +build atmega esp nrf sam sifive stm32 k210 nxp
|
||||
// +build atmega esp nrf sam sifive stm32 k210 nxp rp2040
|
||||
|
||||
package machine
|
||||
|
||||
@@ -6,11 +6,22 @@ import "errors"
|
||||
|
||||
var errUARTBufferEmpty = errors.New("UART buffer empty")
|
||||
|
||||
type UARTConfig struct {
|
||||
BaudRate uint32
|
||||
TX Pin
|
||||
RX Pin
|
||||
}
|
||||
// UARTParity is the parity setting to be used for UART communication.
|
||||
type UARTParity int
|
||||
|
||||
const (
|
||||
// ParityNone means to not use any parity checking. This is
|
||||
// the most common setting.
|
||||
ParityNone UARTParity = 0
|
||||
|
||||
// ParityEven means to expect that the total number of 1 bits sent
|
||||
// should be an even number.
|
||||
ParityEven UARTParity = 1
|
||||
|
||||
// ParityOdd means to expect that the total number of 1 bits sent
|
||||
// should be an odd number.
|
||||
ParityOdd UARTParity = 2
|
||||
)
|
||||
|
||||
// To implement the UART interface for a board, you must declare a concrete type as follows:
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user