Skip to content

Commit 562b4c5

Browse files
authored
Create "pico2-ice" target board (#5062)
* Create "pico2-ice" target board This board has an rp2350b chip on it, as well as a Lattice Semiconductor iCE40UP5K FPGA. More details of this open hardware board here: https://pico2-ice.tinyvision.ai/ Tested on a pico2-ice board with: ~/go/bin/tinygo flash -target=pico2-ice src/examples/blinky1/blinky1.go which blinks the GREEN LED (connected to GPIO0) on this board. Signed-off-by: Tinkerer <tinkerer@zappem.net> * More silkscreen labels for pico2-ice board Reading the schematic and the rev2 board viewer: https://raw.githubusercontent.com/tinyvision-ai-inc/pico2-ice/refs/heads/main/Board/Rev2/bom/ibom.html concluded that the RP2350B GPIO pins are not labeled with these pin numbers in the silkscreen. Instead, the silkscreen refers to uses of the GPIOs or the ICE numbered pins. RP2340B devoted pins map to the A1..4 B1..4 pins on the RP PMOD connector. Also silkscreen "~0".."~6" are labeled as pins N0..N6. Signed-off-by: Tinkerer <tinkerer@zappem.net> * Added a smoketest for pico2-ice board and tidied up GPIO defs Addresses review comments from aykevl. Signed-off-by: Tinkerer <tinkerer@zappem.net>
1 parent 7460734 commit 562b4c5

File tree

7 files changed

+267
-20
lines changed

7 files changed

+267
-20
lines changed

GNUmakefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,8 @@ smoketest: testchdir
621621
@$(MD5SUM) test.hex
622622
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/device-id
623623
@$(MD5SUM) test.hex
624+
$(TINYGO) build -size short -o test.hex -target=pico2-ice examples/blinky1
625+
@$(MD5SUM) test.hex
624626
# test simulated boards on play.tinygo.org
625627
ifneq ($(WASM), 0)
626628
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1

src/machine/board_pico2_ice.go

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//go:build pico2_ice
2+
3+
// Most of the info is from
4+
// https://pico2-ice.tinyvision.ai/md_pinout.html although
5+
// (2025-09-07) RP4 appears twice in that pinout - the schematic is
6+
// more clear. Consistent with other RPi boards, we use GPn instead of
7+
// RPn to reference the RPi connected pins.
8+
9+
package machine
10+
11+
// GPIO pins
12+
const (
13+
GP0 = GPIO0
14+
GP1 = GPIO1
15+
GP2 = GPIO2
16+
GP3 = GPIO3
17+
GP4 = GPIO4
18+
GP5 = GPIO5
19+
GP6 = GPIO6
20+
GP7 = GPIO7
21+
GP8 = GPIO8
22+
GP9 = GPIO9
23+
GP10 = GPIO10
24+
GP11 = GPIO11
25+
GP12 = GPIO12
26+
GP13 = GPIO13
27+
GP14 = GPIO14
28+
GP15 = GPIO15
29+
GP16 = GPIO16
30+
GP17 = GPIO17
31+
GP18 = GPIO18
32+
GP19 = GPIO19
33+
GP20 = GPIO20
34+
GP21 = GPIO21
35+
GP22 = GPIO22
36+
GP23 = GPIO23
37+
GP24 = GPIO24
38+
GP25 = GPIO25
39+
GP26 = GPIO26
40+
GP27 = GPIO27
41+
GP28 = GPIO28
42+
GP29 = GPIO29
43+
GP30 = GPIO30
44+
GP31 = GPIO31
45+
GP32 = GPIO32
46+
GP33 = GPIO33
47+
GP34 = GPIO34
48+
GP35 = GPIO35
49+
GP36 = GPIO36
50+
GP37 = GPIO37
51+
GP38 = GPIO38
52+
GP39 = GPIO39
53+
GP40 = GPIO40
54+
GP41 = GPIO41
55+
GP42 = GPIO42
56+
GP43 = GPIO43
57+
GP44 = GPIO44
58+
GP45 = GPIO45
59+
GP46 = GPIO46
60+
GP47 = GPIO47
61+
62+
// RPi pins shared with ICE. The ICE number is what appears on
63+
// the board silkscreen.
64+
ICE9 = GP28
65+
ICE11 = GP29
66+
ICE14 = GP7
67+
ICE15 = GP6
68+
ICE16 = GP5
69+
ICE17 = GP4
70+
ICE18 = GP27
71+
ICE19 = GP23
72+
ICE20 = GP22
73+
ICE21 = GP26
74+
ICE23 = GP25
75+
ICE25 = GP30
76+
ICE26 = GP24
77+
ICE27 = GP20
78+
79+
// FPGA Clock pin.
80+
ICE35_G0 = GP21
81+
82+
// Silkscreen & Pinout names
83+
ICE_SSN = ICE16
84+
ICE_SO = ICE14
85+
ICE_SI = ICE17
86+
ICE_CK = ICE15
87+
SD = GP2
88+
SC = GP3
89+
90+
FPGA_RSTN = GP31
91+
A3 = GP32
92+
A1 = GP33
93+
A4 = GP34
94+
A2 = GP35
95+
B3 = GP36
96+
B1 = GP37
97+
B4 = GP38
98+
B2 = GP39
99+
N0 = GP40 // On the board these are labeled "~0"
100+
N1 = GP41
101+
N2 = GP42
102+
N3 = GP43
103+
N4 = GP44
104+
N5 = GP45
105+
N6 = GP46
106+
107+
// Functions from Schematic.
108+
ICE_DONE = GP40
109+
USB_BOOT = GP42
110+
111+
// Button
112+
SW1 = GP42
113+
BOOTSEL = GP42
114+
115+
// Tricolor LEDs
116+
LED_RED = GP1
117+
LED_GREEN = GP0
118+
LED_BLUE = GP9
119+
120+
// Onboard LED
121+
LED = LED_GREEN
122+
123+
// Onboard crystal oscillator frequency, in MHz.
124+
xoscFreq = 12 // MHz
125+
)
126+
127+
// This board does not define default i2c pins.
128+
const (
129+
I2C0_SDA_PIN = NoPin
130+
I2C0_SCL_PIN = NoPin
131+
I2C1_SDA_PIN = NoPin
132+
I2C1_SCL_PIN = NoPin
133+
)
134+
135+
// SPI default pins
136+
const (
137+
// Default Serial Clock Bus 0 for SPI communications
138+
SPI0_SCK_PIN = GPIO18
139+
// Default Serial Out Bus 0 for SPI communications
140+
SPI0_SDO_PIN = GPIO19 // Tx
141+
// Default Serial In Bus 0 for SPI communications
142+
SPI0_SDI_PIN = GPIO16 // Rx
143+
144+
// Default Serial Clock Bus 1 for SPI communications
145+
SPI1_SCK_PIN = GPIO10
146+
// Default Serial Out Bus 1 for SPI communications
147+
SPI1_SDO_PIN = GPIO11 // Tx
148+
// Default Serial In Bus 1 for SPI communications
149+
SPI1_SDI_PIN = GPIO12 // Rx
150+
)
151+
152+
// UART pins
153+
const (
154+
UART0_TX_PIN = GPIO0
155+
UART0_RX_PIN = GPIO1
156+
UART1_TX_PIN = GPIO8
157+
UART1_RX_PIN = GPIO9
158+
UART_TX_PIN = UART0_TX_PIN
159+
UART_RX_PIN = UART0_RX_PIN
160+
)
161+
162+
var DefaultUART = UART0
163+
164+
// USB identifiers
165+
const (
166+
usb_STRING_PRODUCT = "Pico2"
167+
usb_STRING_MANUFACTURER = "Raspberry Pi"
168+
)
169+
170+
var (
171+
usb_VID uint16 = 0x2E8A
172+
usb_PID uint16 = 0x000A
173+
)

src/machine/machine_rp2_2040.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,31 @@ const (
124124
fnXIP pinFunc = 0
125125
)
126126

127+
// validPins confirms that the SPI pin selection is a legitimate one
128+
// for the the 2040 chip.
129+
func (spi *SPI) validPins(config SPIConfig) error {
130+
var okSDI, okSDO, okSCK bool
131+
switch spi.Bus {
132+
case rp.SPI0:
133+
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20
134+
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23
135+
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22
136+
case rp.SPI1:
137+
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28
138+
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27
139+
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26
140+
}
141+
switch {
142+
case !okSDI:
143+
return errSPIInvalidSDI
144+
case !okSDO:
145+
return errSPIInvalidSDO
146+
case !okSCK:
147+
return errSPIInvalidSCK
148+
}
149+
return nil
150+
}
151+
127152
// Configure configures the gpio pin as per mode.
128153
func (p Pin) Configure(config PinConfig) {
129154
if p == NoPin {

src/machine/machine_rp2_2350a.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
package machine
44

5+
import "device/rp"
6+
57
// Analog pins on RP2350a.
68
const (
79
ADC0 Pin = GPIO26
@@ -12,3 +14,28 @@ const (
1214
// fifth ADC channel.
1315
thermADC = 30
1416
)
17+
18+
// validPins confirms that the SPI pin selection is a legitimate one
19+
// for the the 2350a chip.
20+
func (spi *SPI) validPins(config SPIConfig) error {
21+
var okSDI, okSDO, okSCK bool
22+
switch spi.Bus {
23+
case rp.SPI0:
24+
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20
25+
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23
26+
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22
27+
case rp.SPI1:
28+
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28
29+
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27
30+
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26
31+
}
32+
switch {
33+
case !okSDI:
34+
return errSPIInvalidSDI
35+
case !okSDO:
36+
return errSPIInvalidSDO
37+
case !okSCK:
38+
return errSPIInvalidSCK
39+
}
40+
return nil
41+
}

src/machine/machine_rp2_2350b.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
package machine
44

5+
import "device/rp"
6+
57
// RP2350B has additional pins.
68

79
const (
@@ -46,3 +48,28 @@ var (
4648
PWM10 = getPWMGroup(10)
4749
PWM11 = getPWMGroup(11)
4850
)
51+
52+
// validPins confirms that the SPI pin selection is a legitimate one
53+
// for the the 2350b chip.
54+
func (spi *SPI) validPins(config SPIConfig) error {
55+
var okSDI, okSDO, okSCK bool
56+
switch spi.Bus {
57+
case rp.SPI0:
58+
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20 || config.SDI == 32 || config.SDI == 36
59+
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23 || config.SDO == 35 || config.SDO == 39
60+
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22 || config.SCK == 34 || config.SCK == 38
61+
case rp.SPI1:
62+
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28 || config.SDI == 40 || config.SDI == 44
63+
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27 || config.SDO == 31 || config.SDO == 43 || config.SDO == 47
64+
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26 || config.SCK == 30 || config.SCK == 42 || config.SCK == 46
65+
}
66+
switch {
67+
case !okSDI:
68+
return errSPIInvalidSDI
69+
case !okSDO:
70+
return errSPIInvalidSDO
71+
case !okSCK:
72+
return errSPIInvalidSCK
73+
}
74+
return nil
75+
}

src/machine/machine_rp2_spi.go

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -165,27 +165,9 @@ func (spi *SPI) Configure(config SPIConfig) error {
165165
config.SDI = SPI1_SDI_PIN
166166
}
167167
}
168-
var okSDI, okSDO, okSCK bool
169-
switch spi.Bus {
170-
case rp.SPI0:
171-
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20
172-
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23
173-
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22
174-
case rp.SPI1:
175-
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28
176-
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27
177-
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26
168+
if err := spi.validPins(config); err != nil {
169+
return err
178170
}
179-
180-
switch {
181-
case !okSDI:
182-
return errSPIInvalidSDI
183-
case !okSDO:
184-
return errSPIInvalidSDO
185-
case !okSCK:
186-
return errSPIInvalidSCK
187-
}
188-
189171
if config.Frequency == 0 {
190172
config.Frequency = defaultBaud
191173
}

targets/pico2-ice.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"inherits": [
3+
"rp2350b"
4+
],
5+
"build-tags": ["pico2_ice"],
6+
"serial-port": ["2e8a:000A"],
7+
"default-stack-size": 8192,
8+
"ldflags": [
9+
"--defsym=__flash_size=4M"
10+
]
11+
}

0 commit comments

Comments
 (0)