Updates have slowed down, and there was a reason for this. After reports in the forums, it is possible for an upgrade to go bad, and a device to get bricked. There is no way for me to fix this in the field, so it's been a very scary problem as I have to replace the device. I can't post an update on the website which automatically updates you to the latest firmware if there is a chance it will break the device. That would be awful. I was forced to address this because I'm nearly out of stock so I'm producing more inventory. Since the bootloader is programmed during manufacturing, that meant I had to come up with a fix before manufacturing started. Time was running out as was inventory. Since my time is limited outside work, I had an absolutely awful month. 14 hour days, Work, Home, Baby, Flirc. From dusk till dawn, 5 hours of sleep, and spending every second I can coding. The result is a new bootloader.I will re-write my GUI so that old devices are not automatically updated. It is up to the user to go to the forums and do this themselves. Since there is only a percentage chance that the device will get bricked, I would rather give the user the option and have to replace the device, then decide to cancel updates for all previously shipped devices. Especially to all those who have been patiently waiting for new features. Stop now if you don't want to read technical jargon.The problem with my old bootloader was simply due to the fact that I started this project years ago, and that portion was done when I was a novice. I've grown leaps and bounds since then and at the time, had gotten something to work, and said, 'ship it'. In fact, most of it was glued together from shit I found on the internet. That was my first mistake, I didn't understand all of it. So I set out to re-write it. To help protect my intellectual property, I encrypt the firmware images. I do this because I don't want people stealing from me, especially after I'm trying to make a difference. The problem was with the encryption/decryption library I was using. It was junk. I remember at the time that the bootloader was extremely sensitive. Moving a variable, or declaring another would completely break it. Why? Who knew at the time, so once it worked I feared to ever touch it again.But re-visiting this, it was extremely clear within moments. I examined the elf, and found that my BSS size pretty close to the microcontroller's limit. So I started turning on optimizations and re-wrote the code to be a bit more efficient, but it was still happening. My stack was getting corrupt because I was running out of SRAM, which explains the breaking when adding/removing variables.So after I thought I had fixed that, I went to re-writing the way it works. Here is how it worked before. I would send down a page of the firmware, stick it in SRAM, and self program. A static variable was kept on the device which represented the current page. This auto-incemented. FAIL! That's a terrible idea, the device and host can get seriously out of sync, then who knows what page you are programming where.The next problem happened because the microcontroller I'm using doesn't support USB out of the box. This was a great idea at the time, a soft-stack approach helped save money on the hardware. However, this is no longer the case, but I'm stuck as moving now would cost me too much time and energy. So why is this a problem? That's because this particular soft-stack can't do CRC calculations on the incoming packets (this is supposed to be included in USB). What does that mean? Data can get corrupt from host to device. FAIL.Another problem, I had the option of forcing the device back into tho firmware from the bootloader, which anyone can do at anytime. FAIL.So I re-wrote my entire library. In doing so, my firmware was getting so complicated to handle the different versions of the device, I re-architected this from the ground up so it's no longer a problem.I found a new encryption library, re-wrote my bootloader, and version 2.0 was born. Here is how it works. The host puts together a packet. The packet looks like this:struct packet {
uint8_t buf[SPM_PAGESIZE];
uint16_t page_index;
uint8_t crc;
} __attribute__((packed));So right off the bat, you can see I addressed two problems. I send down the page to the device, and I also do my own CRC calculation. On the device, the crc is calculated on the received data, and if it's not equal to the received crc value, then an error is reported and a retry occurs. Coincidentally, since the page number is sent with the device, if there was an error, the device can never program the incorrect page. The host will never allow the device to enter the main firmware image unless the device has received an image successfully. I also read back the programmed page and verify that it was written correctly. I've implemented everything I can think of to ensure there are no problems.After everything was done, I don't have a single byte of room in my bootloader. It's mean, lean, and does the job.