Search › A-Z › A › Arduino Uno (AVR)
Arduino Uno (AVR)
Arduino Uno (AVR) is an Arduino Uno — the ATmega328P 8-bit AVR microcontroller board — running in the browser on avr8js, Wokwi's open-source AVR instruction-set simulator (pure TypeScript/JavaScript, MIT). A small public-domain sketch, hand-written in AVR assembly and compiled to a flash image, boots by default: it brings up USART0 and prints a greeting to an on-screen serial monitor, then walks a lit LED across PORTB while two on-screen buttons, wired to input pins, light the top LEDs. Because the CPU, SRAM and peripherals are ordinary JavaScript, the whole ATmega328P plugs into this site's shared debugger: a new AVR disassembler, live R0-R31 / SP / PC / SREG, side-effect-free flash and data memory, single-instruction step, execution breakpoints and write-watchpoints.
Runs on: Web browser
Arduino Uno (AVR) Online Emulator
Play Arduino Uno (AVR) using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Blink + Serial + LEDs | Arduino Uno (AVR) | Arduino Uno | open | Open ⛶ | |
| Blink (onboard LED) | Arduino Uno (AVR) | Arduino Uno | open | Open ⛶ |
Chips
Notes
Embedding
avr8js is Wokwi's AVR simulator, published as a TypeScript/JavaScript library. There is no bundler requirement to use it: bundle the published ESM once to a browser global (window.avr8js) with esbuild, then build the machine around the core yourself so the debugger can drive it. Nothing in the core is patched.
Boot. Decode the compiled sketch (a little-endian array of 16-bit flash words) into a Uint16Array, construct a CPU with 2 KB of SRAM (so SP resets to 0x08FF, the real ATmega328P RAMEND), attach the GPIO ports and USART, then run your own loop over avrInstruction(cpu) + cpu.tick():
var cpu = new avr8js.CPU(flashWords, 2048); // 32 regs + I/O + 2K SRAM
var portB = new avr8js.AVRIOPort(cpu, avr8js.portBConfig); // the 8 LEDs
var portD = new avr8js.AVRIOPort(cpu, avr8js.portDConfig); // the buttons
var usart = new avr8js.AVRUSART(cpu, avr8js.usart0Config, 16000000);
usart.onByteTransmit = function(b){ serial += String.fromCharCode(b); };
(function frame(){
for (var i = 0; i < BUDGET; i++) {
if (breakpoints.has(cpu.pc * 2)) break; // PC is a WORD index
avr8js.avrInstruction(cpu); // one AVR instruction
cpu.tick(); // service timers / USART clock events
}
requestAnimationFrame(frame);
})();
Everything is plain JavaScript state — no wasm heap. The whole machine is readable and writable live:
| Member | Kind | What it does |
|---|---|---|
avr8js.avrInstruction(cpu) | function | Execute exactly one AVR instruction, advancing cpu.pc and cpu.cycles. The single-step primitive. |
cpu.pc / cpu.cycles | field | Program counter (a word index into flash) and the cycle counter. |
cpu.data (Uint8Array) | field | The whole data space: R0-R31 at 0x00-0x1F, the I/O registers (PINB/DDRB/PORTB at 0x23-0x25, …), SP at 0x5D/0x5E, SREG at 0x5F, then SRAM. |
cpu.progBytes (Uint8Array) | field | Flash as bytes — read side-effect-free for the disassembly and hex views. |
cpu.writeData(a,v) | method | The single memory-write path used by ST/STS/STD/OUT/PUSH — wrap it to implement write-watchpoints. |
port.pinState(i) / port.setPin(i,hi) | method | Read a GPIO pin (drives the LEDs) / drive an input pin from an on-screen button. |
usart.onByteTransmit / usart.writeByte(b) | hook | Serial TX out (to the monitor) and serial RX in (from the keyboard). |
Because the CPU, memory and peripherals are ordinary JavaScript, the debugger single-steps with avrInstruction, reads and writes registers straight off cpu.data, and implements breakpoints and watchpoints as host-side checks around the loop — no changes to avr8js.
Debugger integration
The plug-in (arduino-debug.js) describes the ATmega328P to the shared debugger and nothing more:
- A new AVR decoder. There was no AVR disassembler, so
/debugger/src/cpus/avr.jswas written and registered as decoder'avr'. It decodes the 8-bit AVR set — the ALU ops, theLDI/CPI/SUBI/…immediates,MOV/MOVW, theLD/STforms with the X/Y/Z pointers (pre-dec / post-inc) andLDD/STD, the 2-wordLDS/STS/JMP/CALL,RJMP/RCALL/IJMP, the wholeBRxxbranch family,IN/OUT, the bit/skip ops (SBI/CBI/SBIC/SBIS/SBRC/SBRS/BST/BLD) and the SREG set/clear ops. Flash is addressed as bytes (AVR words are little-endian), so an instruction is 2 or 4 bytes; anything unrecognised decodes as.word. - Registers are read live each refresh: all of R0-R31, the pointer pairs X/Y/Z, SP, PC, and SREG broken out into its
I T H S V N Z Cflags. Every one has aset()that writes straight back intocpu.data. - Memory is exposed as three chips, all read side-effect-free: Flash (
cpu.progBytes, disassembled with the newavrdecoder), the Data space (registers + I/O registers + SRAM, straight offcpu.data), and the I/O registers alone as a focused window over0x20-0xFF. - Single step is one
avrInstruction(cpu). Breakpoints are host-side checks ofcpu.pc*2against a set of flash byte addresses. Write-watchpoints wrapcpu.writeDataand pause the loop the moment a watched data-space address (e.g.PORTBat0x25) is written.
Architecture
The Arduino Uno (2010) is the board that put the AVR microcontroller in front of a generation of makers. This build models its heart, the ATmega328P:
- AVR CPU — an 8-bit RISC core with 32 general registers (R0-R31), a 16-bit program counter, an 8-bit SREG, and a Harvard architecture (separate flash and SRAM). Run one instruction at a time by
avr8js. - 32 KB flash — where the compiled sketch lives (word-addressed). 2 KB SRAM above the register / I/O file; SP resets to
0x08FF. - GPIO ports B/C/D — the digital pins. PORTB carries the eight LEDs of this demo (PB5 is the Uno's onboard "L" LED); PORTD carries the two push-buttons.
- USART0 — the serial port that appears on the Uno as USB-serial; here it drives the on-screen serial monitor and accepts typed input.
The bundled program is a small public-domain demo sketch written in AVR assembly and assembled with avr8js's own assembler: it brings up USART0, prints a greeting, then walks a lit LED across PORTB while mirroring the two buttons onto the top LEDs. Because it is real AVR machine code, the whole thing single-steps in the debugger.