+ if (bank->prot_blocks) {
+ free(bank->prot_blocks);
+ bank->num_prot_blocks = 0;
+ bank->prot_blocks = NULL;
+ }
+
+ /* if explicitely called out as OTP bank, short circuit probe */
+ if (stm32x_is_otp(bank)) {
+ if (stm32x_otp_is_f7(bank)) {
+ otp_size_in_b = STM32F7_OTP_SIZE;
+ otp_sector_size = STM32F7_OTP_SECTOR_SIZE;
+ } else {
+ otp_size_in_b = STM32F2_OTP_SIZE;
+ otp_sector_size = STM32F2_OTP_SECTOR_SIZE;
+ }
+
+ num_sectors = otp_size_in_b / otp_sector_size;
+ LOG_INFO("flash size = %d bytes", otp_size_in_b);
+
+ assert(num_sectors > 0);
+
+ bank->num_sectors = num_sectors;
+ bank->sectors = calloc(sizeof(struct flash_sector), num_sectors);
+
+ if (stm32x_otp_is_f7(bank))
+ bank->size = STM32F7_OTP_SIZE;
+ else
+ bank->size = STM32F2_OTP_SIZE;
+
+ for (i = 0; i < num_sectors; i++) {
+ bank->sectors[i].offset = i * otp_sector_size;
+ bank->sectors[i].size = otp_sector_size;
+ bank->sectors[i].is_erased = 1;
+ bank->sectors[i].is_protected = 0;
+ }
+
+ stm32x_info->probed = true;
+ return ERROR_OK;
+ }
+
+ /* read stm32 device id register */
+ int retval = stm32x_get_device_id(bank, &device_id);
+ if (retval != ERROR_OK)
+ return retval;
+ LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
+ device_id &= 0xfff; /* only bits 0-11 are used further on */
+
+ /* set max flash size depending on family, id taken from AN2606 */
+ switch (device_id) {
+ case 0x411: /* F20x/21x */
+ case 0x413: /* F40x/41x */
+ max_flash_size_in_kb = 1024;
+ break;
+
+ case 0x419: /* F42x/43x */
+ case 0x434: /* F469/479 */
+ stm32x_info->has_extra_options = true;
+ max_flash_size_in_kb = 2048;
+ break;
+
+ case 0x423: /* F401xB/C */
+ max_flash_size_in_kb = 256;
+ break;
+
+ case 0x421: /* F446 */
+ case 0x431: /* F411 */
+ case 0x433: /* F401xD/E */
+ case 0x441: /* F412 */
+ max_flash_size_in_kb = 512;
+ break;
+
+ case 0x458: /* F410 */
+ max_flash_size_in_kb = 128;
+ break;
+
+ case 0x449: /* F74x/75x */
+ max_flash_size_in_kb = 1024;
+ max_sector_size_in_kb = 256;
+ flash_size_reg = 0x1FF0F442;
+ stm32x_info->has_extra_options = true;
+ stm32x_info->has_boot_addr = true;
+ break;
+
+ case 0x451: /* F76x/77x */
+ max_flash_size_in_kb = 2048;
+ max_sector_size_in_kb = 256;
+ flash_size_reg = 0x1FF0F442;
+ stm32x_info->has_extra_options = true;
+ stm32x_info->has_boot_addr = true;
+ break;
+
+ case 0x452: /* F72x/73x */
+ max_flash_size_in_kb = 512;
+ flash_size_reg = 0x1FF07A22; /* yes, 0x1FF*0*7A22, not 0x1FF*F*7A22 */
+ stm32x_info->has_extra_options = true;
+ stm32x_info->has_boot_addr = true;
+ stm32x_info->has_optcr2_pcrop = true;
+ break;
+
+ case 0x463: /* F413x/423x */
+ max_flash_size_in_kb = 1536;
+ stm32x_info->has_extra_options = true;
+ stm32x_info->protection_bits = 15;
+ num_prot_blocks = 15;
+ break;
+
+ default:
+ LOG_WARNING("Cannot identify target as a STM32 family.");
+ return ERROR_FAIL;
+ }
+
+ /* get flash size from target. */
+ retval = target_read_u16(target, flash_size_reg, &flash_size_in_kb);
+
+ /* failed reading flash size or flash size invalid (early silicon),
+ * default to max target family */
+ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
+ LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash",
+ max_flash_size_in_kb);
+ flash_size_in_kb = max_flash_size_in_kb;
+ }
+
+ /* if the user sets the size manually then ignore the probed value
+ * this allows us to work around devices that have a invalid flash size register value */
+ if (stm32x_info->user_bank_size) {
+ LOG_INFO("ignoring flash probed value, using configured bank size");
+ flash_size_in_kb = stm32x_info->user_bank_size / 1024;
+ }
+
+ LOG_INFO("flash size = %d kbytes", flash_size_in_kb);
+
+ /* did we assign flash size? */
+ assert(flash_size_in_kb != 0xffff);
+
+ /* F42x/43x/469/479 1024 kiByte devices have a dual bank option */
+ if ((device_id == 0x419) || (device_id == 0x434)) {
+ uint32_t optiondata;
+ retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
+ if (retval != ERROR_OK) {
+ LOG_DEBUG("unable to read option bytes");
+ return retval;
+ }
+ if ((flash_size_in_kb > 1024) || (optiondata & OPTCR_DB1M)) {
+ stm32x_info->has_large_mem = true;
+ LOG_INFO("Dual Bank %d kiB STM32F42x/43x/469/479 found", flash_size_in_kb);
+ } else {
+ stm32x_info->has_large_mem = false;
+ LOG_INFO("Single Bank %d kiB STM32F42x/43x/469/479 found", flash_size_in_kb);
+ }
+ }
+
+ /* F76x/77x devices have a dual bank option */
+ if (device_id == 0x451) {
+ uint32_t optiondata;
+ retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
+ if (retval != ERROR_OK) {
+ LOG_DEBUG("unable to read option bytes");
+ return retval;
+ }
+ if (optiondata & OPTCR_NDBANK) {
+ stm32x_info->has_large_mem = false;
+ LOG_INFO("Single Bank %d kiB STM32F76x/77x found", flash_size_in_kb);
+ } else {
+ stm32x_info->has_large_mem = true;
+ max_sector_size_in_kb >>= 1; /* sector size divided by 2 in dual-bank mode */
+ LOG_INFO("Dual Bank %d kiB STM32F76x/77x found", flash_size_in_kb);
+ }
+ }
+
+ /* calculate numbers of pages */
+ int num_pages = flash_size_in_kb / max_sector_size_in_kb
+ + (stm32x_info->has_large_mem ? 8 : 4);
+