int
PX4IO_Uploader::upload(const char *filenames[])
{
	int	ret;
	const char *filename = NULL;
	size_t fw_size;

#ifndef PX4IO_SERIAL_DEVICE
#error Must define PX4IO_SERIAL_DEVICE in board configuration to support firmware upload
#endif

	/* allow an early abort and look for file first */
	for (unsigned i = 0; filenames[i] != nullptr; i++) {
		_fw_fd = open(filenames[i], O_RDONLY);

		if (_fw_fd < 0) {
			log("failed to open %s", filenames[i]);
			continue;
		}

		log("using firmware from %s", filenames[i]);
		filename = filenames[i];
		break;
	}

	if (filename == NULL) {
		log("no firmware found");
		close(_io_fd);
		_io_fd = -1;
		return -ENOENT;
	}

	_io_fd = open(PX4IO_SERIAL_DEVICE, O_RDWR);

	if (_io_fd < 0) {
		log("could not open interface");
		return -errno;
	}

	/* save initial uart configuration to reset after the update */
	struct termios t_original;
	tcgetattr(_io_fd, &t_original);

	/* adjust line speed to match bootloader */
	struct termios t;
	tcgetattr(_io_fd, &t);
	cfsetspeed(&t, 115200);
	tcsetattr(_io_fd, TCSANOW, &t);

	/* look for the bootloader for 150 ms */
	for (int i = 0; i < 15; i++) {
		ret = sync();
		if (ret == OK) {
			break;
		} else {
			usleep(10000);
		}
	}

	if (ret != OK) {
		/* this is immediately fatal */
		log("bootloader not responding");
		tcsetattr(_io_fd, TCSANOW, &t_original);
		close(_io_fd);
		_io_fd = -1;
		return -EIO;
	}

	struct stat st;
	if (stat(filename, &st) != 0) {
		log("Failed to stat %s - %d\n", filename, (int)errno);
		tcsetattr(_io_fd, TCSANOW, &t_original);
		close(_io_fd);
		_io_fd = -1;
		return -errno;
	}
	fw_size = st.st_size;

	if (_fw_fd == -1) {
		tcsetattr(_io_fd, TCSANOW, &t_original);
		close(_io_fd);
		_io_fd = -1;
		return -ENOENT;
	}

	/* do the usual program thing - allow for failure */
	for (unsigned retries = 0; retries < 1; retries++) {
		if (retries > 0) {
			log("retrying update...");
			ret = sync();

			if (ret != OK) {
				/* this is immediately fatal */
				log("bootloader not responding");
				tcsetattr(_io_fd, TCSANOW, &t_original);
				close(_io_fd);
				_io_fd = -1;
				return -EIO;
			}
		}

		ret = get_info(INFO_BL_REV, bl_rev);

		if (ret == OK) {
			if (bl_rev <= BL_REV) {
				log("found bootloader revision: %d", bl_rev);
			} else {
				log("found unsupported bootloader revision %d, exiting", bl_rev);
				tcsetattr(_io_fd, TCSANOW, &t_original);
				close(_io_fd);
				_io_fd = -1;
				return OK;
			}
		}

		ret = erase();

		if (ret != OK) {
			log("erase failed");
			continue;
		}

		ret = program(fw_size);

		if (ret != OK) {
			log("program failed");
			continue;
		}

		if (bl_rev <= 2) {
			ret = verify_rev2(fw_size);
		} else {
			/* verify rev 3 and higher. Every version *needs* to be verified. */
			ret = verify_rev3(fw_size);
		}

		if (ret != OK) {
			log("verify failed");
			continue;
		}

		ret = reboot();

		if (ret != OK) {
			log("reboot failed");
			tcsetattr(_io_fd, TCSANOW, &t_original);
			close(_io_fd);
			_io_fd = -1;
			return ret;
		}

		log("update complete");

		ret = OK;
		break;
	}

	/* reset uart to previous/default baudrate */
	tcsetattr(_io_fd, TCSANOW, &t_original);

	close(_fw_fd);
	close(_io_fd);
	_io_fd = -1;

	// sleep for enough time for the IO chip to boot. This makes
	// forceupdate more reliably startup IO again after update
	up_udelay(100*1000);

	return ret;
}
Beispiel #2
0
/*
  upload a firmware to the IOMCU
 */
bool AP_IOMCU::upload_fw(void)
{
    // set baudrate for bootloader
    uart.begin(115200, 256, 256);

    bool ret = false;

    /* look for the bootloader for 150 ms */
    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");

    // sleep for enough time for the IO chip to boot
    hal.scheduler->delay(100);

    return true;
}