mirror of https://github.com/ArduPilot/ardupilot
AP_Bootloader: added progress and status to fw upload
This commit is contained in:
parent
29876f649a
commit
e18abc3a9b
|
@ -3,6 +3,30 @@
|
||||||
<TITLE>AP_Bootloader</TITLE>
|
<TITLE>AP_Bootloader</TITLE>
|
||||||
</HEAD>
|
</HEAD>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function dynamic_load(div_id, uri, period_ms) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', uri);
|
||||||
|
|
||||||
|
xhr.setRequestHeader("Cache-Control", "no-cache, no-store, max-age=0");
|
||||||
|
xhr.setRequestHeader("Expires", "Tue, 01 Jan 1980 1:00:00 GMT");
|
||||||
|
xhr.setRequestHeader("Pragma", "no-cache");
|
||||||
|
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
var output = document.getElementById(div_id);
|
||||||
|
if (uri.endsWith('.shtml') || uri.endsWith('.html')) {
|
||||||
|
output.innerHTML = xhr.responseText;
|
||||||
|
} else {
|
||||||
|
output.textContent = xhr.responseText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(function() { dynamic_load(div_id,uri, period_ms); }, period_ms);
|
||||||
|
}
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<h1>Bootloader</h1>
|
<h1>Bootloader</h1>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
@ -19,5 +43,9 @@
|
||||||
<input type="button" onclick="location.href='/REBOOT';" value="Reboot" />
|
<input type="button" onclick="location.href='/REBOOT';" value="Reboot" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<body onload="javascript: dynamic_load('bootloader_status','/bootloader_status.html',100)">
|
||||||
|
<div id="bootloader_status"></div>
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
||||||
</HTML>
|
</HTML>
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <AP_CheckFirmware/AP_CheckFirmware.h>
|
#include <AP_CheckFirmware/AP_CheckFirmware.h>
|
||||||
#include "app_comms.h"
|
#include "app_comms.h"
|
||||||
#include "can.h"
|
#include "can.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifndef AP_NETWORKING_BOOTLOADER_DEFAULT_MAC_ADDR
|
#ifndef AP_NETWORKING_BOOTLOADER_DEFAULT_MAC_ADDR
|
||||||
#define AP_NETWORKING_BOOTLOADER_DEFAULT_MAC_ADDR "C2:AF:51:03:CF:46"
|
#define AP_NETWORKING_BOOTLOADER_DEFAULT_MAC_ADDR "C2:AF:51:03:CF:46"
|
||||||
|
@ -403,9 +405,11 @@ void BL_Network::handle_post(SocketAPM *sock, uint32_t content_length)
|
||||||
/*
|
/*
|
||||||
erase all of flash
|
erase all of flash
|
||||||
*/
|
*/
|
||||||
|
status_printf("Erasing ...");
|
||||||
flash_set_keep_unlocked(true);
|
flash_set_keep_unlocked(true);
|
||||||
uint32_t sec=0;
|
uint32_t sec=0;
|
||||||
while (flash_func_erase_sector(sec)) {
|
while (flash_func_erase_sector(sec)) {
|
||||||
|
thread_sleep_ms(10);
|
||||||
sec++;
|
sec++;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -433,6 +437,8 @@ void BL_Network::handle_post(SocketAPM *sock, uint32_t content_length)
|
||||||
}
|
}
|
||||||
flash_write_buffer(ofs, buf, n/4);
|
flash_write_buffer(ofs, buf, n/4);
|
||||||
ofs += n;
|
ofs += n;
|
||||||
|
uint8_t pct = ofs*100/max_ofs;
|
||||||
|
status_printf("Flashing %u%%", unsigned(pct));
|
||||||
}
|
}
|
||||||
if (ofs % 32 != 0) {
|
if (ofs % 32 != 0) {
|
||||||
// pad to 32 bytes
|
// pad to 32 bytes
|
||||||
|
@ -443,7 +449,12 @@ void BL_Network::handle_post(SocketAPM *sock, uint32_t content_length)
|
||||||
flash_set_keep_unlocked(false);
|
flash_set_keep_unlocked(false);
|
||||||
const auto ok = check_good_firmware();
|
const auto ok = check_good_firmware();
|
||||||
if (ok == check_fw_result_t::CHECK_FW_OK) {
|
if (ok == check_fw_result_t::CHECK_FW_OK) {
|
||||||
jump_to_app();
|
need_launch = true;
|
||||||
|
status_printf("Flash done: OK");
|
||||||
|
const char *str = "<html><head><meta http-equiv=\"refresh\" content=\"4; url=/\"></head><body>Flash OK, booting</body></html>";
|
||||||
|
sock->send(str, strlen(str));
|
||||||
|
} else {
|
||||||
|
status_printf("Flash done: ERR:%u", unsigned(ok));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +468,12 @@ void BL_Network::handle_request(SocketAPM *sock)
|
||||||
*/
|
*/
|
||||||
char *headers = read_headers(sock);
|
char *headers = read_headers(sock);
|
||||||
|
|
||||||
|
const char *header = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: text/html\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n";
|
||||||
|
sock->send(header, strlen(header));
|
||||||
|
|
||||||
if (strncmp(headers, "POST / ", 7) == 0) {
|
if (strncmp(headers, "POST / ", 7) == 0) {
|
||||||
const char *clen = "\r\nContent-Length:";
|
const char *clen = "\r\nContent-Length:";
|
||||||
const char *p = strstr(headers, clen);
|
const char *p = strstr(headers, clen);
|
||||||
|
@ -464,23 +481,33 @@ void BL_Network::handle_request(SocketAPM *sock)
|
||||||
p += strlen(clen);
|
p += strlen(clen);
|
||||||
const uint32_t content_length = atoi(p);
|
const uint32_t content_length = atoi(p);
|
||||||
handle_post(sock, content_length);
|
handle_post(sock, content_length);
|
||||||
|
delete headers;
|
||||||
|
delete sock;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(headers, "GET /REBOOT", 11) == 0) {
|
/*
|
||||||
|
check for async status
|
||||||
|
*/
|
||||||
|
const char *get_status = "GET /bootloader_status.html";
|
||||||
|
if (strncmp(headers, get_status, strlen(get_status)) == 0) {
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(status_mtx);
|
||||||
|
sock->send(bl_status, strlen(bl_status));
|
||||||
|
}
|
||||||
|
delete headers;
|
||||||
|
delete sock;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_reboot = "GET /REBOOT";
|
||||||
|
if (strncmp(headers, get_reboot, strlen(get_reboot)) == 0) {
|
||||||
need_reboot = true;
|
need_reboot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
/*
|
|
||||||
we only need one URL in the bootloader
|
|
||||||
*/
|
|
||||||
const char *header = "HTTP/1.1 200 OK\r\n"
|
|
||||||
"Content-Type: text/html\r\n"
|
|
||||||
"Connection: close\r\n"
|
|
||||||
"\r\n";
|
|
||||||
const auto *msg = AP_ROMFS::find_decompress("index.html", size);
|
const auto *msg = AP_ROMFS::find_decompress("index.html", size);
|
||||||
sock->send(header, strlen(header));
|
|
||||||
if (need_reboot) {
|
if (need_reboot) {
|
||||||
const char *str = "<html><head><meta http-equiv=\"refresh\" content=\"2; url=/\"></head></html>";
|
const char *str = "<html><head><meta http-equiv=\"refresh\" content=\"2; url=/\"></head></html>";
|
||||||
sock->send(str, strlen(str));
|
sock->send(str, strlen(str));
|
||||||
|
@ -490,9 +517,22 @@ void BL_Network::handle_request(SocketAPM *sock)
|
||||||
delete msg2;
|
delete msg2;
|
||||||
}
|
}
|
||||||
delete headers;
|
delete headers;
|
||||||
|
delete sock;
|
||||||
AP_ROMFS::free(msg);
|
AP_ROMFS::free(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct req_context {
|
||||||
|
BL_Network *driver;
|
||||||
|
SocketAPM *sock;
|
||||||
|
};
|
||||||
|
|
||||||
|
void BL_Network::net_request_trampoline(void *ctx)
|
||||||
|
{
|
||||||
|
auto *req = (req_context *)ctx;
|
||||||
|
req->driver->handle_request(req->sock);
|
||||||
|
delete req;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
web server thread
|
web server thread
|
||||||
*/
|
*/
|
||||||
|
@ -508,11 +548,23 @@ void BL_Network::web_server(void)
|
||||||
need_reboot = false;
|
need_reboot = false;
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
if (need_launch) {
|
||||||
|
need_launch = false;
|
||||||
|
thread_sleep_ms(1000);
|
||||||
|
jump_to_app();
|
||||||
|
}
|
||||||
if (sock == nullptr) {
|
if (sock == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
handle_request(sock);
|
// a neq thread for each connection to allow for AJAX
|
||||||
delete sock;
|
auto *req = new req_context;
|
||||||
|
req->driver = this;
|
||||||
|
req->sock = sock;
|
||||||
|
thread_create_alloc(THD_WORKING_AREA_SIZE(2048),
|
||||||
|
"net_request",
|
||||||
|
60,
|
||||||
|
net_request_trampoline,
|
||||||
|
req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,5 +605,17 @@ void BL_Network::save_comms_ip(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
update status message
|
||||||
|
*/
|
||||||
|
void BL_Network::status_printf(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(status_mtx);
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(bl_status, sizeof(bl_status), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // AP_BOOTLOADER_NETWORK_ENABLED
|
#endif // AP_BOOTLOADER_NETWORK_ENABLED
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ private:
|
||||||
|
|
||||||
void net_thread(void);
|
void net_thread(void);
|
||||||
void web_server(void);
|
void web_server(void);
|
||||||
|
static void net_request_trampoline(void *);
|
||||||
void handle_request(SocketAPM *);
|
void handle_request(SocketAPM *);
|
||||||
void handle_post(SocketAPM *, uint32_t content_length);
|
void handle_post(SocketAPM *, uint32_t content_length);
|
||||||
char *read_headers(SocketAPM *);
|
char *read_headers(SocketAPM *);
|
||||||
|
@ -45,6 +46,11 @@ private:
|
||||||
} addr;
|
} addr;
|
||||||
|
|
||||||
bool need_reboot;
|
bool need_reboot;
|
||||||
|
bool need_launch;
|
||||||
|
HAL_Semaphore status_mtx;
|
||||||
|
char bl_status[256];
|
||||||
|
|
||||||
|
void status_printf(const char *fmt, ...);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AP_BOOTLOADER_NETWORK_ENABLED
|
#endif // AP_BOOTLOADER_NETWORK_ENABLED
|
||||||
|
|
Loading…
Reference in New Issue