* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
/* other registers */
#define DBGMCU_IDCODE 0xE0042000
#define F_SIZE 0x1FF8004C
+#define F_SIZE_MP 0x1FF800CC /* on 0x427 Medium+ and 0x436 HD devices */
/* Constants */
#define FLASH_PAGE_SIZE 256
struct stm32lx_flash_bank {
int probed;
bool has_dual_banks;
+ uint32_t user_bank_size;
};
/* flash bank stm32lx <base> <size> 0 0 <target#>
stm32lx_info->probed = 0;
stm32lx_info->has_dual_banks = false;
+ stm32lx_info->user_bank_size = bank->size;
return ERROR_OK;
}
uint32_t wrpr;
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
/*
* Read the WRPR word, and check each bit (corresponding to each
* flash sector
case 0x416:
max_flash_size_in_kb = 128;
break;
+ case 0x427:
+ /* single bank, high density */
+ max_flash_size_in_kb = 256;
+ break;
case 0x436:
/* According to ST, the devices with id 0x436 have dual bank flash and comes with
* a total flash size of 384k or 256kb. However, the first bank is always 192kb,
return ERROR_FAIL;
}
- /* Get the flash size from target. */
- retval = target_read_u16(target, F_SIZE, &flash_size_in_kb);
+ /* Get the flash size from target. 0x427 and 0x436 devices use a
+ * different location for the Flash Size register, please see RM0038 r8 or
+ * newer. */
+ if ((device_id & 0xfff) == 0x427 || (device_id & 0xfff) == 0x436)
+ retval = target_read_u16(target, F_SIZE_MP, &flash_size_in_kb);
+ else
+ retval = target_read_u16(target, F_SIZE, &flash_size_in_kb);
+
+ /* 0x436 devices report their flash size as a 0 or 1 code indicating 384K
+ * or 256K, respectively. Please see RM0038 r8 or newer and refer to
+ * section 30.1.1. */
+ if (retval == ERROR_OK && (device_id & 0xfff) == 0x436) {
+ if (flash_size_in_kb == 0)
+ flash_size_in_kb = 384;
+ else if (flash_size_in_kb == 1)
+ flash_size_in_kb = 256;
+ }
/* Failed reading flash size or flash size invalid (early silicon),
* default to max target family */
/* 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 (bank->size) {
- flash_size_in_kb = bank->size / 1024;
+ if (stm32lx_info->user_bank_size) {
+ flash_size_in_kb = stm32lx_info->user_bank_size / 1024;
LOG_INFO("ignoring flash probed value, using configured bank size: %dkbytes", flash_size_in_kb);
}
{
/* This method must return a string displaying information about the bank */
- struct target *target = bank->target;
- uint32_t device_id;
- int printed;
+ uint32_t dbgmcu_idcode;
/* read stm32 device id register */
- int retval = target_read_u32(target, DBGMCU_IDCODE, &device_id);
+ int retval = target_read_u32(bank->target, DBGMCU_IDCODE, &dbgmcu_idcode);
if (retval != ERROR_OK)
return retval;
- if ((device_id & 0xfff) == 0x416) {
- printed = snprintf(buf, buf_size, "stm32lx - Rev: ");
- buf += printed;
- buf_size -= printed;
+ uint16_t device_id = dbgmcu_idcode & 0xfff;
+ uint16_t rev_id = dbgmcu_idcode >> 16;
+ const char *device_str;
+ const char *rev_str = NULL;
- switch (device_id >> 16) {
- case 0x1000:
- snprintf(buf, buf_size, "A");
- break;
+ switch (device_id) {
+ case 0x416:
+ device_str = "STM32L1xx (Low/Medium Density)";
- case 0x1008:
- snprintf(buf, buf_size, "Y");
- break;
+ switch (rev_id) {
+ case 0x1000:
+ rev_str = "A";
+ break;
- case 0x1018:
- snprintf(buf, buf_size, "X");
- break;
+ case 0x1008:
+ rev_str = "Y";
+ break;
- case 0x1038:
- snprintf(buf, buf_size, "W");
- break;
+ case 0x1018:
+ rev_str = "X";
+ break;
- case 0x1078:
- snprintf(buf, buf_size, "V");
- break;
+ case 0x1038:
+ rev_str = "W";
+ break;
- default:
- snprintf(buf, buf_size, "unknown");
- break;
+ case 0x1078:
+ rev_str = "V";
+ 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;
+ break;
- case 0x1008:
- snprintf(buf, buf_size, "Z");
- break;
+ case 0x427:
+ device_str = "STM32L1xx (Medium+ Density)";
- case 0x1018:
- snprintf(buf, buf_size, "Y");
- break;
+ switch (rev_id) {
+ case 0x1018:
+ rev_str = "A";
+ break;
+ }
+ break;
- default:
- snprintf(buf, buf_size, "unknown");
- break;
+ case 0x436:
+ device_str = "STM32L1xx (Medium+/High Density)";
+
+ switch (rev_id) {
+ case 0x1000:
+ rev_str = "A";
+ break;
+
+ case 0x1008:
+ rev_str = "Z";
+ break;
+
+ case 0x1018:
+ rev_str = "Y";
+ break;
}
- } else {
- snprintf(buf, buf_size, "Cannot identify target as a stm32lx");
+ break;
+
+ default:
+ snprintf(buf, buf_size, "Cannot identify target as a STM32L1");
return ERROR_FAIL;
}
+ if (rev_str != NULL)
+ snprintf(buf, buf_size, "%s - Rev: %s", device_str, rev_str);
+ else
+ snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", device_str, rev_id);
+
return ERROR_OK;
}