blob: 1c1fde432707ace3487c8ee3968ec6cf1833f143 [file] [log] [blame]
Brian Silverman3aa0d542014-01-25 17:16:43 -08001#include "cape/bootloader_handoff.h"
2
3#include <string.h>
4
5#include "cape/uart_byte.h"
6#include "cape/uart_common.h"
7#include "cape/crc.h"
8#include "cape/util.h"
9
10// The protocol is pretty simple. Basically, when the bootloader is started, it
11// expects repeated "packets" of data to write. It starts at MAIN_FLASH_START,
12// erases from MAIN_FLASH_START_SECTOR to MAIN_FLASH_END_SECTOR, and keeps
13// writing until MAIN_FLASH_END (if it gets data).
14//
15// The bootloader sends READY when it is first ready to receive bytes. It then
16// expects DATA_BYTES-sized packets (+ the checksum calculated with the standard
17// CRC algorithm). When it successfully receives one and writes it out, it sends
18// ACK. If it has any errors, it waits until there's a 1-second gap (or it
19// receives all the bytes and sees a checksum error) and then sends a NACK.
20
21#define DATA_BYTES 256
22
23#define ACK 0x79
24#define NACK 0x1F
25#define READY 0x7F
26
27static void process_buffer(uint32_t *buffer) {
28 static uint32_t *out_pointer = (uint32_t *)MAIN_FLASH_START;
29 if ((out_pointer + DATA_BYTES / 4) >= (uint32_t *)MAIN_FLASH_END) return;
30
31 while (FLASH->SR & FLASH_SR_BSY) {}
32 FLASH->CR |= FLASH_CR_PG;
33 for (int i = 0; i < (DATA_BYTES / 4); ++i) {
34 *(out_pointer++) = buffer[i];
35 }
36 while (FLASH->SR & FLASH_SR_BSY) {}
37 FLASH->CR &= ~FLASH_CR_PG;
38}
39
40__attribute__((noreturn)) void bootloader_start(void) {
41 crc_init();
42
43 // Unlock the flash so we can program it.
44 FLASH->KEYR = 0x45670123;
45 FLASH->KEYR = 0xCDEF89AB;
46 while (FLASH->CR & FLASH_CR_LOCK) {}
47
48 FLASH->CR =
49 (FLASH->CR & ~(FLASH_CR_PSIZE_0 | FLASH_CR_PSIZE_1)) | FLASH_CR_PSIZE_1;
50
51 FLASH->CR |= FLASH_CR_SER;
52 for (int i = MAIN_FLASH_START_SECTOR; i <= MAIN_FLASH_END_SECTOR; ++i) {
53 while (FLASH->SR & FLASH_SR_BSY) {}
54 FLASH->CR = (FLASH->CR & ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 |
55 FLASH_CR_SNB_2 | FLASH_CR_SNB_3)) |
56 i << 3;
57 FLASH->CR |= FLASH_CR_STRT;
58 while (FLASH->CR & FLASH_SR_BSY) {}
59 }
60 FLASH->CR &= ~FLASH_CR_SER;
61
62 uart_common_configure(115200);
63 uart_byte_configure();
64
65 uint8_t buffer[DATA_BYTES + 4] __attribute__((aligned(4)));
66 // Whether we've already encountered an error in this block or not.
67 int error = 0;
68 int bytes_received = 0;
69
70 uart_byte_send(READY);
71
72 while (1) {
73 // Receive with a 1 second timeout.
74 int received = uart_byte_receive(60000, 1000 - 1);
75 if (received < 0) {
76 if (received == -1) {
77 uart_byte_send(NACK);
78 error = 0;
79 bytes_received = 0;
80 } else {
81 error = 1;
82 }
83 } else { // successfully received a byte
84 if (error == 0) {
85 buffer[bytes_received++] = (uint8_t)received;
86 if (bytes_received == sizeof(buffer)) {
87 bytes_received = 0;
88 uint32_t checksum;
89 memcpy(&checksum, &buffer[DATA_BYTES], 4);
90 uint32_t *buffer32;
91 uint8_t *buffer8 = buffer;
92 memcpy(&buffer32, &buffer8, 4);
93 if (crc_calculate(buffer32, DATA_BYTES / 4) != checksum) {
94 uart_byte_send(NACK);
95 } else {
96 process_buffer(buffer32);
97 uart_byte_send(ACK);
98 }
99 }
100 }
101 }
102 }
103}