|  | @@ -9,30 +9,12 @@
 | 
	
		
			
				|  |  |   * See the file COPYING for more details, or visit <http://unlicense.org>.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* Main bootloader: flashes the main firmware (last 96kB of Flash). */
 | 
	
		
			
				|  |  | +/* Main bootloader: flashes the main firmware. */
 | 
	
		
			
				|  |  |  #define FIRMWARE_START 0x08002000
 | 
	
		
			
				|  |  |  #define FIRMWARE_END   0x08010000
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  int EXC_reset(void) __attribute__((alias("main")));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void canary_init(void)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    _irq_stackbottom[0] = _thread_stackbottom[0] = 0xdeadbeef;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void canary_check(void)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    ASSERT(_irq_stackbottom[0] == 0xdeadbeef);
 | 
	
		
			
				|  |  | -    ASSERT(_thread_stackbottom[0] == 0xdeadbeef);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void erase_old_firmware(void)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    uint32_t p;
 | 
	
		
			
				|  |  | -    for (p = FIRMWARE_START; p < FIRMWARE_END; p += FLASH_PAGE_SIZE)
 | 
	
		
			
				|  |  | -        fpec_page_erase(p);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static enum {
 | 
	
		
			
				|  |  |      ST_inactive,
 | 
	
		
			
				|  |  |      ST_command_wait,
 | 
	
	
		
			
				|  | @@ -42,6 +24,8 @@ static enum {
 | 
	
		
			
				|  |  |  static uint8_t u_buf[256];
 | 
	
		
			
				|  |  |  static uint32_t u_prod;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static bool_t pa14_strapped;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static struct gw_info gw_info = {
 | 
	
		
			
				|  |  |      /* Max Revs == 0 signals that this is the Bootloader. */
 | 
	
		
			
				|  |  |      .max_rev = 0,
 | 
	
	
		
			
				|  | @@ -76,13 +60,20 @@ static struct {
 | 
	
		
			
				|  |  |      uint32_t cur;
 | 
	
		
			
				|  |  |  } update;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void erase_old_firmware(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    uint32_t p;
 | 
	
		
			
				|  |  | +    for (p = FIRMWARE_START; p < FIRMWARE_END; p += FLASH_PAGE_SIZE)
 | 
	
		
			
				|  |  | +        fpec_page_erase(p);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void update_prep(uint32_t len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      fpec_init();
 | 
	
		
			
				|  |  |      erase_old_firmware();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      state = ST_update;
 | 
	
		
			
				|  |  | -    memset(&update, 0, sizeof(update));
 | 
	
		
			
				|  |  | +    update.cur = 0;
 | 
	
		
			
				|  |  |      update.len = len;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      printk("Update: %u bytes\n", len);
 | 
	
	
		
			
				|  | @@ -105,12 +96,14 @@ static void update_continue(void)
 | 
	
		
			
				|  |  |          memcpy(u_buf, &u_buf[nr], u_prod);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (update.cur >= update.len) {
 | 
	
		
			
				|  |  | +    if ((update.cur >= update.len) && ep_tx_ready(EP_TX)) {
 | 
	
		
			
				|  |  |          uint16_t crc = crc16_ccitt((void *)FIRMWARE_START, update.len, 0xffff);
 | 
	
		
			
				|  |  |          printk("Final CRC: %04x (%s)\n", crc, crc ? "FAIL" : "OK");
 | 
	
		
			
				|  |  |          u_buf[0] = !!crc;
 | 
	
		
			
				|  |  |          state = ST_command_wait;
 | 
	
		
			
				|  |  |          end_command(u_buf, 1);
 | 
	
		
			
				|  |  | +        if (crc)
 | 
	
		
			
				|  |  | +            erase_old_firmware();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -130,7 +123,7 @@ static void process_command(void)
 | 
	
		
			
				|  |  |          gw_info.fw_minor = fw_minor;
 | 
	
		
			
				|  |  |          /* sample_freq is used as flags: bit 0 indicates if we entered 
 | 
	
		
			
				|  |  |           * the bootloader because PA14 is strapped to GND. */
 | 
	
		
			
				|  |  | -        gw_info.sample_freq = !gpio_read_pin(gpioa, 14);
 | 
	
		
			
				|  |  | +        gw_info.sample_freq = pa14_strapped;
 | 
	
		
			
				|  |  |          memcpy(&u_buf[2], &gw_info, sizeof(gw_info));
 | 
	
		
			
				|  |  |          resp_sz += 32;
 | 
	
		
			
				|  |  |          break;
 | 
	
	
		
			
				|  | @@ -193,17 +186,24 @@ int main(void)
 | 
	
		
			
				|  |  |          memcpy(_sdat, _ldat, _edat-_sdat);
 | 
	
		
			
				|  |  |      memset(_sbss, 0, _ebss-_sbss);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /* Turn on AFIO and GPIOA clocks. */
 | 
	
		
			
				|  |  | +    rcc->apb2enr = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /* Turn off serial-wire JTAG and reclaim the GPIOs. */
 | 
	
		
			
				|  |  |      afio->mapr = AFIO_MAPR_SWJ_CFG_DISABLED;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* Enable GPIOA, set all pins as floating, except PA14 = weak pull-up. */
 | 
	
		
			
				|  |  | -    rcc->apb2enr = RCC_APB2ENR_IOPAEN;
 | 
	
		
			
				|  |  |      gpioa->odr = 0xffffu;
 | 
	
		
			
				|  |  |      gpioa->crh = 0x48444444u;
 | 
	
		
			
				|  |  | -    gpioc->crl = 0x44444444u;
 | 
	
		
			
				|  |  | +    gpioa->crl = 0x44444444u;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* Wait for PA14 to be pulled HIGH. */
 | 
	
		
			
				|  |  | +    cpu_relax();
 | 
	
		
			
				|  |  | +    cpu_relax();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* Enter update mode only if PA14 (DCLK) is strapped to GND. */
 | 
	
		
			
				|  |  | -    if (gpio_read_pin(gpioa, 14)) {
 | 
	
		
			
				|  |  | +    pa14_strapped = !gpio_read_pin(gpioa, 14);
 | 
	
		
			
				|  |  | +    if (!pa14_strapped) {
 | 
	
		
			
				|  |  |          /* Nope, so jump straight at the main firmware. */
 | 
	
		
			
				|  |  |          uint32_t sp = *(uint32_t *)FIRMWARE_START;
 | 
	
		
			
				|  |  |          uint32_t pc = *(uint32_t *)(FIRMWARE_START + 4);
 | 
	
	
		
			
				|  | @@ -214,7 +214,6 @@ int main(void)
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    canary_init();
 | 
	
		
			
				|  |  |      stm32_init();
 | 
	
		
			
				|  |  |      console_init();
 | 
	
		
			
				|  |  |      console_crash_on_input();
 | 
	
	
		
			
				|  | @@ -225,12 +224,9 @@ int main(void)
 | 
	
		
			
				|  |  |      printk("** Keir Fraser <keir.xen@gmail.com>\n");
 | 
	
		
			
				|  |  |      printk("** https://github.com/keirf/Greaseweazle\n\n");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    gpio_configure_pin(gpioa, 14, GPI_pull_up);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      usb_init();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for (;;) {
 | 
	
		
			
				|  |  | -        canary_check();
 | 
	
		
			
				|  |  |          usb_process();
 | 
	
		
			
				|  |  |          update_process();
 | 
	
		
			
				|  |  |      }
 |