STM32L: Write partial-page flash data after full-page data
[fw/openocd] / src / flash / nor / stm32lx.c
index 58a2a80b02edb8a1010ee21342b7a41e94ded778..3bc6eed97006fd484db77eabe6b27cd86def91ad 100644 (file)
@@ -409,6 +409,7 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
        }
 
        bytes_written = 128 * halfpages_number;
+       address += bytes_written;
 
        retval = stm32lx_unlock_program_memory(bank);
        if (retval != ERROR_OK)
@@ -461,9 +462,8 @@ static int stm32lx_probe(struct flash_bank *bank)
        struct target *target = bank->target;
        struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
        int i;
-       uint16_t flash_size;
+       uint16_t flash_size_in_kb;
        uint32_t device_id;
-       uint32_t reg32;
 
        stm32lx_info->probed = 0;
 
@@ -474,78 +474,27 @@ static int stm32lx_probe(struct flash_bank *bank)
 
        LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id);
 
-       if ((device_id & 0xfff) != 0x416) {
-               LOG_WARNING("Cannot identify target as a STM32L family.");
-               return ERROR_FAIL;
-       }
-
-       /* Read the RDP byte and check if it is 0xAA */
-       uint8_t rdp;
-       retval = target_read_u32(target, FLASH_OBR, &reg32);
-       if (retval != ERROR_OK)
-               return retval;
-       rdp = reg32 & 0xFF;
-       if (rdp != 0xAA) {
-               /*
-                * Unlocking the option byte is done by unlocking the PECR, then
-                * by writing the 2 option byte keys to OPTKEYR
-                */
-
-               /* To unlock the PECR write the 2 PEKEY to the PEKEYR register */
-               retval = target_write_u32(target, FLASH_PEKEYR, PEKEY1);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               retval = target_write_u32(target, FLASH_PEKEYR, PEKEY2);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* Make sure it worked */
-               retval = target_read_u32(target, FLASH_PECR, &reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               if (reg32 & FLASH_PECR__PELOCK)
-                       return ERROR_FLASH_OPERATION_FAILED;
-
-               retval = target_write_u32(target, FLASH_OPTKEYR, OPTKEY1);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = target_write_u32(target, FLASH_OPTKEYR, OPTKEY2);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               retval = target_read_u32(target, FLASH_PECR, &reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               if (reg32 & FLASH_PECR__OPTLOCK) {
-                       LOG_ERROR("OPTLOCK is not cleared");
-                       return ERROR_FLASH_OPERATION_FAILED;
-               }
-
-               /* Then, write RDP to 0x00 to set level 1 */
-               reg32 = ((~0xAA) << 16) | (0xAA);
-               retval = target_write_u32(target, OB_RDP, reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR */
-               reg32 = FLASH_PECR__OBL_LAUNCH;
-               retval = target_write_u32(target, FLASH_PECR, reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
        /* get flash size from target. */
-       retval = target_read_u16(target, F_SIZE, &flash_size);
+       retval = target_read_u16(target, F_SIZE, &flash_size_in_kb);
        if (retval != ERROR_OK)
                return retval;
 
-       /* check for valid flash size */
-       if (flash_size == 0xffff) {
-               /* number of sectors incorrect on revA */
-               LOG_ERROR("STM32 flash size failed, probe inaccurate");
+       if ((device_id & 0xfff) == 0x416) {
+               /* check for early silicon */
+               if (flash_size_in_kb == 0xffff) {
+                       /* number of sectors may be incorrrect on early silicon */
+                       LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
+                       flash_size_in_kb = 128;
+               }
+       } else if ((device_id & 0xfff) == 0x436) {
+               /* check for early silicon */
+               if (flash_size_in_kb == 0xffff) {
+                       /* number of sectors may be incorrrect on early silicon */
+                       LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 384k flash");
+                       flash_size_in_kb = 384;
+               }
+       } else {
+               LOG_WARNING("Cannot identify target as a STM32L family.");
                return ERROR_FAIL;
        }
 
@@ -553,8 +502,8 @@ static int stm32lx_probe(struct flash_bank *bank)
         * 16 pages for a protection area */
 
        /* calculate numbers of sectors (4kB per sector) */
-       int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE;
-       LOG_INFO("flash size = %dkbytes", flash_size);
+       int num_sectors = (flash_size_in_kb * 1024) / FLASH_SECTOR_SIZE;
+       LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
 
        if (bank->sectors) {
                free(bank->sectors);
@@ -562,7 +511,7 @@ static int stm32lx_probe(struct flash_bank *bank)
        }
 
        bank->base = FLASH_BANK0_ADDRESS;
-       bank->size = flash_size * 1024;
+       bank->size = flash_size_in_kb * 1024;
        bank->num_sectors = num_sectors;
        bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
        if (bank->sectors == NULL) {
@@ -668,6 +617,33 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
                        case 0x1008:
                                snprintf(buf, buf_size, "Y");
                                break;
+
+                       case 0x1038:
+                               snprintf(buf, buf_size, "W");
+                               break;
+
+                       case 0x1078:
+                               snprintf(buf, buf_size, "V");
+                               break;
+
+                       default:
+                               snprintf(buf, buf_size, "unknown");
+                               break;
+               }
+       } else if ((device_id & 0xfff) == 0x436) {
+               printed = snprintf(buf, buf_size, "stm32lx (HD) - Rev: ");
+               buf += printed;
+               buf_size -= printed;
+
+               switch (device_id >> 16) {
+                       case 0x1000:
+                               snprintf(buf, buf_size, "A");
+                               break;
+
+                       case 0x1008:
+                               snprintf(buf, buf_size, "Z");
+                               break;
+
                        default:
                                snprintf(buf, buf_size, "unknown");
                                break;