|
23 | 23 |
|
24 | 24 | #include <stdlib.h> |
25 | 25 | #include <stdint.h> |
| 26 | +#include <string.h> |
26 | 27 | #include "system.h" |
27 | 28 | #include "timer.h" |
28 | 29 | #include "led.h" |
| 30 | +#include "hal.h" |
29 | 31 | #include "wolfboot/wolfboot.h" |
30 | 32 |
|
31 | 33 | #ifdef PLATFORM_stm32f4 |
32 | 34 |
|
| 35 | +extern int update_started; |
| 36 | + |
| 37 | +#define UART3 (0x40004800) |
| 38 | + |
| 39 | +#define UART3_SR (*(volatile uint32_t *)(UART3)) |
| 40 | +#define UART3_DR (*(volatile uint32_t *)(UART3 + 0x04)) |
| 41 | +#define UART3_BRR (*(volatile uint32_t *)(UART3 + 0x08)) |
| 42 | +#define UART3_CR1 (*(volatile uint32_t *)(UART3 + 0x0c)) |
| 43 | +#define UART3_CR2 (*(volatile uint32_t *)(UART3 + 0x10)) |
| 44 | + |
| 45 | +#define UART_CR1_UART_ENABLE (1 << 13) |
| 46 | +#define UART_CR1_SYMBOL_LEN (1 << 12) |
| 47 | +#define UART_CR1_PARITY_ENABLED (1 << 10) |
| 48 | +#define UART_CR1_PARITY_ODD (1 << 9) |
| 49 | +#define UART_CR1_TX_ENABLE (1 << 3) |
| 50 | +#define UART_CR1_RX_ENABLE (1 << 2) |
| 51 | +#define UART_CR2_STOPBITS (3 << 12) |
| 52 | +#define UART_SR_TX_EMPTY (1 << 7) |
| 53 | +#define UART_SR_RX_NOTEMPTY (1 << 5) |
| 54 | + |
| 55 | + |
| 56 | +#define CLOCK_SPEED (168000000) |
| 57 | + |
| 58 | +#define APB1_CLOCK_ER (*(volatile uint32_t *)(0x40023840)) |
| 59 | +#define UART3_APB1_CLOCK_ER_VAL (1 << 18) |
| 60 | + |
| 61 | +#define AHB1_CLOCK_ER (*(volatile uint32_t *)(0x40023830)) |
| 62 | +#define GPIOD_AHB1_CLOCK_ER (1 << 3) |
| 63 | +#define GPIOD_BASE 0x40020c00 |
| 64 | +#define GPIOD_MODE (*(volatile uint32_t *)(GPIOD_BASE + 0x00)) |
| 65 | +#define GPIOD_AFL (*(volatile uint32_t *)(GPIOD_BASE + 0x20)) |
| 66 | +#define GPIOD_AFH (*(volatile uint32_t *)(GPIOD_BASE + 0x24)) |
| 67 | +#define GPIO_MODE_AF (2) |
| 68 | +#define UART3_PIN_AF 7 |
| 69 | +#define UART3_RX_PIN 9 |
| 70 | +#define UART3_TX_PIN 8 |
| 71 | + |
| 72 | +#define MSGSIZE 16 |
| 73 | +#define PAGESIZE (256) |
| 74 | +static uint8_t page[PAGESIZE]; |
| 75 | +static const char ERR='!'; |
| 76 | +static const char START='*'; |
| 77 | +static const char UPDATE='U'; |
| 78 | +static const char ACK='#'; |
| 79 | +static uint8_t msg[MSGSIZE]; |
| 80 | + |
| 81 | + |
| 82 | +void uart_write(const char c) |
| 83 | +{ |
| 84 | + uint32_t reg; |
| 85 | + do { |
| 86 | + reg = UART3_SR; |
| 87 | + } while ((reg & UART_SR_TX_EMPTY) == 0); |
| 88 | + UART3_DR = c; |
| 89 | +} |
| 90 | + |
| 91 | +static void uart_pins_setup(void) |
| 92 | +{ |
| 93 | + uint32_t reg; |
| 94 | + AHB1_CLOCK_ER |= GPIOD_AHB1_CLOCK_ER; |
| 95 | + /* Set mode = AF */ |
| 96 | + reg = GPIOD_MODE & ~ (0x03 << (UART3_RX_PIN * 2)); |
| 97 | + GPIOD_MODE = reg | (2 << (UART3_RX_PIN * 2)); |
| 98 | + reg = GPIOD_MODE & ~ (0x03 << (UART3_TX_PIN * 2)); |
| 99 | + GPIOD_MODE = reg | (2 << (UART3_TX_PIN * 2)); |
| 100 | + |
| 101 | + /* Alternate function: use high pins (8 and 9) */ |
| 102 | + reg = GPIOD_AFH & ~(0xf << ((UART3_TX_PIN - 8) * 4)); |
| 103 | + GPIOD_AFH = reg | (UART3_PIN_AF << ((UART3_TX_PIN - 8) * 4)); |
| 104 | + reg = GPIOD_AFH & ~(0xf << ((UART3_RX_PIN - 8) * 4)); |
| 105 | + GPIOD_AFH = reg | (UART3_PIN_AF << ((UART3_RX_PIN - 8) * 4)); |
| 106 | +} |
| 107 | + |
| 108 | +int uart_setup(uint32_t bitrate, uint8_t data, char parity, uint8_t stop) |
| 109 | +{ |
| 110 | + uint32_t reg; |
| 111 | + /* Enable pins and configure for AF7 */ |
| 112 | + uart_pins_setup(); |
| 113 | + /* Turn on the device */ |
| 114 | + APB1_CLOCK_ER |= UART3_APB1_CLOCK_ER_VAL; |
| 115 | + |
| 116 | + /* Configure for TX + RX */ |
| 117 | + UART3_CR1 |= (UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE); |
| 118 | + |
| 119 | + /* Configure clock */ |
| 120 | + UART3_BRR = CLOCK_SPEED / bitrate; |
| 121 | + |
| 122 | + /* Configure data bits */ |
| 123 | + if (data == 8) |
| 124 | + UART3_CR1 &= ~UART_CR1_SYMBOL_LEN; |
| 125 | + else |
| 126 | + UART3_CR1 |= UART_CR1_SYMBOL_LEN; |
| 127 | + |
| 128 | + /* Configure parity */ |
| 129 | + switch (parity) { |
| 130 | + case 'O': |
| 131 | + UART3_CR1 |= UART_CR1_PARITY_ODD; |
| 132 | + /* fall through to enable parity */ |
| 133 | + case 'E': |
| 134 | + UART3_CR1 |= UART_CR1_PARITY_ENABLED; |
| 135 | + break; |
| 136 | + default: |
| 137 | + UART3_CR1 &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD); |
| 138 | + } |
| 139 | + /* Set stop bits */ |
| 140 | + reg = UART3_CR2 & ~UART_CR2_STOPBITS; |
| 141 | + if (stop > 1) |
| 142 | + UART3_CR2 = reg & (2 << 12); |
| 143 | + else |
| 144 | + UART3_CR2 = reg; |
| 145 | + |
| 146 | + /* Turn on uart */ |
| 147 | + UART3_CR1 |= UART_CR1_UART_ENABLE; |
| 148 | + |
| 149 | + return 0; |
| 150 | +} |
| 151 | + |
| 152 | +char uart_read(void) |
| 153 | +{ |
| 154 | + char c; |
| 155 | + volatile uint32_t reg; |
| 156 | + do { |
| 157 | + reg = UART3_SR; |
| 158 | + } while ((reg & UART_SR_RX_NOTEMPTY) == 0); |
| 159 | + c = (char)(UART3_DR & 0xff); |
| 160 | + return c; |
| 161 | +} |
| 162 | + |
| 163 | +static void ack(uint32_t _off) |
| 164 | +{ |
| 165 | + uint8_t *off = (uint8_t *)(&_off); |
| 166 | + int i; |
| 167 | + uart_write(ACK); |
| 168 | + for (i = 0; i < 4; i++) { |
| 169 | + uart_write(off[i]); |
| 170 | + } |
| 171 | +} |
| 172 | + |
| 173 | +static int check(uint8_t *pkt, int size) |
| 174 | +{ |
| 175 | + int i; |
| 176 | + uint16_t c = 0; |
| 177 | + uint16_t c_rx = *((uint16_t *)(pkt + 2)); |
| 178 | + uint16_t *p = (uint16_t *)(pkt + 4); |
| 179 | + for (i = 0; i < ((size - 4) >> 1); i++) |
| 180 | + c += p[i]; |
| 181 | + if (c == c_rx) |
| 182 | + return 0; |
| 183 | + return -1; |
| 184 | +} |
| 185 | + |
33 | 186 | void main(void) { |
34 | | - uint32_t version; |
| 187 | + uint32_t tlen = 0; |
| 188 | + volatile uint32_t recv_seq; |
| 189 | + uint32_t r_total = 0; |
| 190 | + uint32_t tot_len = 0; |
| 191 | + uint32_t next_seq = 0; |
| 192 | + uint32_t version = 0; |
| 193 | + uint8_t *v_array = (uint8_t *)&version; |
| 194 | + int i; |
| 195 | + memset(page, 0xFF, PAGESIZE); |
35 | 196 | boot_led_on(); |
36 | 197 | flash_set_waitstates(); |
37 | 198 | clock_config(); |
38 | 199 | led_pwm_setup(); |
39 | 200 | pwm_init(CPU_FREQ, 0); |
40 | | - /* Dim the led by altering the PWM duty-cicle |
| 201 | + /* Dim the led by altering the PWM duty-cicle |
41 | 202 | * in isr_tim2 (timer.c) |
42 | 203 | * |
43 | 204 | * Every 50ms, the duty cycle of the PWM connected |
44 | 205 | * to the blue led increases/decreases making a pulse |
45 | 206 | * effect. |
46 | 207 | */ |
47 | 208 | timer_init(CPU_FREQ, 1, 50); |
48 | | - version = wolfBoot_current_firmware_version(); |
49 | | - if (version & 0x01) { |
50 | | - /* Odd version: unstable, trigger update */ |
51 | | - if (wolfBoot_update_firmware_version() != 0) |
| 209 | + uart_setup(115200, 8, 'N', 1); |
| 210 | + memset(page, 0xFF, PAGESIZE); |
| 211 | + asm volatile ("cpsie i"); |
| 212 | + /* Initiate update */ |
| 213 | + |
| 214 | + //wolfBoot_success(); |
| 215 | + |
| 216 | + hal_flash_unlock(); |
| 217 | + uart_write(START); |
| 218 | + while (1) { |
| 219 | + r_total = 0; |
| 220 | + do { |
| 221 | + while(r_total < 2) { |
| 222 | + msg[r_total++] = uart_read(); |
| 223 | + if ((r_total == 2) && ((msg[0] != 0xA5) || msg[1] != 0x5A)) { |
| 224 | + r_total = 0; |
| 225 | + continue; |
| 226 | + } |
| 227 | + } |
| 228 | + msg[r_total++] = uart_read(); |
| 229 | + if ((tot_len == 0) && r_total == 2 + sizeof(uint32_t)) |
| 230 | + break; |
| 231 | + if ((r_total > 8) && (tot_len <= ((r_total - 8) + next_seq))) |
| 232 | + break; |
| 233 | + } while (r_total < MSGSIZE); |
| 234 | + if (tot_len == 0) { |
| 235 | + tlen = msg[2] + (msg[3] << 8) + (msg[4] << 16) + (msg[5] << 24); |
| 236 | + if (tlen > WOLFBOOT_PARTITION_SIZE - 8) { |
| 237 | + uart_write(ERR); |
| 238 | + uart_write(ERR); |
| 239 | + uart_write(ERR); |
| 240 | + uart_write(ERR); |
| 241 | + uart_write(START); |
| 242 | + recv_seq = 0; |
| 243 | + tot_len = 0; |
| 244 | + update_started = 1; |
| 245 | + continue; |
| 246 | + } |
| 247 | + tot_len = tlen; |
| 248 | + ack(0); |
| 249 | + continue; |
| 250 | + } |
| 251 | + if (check(msg, r_total) < 0) { |
| 252 | + ack(next_seq); |
| 253 | + continue; |
| 254 | + } |
| 255 | + recv_seq = msg[4] + (msg[5] << 8) + (msg[6] << 16) + (msg[7] << 24); |
| 256 | + if (recv_seq == next_seq) |
| 257 | + { |
| 258 | + int psize = r_total - 8; |
| 259 | + int page_idx = recv_seq % PAGESIZE; |
| 260 | + memcpy(&page[recv_seq % PAGESIZE], msg + 8, psize); |
| 261 | + page_idx += psize; |
| 262 | + if ((page_idx == PAGESIZE) || (next_seq + psize >= tot_len)) { |
| 263 | + uint32_t dst = (WOLFBOOT_PARTITION_UPDATE_ADDRESS + recv_seq + psize) - page_idx; |
| 264 | + if ((dst % WOLFBOOT_SECTOR_SIZE) == 0) { |
| 265 | + hal_flash_erase(dst, WOLFBOOT_SECTOR_SIZE); |
| 266 | + } |
| 267 | + hal_flash_write(dst, page, PAGESIZE); |
| 268 | + memset(page, 0xFF, PAGESIZE); |
| 269 | + } |
| 270 | + next_seq += psize; |
| 271 | + } |
| 272 | + ack(next_seq); |
| 273 | + if (next_seq >= tot_len) { |
| 274 | + /* Update complete */ |
52 | 275 | wolfBoot_update_trigger(); |
53 | | - } else { |
54 | | - /* Even version, stabilise */ |
55 | | - wolfBoot_success(); |
| 276 | + hal_flash_lock(); |
| 277 | + break; |
| 278 | + } |
56 | 279 | } |
57 | | - asm volatile ("cpsie i"); |
| 280 | + /* Wait for reboot */ |
58 | 281 | while(1) |
59 | | - WFI(); |
| 282 | + ; |
60 | 283 | } |
61 | 284 | #endif |
62 | 285 |
|
|
0 commit comments