Merge branch 'dev' into feature/usb-common

This commit is contained in:
ardnew
2021-08-02 13:39:59 -05:00
254 changed files with 4461 additions and 531 deletions
-2
View File
@@ -47,8 +47,6 @@ const (
LED = D6
)
var Serial = USB
// USBCDC pins
const (
USBCDC_DM_PIN Pin = PA24
-2
View File
@@ -35,8 +35,6 @@ const (
LED3 Pin = PB03 // RX LED
)
var Serial = USB
// ADC pins
const (
AREF Pin = PA03
-2
View File
@@ -74,5 +74,3 @@ const (
PB30 Pin = 62
PB31 Pin = 63
)
var Serial = USB
-2
View File
@@ -15,8 +15,6 @@ const (
BUTTON = PB31
)
var Serial = USB
const (
// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf
+7 -1
View File
@@ -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 (
+1 -2
View File
@@ -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
+1
View File
@@ -41,6 +41,7 @@ const (
const (
LED = D13
NEOPIXELS = D8
WS2812 = D8
BUTTONA = D4
BUTTONB = D5
+1 -5
View File
@@ -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
-2
View File
@@ -68,8 +68,6 @@ const (
ADC3 Pin = IO39
)
var Serial = UART0
// UART0 pins
const (
UART_TX_PIN = IO1
+1 -2
View File
@@ -44,10 +44,9 @@ const (
const (
LED = D13
NEOPIXELS = D8
WS2812 = D8
)
var Serial = USB
// USBCDC pins
const (
USBCDC_DM_PIN = PA24
+2 -3
View File
@@ -36,11 +36,10 @@ const (
)
const (
LED = D13
LED = D13
WS2812 = D8
)
var Serial = USB
// USBCDC pins
const (
USBCDC_DM_PIN = PA24
+105
View File
@@ -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
)
+7 -7
View File
@@ -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
)
+2 -1
View File
@@ -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() {
+27
View File
@@ -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
)
+1 -2
View File
@@ -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)
+1 -1
View File
@@ -35,7 +35,7 @@ const (
LED_BLUE = P21
)
var Serial = UART0
var DefaultUART = UART0
const (
// TODO: figure out the pin numbers for these.
-2
View File
@@ -37,8 +37,6 @@ const (
LED = D13
)
var Serial = USB
// USBCDC pins
const (
USBCDC_DM_PIN = PA24
-5
View File
@@ -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
+1 -1
View File
@@ -54,7 +54,7 @@ const (
I2C0_SDA_PIN = PA10
)
var Serial = UART0
var DefaultUART = UART0
var (
+1 -1
View File
@@ -52,7 +52,7 @@ const (
LED_BLUE = D14
)
var Serial = UART0
var DefaultUART = UART0
// Default pins for UARTHS.
const (
+1
View File
@@ -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(),
+2 -3
View File
@@ -37,11 +37,10 @@ const (
)
const (
LED = D13
LED = D13
WS2812 = D40
)
var Serial = USB
// USBCDC pins
const (
USBCDC_DM_PIN = PA24
+1 -1
View File
@@ -12,7 +12,7 @@ const (
BUTTONB Pin = P11
)
var Serial = UART0
var DefaultUART = UART0
// UART pins
const (
+1 -1
View File
@@ -12,7 +12,7 @@ const (
BUTTONB Pin = 26
)
var Serial = UART0
var DefaultUART = UART0
// UART pins
const (
+95
View File
@@ -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
)
+98
View File
@@ -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
)
-5
View File
@@ -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
-2
View File
@@ -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
-3
View File
@@ -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
+1 -1
View File
@@ -34,7 +34,7 @@ var (
Buffer: NewRingBuffer(),
Bus: stm32.USART2,
}
Serial = UART2
DefaultUART = UART2
)
func init() {
+1 -1
View File
@@ -38,7 +38,7 @@ var (
TxAltFuncSelector: UART_ALT_FN,
RxAltFuncSelector: UART_ALT_FN,
}
Serial = UART1
DefaultUART = UART1
)
func init() {
+7 -1
View File
@@ -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{
+7 -1
View File
@@ -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{
+1 -1
View File
@@ -38,7 +38,7 @@ var (
TxAltFuncSelector: UART_ALT_FN,
RxAltFuncSelector: UART_ALT_FN,
}
Serial = UART1
DefaultUART = UART1
)
const (
+1 -1
View File
@@ -41,7 +41,7 @@ const (
// UART
var (
Serial = UART0
DefaultUART = UART0
)
const (
+1 -1
View File
@@ -41,7 +41,7 @@ const (
// UART
var (
Serial = UART0
DefaultUART = UART0
)
const (
+1 -1
View File
@@ -41,7 +41,7 @@ const (
// UART
var (
Serial = UART0
DefaultUART = UART0
)
const (
+1 -1
View File
@@ -19,7 +19,7 @@ const (
LED_BLUE Pin = 23
)
var Serial = UART0
var DefaultUART = UART0
// UART pins
const (
+1 -1
View File
@@ -23,7 +23,7 @@ const (
BUTTON4 Pin = 16
)
var Serial = UART0
var DefaultUART = UART0
// UART pins for NRF52840-DK
const (
+1 -1
View File
@@ -22,7 +22,7 @@ const (
BUTTON4 Pin = 25
)
var Serial = UART0
var DefaultUART = UART0
// UART pins
const (
-5
View File
@@ -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
View File
@@ -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
)
+1 -1
View File
@@ -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:
+1 -2
View File
@@ -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
+1 -2
View File
@@ -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
+1 -2
View File
@@ -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
+3 -1
View File
@@ -42,7 +42,9 @@ const (
)
const (
LED = D13
NEOPIXELS = D11
WS2812 = D11
NEOPIXELS_POWER = D12
)
// USBCDC pins
+1 -1
View File
@@ -29,7 +29,7 @@ const (
BUTTON Pin = 7
)
var Serial = UART0
var DefaultUART = UART0
// UART pins
const (
+5 -1
View File
@@ -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
+2
View File
@@ -87,6 +87,8 @@ var (
TeensyUART5 = UART4
)
var DefaultUART = UART0
const (
defaultUART0RX = D00
defaultUART0TX = D01
+3 -3
View File
@@ -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(),
-2
View File
@@ -325,8 +325,6 @@ const (
OUTPUT_CTR_3V3 = PC15
)
var Serial = USB
// USBCDC pins
const (
USBCDC_DM_PIN = PIN_USB_DM
+1 -1
View File
@@ -27,4 +27,4 @@ const (
const HasLowFrequencyCrystal = true
var Serial = UART0
var DefaultUART = UART0
+1 -1
View File
@@ -122,7 +122,7 @@ func (i2c *I2C) readByte() byte {
}
// Always use UART0 as the serial output.
var Serial = UART0
var DefaultUART = UART0
// UART
var (
+2
View File
@@ -251,6 +251,8 @@ func (p Pin) mux() *volatile.Register32 {
}
}
var DefaultUART = UART0
var (
UART0 = &_UART0
_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}
+2
View File
@@ -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()}
+6 -6
View File
@@ -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
+8 -7
View File
@@ -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
+73 -1
View File
@@ -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)
}
+61
View File
@@ -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
}
}
+47 -2
View File
@@ -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()
}
+361
View File
@@ -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
}
+133
View File
@@ -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)))
}
+7
View File
@@ -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!
+27
View File
@@ -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)
}
+26
View File
@@ -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
}
+27
View File
@@ -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)
}
+92
View File
@@ -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])
}
}
}
+79
View File
@@ -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
}
+56
View File
@@ -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
+41
View File
@@ -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 {
+41
View File
@@ -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 (
+42
View File
@@ -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.
+54
View File
@@ -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
+59
View File
@@ -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 (
+6
View File
@@ -0,0 +1,6 @@
// +build baremetal,serial.none
package machine
// Serial is a null device: writes to it are ignored.
var Serial = NullSerial{}
+6
View File
@@ -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
+6
View File
@@ -0,0 +1,6 @@
// +build baremetal,serial.usb
package machine
// Serial is implemented via USB (USB-CDC).
var Serial = USB
+46
View File
@@ -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
View File
@@ -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:
//