flash/stm32*: Rewrite info functions
[fw/openocd] / src / flash / nor / stm32f1x.c
index 8e5bf79a1342091cf8bf6086bab4cc9d83f5dd96..3c360fcd0f89d748b9a2eeb00a245d4ba176f832 100644 (file)
@@ -21,7 +21,7 @@
  *   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
@@ -124,6 +124,8 @@ struct stm32x_flash_bank {
        uint32_t register_base;
        uint16_t default_rdp;
        int user_data_offset;
+       int option_offset;
+       uint32_t user_bank_size;
 };
 
 static int stm32x_mass_erase(struct flash_bank *bank);
@@ -146,6 +148,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
        stm32x_info->probed = 0;
        stm32x_info->has_dual_banks = false;
        stm32x_info->register_base = FLASH_REG_BASE_B0;
+       stm32x_info->user_bank_size = bank->size;
 
        return ERROR_OK;
 }
@@ -204,7 +207,7 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
        return retval;
 }
 
-int stm32x_check_operation_supported(struct flash_bank *bank)
+static int stm32x_check_operation_supported(struct flash_bank *bank)
 {
        struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
 
@@ -231,7 +234,7 @@ static int stm32x_read_options(struct flash_bank *bank)
        if (retval != ERROR_OK)
                return retval;
 
-       stm32x_info->option_bytes.user_options = (uint16_t)0xFFF0 | ((optiondata >> 2) & 0x0f);
+       stm32x_info->option_bytes.user_options = (optiondata >> stm32x_info->option_offset >> 2) & 0xffff;
        stm32x_info->option_bytes.user_data = (optiondata >> stm32x_info->user_data_offset) & 0xffff;
        stm32x_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5;
 
@@ -361,11 +364,6 @@ static int stm32x_protect_check(struct flash_bank *bank)
        int num_bits;
        int set;
 
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
        int retval = stm32x_check_operation_supported(bank);
        if (ERROR_OK != retval)
                return retval;
@@ -656,7 +654,7 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
        buf_set_u32(reg_params[4].value, 0, 32, address);
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
-       armv7m_info.core_mode = ARMV7M_MODE_ANY;
+       armv7m_info.core_mode = ARM_MODE_THREAD;
 
        retval = target_run_flash_async_algorithm(target, buffer, count, 2,
                        0, NULL,
@@ -857,6 +855,7 @@ static int stm32x_probe(struct flash_bank *bank)
        stm32x_info->probed = 0;
        stm32x_info->register_base = FLASH_REG_BASE_B0;
        stm32x_info->user_data_offset = 10;
+       stm32x_info->option_offset = 0;
 
        /* default factory protection level */
        stm32x_info->default_rdp = 0x5AA5;
@@ -900,6 +899,7 @@ static int stm32x_probe(struct flash_bank *bank)
                stm32x_info->ppage_size = 2;
                max_flash_size_in_kb = 256;
                stm32x_info->user_data_offset = 16;
+               stm32x_info->option_offset = 6;
                stm32x_info->default_rdp = 0x55AA;
                break;
        case 0x428: /* value line High density */
@@ -918,13 +918,16 @@ static int stm32x_probe(struct flash_bank *bank)
                stm32x_info->ppage_size = 2;
                max_flash_size_in_kb = 256;
                stm32x_info->user_data_offset = 16;
+               stm32x_info->option_offset = 6;
                stm32x_info->default_rdp = 0x55AA;
                break;
        case 0x440: /* stm32f0x */
+       case 0x444:
                page_size = 1024;
                stm32x_info->ppage_size = 4;
                max_flash_size_in_kb = 64;
                stm32x_info->user_data_offset = 16;
+               stm32x_info->option_offset = 6;
                stm32x_info->default_rdp = 0x55AA;
                break;
        default:
@@ -956,6 +959,13 @@ static int stm32x_probe(struct flash_bank *bank)
                }
        }
 
+       /* 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 = %dkbytes", flash_size_in_kb);
 
        /* did we assign flash size? */
@@ -1006,203 +1016,174 @@ COMMAND_HANDLER(stm32x_handle_part_id_command)
 
 static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
 {
-       uint32_t device_id;
-       int printed;
+       uint32_t dbgmcu_idcode;
 
                /* read stm32 device id register */
-       int retval = stm32x_get_device_id(bank, &device_id);
+       int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
        if (retval != ERROR_OK)
                return retval;
 
-       if ((device_id & 0xfff) == 0x410) {
-               printed = snprintf(buf, buf_size, "stm32x (Medium Density) - 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 0x0000:
-                               snprintf(buf, buf_size, "A");
-                               break;
+       switch (device_id) {
+       case 0x410:
+               device_str = "stm32x (Medium Density)";
 
-                       case 0x2000:
-                               snprintf(buf, buf_size, "B");
-                               break;
+               switch (rev_id) {
+               case 0x0000:
+                       rev_str = "A";
+                       break;
 
-                       case 0x2001:
-                               snprintf(buf, buf_size, "Z");
-                               break;
+               case 0x2000:
+                       rev_str = "B";
+                       break;
 
-                       case 0x2003:
-                               snprintf(buf, buf_size, "Y");
-                               break;
+               case 0x2001:
+                       rev_str = "Z";
+                       break;
 
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               case 0x2003:
+                       rev_str = "Y";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x412) {
-               printed = snprintf(buf, buf_size, "stm32x (Low Density) - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x412:
+               device_str = "stm32x (Low Density)";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x414) {
-               printed = snprintf(buf, buf_size, "stm32x (High Density) - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       case 0x1001:
-                               snprintf(buf, buf_size, "Z");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x414:
+               device_str = "stm32x (High Density)";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
+
+               case 0x1001:
+                       rev_str = "Z";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x418) {
-               printed = snprintf(buf, buf_size, "stm32x (Connectivity) - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       case 0x1001:
-                               snprintf(buf, buf_size, "Z");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x418:
+               device_str = "stm32x (Connectivity)";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
+
+               case 0x1001:
+                       rev_str = "Z";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x420) {
-               printed = snprintf(buf, buf_size, "stm32x (Value) - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       case 0x1001:
-                               snprintf(buf, buf_size, "Z");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x420:
+               device_str = "stm32x (Value)";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
+
+               case 0x1001:
+                       rev_str = "Z";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x422) {
-               printed = snprintf(buf, buf_size, "stm32f30x - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       case 0x1001:
-                               snprintf(buf, buf_size, "Z");
-                               break;
-
-                       case 0x2000:
-                               snprintf(buf, buf_size, "B");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x422:
+               device_str = "stm32f30x";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
+
+               case 0x1001:
+                       rev_str = "Z";
+                       break;
+
+               case 0x2000:
+                       rev_str = "B";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x428) {
-               printed = snprintf(buf, buf_size, "stm32x (Value HD) - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       case 0x1001:
-                               snprintf(buf, buf_size, "Z");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x428:
+               device_str = "stm32x (Value HD)";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
+
+               case 0x1001:
+                       rev_str = "Z";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x430) {
-               printed = snprintf(buf, buf_size, "stm32x (XL) - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x430:
+               device_str = "stm32x (XL)";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x432) {
-               printed = snprintf(buf, buf_size, "stm32f37x - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "A");
-                               break;
-
-                       case 0x2000:
-                               snprintf(buf, buf_size, "B");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x432:
+               device_str = "stm32f37x";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "A";
+                       break;
+
+               case 0x2000:
+                       rev_str = "B";
+                       break;
                }
-       } else if ((device_id & 0xfff) == 0x440) {
-               printed = snprintf(buf, buf_size, "stm32f0x - Rev: ");
-               buf += printed;
-               buf_size -= printed;
-
-               switch (device_id >> 16) {
-                       case 0x1000:
-                               snprintf(buf, buf_size, "1.0");
-                               break;
-
-                       case 0x2000:
-                               snprintf(buf, buf_size, "2.0");
-                               break;
-
-                       default:
-                               snprintf(buf, buf_size, "unknown");
-                               break;
+               break;
+
+       case 0x440:
+       case 0x444:
+               device_str = "stm32f0x";
+
+               switch (rev_id) {
+               case 0x1000:
+                       rev_str = "1.0";
+                       break;
+
+               case 0x2000:
+                       rev_str = "2.0";
+                       break;
                }
-       } else {
+               break;
+
+       default:
                snprintf(buf, buf_size, "Cannot identify target as a stm32x\n");
                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;
 }
 
@@ -1322,6 +1303,8 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
                return retval;
        command_print(CMD_CTX, "Option Byte: 0x%" PRIx32 "", optionbyte);
 
+       int user_data = optionbyte;
+
        if (buf_get_u32((uint8_t *)&optionbyte, OPT_ERROR, 1))
                command_print(CMD_CTX, "Option Byte Complement Error");
 
@@ -1330,6 +1313,9 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
        else
                command_print(CMD_CTX, "Readout Protection Off");
 
+       /* user option bytes are offset depending on variant */
+       optionbyte >>= stm32x_info->option_offset;
+
        if (buf_get_u32((uint8_t *)&optionbyte, OPT_RDWDGSW, 1))
                command_print(CMD_CTX, "Software Watchdog");
        else
@@ -1353,9 +1339,9 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
        }
 
        command_print(CMD_CTX, "User Option0: 0x%02" PRIx8,
-                       (optionbyte >> stm32x_info->user_data_offset) & 0xff);
+                       (user_data >> stm32x_info->user_data_offset) & 0xff);
        command_print(CMD_CTX, "User Option1: 0x%02" PRIx8,
-                       (optionbyte >> (stm32x_info->user_data_offset + 8)) & 0xff);
+                       (user_data >> (stm32x_info->user_data_offset + 8)) & 0xff);
 
        return ERROR_OK;
 }