blob: 15d28b19ccfdeadbbfbb4e561de2677c8a63cddb [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//
Brian Silverman04fac622014-01-26 18:32:15 -080015// The bootloader sends a NACK when it is first ready to receive bytes. It then
Brian Silverman3aa0d542014-01-25 17:16:43 -080016// 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
Brian Silverman3aa0d542014-01-25 17:16:43 -080025
26static void process_buffer(uint32_t *buffer) {
27 static uint32_t *out_pointer = (uint32_t *)MAIN_FLASH_START;
28 if ((out_pointer + DATA_BYTES / 4) >= (uint32_t *)MAIN_FLASH_END) return;
29
30 while (FLASH->SR & FLASH_SR_BSY) {}
31 FLASH->CR |= FLASH_CR_PG;
32 for (int i = 0; i < (DATA_BYTES / 4); ++i) {
33 *(out_pointer++) = buffer[i];
34 }
35 while (FLASH->SR & FLASH_SR_BSY) {}
36 FLASH->CR &= ~FLASH_CR_PG;
37}
38
39__attribute__((noreturn)) void bootloader_start(void) {
40 crc_init();
41
42 // Unlock the flash so we can program it.
43 FLASH->KEYR = 0x45670123;
44 FLASH->KEYR = 0xCDEF89AB;
45 while (FLASH->CR & FLASH_CR_LOCK) {}
46
47 FLASH->CR =
48 (FLASH->CR & ~(FLASH_CR_PSIZE_0 | FLASH_CR_PSIZE_1)) | FLASH_CR_PSIZE_1;
49
50 FLASH->CR |= FLASH_CR_SER;
51 for (int i = MAIN_FLASH_START_SECTOR; i <= MAIN_FLASH_END_SECTOR; ++i) {
52 while (FLASH->SR & FLASH_SR_BSY) {}
53 FLASH->CR = (FLASH->CR & ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 |
54 FLASH_CR_SNB_2 | FLASH_CR_SNB_3)) |
55 i << 3;
56 FLASH->CR |= FLASH_CR_STRT;
57 while (FLASH->CR & FLASH_SR_BSY) {}
58 }
59 FLASH->CR &= ~FLASH_CR_SER;
60
61 uart_common_configure(115200);
62 uart_byte_configure();
63
64 uint8_t buffer[DATA_BYTES + 4] __attribute__((aligned(4)));
65 // Whether we've already encountered an error in this block or not.
66 int error = 0;
67 int bytes_received = 0;
68
Brian Silverman04fac622014-01-26 18:32:15 -080069 uart_byte_send(NACK);
Brian Silverman3aa0d542014-01-25 17:16:43 -080070
71 while (1) {
72 // Receive with a 1 second timeout.
73 int received = uart_byte_receive(60000, 1000 - 1);
74 if (received < 0) {
75 if (received == -1) {
76 uart_byte_send(NACK);
77 error = 0;
78 bytes_received = 0;
79 } else {
80 error = 1;
81 }
82 } else { // successfully received a byte
83 if (error == 0) {
84 buffer[bytes_received++] = (uint8_t)received;
85 if (bytes_received == sizeof(buffer)) {
86 bytes_received = 0;
87 uint32_t checksum;
88 memcpy(&checksum, &buffer[DATA_BYTES], 4);
89 uint32_t *buffer32;
90 uint8_t *buffer8 = buffer;
91 memcpy(&buffer32, &buffer8, 4);
92 if (crc_calculate(buffer32, DATA_BYTES / 4) != checksum) {
93 uart_byte_send(NACK);
94 } else {
95 process_buffer(buffer32);
96 uart_byte_send(ACK);
97 }
98 }
99 }
100 }
101 }
102}