We write the OTA-loader for ATmega128RFA1 (as part of the Smart Response XE device)
It all started with the acquisition by the author in the secondary market of an interesting device - Smart Response XE ( short description ). It is intended for schools: each student in the class receives a device similar to an electronic notebook or translator of the nineties, the teacher asks a question, and the students type on the keyboards of the devices the answers received via the radio channel (802.15.4) to the receiver connected to the teacher’s PC.
Support for these devices was discontinued several years ago, and the fact that schools bought at $ 100-200 each, now pops up on eBay for 10 or less. Iron there is very suitable for geek experiments:
- 60-key keyboard
- display with a resolution of 384x136, 2 bits per pixel - similar to BK, CGA, but 4 are not colors, but gradations of brightness
- ATmega128RFA1 microcontroller (128 kB flash memory, 4 kB ROM, 16 kB RAM, 802.15.4 standard transceiver)
- external (with respect to the microcontroller, and not the entire device) flash memory of 1 megabyte (128 kilobytes) with SPI
- compartment for 4 AAA elements.
By the name of the microcontroller, it is clear that it belongs to the AVR family, which means that making the Arduino-compatible device is more than trivial ...
From the news on Hackaday, the author found out that they already did it (the same link says what to connect to) , having the opportunity to run games for Arduboy:
But the author is more interested in the opportunity not to play on the device, but to study:
- serial flash SPI
- downloaders for AVR
- standard 802.15.4
The author began by writing a library (GPL v3) that allows you to initialize the display, display text and rectangles, and also access flash memory with the SPI interface. Then he began to come up with ideas for the practical use of the device: a pocket-sized VT-100-compatible terminal, multi-player games. Having remade the three devices, he decided to “teach” them how to get sketches “through the air”. Which would be not only interesting, but also very convenient: it is difficult to open the device case each time, and under the battery cover there are only openings that allow you to connect a JTAG programmer to the board.
This is enough to fill the Arduino bootloader, but not a sketch - the serial port is not output there, you still can’t do without opening the case. Also, the TX0 and RX0 lines of the first serial port are aligned with the polling lines of the keyboard matrix, namely, those along which the function keys are polled to the sides of the display. But what to do - the author built this:
There he brought out the JTAG lines, and now it is not necessary to open the battery compartment. And in order to be able to fill in the sketches, I brought both serial ports to the same connector, adding also a switch, because when the batteries are installed, the device cannot be physically turned off differently.
It took quite a while to work with a soldering iron, a clerical knife and a glue gun. In general, “over the air” pouring sketches is much more convenient, it is urgent to invent something for this.
Arduino IDE uses avrdude to fill in sketches . It interacts with the microcontroller using the STK500 protocol., allowing you to transfer files in both directions. It is poorly compatible with channels where variable delays, distortion and data loss are possible. If something goes off or rustles in the serial channel, you can go crazy in search of a cause. Once the author tormented for half a day until he realized that the problem was in the bad cable, as well as the capricious interface converter CP2102. Even a microcontroller with a built-in interface converter, for example, ATmega32u4, can sometimes be so naughty. Each Arduino user has noticed that errors when uploading sketches are not so rare. Sometimes recording goes fine, and an error is detected during verification reading. This does not mean that there was an error while writing - the failure was while reading. Now imagine that when working "over the air" the same thing will happen, but much more often.
Having tried different ways to overcome this problem, the author came up with the following. The device has a 128-kilobyte flash memory with SPI interface - we receive data via wires (remember that the author already has one device with a connector on the side), we use this memory as a buffer, and send data to another device via a radio channel. Such a hello from Cybiko.
After writing the code for working with the radio channel, as well as the font, the bootloader became longer than 4 kilobytes. Therefore, the HFUSE value had to be changed from 0xDA to 0xD8. Now the bootloader can be up to 8 kilobytes long, and the starting address has become 0x1E000. This is reflected in the Makefile, but should be taken into account when filling the bootloader with avrdude.
The 802.15.4 standard transceiver in the ATmega128RFA1 was originally designed to operate on the protocolZigBee , which is rather complicated, so the author decided instead to just transfer packets. This is hardware implemented in the ATmega128RFA1, so a bit of code is required. Also, for simplicity, the author decided to use a fixed channel, preventing him from choosing it even manually. The 802.15.4 standard supports 16 channels with numbers from 11 to 26. They are quite clogged, some also overlap WiFi channels (red indicates ZigBee channels, blue, green and yellow - WiFi).
It turned out that channels 15 and 26 are the least susceptible to interference from WiFi. The author chose the second of them. Disclaimer: The translator does not know if ZigBee is so simplified. Maybe it’s worth a little more programming and its full implementation?
On the first of the devices, it is necessary to implement a state machine that transmits data using the STK500 protocol. For the most part, messages sent and received are self-sufficient, but some are tied to those that have passed through the channel earlier. A description of the dialogue is given here .
An important component of this dialogue is the transfer of packets intended for writing to the flash memory of the destination device. Simple microcontrollers of the AVR family have a page size of 128 bytes, but ATmega128RFA1 has a size of 256. And the flash memory that connects via the SPI protocol has the same size. The program in the first device when pouring the sketch does not immediately transfer it to the second, but writes it to this memory. When the Arduino IDE checks the correctness of the recording, they send it what was written there. Now you need to transfer the received data over the air to the second device. At the same time, switching from reception to transmission and vice versa occurs quite often. The STK500 protocol is indifferent to delays, but does not tolerate data loss (strange, but it is said above that delays in data transmission also affect). And losses in wireless transmission are inevitable. ATmega128RFA1 has a built-in hardware implementation of repeated requests with doubts about the correct transmission, but the author decided to implement the same programmatically on his own. He developed a protocol in which much more data passes in one direction than in the other.
It is imperfect, but everything works. A 256-byte page is divided into four segments, each of which is transmitted over the air as a packet. A packet holds up to 125 bytes of data plus one byte - length and two - CRC. So fragments 64 bytes long together with page and segment numbers (from 0 to 3) are placed there. In the receiving device, a variable is provided that allows you to track how many segments are received, and when all four are received, confirmation is sent to the sending device that the entire page has been received. No confirmation (CRC did not match) - send the whole page again. The speed at the same time turns out even more than when transmitting via cable. See:
But actually, it would be necessary to provide a convenient way to connect cable devices to the devices for filling in sketches and on it. For example, put inside such an interface converter on CP2102, as in the photo, and stick it to the board so that it can withstand the force when connecting and disconnecting the Micro USB cable.
It also has a 3.3-volt stabilizer (and how to use it in a device with 6-volt power supply - if only there is the same stabilizer, and you can add two diodes to automatically choose which one the device will be powered from). All three LEDs should be removed from the interface converter board, otherwise they will additionally load the batteries when working from them, and also interfere with the keyboard polling and work with flash memory with the SPI interface.
The pursuit of the goal turned out to be even more interesting than its achievement (and you don’t need that joke about the bus). The author learned a lot about bootloaders for AVR, flash memory with SPI, STK500 protocol and 802.15.4 standard.
All other code in addition to the library described above is here , and it is also under GPL v3. The author’s twitter is here .