Tutorial: Programmare Atmega328 con Assembler e Web Serial API

Questa pagina spiega il funzionamento di uno strumento didattico scritto in HTML e JavaScript per programmare il microcontrollore Atmega328 (ad esempio quello di Arduino Uno) usando il linguaggio assembler e la Web Serial API.

1. Interfaccia utente

La pagina presenta una textarea per inserire istruzioni assembler, due bottoni (per compilare e flashare il microcontrollore e per tradurre la pagina) e un'area di log per mostrare messaggi e stati.

<textarea id="input">sbi 4,5
sbi 5,5</textarea>
<button id="compileBtn">Compila e Flash</button>
<pre id="log"></pre>
  

2. Conversione da assembler a opcode

Il microcontrollore interpreta le istruzioni assembler come codici macchina (opcode) a 16 bit. Il codice fa così:

const opcodeMap = {
  sbi: 0x9A00,
  cbi: 0x9800,
};
  

3. Preparazione del buffer da flashare

Il microcontrollore viene programmato scrivendo pagine di memoria flash di 128 byte (64 istruzioni da 2 byte ciascuna). Il codice crea un buffer Uint8Array di 128 byte in cui inserisce le istruzioni codificate.

function createFlashPageMultiple(instructions) {
  const buffer = new Uint8Array(128);
  for (let i = 0; i < instructions.length && i < 64; i++) {
    buffer[i * 2] = instructions[i] & 0xFF;
    buffer[i * 2 + 1] = (instructions[i] >> 8) & 0xFF;
  }
  return buffer;
}
  

4. Comunicazione con Atmega328 via Web Serial e protocollo STK500

La comunicazione con il microcontrollore avviene usando la Web Serial API del browser e il protocollo di programmazione STK500.

async function flashPage(port, buffer) {
  const writer = port.writable.getWriter();
  const reader = port.readable.getReader();

  await sleep(1500); // attesa reset

  for (let i = 0; i < 3; i++) {
    await writer.write(Uint8Array.from([0x30, 0x20]));
    await reader.read();
  }

  await writer.write(Uint8Array.from([0x50, 0x20]));
  await reader.read();

  await writer.write(Uint8Array.from([0x55, 0x80, 0x00, 0x20]));
  await reader.read();

  await writer.write(Uint8Array.from([0x64, 0x00, 0x80, 0x46]));
  await writer.write(buffer);
  await writer.write(Uint8Array.of(0x20));
  await reader.read();

  await writer.write(Uint8Array.from([0x51, 0x20]));
  await reader.read();

  writer.releaseLock();
  reader.releaseLock();
}
  

5. Come usare il bottone "Compila e Flash"

Quando premi il bottone:

  1. Il testo assembler viene convertito in opcode.
  2. Si crea il buffer da inviare.
  3. Il browser chiede di scegliere la porta seriale (es. USB di Arduino).
  4. Si apre la porta e si inviano i comandi per flashare la memoria.
  5. Al termine si chiude la porta.
  6. I messaggi di stato e di errore sono mostrati nella finestra di log.

6. Considerazioni finali

Questo strumento è un esempio semplice e didattico per capire:

Puoi usare e modificare questo codice per imparare e sperimentare la programmazione embedded da browser, senza tool esterni.