SearchA-ZA › Arduino Uno (AVR)

Arduino Uno (AVR)

2010 Open source · MIT PD sketch · open Online

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.

Visit avr8js on GitHub ↗

Visit the official site ↗

Runs on: Web browser

Arduino Uno (AVR) Online Emulator

Play Arduino Uno (AVR) using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Blink + Serial + LEDsArduino Uno (AVR)Arduino UnoopenOpen ⛶
Blink (onboard LED)Arduino Uno (AVR)Arduino UnoopenOpen ⛶

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:

MemberKindWhat it does
avr8js.avrInstruction(cpu)functionExecute exactly one AVR instruction, advancing cpu.pc and cpu.cycles. The single-step primitive.
cpu.pc / cpu.cyclesfieldProgram counter (a word index into flash) and the cycle counter.
cpu.data (Uint8Array)fieldThe 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)fieldFlash as bytes — read side-effect-free for the disassembly and hex views.
cpu.writeData(a,v)methodThe single memory-write path used by ST/STS/STD/OUT/PUSH — wrap it to implement write-watchpoints.
port.pinState(i) / port.setPin(i,hi)methodRead a GPIO pin (drives the LEDs) / drive an input pin from an on-screen button.
usart.onByteTransmit / usart.writeByte(b)hookSerial 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.js was written and registered as decoder 'avr'. It decodes the 8-bit AVR set — the ALU ops, the LDI/CPI/SUBI/… immediates, MOV/MOVW, the LD/ST forms with the X/Y/Z pointers (pre-dec / post-inc) and LDD/STD, the 2-word LDS/STS/JMP/CALL, RJMP/RCALL/IJMP, the whole BRxx branch 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 C flags. Every one has a set() that writes straight back into cpu.data.
  • Memory is exposed as three chips, all read side-effect-free: Flash (cpu.progBytes, disassembled with the new avr decoder), the Data space (registers + I/O registers + SRAM, straight off cpu.data), and the I/O registers alone as a focused window over 0x20-0xFF.
  • Single step is one avrInstruction(cpu). Breakpoints are host-side checks of cpu.pc*2 against a set of flash byte addresses. Write-watchpoints wrap cpu.writeData and pause the loop the moment a watched data-space address (e.g. PORTB at 0x25) 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.