In engineering education there is an ever-present problem with technology-anchored pedagogy: when do you switch from current technology to the next one? Right now, the cool kid on the block in the RISC-V architecture. Will it be the next ARM or will it be the next PowerPC or MIPS? It's hard to tell. However, a collegial choice has been made in our department to adopt it in our undergraduate curriculum, so RISC-V it is.
We're now using RISC-V as the target of choice in our Computer Organization course, EECS 2021. Unfortunately, low stock issues have hit our ESP32-C3 development board and so alternatives need to be found. I'm going to explore the RISC-V RP2350 from the folks at Raspberry Pi as chip supply, in December 2025, appears to be good and multiple manufacturers have inexpensive development boards. (e.g. the OG Nano 2, and also Adafruit, Seeed, Waveshare, DFRobot, Sparkfun, etc.), from international distributors like DIgikey and Mouser to Canadian ones like PiShop and RobotShop)


RP2350 boards are supported, through extensions, in the Arduino 2.0 IDE. This provides a boot loader-based toolchain with C++ as the main development language while also supporting Assembler, both in-line and as add-on files.
The RP2350 is a unique device, with both ARM Cortex and RISC-V processors on board. The Arduino IDE supports switching between them from a drop-down menu in the IDE.
- Seeed Studio Xiao-RP2350: works in Arduino 2.0 IDE
It's possible to do in-line assembler and to have the processor send serial data back to the Arduino's Serial Monitor.
It's also possible to write a C++ program in the Arduino IDE and call an assembler file. Here,
// riscv_with_asm.ino
extern "C" void test(void); // permits calling the assembler function, test in test.S.
void setup() {
// set up LED and make it blink...
test(); // call the assembler function (blinking LED)
}
void loop() {
/* this never runs...*/
delay(1000);
}
and here I've blatantly copied the main.s file from the bare-metal-rp2350 GitHub project by Igor Michalak and renamed the file and function to test.S, as follows:
# test.S
####################
### Simple Blink ###
####################
# by Igor Michalak @ https://github.com/igormichalak/bare-metal-rp2350/blob/master/main.s
.section .text
.equ ATOMIC_XOR, 0x1000
.equ ATOMIC_SET, 0x2000
.equ ATOMIC_CLEAR, 0x3000
.equ RESETS_BASE, 0x40020000
.equ RESETS_RESET, RESETS_BASE+0x0
.equ RESETS_RESET_DONE, RESETS_BASE+0x8
.equ IO_BANK0_BASE, 0x40028000
.equ IO_BANK0_GPIO25_CTRL, IO_BANK0_BASE+0x0cc
.equ PADS_BANK0_BASE, 0x40038000
.equ PADS_BANK0_GPIO25, PADS_BANK0_BASE+0x68
.equ SIO_BASE, 0xd0000000
.equ SIO_GPIO_OE_SET, SIO_BASE+0x038
.equ SIO_GPIO_OUT_SET, SIO_BASE+0x018
.equ SIO_GPIO_OUT_CLR, SIO_BASE+0x020
.equ TIMER0_BASE, 0x400b0000
.equ TIMER0_TIMEHR, TIMER0_BASE+0x08
.equ TIMER0_TIMELR, TIMER0_BASE+0x0c
.equ TIMER0_TIMERAWH, TIMER0_BASE+0x24
.equ TIMER0_TIMERAWL, TIMER0_BASE+0x28
.global test
test:
li t0, (1<<6)|(1<<9)
li t1, RESETS_RESET+ATOMIC_CLEAR
sw t0, (t1)
li t1, RESETS_RESET_DONE
1:
lw t2, (t1)
and t2, t2, t0
bne t2, t0, 1b
li t0, 0x1f
li t1, IO_BANK0_GPIO25_CTRL+ATOMIC_CLEAR
sw t0, (t1)
li t0, 0x05
li t1, IO_BANK0_GPIO25_CTRL+ATOMIC_SET
sw t0, (t1)
li t0, (1<<25)
li t1, SIO_GPIO_OE_SET
sw t0, (t1)
li t0, (1<<7)|(1<<8)
li t1, PADS_BANK0_GPIO25+ATOMIC_CLEAR
sw t0, (t1)
li t0, (1<<25)
li t1, SIO_GPIO_OUT_SET
li t2, SIO_GPIO_OUT_CLR
loop:
sw t0, (t1)
li a0, 100
call wait_ms
sw t0, (t2)
li a0, 100
call wait_ms
j loop
# Don't use with durations longer than 1 hour.
wait_ms:
mv a2, a0
li a0, TIMER0_TIMELR
li a1, TIMER0_TIMEHR
lw a0, (a0)
lw a1, (a1)
li a3, 1000
mul a2, a2, a3
add a0, a0, a2
sltu a3, a0, a2
add a1, a1, a3
li a2, TIMER0_TIMERAWL
li a3, TIMER0_TIMERAWH
1:
lw a5, (a3)
blt a5, a1, 1b
2:
lw a5, (a3)
bne a5, a1, 3f
lw a4, (a2)
blt a4, a0, 2b
3:
ret
This is just a proof of concept. I'd like to go further and incorporate this as inline Assembler in the .ino file, for instance. More later...


James Andrew Smith is a Professional Engineer and Associate Professor in the Electrical Engineering and Computer Science Department of York University’s Lassonde School, with degrees in Electrical and Mechanical Engineering from the University of Alberta and McGill University. Previously a program director in biomedical engineering, his research background spans robotics, locomotion, human birth, music and engineering education. While on sabbatical in 2018-19 with his wife and kids he lived in Strasbourg, France and he taught at the INSA Strasbourg and Hochschule Karlsruhe and wrote about his personal and professional perspectives. James is a proponent of using social media to advocate for justice, equity, diversity and inclusion as well as evidence-based applications of research in the public sphere. You can find him on Twitter. You can find him on BlueSky. Originally from Québec City, he now lives in Toronto, Canada.
