The overview, with examples running, is on the board page and The Arduino Uno R4 Minima model (every register).

The Arduino Uno R4 Minima

The Uno everyone buys now: the same board, the same 5 V pins, an Arm Cortex-M4 underneath instead of an 8-bit AVR.

What it is

A Renesas RA4M1 at 48 MHz: an Arm Cortex-M4 with 256 KB of flash and 32 KB of SRAM, where an Uno R3 has an ATmega328P at 16 MHz with 32 KB and 2 KB. The board is 68.6 by 53.3 mm, the Uno outline to a tenth of a millimeter, so it takes an Uno shield and it does not go into a breadboard: wire it with jumpers from the headers. The reference page is The Arduino Uno R4 Minima model.

This is the Minima, the one with the USB-C socket and no WiFi. The Uno R4 WiFi is a second chip on the same outline and is not modeled here.

Serial is the USB

This is the first thing that surprises someone arriving from an Uno R3.

On an Uno a second chip turns USB into a UART, and Serial is the microcontroller's USART0 on pins 0 and 1. On an R4 there is no second chip: the USB device is on the RA4M1 itself. Serial is the socket, and Serial1 is the UART on pins 0 and 1, a port of its own.

So in the editor:

  • What you print to Serial appears in the serial monitor.
  • What you print to Serial1 also appears in the monitor (a board has one host channel here), and it comes out of pin 1 as bits as well, so a scope or a second board wired to that pin sees it.

The built-in Serial program prints to both, so the difference is on screen.

Mokxi models the USB as a byte pipe with the register names on it: enough for a serial port, and nothing above it. There is no enumeration, no descriptors and no host, so while (!Serial) {} returns at once here and pauses for a moment on a desk.

Pins

Twenty of them, counted the way the silkscreen does:

  • 0 to 13 along the digital header, with the built-in LED on 13.
  • A0 to A5 along the bottom, which are also digital pins 14 to 19.

The LED on 13 is active high: digitalWrite(LED_BUILTIN, HIGH) lights it, as on an Uno.

Six pins do hardware PWM with analogWrite, at 490 Hz: 3, 5, 6, 9, 10 and 11: the six with a tilde on the silkscreen, the same six as an Uno.

SDA and SCL beside AREF are A4 and A5, as on an Uno. One trace, two holes.

There is no INPUT_PULLDOWN on this chip. An RA4M1 pin has a pull-up and nothing else; asking for a pull-down gets a plain floating input, and the runtime says so rather than pretending.

The ADC is fourteen bits and analogRead gives you ten

The RA4M1's converter is fourteen bits, 0 to 16383. analogRead returns ten (0 to 1023) because that is what the Arduino core does and what every sketch written for an Uno expects: analogRead(A0) > 512 has to mean the same thing on both boards.

Call analogReadResolution(14) and you get all fourteen. The built-in Analog program prints both from the same pin, half a second apart, so the difference is visible.

Full scale is the 5 V rail, not 3.3, which is why a sensor written for an Uno moves across without a divider.

There is no attachInterrupt

On an RA4M1, which peripheral event reaches which interrupt is programmed in the ICU's event-link registers. The ICU is not modeled here, and its event numbers are not something this model can state honestly, so it was left out rather than invented. Nothing raises a peripheral interrupt; SysTick, which is a core exception and needs no link, is the whole interrupt story.

So a sketch polls. For a button (which is what most attachInterrupt sketches are), that is what most sketches do anyway, and the built-in Button program is written that way.

Floating point works, and it is soft float

The real RA4M1 has a single-precision FPU. The core this model runs on does not, so the runtime is built for soft float: float arithmetic gives the right answers and is done in integer instructions. A binary built elsewhere with a hard-float ABI faults on its first VFP instruction rather than returning a wrong number.

Stock Arduino libraries

A tutorial that includes Servo.h, Wire.h, SPI.h, EEPROM.h, LiquidCrystal_I2C.h, Adafruit_GFX.h with Adafruit_SSD1306.h and DHT.h compiles here as it stands. Each is Mokxi's own header under the upstream name, written on the drivers for the parts in the bin, and none of it is the upstream library's code.

  • Wire.begin() puts the I2C bus on A4 (SDA) and A5 (SCL).
  • EEPROM.h works, but the model does not have the RA4M1's data flash, so the bytes live in 4 KB of RAM: they read back within a Run and are gone at a reset.
  • Adafruit_NeoPixel.h stops with a message: a WS2812 bit is too short to make by hand on this board, and only the ESP32-C3 and ESP32-C6 drive the strip.

The code editor and compiling lists what each one covers and how it differs from the upstream library.

The firmware

Four built-in programs: Blink, Button, Serial and Analog.

An Uno sketch's source will usually build for the R4. An Uno's compiled ELF will not run on it: different architecture, different register map, different vector table. Build it for the R4 and it runs.

What is accurate, and what is not

Some of this model's addresses are quoted from the RA4M1 user's manual and some are the model's own belief. That distinction is written down rather than glossed over: section 7 of the contract lists, one by one, which numbers are which.

And what is approximated, as opposed to unverified. The core runs at 48 MHz whatever the clock registers are programmed to, because the clock tree is not modeled. ADC14 has no error in it: no sample-and-hold, no nonlinearity, no noise and no offset. The pads are three states and a threshold, with no hysteresis and no drive-strength setting. The 5 V rail is an ideal source that cannot sag. And Serial's pipe never fills, so a sketch that would back up against a USB frame boundary on a desk never waits here.

In short: the core, the clock, the memory map, the port and PFS registers, SCI and the pin map are the manual's. The GPT base address and its register offsets, the ADC14 offsets, the USB registers, A4 and A5's converter channels, and which GPT channel each PWM pin is, are believed and marked unverified. The clock and millis are checked by a test that runs the shipped firmware (crates/unor4/tests/runtime.rs), not merely claimed.

What is not modeled

A USB stack above the byte pipe. The ICU, and so every peripheral interrupt. The AGT, the clock generation circuit, the watchdogs, I2C, SPI, CAN, the DTC, the RTC, the DAC, the comparators and the touch unit. Vendor binaries (the Renesas FSP and the Arduino R4 core) do not run here; the firmware runtime is ours. Shields are not physical parts here; wire the same circuit on the breadboard.