diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index d1260dad..e274a38b 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -33,9 +33,7 @@ #define PLATFORM_HAS_TRACESWO #define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware " FIRMWARE_VERSION ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" /* Important pin mappings for STM32 implementation: * diff --git a/src/platforms/hydrabus/platform.h b/src/platforms/hydrabus/platform.h index b340f970..d0ba61aa 100644 --- a/src/platforms/hydrabus/platform.h +++ b/src/platforms/hydrabus/platform.h @@ -36,7 +36,6 @@ #define BOARD_IDENT "Black Magic Probe (HydraBus), (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for HydraBus, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (HydraBus)" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" /* Important pin mappings for STM32 implementation: * diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 397dd8c1..c18a8c8f 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -38,7 +38,6 @@ #define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)" #define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)" #define DFU_IDENT "Black Magic Firmware Upgrade" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,120*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" /* Important pin mappings for STM32 implementation: diff --git a/src/platforms/stlink/Flashsize_F103 b/src/platforms/stlink/Flashsize_F103 new file mode 100644 index 00000000..d4ece0f3 --- /dev/null +++ b/src/platforms/stlink/Flashsize_F103 @@ -0,0 +1,39 @@ +Announced versus available Flash size on F103 +============================================ +Up to Stlink V2, the CPU soldered on the board was a F103C8 with 64 kiByte +flash. Up to about version 280 of BMP, this limit was not hit when linked +against nanolib. + +StlinkV2-1 has a STM32F103CB, like a genuine BMP. + +However with more and more devices supported, BMP at about version 282 hit +this limit. There are two ways to work around: +- Branch STlink V2-1 as separate platform and and care for the original STlink + platform by restricting/ommitting features. +- Rely on uncertain upper flash on F103C8 + +The first option needs more care as an additional platform is introduced and +will restrict usage of older STlinks as BMPs. + +However F103C8 and F103CB have the same chip and upper flash exists on F103C8. +This flash may have been tested bad, or not have been tested at all, +or, in the best case, was tested good but market requirements made STM sell +it as F103C8. + +Ignoring the chip marking and using an F103C8 blindly as a F103Cb is done +already with few problems on many china boards (e.g. blue pill). Probably +this second approach will work for many of the older STLinks. + +Use at your own risk! + +With DFU upload available in the bootloader, you can verify by uploading the +binary from flash and comparing it against the binary downloaded. +- Download new BMP binary (if not already done) + dfu-util -s 0x08002000:leave:force -D blackmagic.bin +- Get length of binary + > ls -l blackmagic.bin + -rwxr-xr-x 1 bon users 57372 15. Apr 14:17 blackmagic.bin +- Upload binary from flash + > dfu-util -s 0x08002000:leave:force:57372 -U blackmagic.bin.1 +- Compare + > diff blackmagic.bin* diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index ef030541..54125a9a 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -37,7 +37,6 @@ #define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" /* Important pin mappings for STM32 implementation: diff --git a/src/platforms/stm32/dfu_f1.c b/src/platforms/stm32/dfu_f1.c index a0955170..83e95ec1 100644 --- a/src/platforms/stm32/dfu_f1.c +++ b/src/platforms/stm32/dfu_f1.c @@ -77,11 +77,25 @@ void dfu_protect(dfu_mode_t mode) } #endif } - else if (mode == UPD_MODE) { + /* There is no way we can update the bootloader with a programm running + * on the same device when the bootloader pages are write + * protected or the device is read protected! + * + * Erasing option bytes to remove write protection will make the + * device read protected. Read protection means that the first pages + * get write protected again (PM0075, 2.4.1 Read protection.) + * + * Removing read protection after option erase results in device mass + * erase, crashing the update (PM0075, 2.4.2, Unprotection, Case 1). + */ +#if 0 + else if ((mode == UPD_MODE) && ((FLASH_WRPR & 0x03) != 0x03)) { flash_unlock(); FLASH_CR = 0; flash_erase_option_bytes(); + flash_program_option_bytes(FLASH_OBP_RDP, FLASH_OBP_RDP_KEY); } +#endif } void dfu_jump_app_if_valid(void) diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index 7b733d71..61cfd041 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -22,10 +22,11 @@ #include #if defined(STM32F1) # include -#elif defined(STM32F2) -# include +# define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,000*001Kg" +# define DFU_IFACE_STRING_OFFSET 38 #elif defined(STM32F4) # include +# define DFU_IFACE_STRING "/0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" #endif #include #include @@ -48,6 +49,7 @@ static struct { uint32_t addr; uint16_t blocknum; } prog; +static uint8_t current_error; const struct usb_device_descriptor dev = { .bLength = USB_DT_DEVICE_SIZE, @@ -69,7 +71,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -112,21 +114,23 @@ const struct usb_config_descriptor config = { }; static char serial_no[9]; +static char if_string[] = DFU_IFACE_STRING; static const char *usb_strings[] = { "Black Sphere Technologies", BOARD_IDENT_DFU, serial_no, /* This string is used by ST Microelectronics' DfuSe utility */ - DFU_IFACE_STRING, + if_string, }; +static char upd_if_string[] = UPD_IFACE_STRING; static const char *usb_strings_upd[] = { "Black Sphere Technologies", BOARD_IDENT_UPD, serial_no, /* This string is used by ST Microelectronics' DfuSe utility */ - UPD_IFACE_STRING, + upd_if_string, }; static uint32_t get_le32(const void *vp) @@ -149,7 +153,8 @@ static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout) /* Device will reset when read is complete */ usbdfu_state = STATE_DFU_MANIFEST; return DFU_STATUS_OK; - + case STATE_DFU_ERROR: + return current_error; default: return DFU_STATUS_OK; } @@ -159,23 +164,17 @@ static void usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) { (void)req; + (void)dev; switch(usbdfu_state) { case STATE_DFU_DNBUSY: flash_unlock(); if(prog.blocknum == 0) { - uint32_t addr = get_le32(prog.buf + 1); - if ((addr < app_address) || (addr >= max_address)) { - flash_lock(); - usbd_ep_stall_set(dev, 0, 1); - return; - } + int32_t addr = get_le32(prog.buf + 1); switch(prog.buf[0]) { case CMD_ERASE: dfu_check_and_do_sector_erase(addr); - case CMD_SETADDR: - prog.addr = addr; } } else { uint32_t baseaddr = prog.addr + @@ -218,6 +217,15 @@ static int usbdfu_control_request(usbd_device *dev, prog.blocknum = req->wValue; prog.len = *len; memcpy(prog.buf, *buf, *len); + if ((req->wValue == 0) && (prog.buf[0] == CMD_SETADDR)) { + uint32_t addr = get_le32(prog.buf + 1); + if ((addr < app_address) || (addr >= max_address)) { + current_error = DFU_STATUS_ERR_TARGET; + usbdfu_state = STATE_DFU_ERROR; + return 1; + } else + prog.addr = addr; + } usbdfu_state = STATE_DFU_DNLOAD_SYNC; return 1; } @@ -231,8 +239,22 @@ static int usbdfu_control_request(usbd_device *dev, usbdfu_state = STATE_DFU_IDLE; return 1; case DFU_UPLOAD: - /* Upload not supported for now */ - return 0; + if ((usbdfu_state == STATE_DFU_IDLE) || + (usbdfu_state == STATE_DFU_DNLOAD_IDLE) || + (usbdfu_state == STATE_DFU_UPLOAD_IDLE)) { + prog.blocknum = req->wValue; + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + if(prog.blocknum > 1) { + uint32_t baseaddr = prog.addr + + ((prog.blocknum - 2) * + dfu_function.wTransferSize); + memcpy(*buf, (void*)baseaddr, *len); + } + return 1; + } else { + usbd_ep_stall_set(dev, 0, 1); + return 0; + } case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ @@ -278,6 +300,33 @@ void dfu_main(void) usbd_poll(usbdev); } +#if defined(DFU_IFACE_STRING_OFFSET) +static void set_dfu_iface_string(uint32_t size) +{ + uint32_t res; + char *p = if_string + DFU_IFACE_STRING_OFFSET; + /* We do not want the whole printf library in the bootloader. + * Fill the size digits by hand. + */ + res = size / 100; + if (res > 9) { + *p++ = '9'; + *p++ = '9'; + *p++ = '9'; + return; + } else { + *p++ = res + '0'; + size -= res * 100; + } + res = size / 10; + *p++ = res + '0'; + size -= res * 10; + *p++ = size + '0'; +} +#else +# define set_dfu_iface_string() +#endif + static char *get_dev_unique_id(char *s) { #if defined(STM32F4) || defined(STM32F2) @@ -298,10 +347,21 @@ static char *get_dev_unique_id(char *s) *(unique_id_p + 1) + *(unique_id_p + 2); int i; + uint32_t fuse_flash_size; /* Calculated the upper flash limit from the exported data in theparameter block*/ - max_address = (*(uint32_t *) FLASH_SIZE_R) <<10; + fuse_flash_size = *(uint32_t *) FLASH_SIZE_R & 0xfff; + set_dfu_iface_string(fuse_flash_size - 8); + if (fuse_flash_size == 0x40) /* Handle F103x8 as F103xC! */ + fuse_flash_size = 0x80; + max_address = FLASH_BASE + (fuse_flash_size << 10); + /* If bootloader pages are write protected or device is read + * protected, deny bootloader update. + * User can still force updates, at his own risk! + */ + if (((FLASH_WRPR & 0x03) != 0x03) || (FLASH_OBR & FLASH_OBR_RDPRT_EN)) + upd_if_string[30] = '0'; /* Fetch serial number from chip's unique ID */ for(i = 0; i < 8; i++) { s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 74bb7873..dbe42074 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -33,7 +33,6 @@ #define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (SWLINK)" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" /* Pin mappings: diff --git a/src/target/cortexa.c b/src/target/cortexa.c index ba273754..9ef239c5 100644 --- a/src/target/cortexa.c +++ b/src/target/cortexa.c @@ -33,7 +33,7 @@ #include "target.h" #include "target_internal.h" -static char cortexa_driver_str[] = "ARM Cortex-A"; +static const char cortexa_driver_str[] = "ARM Cortex-A"; static bool cortexa_attach(target *t); static void cortexa_detach(target *t); diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 80e1caf6..4e941060 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -34,7 +34,7 @@ #include -static char cortexm_driver_str[] = "ARM Cortex-M"; +static const char cortexm_driver_str[] = "ARM Cortex-M"; static bool cortexm_vector_catch(target *t, int argc, char *argv[]); diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c index 4546be58..a30a8050 100644 --- a/src/target/jtag_scan.c +++ b/src/target/jtag_scan.c @@ -32,11 +32,11 @@ struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1]; int jtag_dev_count; -static struct jtag_dev_descr_s { - uint32_t idcode; - uint32_t idmask; - char *descr; - void (*handler)(jtag_dev_t *dev); +static const struct jtag_dev_descr_s { + const uint32_t idcode; + const uint32_t idmask; + const char * const descr; + void (*const handler)(jtag_dev_t *dev); } dev_descr[] = { {.idcode = 0x0BA00477, .idmask = 0x0FFF0FFF, .descr = "ARM Limited: ADIv5 JTAG-DP port.", diff --git a/src/target/jtag_scan.h b/src/target/jtag_scan.h index e96f6e70..3c723f4a 100644 --- a/src/target/jtag_scan.h +++ b/src/target/jtag_scan.h @@ -36,7 +36,7 @@ typedef struct jtag_dev_s { uint8_t ir_postscan; uint32_t idcode; - char *descr; + const char *descr; uint32_t current_ir;