123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- #include <AP_HAL/AP_HAL.h>
- #if HAL_WITH_IO_MCU
- #include "AP_IOMCU.h"
- #include <AP_ROMFS/AP_ROMFS.h>
- #include <AP_Math/crc.h>
- #define debug(fmt, args ...) do { hal.console->printf("IOMCU: " fmt "\n", ## args); } while(0)
- extern const AP_HAL::HAL &hal;
- bool AP_IOMCU::upload_fw(void)
- {
-
- uart.begin(115200, 256, 256);
- bool ret = false;
-
- for (uint8_t i = 0; i < 15; i++) {
- ret = sync();
- if (ret) {
- break;
- }
- hal.scheduler->delay(10);
- }
- if (!ret) {
- debug("IO update failed sync");
- return false;
- }
- uint32_t bl_rev;
- ret = get_info(INFO_BL_REV, bl_rev);
- if (!ret) {
- debug("Err: failed to contact bootloader");
- return false;
- }
- if (bl_rev > BL_REV) {
- debug("Err: unsupported bootloader revision %u", unsigned(bl_rev));
- return false;
- }
- debug("found bootloader revision: %u", unsigned(bl_rev));
- ret = erase();
- if (!ret) {
- debug("erase failed");
- return false;
- }
- ret = program(fw_size);
- if (!ret) {
- debug("program failed");
- return false;
- }
- if (bl_rev <= 2) {
- ret = verify_rev2(fw_size);
- } else {
- ret = verify_rev3(fw_size);
- }
- if (!ret) {
- debug("verify failed");
- return false;
- }
- ret = reboot();
- if (!ret) {
- debug("reboot failed");
- return false;
- }
- debug("update complete");
-
- hal.scheduler->delay(100);
- return true;
- }
- bool AP_IOMCU::recv_byte_with_timeout(uint8_t *c, uint32_t timeout_ms)
- {
- uint32_t start = AP_HAL::millis();
- do {
- int16_t v = uart.read();
- if (v >= 0) {
- *c = uint8_t(v);
- return true;
- }
- hal.scheduler->delay_microseconds(50);
- } while (AP_HAL::millis() - start < timeout_ms);
- return false;
- }
- bool AP_IOMCU::recv_bytes(uint8_t *p, uint32_t count)
- {
- bool ret = true;
- while (count--) {
- ret = recv_byte_with_timeout(p++, 5000);
- if (!ret) {
- break;
- }
- }
- return ret;
- }
- void AP_IOMCU::drain(void)
- {
- uint8_t c;
- bool ret;
- do {
- ret = recv_byte_with_timeout(&c, 40);
- } while (ret);
- }
- bool AP_IOMCU::send(uint8_t c)
- {
- if (uart.write(c) != 1) {
- return false;
- }
- return true;
- }
- bool AP_IOMCU::send(const uint8_t *p, uint32_t count)
- {
- bool ret = true;
- while (count--) {
- ret = send(*p++);
- if (!ret) {
- break;
- }
- }
- return ret;
- }
- bool AP_IOMCU::get_sync(uint32_t timeout_ms)
- {
- uint8_t c[2];
- bool ret;
- ret = recv_byte_with_timeout(c, timeout_ms);
- if (!ret) {
- return false;
- }
- ret = recv_byte_with_timeout(c + 1, timeout_ms);
- if (!ret) {
- return ret;
- }
- if ((c[0] != PROTO_INSYNC) || (c[1] != PROTO_OK)) {
- debug("bad sync 0x%02x,0x%02x", c[0], c[1]);
- return false;
- }
- return true;
- }
- bool AP_IOMCU::sync()
- {
- drain();
-
- for (uint32_t i = 0; i < (PROG_MULTI_MAX + 6); i++) {
- send(0);
- }
- send(PROTO_GET_SYNC);
- send(PROTO_EOC);
- return get_sync();
- }
- bool AP_IOMCU::get_info(uint8_t param, uint32_t &val)
- {
- bool ret;
- send(PROTO_GET_DEVICE);
- send(param);
- send(PROTO_EOC);
- ret = recv_bytes((uint8_t *)&val, sizeof(val));
- if (!ret) {
- return ret;
- }
- return get_sync();
- }
- bool AP_IOMCU::erase()
- {
- debug("erase...");
- send(PROTO_CHIP_ERASE);
- send(PROTO_EOC);
- return get_sync(10000);
- }
- bool AP_IOMCU::program(uint32_t size)
- {
- bool ret = false;
- uint32_t sent = 0;
- if (size & 3) {
- return false;
- }
- debug("programming %u bytes...", (unsigned)size);
- while (sent < size) {
-
- uint32_t n = size - sent;
- if (n > PROG_MULTI_MAX) {
- n = PROG_MULTI_MAX;
- }
- send(PROTO_PROG_MULTI);
- send(n);
- send(&fw[sent], n);
- send(PROTO_EOC);
- ret = get_sync(1000);
- if (!ret) {
- debug("Failed at %u", (unsigned)sent);
- return false;
- }
- sent += n;
- }
- debug("upload OK");
- return true;
- }
- bool AP_IOMCU::verify_rev2(uint32_t size)
- {
- bool ret;
- size_t sent = 0;
- debug("verify...");
- send(PROTO_CHIP_VERIFY);
- send(PROTO_EOC);
- ret = get_sync();
- if (!ret) {
- return ret;
- }
- while (sent < size) {
-
- uint32_t n = size - sent;
- if (n > 4) {
- n = 4;
- }
- send(PROTO_READ_MULTI);
- send(n);
- send(PROTO_EOC);
- for (uint8_t i = 0; i<n; i++) {
- uint8_t c;
- ret = recv_byte_with_timeout(&c, 5000);
- if (!ret) {
- debug("%d: got %d waiting for bytes", sent + i, ret);
- return ret;
- }
- if (c != fw[sent+i]) {
- debug("%d: got 0x%02x expected 0x%02x", sent + i, c, fw[sent+i]);
- return false;
- }
- }
- sent += n;
- ret = get_sync();
- if (!ret) {
- debug("timeout waiting for post-verify sync");
- return ret;
- }
- }
- return true;
- }
- bool AP_IOMCU::verify_rev3(uint32_t fw_size_local)
- {
- bool ret;
- uint32_t sum = 0;
- uint32_t crc = 0;
- uint32_t fw_size_remote;
- const uint8_t fill_blank = 0xff;
- debug("verify...");
- ret = get_info(INFO_FLASH_SIZE, fw_size_remote);
- send(PROTO_EOC);
- if (!ret) {
- debug("could not read firmware size");
- return ret;
- }
- sum = crc_crc32(0, fw, fw_size_local);
-
- for (uint32_t i=0; i<fw_size_remote - fw_size_local; i++) {
- sum = crc_crc32(sum, &fill_blank, 1);
- }
-
- send(PROTO_GET_CRC);
- send(PROTO_EOC);
- ret = recv_bytes((uint8_t *)(&crc), sizeof(crc));
- if (!ret) {
- debug("did not receive CRC checksum");
- return ret;
- }
-
- if (sum != crc) {
- debug("CRC wrong: received: 0x%x, expected: 0x%x", (unsigned)crc, (unsigned)sum);
- return false;
- }
- crc_is_ok = true;
-
- return true;
- }
- bool AP_IOMCU::reboot()
- {
- send(PROTO_REBOOT);
- hal.scheduler->delay(200);
- send(PROTO_EOC);
- hal.scheduler->delay(200);
- return true;
- }
- #endif
|