|
@@ -10,13 +10,9 @@
|
|
|
*/
|
|
|
|
|
|
#if MCU == STM32F1
|
|
|
-/* 8kB-64kB (56kB total) */
|
|
|
#define FIRMWARE_START 0x08002000
|
|
|
-#define FIRMWARE_END 0x08010000
|
|
|
#elif MCU == STM32F7 || MCU == AT32F4
|
|
|
-/* 16kB-64KB (48kB total) */
|
|
|
#define FIRMWARE_START 0x08004000
|
|
|
-#define FIRMWARE_END 0x08010000
|
|
|
#endif
|
|
|
|
|
|
int EXC_reset(void) __attribute__((alias("main")));
|
|
@@ -32,7 +28,8 @@ static enum {
|
|
|
ST_update,
|
|
|
} state = ST_inactive;
|
|
|
|
|
|
-static uint8_t u_buf[2048] aligned(4);
|
|
|
+extern uint8_t u_buf[];
|
|
|
+#define U_BUF_SZ 2048
|
|
|
static uint32_t u_prod;
|
|
|
|
|
|
static bool_t upd_strapped;
|
|
@@ -81,23 +78,37 @@ static struct {
|
|
|
uint32_t cur;
|
|
|
} update;
|
|
|
|
|
|
-static void erase_old_firmware(void)
|
|
|
+static void erase_old_firmware(uint32_t len)
|
|
|
{
|
|
|
uint32_t p;
|
|
|
- for (p = FIRMWARE_START; p < FIRMWARE_END; p += FLASH_PAGE_SIZE)
|
|
|
+ uint32_t start = FIRMWARE_START;
|
|
|
+ uint32_t end = start + len;
|
|
|
+ for (p = start; p < end; p += FLASH_PAGE_SIZE)
|
|
|
fpec_page_erase(p);
|
|
|
}
|
|
|
|
|
|
-static void update_prep(uint32_t len)
|
|
|
+static uint8_t update_prep(uint32_t len)
|
|
|
{
|
|
|
+ unsigned int flash_end = (uint32_t)_stext + (flash_kb << 10);
|
|
|
+
|
|
|
+ /* Just a bad-sized payload. Shouldn't even have got here. Bad command. */
|
|
|
+ if (len & 3)
|
|
|
+ return ACK_BAD_COMMAND;
|
|
|
+
|
|
|
+ /* Doesn't fit in available Flash memory? Return a special error code. */
|
|
|
+ if (len > (flash_end - FIRMWARE_START))
|
|
|
+ return ACK_OUT_OF_FLASH;
|
|
|
+
|
|
|
fpec_init();
|
|
|
- erase_old_firmware();
|
|
|
+ erase_old_firmware(len);
|
|
|
|
|
|
state = ST_update;
|
|
|
update.cur = 0;
|
|
|
update.len = len;
|
|
|
|
|
|
printk("Update: %u bytes\n", len);
|
|
|
+
|
|
|
+ return ACK_OKAY;
|
|
|
}
|
|
|
|
|
|
static void update_continue(void)
|
|
@@ -105,7 +116,7 @@ static void update_continue(void)
|
|
|
int len;
|
|
|
|
|
|
if ((len = ep_rx_ready(EP_RX)) >= 0) {
|
|
|
- len = min_t(int, len, update.len - update.cur);
|
|
|
+ len = min_t(int, len, update.len - update.cur - u_prod);
|
|
|
usb_read(EP_RX, &u_buf[u_prod], len);
|
|
|
u_prod += len;
|
|
|
}
|
|
@@ -125,7 +136,7 @@ static void update_continue(void)
|
|
|
state = ST_command_wait;
|
|
|
end_command(u_buf, 1);
|
|
|
if (crc)
|
|
|
- erase_old_firmware();
|
|
|
+ erase_old_firmware(update.len);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -155,9 +166,8 @@ static void process_command(void)
|
|
|
case CMD_UPDATE: {
|
|
|
uint32_t u_len = *(uint32_t *)&u_buf[2];
|
|
|
if (len != 6) goto bad_command;
|
|
|
- if (u_len & 3) goto bad_command;
|
|
|
- update_prep(u_len);
|
|
|
- break;
|
|
|
+ u_buf[1] = update_prep(u_len);
|
|
|
+ goto out;
|
|
|
}
|
|
|
case CMD_SWITCH_FW_MODE: {
|
|
|
uint8_t mode = u_buf[2];
|
|
@@ -200,7 +210,7 @@ static void update_process(void)
|
|
|
}
|
|
|
|
|
|
len = ep_rx_ready(EP_RX);
|
|
|
- if ((len >= 0) && (len < (sizeof(u_buf)-u_prod))) {
|
|
|
+ if ((len >= 0) && (len < (U_BUF_SZ-u_prod))) {
|
|
|
usb_read(EP_RX, &u_buf[u_prod], len);
|
|
|
u_prod += len;
|
|
|
}
|
|
@@ -316,8 +326,10 @@ int main(void)
|
|
|
board_init();
|
|
|
|
|
|
printk("\n** Greaseweazle Update Bootloader v%u.%u\n", fw_major, fw_minor);
|
|
|
+#if MCU != STM32F1 /* Not enough Flash space */
|
|
|
printk("** Keir Fraser <keir.xen@gmail.com>\n");
|
|
|
printk("** https://github.com/keirf/Greaseweazle\n\n");
|
|
|
+#endif
|
|
|
|
|
|
usb_init();
|
|
|
|