stm32: add new stm32f0 device id
[fw/openocd] / src / flash / nor / stm32f1x.c
index 2d86e56655ae3af6e4f9a456eccec936c484f61d..5ad0b62279d37d0f5578b55ef0c93b87cb627722 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)0xFFF8 | ((optiondata >> 2) & 0x07);
+       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;
 
@@ -656,7 +659,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 +860,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 +904,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 +923,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 +964,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? */
@@ -1180,7 +1195,8 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
                                snprintf(buf, buf_size, "unknown");
                                break;
                }
-       } else if ((device_id & 0xfff) == 0x440) {
+       } else if (((device_id & 0xfff) == 0x440) ||
+                       ((device_id & 0xfff) == 0x444)) {
                printed = snprintf(buf, buf_size, "stm32f0x - Rev: ");
                buf += printed;
                buf_size -= printed;
@@ -1322,6 +1338,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 +1348,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 +1374,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;
 }
@@ -1364,9 +1385,9 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
 {
        struct target *target = NULL;
        struct stm32x_flash_bank *stm32x_info = NULL;
-       uint16_t optionbyte = 0xF8;
+       uint16_t optionbyte;
 
-       if (CMD_ARGC < 4)
+       if (CMD_ARGC < 2)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        struct flash_bank *bank;
@@ -1387,34 +1408,41 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
        if (ERROR_OK != retval)
                return retval;
 
-       /* REVISIT: ignores some options which we will display...
-        * and doesn't insist on the specified syntax.
-        */
-
-       /* OPT_RDWDGSW */
-       if (strcmp(CMD_ARGV[1], "SWWDG") == 0)
-               optionbyte |= (1 << 0);
-       else    /* REVISIT must be "HWWDG" then ... */
-               optionbyte &= ~(1 << 0);
-
-       /* OPT_RDRSTSTOP */
-       if (strcmp(CMD_ARGV[2], "NORSTSTOP") == 0)
-               optionbyte |= (1 << 1);
-       else    /* REVISIT must be "RSTSTNDBY" then ... */
-               optionbyte &= ~(1 << 1);
-
-       /* OPT_RDRSTSTDBY */
-       if (strcmp(CMD_ARGV[3], "NORSTSTNDBY") == 0)
-               optionbyte |= (1 << 2);
-       else    /* REVISIT must be "RSTSTOP" then ... */
-               optionbyte &= ~(1 << 2);
-
-       if (CMD_ARGC > 4 && stm32x_info->has_dual_banks) {
-               /* OPT_BFB2 */
-               if (strcmp(CMD_ARGV[4], "BOOT0") == 0)
-                       optionbyte |= (1 << 3);
-               else
-                       optionbyte &= ~(1 << 3);
+       retval = stm32x_read_options(bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       /* start with current options */
+       optionbyte = stm32x_info->option_bytes.user_options;
+
+       /* skip over flash bank */
+       CMD_ARGC--;
+       CMD_ARGV++;
+
+       while (CMD_ARGC) {
+               if (strcmp("SWWDG", CMD_ARGV[0]) == 0)
+                       optionbyte |= (1 << 0);
+               else if (strcmp("HWWDG", CMD_ARGV[0]) == 0)
+                       optionbyte &= ~(1 << 0);
+               else if (strcmp("NORSTSTOP", CMD_ARGV[0]) == 0)
+                       optionbyte &= ~(1 << 1);
+               else if (strcmp("RSTSTNDBY", CMD_ARGV[0]) == 0)
+                       optionbyte &= ~(1 << 1);
+               else if (strcmp("NORSTSTNDBY", CMD_ARGV[0]) == 0)
+                       optionbyte &= ~(1 << 2);
+               else if (strcmp("RSTSTOP", CMD_ARGV[0]) == 0)
+                       optionbyte &= ~(1 << 2);
+               else if (stm32x_info->has_dual_banks) {
+                       if (strcmp("BOOT0", CMD_ARGV[0]) == 0)
+                               optionbyte |= (1 << 3);
+                       else if (strcmp("BOOT1", CMD_ARGV[0]) == 0)
+                               optionbyte &= ~(1 << 3);
+                       else
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+               } else
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               CMD_ARGC--;
+               CMD_ARGV++;
        }
 
        if (stm32x_erase_options(bank) != ERROR_OK) {