diff --git a/.circleci/config.yml b/.circleci/config.yml
index a1bfead6..68a43a5e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -79,6 +79,7 @@ commands:
- run: tinygo build -size short -o test.elf -target=pca10056 examples/blinky1
- run: tinygo build -size short -o test.elf -target=pca10056 examples/blinky2
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 examples/blinky1
+ - run: tinygo build -size short -o test.elf -target=trinket-m0 examples/blinky1
- run: tinygo build -size short -o test.elf -target=circuitplay-express examples/blinky1
- run: tinygo build -size short -o test.elf -target=stm32f4disco examples/blinky1
- run: tinygo build -size short -o test.elf -target=stm32f4disco examples/blinky2
diff --git a/src/machine/board_trinket.go b/src/machine/board_trinket.go
new file mode 100644
index 00000000..7d2b89ed
--- /dev/null
+++ b/src/machine/board_trinket.go
@@ -0,0 +1,73 @@
+// +build sam,atsamd21,trinket_m0
+
+package machine
+
+import "device/sam"
+
+// GPIO Pins
+const (
+ D0 = PA08 // PWM available
+ D1 = PA02
+ D2 = PA09 // PWM available
+ D3 = PA07 // PWM available / UART0 RX
+ D4 = PA06 // PWM available / UART0 TX
+ D13 = PA10 // LED
+)
+
+// Analog pins
+const (
+ A0 = D1
+ A1 = D2
+ A2 = D0
+ A3 = D3
+ A4 = D4
+)
+
+const (
+ LED = D13
+)
+
+// UART0 aka USBCDC pins
+const (
+ USBCDC_DM_PIN = PA24
+ USBCDC_DP_PIN = PA25
+)
+
+// UART1 pins
+const (
+ UART_TX_PIN = D4
+ UART_RX_PIN = D3
+)
+
+// SPI pins
+const (
+ SPI0_SCK_PIN = D3
+ SPI0_MOSI_PIN = D4
+ SPI0_MISO_PIN = D2
+)
+
+// SPI on the Trinket M0.
+var (
+ SPI0 = SPI{Bus: sam.SERCOM0_SPI}
+)
+
+// I2C pins
+const (
+ SDA_PIN = D0 // SDA
+ SCL_PIN = D2 // SCL
+)
+
+// I2C on the Trinket M0.
+var (
+ I2C0 = I2C{Bus: sam.SERCOM2_I2CM,
+ SDA: SDA_PIN,
+ SCL: SCL_PIN,
+ PinMode: GPIO_SERCOM_ALT}
+)
+
+// I2S pins
+const (
+ I2S_SCK_PIN = PA10
+ I2S_SD_PIN = PA08
+ I2S_WS_PIN = 0xff // TODO: figure out what this is on Trinket M0.
+)
diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go
index 89a62292..767dca2f 100644
--- a/src/machine/machine_atsamd21.go
+++ b/src/machine/machine_atsamd21.go
@@ -105,151 +105,6 @@ const (
PB31 = 63
)
-// Configure this pin with the given configuration.
-func (p GPIO) Configure(config GPIOConfig) {
- switch config.Mode {
- case GPIO_OUTPUT:
- if p.Pin < 32 {
- sam.PORT.DIRSET0 = (1 << p.Pin)
- // output is also set to input enable so pin can read back its own value
- p.setPinCfg(sam.PORT_PINCFG0_INEN)
- } else {
- sam.PORT.DIRSET1 = (1 << (p.Pin - 32))
- // output is also set to input enable so pin can read back its own value
- p.setPinCfg(sam.PORT_PINCFG0_INEN)
- }
-
- case GPIO_INPUT:
- if p.Pin < 32 {
- sam.PORT.DIRCLR0 = (1 << p.Pin)
- p.setPinCfg(sam.PORT_PINCFG0_INEN)
- } else {
- sam.PORT.DIRCLR1 = (1<
0 {
- // odd pin, so save the even pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
- p.setPMux(val | (GPIO_SERCOM << sam.PORT_PMUX0_PMUXO_Pos))
- } else {
- // even pin, so save the odd pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
- p.setPMux(val | (GPIO_SERCOM << sam.PORT_PMUX0_PMUXE_Pos))
- }
- // enable port config
- p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
-
- case GPIO_SERCOM_ALT:
- if p.Pin&1 > 0 {
- // odd pin, so save the even pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
- p.setPMux(val | (GPIO_SERCOM_ALT << sam.PORT_PMUX0_PMUXO_Pos))
- } else {
- // even pin, so save the odd pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
- p.setPMux(val | (GPIO_SERCOM_ALT << sam.PORT_PMUX0_PMUXE_Pos))
- }
- // enable port config
- p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
-
- case GPIO_COM:
- if p.Pin&1 > 0 {
- // odd pin, so save the even pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
- p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXO_Pos))
- } else {
- // even pin, so save the odd pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
- p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXE_Pos))
- }
- // enable port config
- p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
- case GPIO_ANALOG:
- if p.Pin&1 > 0 {
- // odd pin, so save the even pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
- p.setPMux(val | (GPIO_ANALOG << sam.PORT_PMUX0_PMUXO_Pos))
- } else {
- // even pin, so save the odd pins
- val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
- p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXE_Pos))
- }
- // enable port config
- p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
- }
-}
-
-// Get returns the current value of a GPIO pin.
-func (p GPIO) Get() bool {
- if p.Pin < 32 {
- return (sam.PORT.IN0>>p.Pin)&1 > 0
- } else {
- return (sam.PORT.IN1>>(p.Pin-32))&1 > 0
- }
-}
-
-// Set the pin to high or low.
-// Warning: only use this on an output pin!
-func (p GPIO) Set(high bool) {
- if p.Pin < 32 {
- if high {
- sam.PORT.OUTSET0 = (1 << p.Pin)
- } else {
- sam.PORT.OUTCLR0 = (1 << p.Pin)
- }
- } else {
- if high {
- sam.PORT.OUTSET1 = (1 << (p.Pin - 32))
- } else {
- sam.PORT.OUTCLR1 = (1 << (p.Pin - 32))
- }
- }
-}
-
-// Return the register and mask to enable a given GPIO pin. This can be used to
-// implement bit-banged drivers.
-func (p GPIO) PortMaskSet() (*uint32, uint32) {
- if p.Pin < 32 {
- return (*uint32)(&sam.PORT.OUTSET0), 1 << p.Pin
- } else {
- return (*uint32)(&sam.PORT.OUTSET1), 1 << (p.Pin - 32)
- }
-}
-
-// Return the register and mask to disable a given port. This can be used to
-// implement bit-banged drivers.
-func (p GPIO) PortMaskClear() (*uint32, uint32) {
- if p.Pin < 32 {
- return (*uint32)(&sam.PORT.OUTCLR0), 1 << p.Pin
- } else {
- return (*uint32)(&sam.PORT.OUTCLR1), 1 << (p.Pin - 32)
- }
-}
-
// getPMux returns the value for the correct PMUX register for this pin.
func (p GPIO) getPMux() sam.RegValue8 {
return getPMux(p.Pin)
@@ -1265,420 +1120,6 @@ func (pwm PWM) setPinCfg(val sam.RegValue8) {
setPinCfg(pwm.Pin, val)
}
-// getPMux returns the value for the correct PMUX register for this pin.
-func getPMux(p uint8) sam.RegValue8 {
- pin := p >> 1
- switch pin {
- case 0:
- return sam.PORT.PMUX0_0
- case 1:
- return sam.PORT.PMUX0_1
- case 2:
- return sam.PORT.PMUX0_2
- case 3:
- return sam.PORT.PMUX0_3
- case 4:
- return sam.PORT.PMUX0_4
- case 5:
- return sam.PORT.PMUX0_5
- case 6:
- return sam.PORT.PMUX0_6
- case 7:
- return sam.PORT.PMUX0_7
- case 8:
- return sam.PORT.PMUX0_8
- case 9:
- return sam.PORT.PMUX0_9
- case 10:
- return sam.PORT.PMUX0_10
- case 11:
- return sam.PORT.PMUX0_11
- case 12:
- return sam.PORT.PMUX0_12
- case 13:
- return sam.PORT.PMUX0_13
- case 14:
- return sam.PORT.PMUX0_14
- case 15:
- return sam.PORT.PMUX0_15
- case 16:
- return sam.RegValue8(sam.PORT.PMUX1_0>>0) & 0xff
- case 17:
- return sam.RegValue8(sam.PORT.PMUX1_0>>8) & 0xff
- case 18:
- return sam.RegValue8(sam.PORT.PMUX1_0>>16) & 0xff
- case 19:
- return sam.RegValue8(sam.PORT.PMUX1_0>>24) & 0xff
- case 20:
- return sam.RegValue8(sam.PORT.PMUX1_4>>0) & 0xff
- case 21:
- return sam.RegValue8(sam.PORT.PMUX1_4>>8) & 0xff
- case 22:
- return sam.RegValue8(sam.PORT.PMUX1_4>>16) & 0xff
- case 23:
- return sam.RegValue8(sam.PORT.PMUX1_4>>24) & 0xff
- case 24:
- return sam.RegValue8(sam.PORT.PMUX1_8>>0) & 0xff
- case 25:
- return sam.RegValue8(sam.PORT.PMUX1_8>>8) & 0xff
- case 26:
- return sam.RegValue8(sam.PORT.PMUX1_8>>16) & 0xff
- case 27:
- return sam.RegValue8(sam.PORT.PMUX1_8>>24) & 0xff
- case 28:
- return sam.RegValue8(sam.PORT.PMUX1_12>>0) & 0xff
- case 29:
- return sam.RegValue8(sam.PORT.PMUX1_12>>8) & 0xff
- case 30:
- return sam.RegValue8(sam.PORT.PMUX1_12>>16) & 0xff
- case 31:
- return sam.RegValue8(sam.PORT.PMUX1_12>>24) & 0xff
- default:
- return 0
- }
-}
-
-// setPMux sets the value for the correct PMUX register for this pin.
-func setPMux(p uint8, val sam.RegValue8) {
- pin := p >> 1
- switch pin {
- case 0:
- sam.PORT.PMUX0_0 = val
- case 1:
- sam.PORT.PMUX0_1 = val
- case 2:
- sam.PORT.PMUX0_2 = val
- case 3:
- sam.PORT.PMUX0_3 = val
- case 4:
- sam.PORT.PMUX0_4 = val
- case 5:
- sam.PORT.PMUX0_5 = val
- case 6:
- sam.PORT.PMUX0_6 = val
- case 7:
- sam.PORT.PMUX0_7 = val
- case 8:
- sam.PORT.PMUX0_8 = val
- case 9:
- sam.PORT.PMUX0_9 = val
- case 10:
- sam.PORT.PMUX0_10 = val
- case 11:
- sam.PORT.PMUX0_11 = val
- case 12:
- sam.PORT.PMUX0_12 = val
- case 13:
- sam.PORT.PMUX0_13 = val
- case 14:
- sam.PORT.PMUX0_14 = val
- case 15:
- sam.PORT.PMUX0_15 = val
- case 16:
- sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 17:
- sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 18:
- sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 19:
- sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 20:
- sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 21:
- sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 22:
- sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 23:
- sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 24:
- sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 25:
- sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 26:
- sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 27:
- sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 28:
- sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 29:
- sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 30:
- sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 31:
- sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- }
-}
-
-// getPinCfg returns the value for the correct PINCFG register for this pin.
-func getPinCfg(p uint8) sam.RegValue8 {
- switch p {
- case 0:
- return sam.PORT.PINCFG0_0
- case 1:
- return sam.PORT.PINCFG0_1
- case 2:
- return sam.PORT.PINCFG0_2
- case 3:
- return sam.PORT.PINCFG0_3
- case 4:
- return sam.PORT.PINCFG0_4
- case 5:
- return sam.PORT.PINCFG0_5
- case 6:
- return sam.PORT.PINCFG0_6
- case 7:
- return sam.PORT.PINCFG0_7
- case 8:
- return sam.PORT.PINCFG0_8
- case 9:
- return sam.PORT.PINCFG0_9
- case 10:
- return sam.PORT.PINCFG0_10
- case 11:
- return sam.PORT.PINCFG0_11
- case 12:
- return sam.PORT.PINCFG0_12
- case 13:
- return sam.PORT.PINCFG0_13
- case 14:
- return sam.PORT.PINCFG0_14
- case 15:
- return sam.PORT.PINCFG0_15
- case 16:
- return sam.PORT.PINCFG0_16
- case 17:
- return sam.PORT.PINCFG0_17
- case 18:
- return sam.PORT.PINCFG0_18
- case 19:
- return sam.PORT.PINCFG0_19
- case 20:
- return sam.PORT.PINCFG0_20
- case 21:
- return sam.PORT.PINCFG0_21
- case 22:
- return sam.PORT.PINCFG0_22
- case 23:
- return sam.PORT.PINCFG0_23
- case 24:
- return sam.PORT.PINCFG0_24
- case 25:
- return sam.PORT.PINCFG0_25
- case 26:
- return sam.PORT.PINCFG0_26
- case 27:
- return sam.PORT.PINCFG0_27
- case 28:
- return sam.PORT.PINCFG0_28
- case 29:
- return sam.PORT.PINCFG0_29
- case 30:
- return sam.PORT.PINCFG0_30
- case 31:
- return sam.PORT.PINCFG0_31
- case 32: // PB00
- return sam.RegValue8(sam.PORT.PINCFG1_0>>0) & 0xff
- case 33: // PB01
- return sam.RegValue8(sam.PORT.PINCFG1_0>>8) & 0xff
- case 34: // PB02
- return sam.RegValue8(sam.PORT.PINCFG1_0>>16) & 0xff
- case 35: // PB03
- return sam.RegValue8(sam.PORT.PINCFG1_0>>24) & 0xff
- case 37: // PB04
- return sam.RegValue8(sam.PORT.PINCFG1_4>>0) & 0xff
- case 38: // PB05
- return sam.RegValue8(sam.PORT.PINCFG1_4>>8) & 0xff
- case 39: // PB06
- return sam.RegValue8(sam.PORT.PINCFG1_4>>16) & 0xff
- case 40: // PB07
- return sam.RegValue8(sam.PORT.PINCFG1_4>>24) & 0xff
- case 41: // PB08
- return sam.RegValue8(sam.PORT.PINCFG1_8>>0) & 0xff
- case 42: // PB09
- return sam.RegValue8(sam.PORT.PINCFG1_8>>8) & 0xff
- case 43: // PB10
- return sam.RegValue8(sam.PORT.PINCFG1_8>>16) & 0xff
- case 44: // PB11
- return sam.RegValue8(sam.PORT.PINCFG1_8>>24) & 0xff
- case 45: // PB12
- return sam.RegValue8(sam.PORT.PINCFG1_12>>0) & 0xff
- case 46: // PB13
- return sam.RegValue8(sam.PORT.PINCFG1_12>>8) & 0xff
- case 47: // PB14
- return sam.RegValue8(sam.PORT.PINCFG1_12>>16) & 0xff
- case 48: // PB15
- return sam.RegValue8(sam.PORT.PINCFG1_12>>24) & 0xff
- case 49: // PB16
- return sam.RegValue8(sam.PORT.PINCFG1_16>>0) & 0xff
- case 50: // PB17
- return sam.RegValue8(sam.PORT.PINCFG1_16>>8) & 0xff
- case 51: // PB18
- return sam.RegValue8(sam.PORT.PINCFG1_16>>16) & 0xff
- case 52: // PB19
- return sam.RegValue8(sam.PORT.PINCFG1_16>>24) & 0xff
- case 53: // PB20
- return sam.RegValue8(sam.PORT.PINCFG1_20>>0) & 0xff
- case 54: // PB21
- return sam.RegValue8(sam.PORT.PINCFG1_20>>8) & 0xff
- case 55: // PB22
- return sam.RegValue8(sam.PORT.PINCFG1_20>>16) & 0xff
- case 56: // PB23
- return sam.RegValue8(sam.PORT.PINCFG1_20>>24) & 0xff
- case 57: // PB24
- return sam.RegValue8(sam.PORT.PINCFG1_24>>0) & 0xff
- case 58: // PB25
- return sam.RegValue8(sam.PORT.PINCFG1_24>>8) & 0xff
- case 59: // PB26
- return sam.RegValue8(sam.PORT.PINCFG1_24>>16) & 0xff
- case 60: // PB27
- return sam.RegValue8(sam.PORT.PINCFG1_24>>24) & 0xff
- case 61: // PB28
- return sam.RegValue8(sam.PORT.PINCFG1_28>>0) & 0xff
- case 62: // PB29
- return sam.RegValue8(sam.PORT.PINCFG1_28>>8) & 0xff
- case 63: // PB30
- return sam.RegValue8(sam.PORT.PINCFG1_28>>16) & 0xff
- case 64: // PB31
- return sam.RegValue8(sam.PORT.PINCFG1_28>>24) & 0xff
- default:
- return 0
- }
-}
-
-// setPinCfg sets the value for the correct PINCFG register for this pin.
-func setPinCfg(p uint8, val sam.RegValue8) {
- switch p {
- case 0:
- sam.PORT.PINCFG0_0 = val
- case 1:
- sam.PORT.PINCFG0_1 = val
- case 2:
- sam.PORT.PINCFG0_2 = val
- case 3:
- sam.PORT.PINCFG0_3 = val
- case 4:
- sam.PORT.PINCFG0_4 = val
- case 5:
- sam.PORT.PINCFG0_5 = val
- case 6:
- sam.PORT.PINCFG0_6 = val
- case 7:
- sam.PORT.PINCFG0_7 = val
- case 8:
- sam.PORT.PINCFG0_8 = val
- case 9:
- sam.PORT.PINCFG0_9 = val
- case 10:
- sam.PORT.PINCFG0_10 = val
- case 11:
- sam.PORT.PINCFG0_11 = val
- case 12:
- sam.PORT.PINCFG0_12 = val
- case 13:
- sam.PORT.PINCFG0_13 = val
- case 14:
- sam.PORT.PINCFG0_14 = val
- case 15:
- sam.PORT.PINCFG0_15 = val
- case 16:
- sam.PORT.PINCFG0_16 = val
- case 17:
- sam.PORT.PINCFG0_17 = val
- case 18:
- sam.PORT.PINCFG0_18 = val
- case 19:
- sam.PORT.PINCFG0_19 = val
- case 20:
- sam.PORT.PINCFG0_20 = val
- case 21:
- sam.PORT.PINCFG0_21 = val
- case 22:
- sam.PORT.PINCFG0_22 = val
- case 23:
- sam.PORT.PINCFG0_23 = val
- case 24:
- sam.PORT.PINCFG0_24 = val
- case 25:
- sam.PORT.PINCFG0_25 = val
- case 26:
- sam.PORT.PINCFG0_26 = val
- case 27:
- sam.PORT.PINCFG0_27 = val
- case 28:
- sam.PORT.PINCFG0_28 = val
- case 29:
- sam.PORT.PINCFG0_29 = val
- case 30:
- sam.PORT.PINCFG0_30 = val
- case 31:
- sam.PORT.PINCFG0_31 = val
- case 32: // PB00
- sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 33: // PB01
- sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 34: // PB02
- sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 35: // PB03
- sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 36: // PB04
- sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 37: // PB05
- sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 38: // PB06
- sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 39: // PB07
- sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 40: // PB08
- sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 41: // PB09
- sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 42: // PB10
- sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 43: // PB11
- sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 44: // PB12
- sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 45: // PB13
- sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 46: // PB14
- sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 47: // PB15
- sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 48: // PB16
- sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 49: // PB17
- sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 50: // PB18
- sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 51: // PB19
- sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 52: // PB20
- sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 53: // PB21
- sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 54: // PB22
- sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 55: // PB23
- sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 56: // PB24
- sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 57: // PB25
- sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 58: // PB26
- sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 59: // PB27
- sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- case 60: // PB28
- sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
- case 61: // PB29
- sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
- case 62: // PB30
- sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
- case 63: // PB31
- sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
- }
-}
-
// getTimer returns the timer to be used for PWM on this pin
func (pwm PWM) getTimer() *sam.TCC_Type {
switch pwm.Pin {
diff --git a/src/machine/machine_atsamd21e18.go b/src/machine/machine_atsamd21e18.go
new file mode 100644
index 00000000..61db098f
--- /dev/null
+++ b/src/machine/machine_atsamd21e18.go
@@ -0,0 +1,336 @@
+// +build sam,atsamd21,atsamd21e18
+
+// Peripheral abstraction layer for the atsamd21.
+//
+// Datasheet:
+// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf
+//
+package machine
+
+import (
+ "device/sam"
+)
+
+// Return the register and mask to enable a given GPIO pin. This can be used to
+// implement bit-banged drivers.
+func (p GPIO) PortMaskSet() (*uint32, uint32) {
+ return (*uint32)(&sam.PORT.OUTSET0), 1 << p.Pin
+}
+
+// Return the register and mask to disable a given port. This can be used to
+// implement bit-banged drivers.
+func (p GPIO) PortMaskClear() (*uint32, uint32) {
+ return (*uint32)(&sam.PORT.OUTCLR0), 1 << p.Pin
+}
+
+// Set the pin to high or low.
+// Warning: only use this on an output pin!
+func (p GPIO) Set(high bool) {
+ if high {
+ sam.PORT.OUTSET0 = (1 << p.Pin)
+ } else {
+ sam.PORT.OUTCLR0 = (1 << p.Pin)
+ }
+}
+
+// Get returns the current value of a GPIO pin.
+func (p GPIO) Get() bool {
+ return (sam.PORT.IN0>>p.Pin)&1 > 0
+}
+
+// Configure this pin with the given configuration.
+func (p GPIO) Configure(config GPIOConfig) {
+ switch config.Mode {
+ case GPIO_OUTPUT:
+ sam.PORT.DIRSET0 = (1 << p.Pin)
+ // output is also set to input enable so pin can read back its own value
+ p.setPinCfg(sam.PORT_PINCFG0_INEN)
+
+ case GPIO_INPUT:
+ sam.PORT.DIRCLR0 = (1 << p.Pin)
+ p.setPinCfg(sam.PORT_PINCFG0_INEN)
+
+ case GPIO_INPUT_PULLDOWN:
+ sam.PORT.DIRCLR0 = (1 << p.Pin)
+ sam.PORT.OUTCLR0 = (1 << p.Pin)
+ p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
+
+ case GPIO_INPUT_PULLUP:
+ sam.PORT.DIRCLR0 = (1 << p.Pin)
+ sam.PORT.OUTSET0 = (1 << p.Pin)
+ p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
+
+ case GPIO_SERCOM:
+ if p.Pin&1 > 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_SERCOM << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_SERCOM << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
+
+ case GPIO_SERCOM_ALT:
+ if p.Pin&1 > 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_SERCOM_ALT << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_SERCOM_ALT << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
+
+ case GPIO_COM:
+ if p.Pin&1 > 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
+ case GPIO_ANALOG:
+ if p.Pin&1 > 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_ANALOG << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
+ }
+}
+
+// getPMux returns the value for the correct PMUX register for this pin.
+func getPMux(p uint8) sam.RegValue8 {
+ pin := p >> 1
+ switch pin {
+ case 0:
+ return sam.PORT.PMUX0_0
+ case 1:
+ return sam.PORT.PMUX0_1
+ case 2:
+ return sam.PORT.PMUX0_2
+ case 3:
+ return sam.PORT.PMUX0_3
+ case 4:
+ return sam.PORT.PMUX0_4
+ case 5:
+ return sam.PORT.PMUX0_5
+ case 6:
+ return sam.PORT.PMUX0_6
+ case 7:
+ return sam.PORT.PMUX0_7
+ case 8:
+ return sam.PORT.PMUX0_8
+ case 9:
+ return sam.PORT.PMUX0_9
+ case 10:
+ return sam.PORT.PMUX0_10
+ case 11:
+ return sam.PORT.PMUX0_11
+ case 12:
+ return sam.PORT.PMUX0_12
+ case 13:
+ return sam.PORT.PMUX0_13
+ case 14:
+ return sam.PORT.PMUX0_14
+ case 15:
+ return sam.PORT.PMUX0_15
+ default:
+ return 0
+ }
+}
+
+// setPMux sets the value for the correct PMUX register for this pin.
+func setPMux(p uint8, val sam.RegValue8) {
+ pin := p >> 1
+ switch pin {
+ case 0:
+ sam.PORT.PMUX0_0 = val
+ case 1:
+ sam.PORT.PMUX0_1 = val
+ case 2:
+ sam.PORT.PMUX0_2 = val
+ case 3:
+ sam.PORT.PMUX0_3 = val
+ case 4:
+ sam.PORT.PMUX0_4 = val
+ case 5:
+ sam.PORT.PMUX0_5 = val
+ case 6:
+ sam.PORT.PMUX0_6 = val
+ case 7:
+ sam.PORT.PMUX0_7 = val
+ case 8:
+ sam.PORT.PMUX0_8 = val
+ case 9:
+ sam.PORT.PMUX0_9 = val
+ case 10:
+ sam.PORT.PMUX0_10 = val
+ case 11:
+ sam.PORT.PMUX0_11 = val
+ case 12:
+ sam.PORT.PMUX0_12 = val
+ case 13:
+ sam.PORT.PMUX0_13 = val
+ case 14:
+ sam.PORT.PMUX0_14 = val
+ case 15:
+ sam.PORT.PMUX0_15 = val
+ }
+}
+
+// getPinCfg returns the value for the correct PINCFG register for this pin.
+func getPinCfg(p uint8) sam.RegValue8 {
+ switch p {
+ case 0:
+ return sam.PORT.PINCFG0_0
+ case 1:
+ return sam.PORT.PINCFG0_1
+ case 2:
+ return sam.PORT.PINCFG0_2
+ case 3:
+ return sam.PORT.PINCFG0_3
+ case 4:
+ return sam.PORT.PINCFG0_4
+ case 5:
+ return sam.PORT.PINCFG0_5
+ case 6:
+ return sam.PORT.PINCFG0_6
+ case 7:
+ return sam.PORT.PINCFG0_7
+ case 8:
+ return sam.PORT.PINCFG0_8
+ case 9:
+ return sam.PORT.PINCFG0_9
+ case 10:
+ return sam.PORT.PINCFG0_10
+ case 11:
+ return sam.PORT.PINCFG0_11
+ case 12:
+ return sam.PORT.PINCFG0_12
+ case 13:
+ return sam.PORT.PINCFG0_13
+ case 14:
+ return sam.PORT.PINCFG0_14
+ case 15:
+ return sam.PORT.PINCFG0_15
+ case 16:
+ return sam.PORT.PINCFG0_16
+ case 17:
+ return sam.PORT.PINCFG0_17
+ case 18:
+ return sam.PORT.PINCFG0_18
+ case 19:
+ return sam.PORT.PINCFG0_19
+ case 20:
+ return sam.PORT.PINCFG0_20
+ case 21:
+ return sam.PORT.PINCFG0_21
+ case 22:
+ return sam.PORT.PINCFG0_22
+ case 23:
+ return sam.PORT.PINCFG0_23
+ case 24:
+ return sam.PORT.PINCFG0_24
+ case 25:
+ return sam.PORT.PINCFG0_25
+ case 26:
+ return sam.PORT.PINCFG0_26
+ case 27:
+ return sam.PORT.PINCFG0_27
+ case 28:
+ return sam.PORT.PINCFG0_28
+ case 29:
+ return sam.PORT.PINCFG0_29
+ case 30:
+ return sam.PORT.PINCFG0_30
+ case 31:
+ return sam.PORT.PINCFG0_31
+ default:
+ return 0
+ }
+}
+
+// setPinCfg sets the value for the correct PINCFG register for this pin.
+func setPinCfg(p uint8, val sam.RegValue8) {
+ switch p {
+ case 0:
+ sam.PORT.PINCFG0_0 = val
+ case 1:
+ sam.PORT.PINCFG0_1 = val
+ case 2:
+ sam.PORT.PINCFG0_2 = val
+ case 3:
+ sam.PORT.PINCFG0_3 = val
+ case 4:
+ sam.PORT.PINCFG0_4 = val
+ case 5:
+ sam.PORT.PINCFG0_5 = val
+ case 6:
+ sam.PORT.PINCFG0_6 = val
+ case 7:
+ sam.PORT.PINCFG0_7 = val
+ case 8:
+ sam.PORT.PINCFG0_8 = val
+ case 9:
+ sam.PORT.PINCFG0_9 = val
+ case 10:
+ sam.PORT.PINCFG0_10 = val
+ case 11:
+ sam.PORT.PINCFG0_11 = val
+ case 12:
+ sam.PORT.PINCFG0_12 = val
+ case 13:
+ sam.PORT.PINCFG0_13 = val
+ case 14:
+ sam.PORT.PINCFG0_14 = val
+ case 15:
+ sam.PORT.PINCFG0_15 = val
+ case 16:
+ sam.PORT.PINCFG0_16 = val
+ case 17:
+ sam.PORT.PINCFG0_17 = val
+ case 18:
+ sam.PORT.PINCFG0_18 = val
+ case 19:
+ sam.PORT.PINCFG0_19 = val
+ case 20:
+ sam.PORT.PINCFG0_20 = val
+ case 21:
+ sam.PORT.PINCFG0_21 = val
+ case 22:
+ sam.PORT.PINCFG0_22 = val
+ case 23:
+ sam.PORT.PINCFG0_23 = val
+ case 24:
+ sam.PORT.PINCFG0_24 = val
+ case 25:
+ sam.PORT.PINCFG0_25 = val
+ case 26:
+ sam.PORT.PINCFG0_26 = val
+ case 27:
+ sam.PORT.PINCFG0_27 = val
+ case 28:
+ sam.PORT.PINCFG0_28 = val
+ case 29:
+ sam.PORT.PINCFG0_29 = val
+ case 30:
+ sam.PORT.PINCFG0_30 = val
+ case 31:
+ sam.PORT.PINCFG0_31 = val
+ }
+}
diff --git a/src/machine/machine_atsamd21g18.go b/src/machine/machine_atsamd21g18.go
new file mode 100644
index 00000000..0f73ff63
--- /dev/null
+++ b/src/machine/machine_atsamd21g18.go
@@ -0,0 +1,571 @@
+// +build sam,atsamd21,atsamd21g18
+
+// Peripheral abstraction layer for the atsamd21.
+//
+// Datasheet:
+// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf
+//
+package machine
+
+import (
+ "device/sam"
+)
+
+// Return the register and mask to enable a given GPIO pin. This can be used to
+// implement bit-banged drivers.
+func (p GPIO) PortMaskSet() (*uint32, uint32) {
+ if p.Pin < 32 {
+ return (*uint32)(&sam.PORT.OUTSET0), 1 << p.Pin
+ } else {
+ return (*uint32)(&sam.PORT.OUTSET1), 1 << (p.Pin - 32)
+ }
+}
+
+// Return the register and mask to disable a given port. This can be used to
+// implement bit-banged drivers.
+func (p GPIO) PortMaskClear() (*uint32, uint32) {
+ if p.Pin < 32 {
+ return (*uint32)(&sam.PORT.OUTCLR0), 1 << p.Pin
+ } else {
+ return (*uint32)(&sam.PORT.OUTCLR1), 1 << (p.Pin - 32)
+ }
+}
+
+// Set the pin to high or low.
+// Warning: only use this on an output pin!
+func (p GPIO) Set(high bool) {
+ if p.Pin < 32 {
+ if high {
+ sam.PORT.OUTSET0 = (1 << p.Pin)
+ } else {
+ sam.PORT.OUTCLR0 = (1 << p.Pin)
+ }
+ } else {
+ if high {
+ sam.PORT.OUTSET1 = (1 << (p.Pin - 32))
+ } else {
+ sam.PORT.OUTCLR1 = (1 << (p.Pin - 32))
+ }
+ }
+}
+
+// Get returns the current value of a GPIO pin.
+func (p GPIO) Get() bool {
+ if p.Pin < 32 {
+ return (sam.PORT.IN0>>p.Pin)&1 > 0
+ } else {
+ return (sam.PORT.IN1>>(p.Pin-32))&1 > 0
+ }
+}
+
+// Configure this pin with the given configuration.
+func (p GPIO) Configure(config GPIOConfig) {
+ switch config.Mode {
+ case GPIO_OUTPUT:
+ if p.Pin < 32 {
+ sam.PORT.DIRSET0 = (1 << p.Pin)
+ // output is also set to input enable so pin can read back its own value
+ p.setPinCfg(sam.PORT_PINCFG0_INEN)
+ } else {
+ sam.PORT.DIRSET1 = (1 << (p.Pin - 32))
+ // output is also set to input enable so pin can read back its own value
+ p.setPinCfg(sam.PORT_PINCFG0_INEN)
+ }
+
+ case GPIO_INPUT:
+ if p.Pin < 32 {
+ sam.PORT.DIRCLR0 = (1 << p.Pin)
+ p.setPinCfg(sam.PORT_PINCFG0_INEN)
+ } else {
+ sam.PORT.DIRCLR1 = (1< 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_SERCOM << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_SERCOM << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
+
+ case GPIO_SERCOM_ALT:
+ if p.Pin&1 > 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_SERCOM_ALT << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_SERCOM_ALT << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
+
+ case GPIO_COM:
+ if p.Pin&1 > 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
+ case GPIO_ANALOG:
+ if p.Pin&1 > 0 {
+ // odd pin, so save the even pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
+ p.setPMux(val | (GPIO_ANALOG << sam.PORT_PMUX0_PMUXO_Pos))
+ } else {
+ // even pin, so save the odd pins
+ val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
+ p.setPMux(val | (GPIO_COM << sam.PORT_PMUX0_PMUXE_Pos))
+ }
+ // enable port config
+ p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
+ }
+}
+
+// getPMux returns the value for the correct PMUX register for this pin.
+func getPMux(p uint8) sam.RegValue8 {
+ pin := p >> 1
+ switch pin {
+ case 0:
+ return sam.PORT.PMUX0_0
+ case 1:
+ return sam.PORT.PMUX0_1
+ case 2:
+ return sam.PORT.PMUX0_2
+ case 3:
+ return sam.PORT.PMUX0_3
+ case 4:
+ return sam.PORT.PMUX0_4
+ case 5:
+ return sam.PORT.PMUX0_5
+ case 6:
+ return sam.PORT.PMUX0_6
+ case 7:
+ return sam.PORT.PMUX0_7
+ case 8:
+ return sam.PORT.PMUX0_8
+ case 9:
+ return sam.PORT.PMUX0_9
+ case 10:
+ return sam.PORT.PMUX0_10
+ case 11:
+ return sam.PORT.PMUX0_11
+ case 12:
+ return sam.PORT.PMUX0_12
+ case 13:
+ return sam.PORT.PMUX0_13
+ case 14:
+ return sam.PORT.PMUX0_14
+ case 15:
+ return sam.PORT.PMUX0_15
+ case 16:
+ return sam.RegValue8(sam.PORT.PMUX1_0>>0) & 0xff
+ case 17:
+ return sam.RegValue8(sam.PORT.PMUX1_0>>8) & 0xff
+ case 18:
+ return sam.RegValue8(sam.PORT.PMUX1_0>>16) & 0xff
+ case 19:
+ return sam.RegValue8(sam.PORT.PMUX1_0>>24) & 0xff
+ case 20:
+ return sam.RegValue8(sam.PORT.PMUX1_4>>0) & 0xff
+ case 21:
+ return sam.RegValue8(sam.PORT.PMUX1_4>>8) & 0xff
+ case 22:
+ return sam.RegValue8(sam.PORT.PMUX1_4>>16) & 0xff
+ case 23:
+ return sam.RegValue8(sam.PORT.PMUX1_4>>24) & 0xff
+ case 24:
+ return sam.RegValue8(sam.PORT.PMUX1_8>>0) & 0xff
+ case 25:
+ return sam.RegValue8(sam.PORT.PMUX1_8>>8) & 0xff
+ case 26:
+ return sam.RegValue8(sam.PORT.PMUX1_8>>16) & 0xff
+ case 27:
+ return sam.RegValue8(sam.PORT.PMUX1_8>>24) & 0xff
+ case 28:
+ return sam.RegValue8(sam.PORT.PMUX1_12>>0) & 0xff
+ case 29:
+ return sam.RegValue8(sam.PORT.PMUX1_12>>8) & 0xff
+ case 30:
+ return sam.RegValue8(sam.PORT.PMUX1_12>>16) & 0xff
+ case 31:
+ return sam.RegValue8(sam.PORT.PMUX1_12>>24) & 0xff
+ default:
+ return 0
+ }
+}
+
+// setPMux sets the value for the correct PMUX register for this pin.
+func setPMux(p uint8, val sam.RegValue8) {
+ pin := p >> 1
+ switch pin {
+ case 0:
+ sam.PORT.PMUX0_0 = val
+ case 1:
+ sam.PORT.PMUX0_1 = val
+ case 2:
+ sam.PORT.PMUX0_2 = val
+ case 3:
+ sam.PORT.PMUX0_3 = val
+ case 4:
+ sam.PORT.PMUX0_4 = val
+ case 5:
+ sam.PORT.PMUX0_5 = val
+ case 6:
+ sam.PORT.PMUX0_6 = val
+ case 7:
+ sam.PORT.PMUX0_7 = val
+ case 8:
+ sam.PORT.PMUX0_8 = val
+ case 9:
+ sam.PORT.PMUX0_9 = val
+ case 10:
+ sam.PORT.PMUX0_10 = val
+ case 11:
+ sam.PORT.PMUX0_11 = val
+ case 12:
+ sam.PORT.PMUX0_12 = val
+ case 13:
+ sam.PORT.PMUX0_13 = val
+ case 14:
+ sam.PORT.PMUX0_14 = val
+ case 15:
+ sam.PORT.PMUX0_15 = val
+ case 16:
+ sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 17:
+ sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 18:
+ sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 19:
+ sam.PORT.PMUX1_0 = (sam.PORT.PMUX1_0 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 20:
+ sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 21:
+ sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 22:
+ sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 23:
+ sam.PORT.PMUX1_4 = (sam.PORT.PMUX1_4 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 24:
+ sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 25:
+ sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 26:
+ sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 27:
+ sam.PORT.PMUX1_8 = (sam.PORT.PMUX1_8 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 28:
+ sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 29:
+ sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 30:
+ sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 31:
+ sam.PORT.PMUX1_12 = (sam.PORT.PMUX1_12 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ }
+}
+
+// getPinCfg returns the value for the correct PINCFG register for this pin.
+func getPinCfg(p uint8) sam.RegValue8 {
+ switch p {
+ case 0:
+ return sam.PORT.PINCFG0_0
+ case 1:
+ return sam.PORT.PINCFG0_1
+ case 2:
+ return sam.PORT.PINCFG0_2
+ case 3:
+ return sam.PORT.PINCFG0_3
+ case 4:
+ return sam.PORT.PINCFG0_4
+ case 5:
+ return sam.PORT.PINCFG0_5
+ case 6:
+ return sam.PORT.PINCFG0_6
+ case 7:
+ return sam.PORT.PINCFG0_7
+ case 8:
+ return sam.PORT.PINCFG0_8
+ case 9:
+ return sam.PORT.PINCFG0_9
+ case 10:
+ return sam.PORT.PINCFG0_10
+ case 11:
+ return sam.PORT.PINCFG0_11
+ case 12:
+ return sam.PORT.PINCFG0_12
+ case 13:
+ return sam.PORT.PINCFG0_13
+ case 14:
+ return sam.PORT.PINCFG0_14
+ case 15:
+ return sam.PORT.PINCFG0_15
+ case 16:
+ return sam.PORT.PINCFG0_16
+ case 17:
+ return sam.PORT.PINCFG0_17
+ case 18:
+ return sam.PORT.PINCFG0_18
+ case 19:
+ return sam.PORT.PINCFG0_19
+ case 20:
+ return sam.PORT.PINCFG0_20
+ case 21:
+ return sam.PORT.PINCFG0_21
+ case 22:
+ return sam.PORT.PINCFG0_22
+ case 23:
+ return sam.PORT.PINCFG0_23
+ case 24:
+ return sam.PORT.PINCFG0_24
+ case 25:
+ return sam.PORT.PINCFG0_25
+ case 26:
+ return sam.PORT.PINCFG0_26
+ case 27:
+ return sam.PORT.PINCFG0_27
+ case 28:
+ return sam.PORT.PINCFG0_28
+ case 29:
+ return sam.PORT.PINCFG0_29
+ case 30:
+ return sam.PORT.PINCFG0_30
+ case 31:
+ return sam.PORT.PINCFG0_31
+ case 32: // PB00
+ return sam.RegValue8(sam.PORT.PINCFG1_0>>0) & 0xff
+ case 33: // PB01
+ return sam.RegValue8(sam.PORT.PINCFG1_0>>8) & 0xff
+ case 34: // PB02
+ return sam.RegValue8(sam.PORT.PINCFG1_0>>16) & 0xff
+ case 35: // PB03
+ return sam.RegValue8(sam.PORT.PINCFG1_0>>24) & 0xff
+ case 37: // PB04
+ return sam.RegValue8(sam.PORT.PINCFG1_4>>0) & 0xff
+ case 38: // PB05
+ return sam.RegValue8(sam.PORT.PINCFG1_4>>8) & 0xff
+ case 39: // PB06
+ return sam.RegValue8(sam.PORT.PINCFG1_4>>16) & 0xff
+ case 40: // PB07
+ return sam.RegValue8(sam.PORT.PINCFG1_4>>24) & 0xff
+ case 41: // PB08
+ return sam.RegValue8(sam.PORT.PINCFG1_8>>0) & 0xff
+ case 42: // PB09
+ return sam.RegValue8(sam.PORT.PINCFG1_8>>8) & 0xff
+ case 43: // PB10
+ return sam.RegValue8(sam.PORT.PINCFG1_8>>16) & 0xff
+ case 44: // PB11
+ return sam.RegValue8(sam.PORT.PINCFG1_8>>24) & 0xff
+ case 45: // PB12
+ return sam.RegValue8(sam.PORT.PINCFG1_12>>0) & 0xff
+ case 46: // PB13
+ return sam.RegValue8(sam.PORT.PINCFG1_12>>8) & 0xff
+ case 47: // PB14
+ return sam.RegValue8(sam.PORT.PINCFG1_12>>16) & 0xff
+ case 48: // PB15
+ return sam.RegValue8(sam.PORT.PINCFG1_12>>24) & 0xff
+ case 49: // PB16
+ return sam.RegValue8(sam.PORT.PINCFG1_16>>0) & 0xff
+ case 50: // PB17
+ return sam.RegValue8(sam.PORT.PINCFG1_16>>8) & 0xff
+ case 51: // PB18
+ return sam.RegValue8(sam.PORT.PINCFG1_16>>16) & 0xff
+ case 52: // PB19
+ return sam.RegValue8(sam.PORT.PINCFG1_16>>24) & 0xff
+ case 53: // PB20
+ return sam.RegValue8(sam.PORT.PINCFG1_20>>0) & 0xff
+ case 54: // PB21
+ return sam.RegValue8(sam.PORT.PINCFG1_20>>8) & 0xff
+ case 55: // PB22
+ return sam.RegValue8(sam.PORT.PINCFG1_20>>16) & 0xff
+ case 56: // PB23
+ return sam.RegValue8(sam.PORT.PINCFG1_20>>24) & 0xff
+ case 57: // PB24
+ return sam.RegValue8(sam.PORT.PINCFG1_24>>0) & 0xff
+ case 58: // PB25
+ return sam.RegValue8(sam.PORT.PINCFG1_24>>8) & 0xff
+ case 59: // PB26
+ return sam.RegValue8(sam.PORT.PINCFG1_24>>16) & 0xff
+ case 60: // PB27
+ return sam.RegValue8(sam.PORT.PINCFG1_24>>24) & 0xff
+ case 61: // PB28
+ return sam.RegValue8(sam.PORT.PINCFG1_28>>0) & 0xff
+ case 62: // PB29
+ return sam.RegValue8(sam.PORT.PINCFG1_28>>8) & 0xff
+ case 63: // PB30
+ return sam.RegValue8(sam.PORT.PINCFG1_28>>16) & 0xff
+ case 64: // PB31
+ return sam.RegValue8(sam.PORT.PINCFG1_28>>24) & 0xff
+ default:
+ return 0
+ }
+}
+
+// setPinCfg sets the value for the correct PINCFG register for this pin.
+func setPinCfg(p uint8, val sam.RegValue8) {
+ switch p {
+ case 0:
+ sam.PORT.PINCFG0_0 = val
+ case 1:
+ sam.PORT.PINCFG0_1 = val
+ case 2:
+ sam.PORT.PINCFG0_2 = val
+ case 3:
+ sam.PORT.PINCFG0_3 = val
+ case 4:
+ sam.PORT.PINCFG0_4 = val
+ case 5:
+ sam.PORT.PINCFG0_5 = val
+ case 6:
+ sam.PORT.PINCFG0_6 = val
+ case 7:
+ sam.PORT.PINCFG0_7 = val
+ case 8:
+ sam.PORT.PINCFG0_8 = val
+ case 9:
+ sam.PORT.PINCFG0_9 = val
+ case 10:
+ sam.PORT.PINCFG0_10 = val
+ case 11:
+ sam.PORT.PINCFG0_11 = val
+ case 12:
+ sam.PORT.PINCFG0_12 = val
+ case 13:
+ sam.PORT.PINCFG0_13 = val
+ case 14:
+ sam.PORT.PINCFG0_14 = val
+ case 15:
+ sam.PORT.PINCFG0_15 = val
+ case 16:
+ sam.PORT.PINCFG0_16 = val
+ case 17:
+ sam.PORT.PINCFG0_17 = val
+ case 18:
+ sam.PORT.PINCFG0_18 = val
+ case 19:
+ sam.PORT.PINCFG0_19 = val
+ case 20:
+ sam.PORT.PINCFG0_20 = val
+ case 21:
+ sam.PORT.PINCFG0_21 = val
+ case 22:
+ sam.PORT.PINCFG0_22 = val
+ case 23:
+ sam.PORT.PINCFG0_23 = val
+ case 24:
+ sam.PORT.PINCFG0_24 = val
+ case 25:
+ sam.PORT.PINCFG0_25 = val
+ case 26:
+ sam.PORT.PINCFG0_26 = val
+ case 27:
+ sam.PORT.PINCFG0_27 = val
+ case 28:
+ sam.PORT.PINCFG0_28 = val
+ case 29:
+ sam.PORT.PINCFG0_29 = val
+ case 30:
+ sam.PORT.PINCFG0_30 = val
+ case 31:
+ sam.PORT.PINCFG0_31 = val
+ case 32: // PB00
+ sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 33: // PB01
+ sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 34: // PB02
+ sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 35: // PB03
+ sam.PORT.PINCFG1_0 = (sam.PORT.PINCFG1_0 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 36: // PB04
+ sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 37: // PB05
+ sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 38: // PB06
+ sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 39: // PB07
+ sam.PORT.PINCFG1_4 = (sam.PORT.PINCFG1_4 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 40: // PB08
+ sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 41: // PB09
+ sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 42: // PB10
+ sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 43: // PB11
+ sam.PORT.PINCFG1_8 = (sam.PORT.PINCFG1_8 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 44: // PB12
+ sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 45: // PB13
+ sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 46: // PB14
+ sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 47: // PB15
+ sam.PORT.PINCFG1_12 = (sam.PORT.PINCFG1_12 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 48: // PB16
+ sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 49: // PB17
+ sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 50: // PB18
+ sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 51: // PB19
+ sam.PORT.PINCFG1_16 = (sam.PORT.PINCFG1_16 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 52: // PB20
+ sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 53: // PB21
+ sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 54: // PB22
+ sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 55: // PB23
+ sam.PORT.PINCFG1_20 = (sam.PORT.PINCFG1_20 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 56: // PB24
+ sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 57: // PB25
+ sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 58: // PB26
+ sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 59: // PB27
+ sam.PORT.PINCFG1_24 = (sam.PORT.PINCFG1_24 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ case 60: // PB28
+ sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 0)) | (sam.RegValue(val) << 0)
+ case 61: // PB29
+ sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 8)) | (sam.RegValue(val) << 8)
+ case 62: // PB30
+ sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 16)) | (sam.RegValue(val) << 16)
+ case 63: // PB31
+ sam.PORT.PINCFG1_28 = (sam.PORT.PINCFG1_28 &^ (0xff << 24)) | (sam.RegValue(val) << 24)
+ }
+}
diff --git a/src/runtime/runtime_atsamd21.go b/src/runtime/runtime_atsamd21.go
index bbbccbe5..3abdc57e 100644
--- a/src/runtime/runtime_atsamd21.go
+++ b/src/runtime/runtime_atsamd21.go
@@ -293,59 +293,6 @@ func handleRTC() {
timerWakeup = true
}
-func initSERCOMClocks() {
- // Turn on clock to SERCOM0 for UART0
- sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM0_
-
- // Use GCLK0 for SERCOM0 aka UART0
- // GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
- // GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
- // GCLK_CLKCTRL_CLKEN ;
- sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM0_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
- (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
- sam.GCLK_CLKCTRL_CLKEN)
- waitForSync()
-
- // Turn on clock to SERCOM1
- sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM1_
- sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM1_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
- (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
- sam.GCLK_CLKCTRL_CLKEN)
- waitForSync()
-
- // Turn on clock to SERCOM2
- sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM2_
- sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM2_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
- (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
- sam.GCLK_CLKCTRL_CLKEN)
- waitForSync()
-
- // Turn on clock to SERCOM3
- sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM3_
- sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM3_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
- (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
- sam.GCLK_CLKCTRL_CLKEN)
- waitForSync()
-
- // Turn on clock to SERCOM4
- sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM4_
-
- // Use GCLK0 for SERCOM4
- sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM4_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
- (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
- sam.GCLK_CLKCTRL_CLKEN)
- waitForSync()
-
- // Turn on clock to SERCOM5
- sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM5_
-
- // Use GCLK0 for SERCOM5
- sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM5_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
- (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
- sam.GCLK_CLKCTRL_CLKEN)
- waitForSync()
-}
-
func initUSBClock() {
// Turn on clock for USB
sam.PM.APBBMASK |= sam.PM_APBBMASK_USB_
diff --git a/src/runtime/runtime_atsamd21e18.go b/src/runtime/runtime_atsamd21e18.go
new file mode 100644
index 00000000..b39da620
--- /dev/null
+++ b/src/runtime/runtime_atsamd21e18.go
@@ -0,0 +1,42 @@
+// +build sam,atsamd21,atsamd21e18
+
+package runtime
+
+import (
+ "device/sam"
+)
+
+func initSERCOMClocks() {
+ // Turn on clock to SERCOM0 for UART0
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM0_
+
+ // Use GCLK0 for SERCOM0 aka UART0
+ // GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
+ // GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+ // GCLK_CLKCTRL_CLKEN ;
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM0_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM1
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM1_
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM1_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM2
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM2_
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM2_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM3
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM3_
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM3_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+}
diff --git a/src/runtime/runtime_atsamd21g18.go b/src/runtime/runtime_atsamd21g18.go
new file mode 100644
index 00000000..22f22a5b
--- /dev/null
+++ b/src/runtime/runtime_atsamd21g18.go
@@ -0,0 +1,60 @@
+// +build sam,atsamd21,atsamd21g18
+
+package runtime
+
+import (
+ "device/sam"
+)
+
+func initSERCOMClocks() {
+ // Turn on clock to SERCOM0 for UART0
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM0_
+
+ // Use GCLK0 for SERCOM0 aka UART0
+ // GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
+ // GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+ // GCLK_CLKCTRL_CLKEN ;
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM0_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM1
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM1_
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM1_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM2
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM2_
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM2_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM3
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM3_
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM3_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM4
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM4_
+
+ // Use GCLK0 for SERCOM4
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM4_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+
+ // Turn on clock to SERCOM5
+ sam.PM.APBCMASK |= sam.PM_APBCMASK_SERCOM5_
+
+ // Use GCLK0 for SERCOM5
+ sam.GCLK.CLKCTRL = sam.RegValue16((sam.GCLK_CLKCTRL_ID_SERCOM5_CORE << sam.GCLK_CLKCTRL_ID_Pos) |
+ (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
+ sam.GCLK_CLKCTRL_CLKEN)
+ waitForSync()
+}
diff --git a/targets/atsamd21e18a.json b/targets/atsamd21e18a.json
new file mode 100644
index 00000000..eb504282
--- /dev/null
+++ b/targets/atsamd21e18a.json
@@ -0,0 +1,15 @@
+{
+ "inherits": ["cortex-m"],
+ "llvm-target": "armv6m-none-eabi",
+ "build-tags": ["atsamd21e18", "atsamd21", "sam"],
+ "cflags": [
+ "--target=armv6m-none-eabi",
+ "-Qunused-arguments"
+ ],
+ "ldflags": [
+ "-T", "targets/atsamd21.ld"
+ ],
+ "extra-files": [
+ "src/device/sam/atsamd21e18a.s"
+ ]
+}
diff --git a/targets/trinket-m0.json b/targets/trinket-m0.json
new file mode 100644
index 00000000..6028ee31
--- /dev/null
+++ b/targets/trinket-m0.json
@@ -0,0 +1,5 @@
+{
+ "inherits": ["atsamd21e18a"],
+ "build-tags": ["sam", "atsamd21e18a", "trinket_m0"],
+ "flash": "bossac -d -i -e -w -v -R --offset=0x2000 {hex}"
+}