
Tutto è iniziato con l'acquisto da parte dell'autore, sul mercato secondario, di un interessante dispositivo: Smart Response XE (). È destinato alle scuole: ogni alunno in classe riceve un dispositivo simile a un quaderno elettronico o a un traduttore degli anni '90, l'insegnante pone una domanda e gli alunni digitano le risposte sulle tastiere dei dispositivi, che vengono trasmesse via radio (802.15.4) a un ricevitore collegato al PC dell'insegnante.
Il supporto per questi dispositivi è cessato diversi anni fa, e quello che le scuole acquistavano a 100-200 dollari l'uno, ora riemerge su eBay a 10 o meno. L'hardware è davvero perfetto per esperimenti da geek:
- una tastiera con 60 tasti
- un display con risoluzione 384×136, 2 bit per pixel — simile a BK, CGA, ma 4 non colori, bensì gradazioni di luminosità
- microcontrollore ATmega128RFA1 (128 kB di memoria flash, 4 kB di EEPROM, 16 kB di RAM, trasmettitore/ricevitore standard 802.15.4)
- memoria flash esterna (rispetto al microcontrollore, non all'intero dispositivo) da 1 megabit (128 kilobyte) con interfaccia SPI
- scomparto per 4 elementi AAA.
Dal nome del microcontrollore è chiaro che appartiene alla famiglia AVR, quindi rendere il dispositivo compatibile con Arduino è un compito più che banale...
Dalla notizia su l'autore ha appreso che questo (allo stesso link è descritto come collegarlo), ottenendo la possibilità di lanciare giochi per Arduboy:

Ma l'autore è più interessato alla possibilità non di giocare con il dispositivo, ma di studiarlo:
- memoria flash con interfaccia seriale SPI
- loader per AVR
- standard 802.15.4
L'autore ha iniziato a scrivere (GPL v3), che consente di inizializzare il display, visualizzare testo e rettangoli, oltre a ottenere accesso alla memoria flash con interfaccia SPI. Poi ha iniziato a ideare idee per utilizzi pratici del dispositivo: un terminale portatile compatibile con VT-100, giochi multiplayer. Dopo aver modificato tre dispositivi, ha deciso di "insegnarli" a ricevere sketch "via etere". Sarebbe stato non solo interessante, ma anche molto conveniente: aprire il corpo del dispositivo ogni volta è difficile, e sotto il coperchio del vano batterie ci sono solo fori che permettono di collegare un programmatore JTAG alla scheda.

Questo è sufficiente per caricare il caricatore Arduino, ma non lo sketch: la porta seriale non è disponibile, e senza aprire il case non si può fare altrimenti. Inoltre, le linee TX0 e RX0 della prima porta seriale sono unite alle linee di interrogazione della matrice della tastiera, vale a dire, quelle che interrogano i tasti funzione sui lati del display. Ma cosa si può fare? L'autore ha realizzato quanto segue:

Ecco che ha portato le linee JTAG, quindi non è più necessario aprire il vano delle batterie. E per poter caricare anche gli sketch, ha collegato anche entrambe le porte seriali a questo connettore, aggiungendo un interruttore, perché con le batterie installate l'apparecchio non può essere spento fisicamente in altro modo.
È stato necessario lavorare a lungo con il saldatore, un cutter e una pistola per colla. In generale, caricare gli sketch 'via aria' è decisamente più comodo, bisogna inventare qualcosa d'urgenza per questo.
L'IDE Arduino per caricare gli sketch utilizza il programma . Questo interagisce con il microcontrollore tramite il protocollo , che consente di trasferire file in entrambe le direzioni. È mal compatibile con i canali dove sono possibili ritardi variabili, distorsioni e perdita di dati. Se nel canale seriale c'è qualche problema o rumore, si può perdere la testa alla ricerca della causa. Una volta l'autore ha passato mezza giornata a capire che era colpa di un cattivo cavo e di un capriccioso convertitore di interfaccia CP2102. Anche un microcontrollore con convertitore di interfaccia integrato, come l'ATmega32u4, a volte può comportarsi così. Ogni utente Arduino ha notato che gli errori durante il caricamento degli sketch non sono così rari. A volte la scrittura avviene correttamente, ma durante la lettura di controllo si riscontra un errore. Questo non significa che ci sia stato un errore durante la scrittura: il fallimento è avvenuto durante la lettura. E ora immaginate che durante il funzionamento 'via aria' possa succedere lo stesso, ma molto più spesso.
Dopo aver provato vari modi per superare questo problema, l'autore ha pensato a quanto segue. Il dispositivo ha una memoria flash da 128 kilobyte con interfaccia SPI: accetta i dati tramite cavi (ricordiamo che l'autore ha già un dispositivo con connettore laterale), utilizziamo questa memoria come buffer e inviamo i dati a un altro dispositivo attraverso il canale radio. Un saluto da Cybiko.
Dopo aver scritto il codice per lavorare con il canale radio, il bootloader è diventato più lungo di 4 kilobyte. Pertanto, il valore di HFUSE è stato cambiato da 0xDA a 0xD8. Ora il bootloader può avere una lunghezza fino a 8 kilobyte, e l'indirizzo iniziale è diventato 0x1E000. Questo è riflesso nel Makefile, ma deve essere considerato anche durante il caricamento. utilizzando avrdude.
Il trasmettitore e ricevitore standard 802.15.4 nell'ATmega128RFA1 è inizialmente progettato per lavorare con il protocollo , che è abbastanza complesso, quindi l'autore ha deciso di trasmettere semplicemente i pacchetti. Questo è implementato a livello hardware nell'ATmega128RFA1, quindi sarà necessario poco codice. Inoltre, per semplificare, l'autore ha deciso di utilizzare un canale fisso, senza permettere nemmeno la selezione manuale. Lo standard 802.15.4 supporta 16 canali con numeri da 11 a 26. Sono piuttosto congestionati, alcuni sovrappongono anche i canali WiFi (i canali ZigBee sono indicati in rosso, quelli WiFi in blu, verde e giallo).

Si è scoperto che i canali 15 e 26 sono i meno soggetti a interferenze da WiFi. L'autore ha scelto il secondo di essi. Dichiarazione: il traduttore non sa se sia permesso semplificare così lo ZigBee. Forse sarebbe meglio programmare ancora un po' e implementarlo completamente?
Sul primo dei dispositivi deve essere implementata una macchina a stati finiti che trasmette dati tramite il protocollo STK500. Nella maggior parte dei casi, i messaggi trasmessi e ricevuti sono autosufficienti, ma alcuni sono legati a quelli già passati attraverso il canale. La descrizione del dialogo è fornita .
Una componente importante di questo dialogo è la trasmissione di pacchetti destinati alla registrazione nella memoria flash del dispositivo di destinazione. Nei semplici microcontrollori della famiglia AVR, la dimensione della pagina è di 128 byte, ma nel caso dell'ATmega128RFA1 è di 256. Anche per quella memoria flash che si collega tramite il protocollo SPI, la dimensione è identica. Quando il programma nel primo dispositivo carica lo sketch, non lo invia direttamente al secondo, ma lo scrive in questa memoria. Quando l'Arduino IDE verifica la correttezza della registrazione, riceve ciò che è stato memorizzato. Ora è necessario trasferire i dati ottenuti attraverso il canale radio al secondo dispositivo. In questo processo, la commutazione dalla ricezione alla trasmissione e viceversa avviene abbastanza spesso. Il protocollo STK500 è indifferente ai ritardi, ma non tollera la perdita di dati (strano, ma sopra si è detto che anche i ritardi nella trasmissione dei dati hanno un impatto). Ma le perdite nella trasmissione wireless sono inevitabili. L'ATmega128RFA1 include un'implementazione hardware delle richieste ripetute in caso di dubbi sulla correttezza della trasmissione, ma l'autore ha deciso di implementare la stessa cosa a livello software. Ha sviluppato un protocollo in cui in una direzione passano molti più dati rispetto all'altra.
Non è perfetto, ma tutto funziona. La pagina di 256 byte è suddivisa in quattro segmenti, ciascuno dei quali viene trasmesso attraverso il canale radio come un pacchetto. Un pacchetto contiene fino a 125 byte di dati più un byte per la lunghezza e due per il CRC. Dunque, frammenti di 64 byte insieme ai numeri di pagina e di segmento (da 0 a 3) vengono inseriti lì. Nel dispositivo ricevente è prevista una variabile che tiene traccia di quanti segmenti sono stati ricevuti, e quando tutti e quattro arrivano, va al dispositivo trasmittente una conferma che l'intera pagina è stata ricevuta. Se non c'è conferma (il CRC non corrisponde), inviamo l'intera pagina di nuovo. La velocità risulta persino maggiore che durante la trasmissione via cavo. Vedi:

Ma in effetti, sarebbe opportuno prevedere un modo comodo per collegare un cavo ai dispositivi per caricare gli sketch anche tramite esso. Ad esempio, inserire un convertitore di interfaccia come il CP2102, come nell'immagine, e attaccarlo alla scheda in modo che resista alla pressione durante il collegamento e lo scollegamento del cavo Micro USB.

C'è anche un regolatore di tensione a 3,3 volt (e come utilizzarlo in un dispositivo alimentato a 6 volt — a meno che non ci sia lo stesso regolatore, e si possano aggiungere due diodi per scegliere automaticamente da quale di essi il dispositivo verrà alimentato). Dalla scheda del convertitore di interfaccia bisogna dissaldare i tre LED, altrimenti caricheranno ulteriormente le batterie quando si utilizza quell'alimentazione e interferiranno con la lettura della tastiera e il funzionamento della memoria flash con interfaccia SPI.
La caccia all'obiettivo si è rivelata addirittura più interessante del suo raggiungimento (e non serve quella barzelletta sull'autobus). L'autore ha appreso molte cose nuove sui bootloader per AVR, sulla memoria flash con interfaccia SPI, sul protocollo STK500 e sullo standard 802.15.4.
Tutto il resto del codice in aggiunta alla libreria descritta sopra — , ed è anch'esso sotto GPL v3. Il Twitter dell'autore — .
Fonte: habr.com
