flash/nor/stm32xx: fix segfault accessing Cortex-M part number
[fw/openocd] / src / flash / nor / stm32f2x.c
index 6510e75dc1ce127706ef8263f5b44c3f6550bd5e..58edca7e1be9a5f6723b345c1cb6a9805d58ed77 100644 (file)
@@ -29,7 +29,7 @@
 #include "imp.h"
 #include <helper/binarybuffer.h>
 #include <target/algorithm.h>
-#include <target/armv7m.h>
+#include <target/cortex_m.h>
 
 /* Regarding performance:
  *
@@ -204,7 +204,7 @@ struct stm32x_flash_bank {
        bool has_extra_options; /* F42x/43x/469/479/7xx */
        bool has_boot_addr;     /* F7xx */
        bool has_optcr2_pcrop;  /* F72x/73x */
-       int protection_bits;    /* F413/423 */
+       unsigned int protection_bits; /* F413/423 */
        uint32_t user_bank_size;
 };
 
@@ -571,7 +571,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
 {
        struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
        struct flash_sector *prot_blocks;
-       int num_prot_blocks;
+       unsigned int num_prot_blocks;
        int retval;
 
        /* if it's the OTP bank, look at the lock bits there */
@@ -593,7 +593,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
                prot_blocks = bank->sectors;
        }
 
-       for (int i = 0; i < num_prot_blocks; i++)
+       for (unsigned int i = 0; i < num_prot_blocks; i++)
                prot_blocks[i].is_protected =
                        ~(stm32x_info->option_bytes.protection >> i) & 1;
 
@@ -636,8 +636,8 @@ static int stm32x_erase(struct flash_bank *bank, unsigned int first,
 
        for (unsigned int i = first; i <= last; i++) {
                unsigned int snb;
-               if (stm32x_info->has_large_mem && i >= 12)
-                       snb = (i - 12) | 0x10;
+               if (stm32x_info->has_large_mem && i >= (bank->num_sectors / 2))
+                       snb = (i - (bank->num_sectors / 2)) | 0x10;
                else
                        snb = i;
 
@@ -649,8 +649,6 @@ static int stm32x_erase(struct flash_bank *bank, unsigned int first,
                retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
                if (retval != ERROR_OK)
                        return retval;
-
-               bank->sectors[i].is_erased = 1;
        }
 
        retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
@@ -906,9 +904,8 @@ static void setup_sector(struct flash_bank *bank, unsigned int i,
        LOG_DEBUG("sector %u: %ukBytes", i, size >> 10);
 }
 
-static uint16_t sector_size_in_kb(int i, uint16_t max_sector_size_in_kb)
+static uint16_t sector_size_in_kb(unsigned int i, uint16_t max_sector_size_in_kb)
 {
-       assert(i >= 0);
        if (i < 4)
                return max_sector_size_in_kb / 8;
        if (i == 4)
@@ -916,13 +913,13 @@ static uint16_t sector_size_in_kb(int i, uint16_t max_sector_size_in_kb)
        return max_sector_size_in_kb;
 }
 
-static int calculate_number_of_sectors(struct flash_bank *bank,
+static unsigned int calculate_number_of_sectors(struct flash_bank *bank,
                uint16_t flash_size_in_kb,
                uint16_t max_sector_size_in_kb)
 {
        struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
        uint16_t remaining_flash_size_in_kb = flash_size_in_kb;
-       int nr_sectors;
+       unsigned int nr_sectors;
 
        /* Dual Bank Flash has two identically-arranged banks of sectors. */
        if (stm32x_info->has_large_mem)
@@ -943,11 +940,11 @@ static int calculate_number_of_sectors(struct flash_bank *bank,
        return stm32x_info->has_large_mem ? nr_sectors*2 : nr_sectors;
 }
 
-static void setup_bank(struct flash_bank *bank, int start,
+static void setup_bank(struct flash_bank *bank, unsigned int start,
        uint16_t flash_size_in_kb, uint16_t max_sector_size_in_kb)
 {
        uint16_t remaining_flash_size_in_kb = flash_size_in_kb;
-       int sector_index = 0;
+       unsigned int sector_index = 0;
        while (remaining_flash_size_in_kb > 0) {
                uint16_t size_in_kb = sector_size_in_kb(sector_index, max_sector_size_in_kb);
                if (size_in_kb > remaining_flash_size_in_kb) {
@@ -969,25 +966,17 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
         * Only effects Rev A silicon */
 
        struct target *target = bank->target;
-       uint32_t cpuid;
 
        /* read stm32 device id register */
        int retval = target_read_u32(target, 0xE0042000, device_id);
        if (retval != ERROR_OK)
                return retval;
 
-       if ((*device_id & 0xfff) == 0x411) {
-               /* read CPUID reg to check core type */
-               retval = target_read_u32(target, 0xE000ED00, &cpuid);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* check for cortex_m4 */
-               if (((cpuid >> 4) & 0xFFF) == 0xC24) {
-                       *device_id &= ~((0xFFFF << 16) | 0xfff);
-                       *device_id |= (0x1000 << 16) | 0x413;
-                       LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");
-               }
+       if ((*device_id & 0xfff) == 0x411
+                       && cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO) {
+               *device_id &= ~((0xFFFF << 16) | 0xfff);
+               *device_id |= (0x1000 << 16) | 0x413;
+               LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");
        }
        return retval;
 }
@@ -996,7 +985,7 @@ static int stm32x_probe(struct flash_bank *bank)
 {
        struct target *target = bank->target;
        struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
-       int i, num_prot_blocks, num_sectors;
+       unsigned int num_prot_blocks, num_sectors;
        uint16_t flash_size_in_kb;
        uint16_t otp_size_in_b;
        uint16_t otp_sector_size;
@@ -1014,16 +1003,17 @@ static int stm32x_probe(struct flash_bank *bank)
        stm32x_info->protection_bits = 12;              /* max. number of nWRPi bits (in FLASH_OPTCR !!!) */
        num_prot_blocks = 0;
 
-       if (bank->sectors) {
-               free(bank->sectors);
-               bank->num_sectors = 0;
-               bank->sectors = NULL;
-       }
+       free(bank->sectors);
+       bank->num_sectors = 0;
+       bank->sectors = NULL;
 
-       if (bank->prot_blocks) {
-               free(bank->prot_blocks);
-               bank->num_prot_blocks = 0;
-               bank->prot_blocks = NULL;
+       free(bank->prot_blocks);
+       bank->num_prot_blocks = 0;
+       bank->prot_blocks = NULL;
+
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_TARGET_NOT_EXAMINED;
        }
 
        /* if explicitly called out as OTP bank, short circuit probe */
@@ -1049,7 +1039,7 @@ static int stm32x_probe(struct flash_bank *bank)
                else
                        bank->size = STM32F2_OTP_SIZE;
 
-               for (i = 0; i < num_sectors; i++) {
+               for (unsigned int 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;
@@ -1190,18 +1180,18 @@ static int stm32x_probe(struct flash_bank *bank)
        }
 
        /* calculate numbers of pages */
-       int num_pages = calculate_number_of_sectors(
+       unsigned int num_pages = calculate_number_of_sectors(
                        bank, flash_size_in_kb, max_sector_size_in_kb);
 
        bank->base = base_address;
        bank->num_sectors = num_pages;
        bank->sectors = calloc(num_pages, sizeof(struct flash_sector));
-       for (i = 0; i < num_pages; i++) {
+       for (unsigned int i = 0; i < num_pages; i++) {
                bank->sectors[i].is_erased = -1;
                bank->sectors[i].is_protected = 0;
        }
        bank->size = 0;
-       LOG_DEBUG("allocated %d sectors", num_pages);
+       LOG_DEBUG("allocated %u sectors", num_pages);
 
        /* F76x/77x in dual bank mode */
        if ((device_id == 0x451) && stm32x_info->has_large_mem)
@@ -1209,9 +1199,9 @@ static int stm32x_probe(struct flash_bank *bank)
 
        if (num_prot_blocks) {
                bank->prot_blocks = malloc(sizeof(struct flash_sector) * num_prot_blocks);
-               for (i = 0; i < num_prot_blocks; i++)
+               for (unsigned int i = 0; i < num_prot_blocks; i++)
                        bank->prot_blocks[i].is_protected = 0;
-               LOG_DEBUG("allocated %d prot blocks", num_prot_blocks);
+               LOG_DEBUG("allocated %u prot blocks", num_prot_blocks);
        }
 
        if (stm32x_info->has_large_mem) {
@@ -1222,7 +1212,7 @@ static int stm32x_probe(struct flash_bank *bank)
 
                /* F767x/F77x in dual mode, one protection bit refers to two adjacent sectors */
                if (device_id == 0x451) {
-                       for (i = 0; i < num_prot_blocks; i++) {
+                       for (unsigned int i = 0; i < num_prot_blocks; i++) {
                                bank->prot_blocks[i].offset = bank->sectors[i << 1].offset;
                                bank->prot_blocks[i].size = bank->sectors[i << 1].size
                                                + bank->sectors[(i << 1) + 1].size;
@@ -1234,7 +1224,7 @@ static int stm32x_probe(struct flash_bank *bank)
 
                /* F413/F423, sectors 14 and 15 share one common protection bit */
                if (device_id == 0x463) {
-                       for (i = 0; i < num_prot_blocks; i++) {
+                       for (unsigned int i = 0; i < num_prot_blocks; i++) {
                                bank->prot_blocks[i].offset = bank->sectors[i].offset;
                                bank->prot_blocks[i].size = bank->sectors[i].size;
                        }
@@ -1256,7 +1246,7 @@ static int stm32x_auto_probe(struct flash_bank *bank)
        return stm32x_probe(bank);
 }
 
-static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
+static int get_stm32x_info(struct flash_bank *bank, struct command_invocation *cmd)
 {
        uint32_t dbgmcu_idcode;
 
@@ -1421,14 +1411,14 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
                break;
 
        default:
-               snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4/7\n");
+               command_print_sameline(cmd, "Cannot identify target as a STM32F2/4/7\n");
                return ERROR_FAIL;
        }
 
-       if (rev_str != NULL)
-               snprintf(buf, buf_size, "%s - Rev: %s", device_str, rev_str);
+       if (rev_str)
+               command_print_sameline(cmd, "%s - Rev: %s", device_str, rev_str);
        else
-               snprintf(buf, buf_size, "%s - Rev: unknown (0x%04" PRIx16 ")", device_str, rev_id);
+               command_print_sameline(cmd, "%s - Rev: unknown (0x%04" PRIx16 ")", device_str, rev_id);
 
        return ERROR_OK;
 }
@@ -1443,7 +1433,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
 
        struct flash_bank *bank;
        int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        stm32x_info = bank->driver_priv;
@@ -1482,7 +1472,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
 
        struct flash_bank *bank;
        int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        stm32x_info = bank->driver_priv;
@@ -1569,15 +1559,11 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
 
        struct flash_bank *bank;
        int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        retval = stm32x_mass_erase(bank);
        if (retval == ERROR_OK) {
-               /* set all sectors as erased */
-               for (unsigned int i = 0; i < bank->num_sectors; i++)
-                       bank->sectors[i].is_erased = 1;
-
                command_print(CMD, "stm32x mass erase complete");
        } else {
                command_print(CMD, "stm32x mass erase failed");
@@ -1598,11 +1584,11 @@ COMMAND_HANDLER(stm32f2x_handle_options_read_command)
        }
 
        retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        retval = stm32x_read_options(bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        stm32x_info = bank->driver_priv;
@@ -1644,11 +1630,11 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command)
        }
 
        retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        retval = stm32x_read_options(bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        stm32x_info = bank->driver_priv;
@@ -1706,7 +1692,7 @@ COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command)
        }
 
        retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        stm32x_info = bank->driver_priv;
@@ -1720,7 +1706,7 @@ COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command)
                                " finally unlock it. Clears PCROP and mass erases flash.");
 
        retval = stm32x_read_options(bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], optcr2_pcrop);
@@ -1744,7 +1730,7 @@ COMMAND_HANDLER(stm32x_handle_otp_command)
 
        struct flash_bank *bank;
        int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
        if (stm32x_is_otp(bank)) {
                if (strcmp(CMD_ARGV[1], "enable") == 0) {
@@ -1766,7 +1752,7 @@ COMMAND_HANDLER(stm32x_handle_otp_command)
        return retval;
 }
 
-static const struct command_registration stm32x_exec_command_handlers[] = {
+static const struct command_registration stm32f2x_exec_command_handlers[] = {
        {
                .name = "lock",
                .handler = stm32x_handle_lock_command,
@@ -1819,20 +1805,20 @@ static const struct command_registration stm32x_exec_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
-static const struct command_registration stm32x_command_handlers[] = {
+static const struct command_registration stm32f2x_command_handlers[] = {
        {
                .name = "stm32f2x",
                .mode = COMMAND_ANY,
                .help = "stm32f2x flash command group",
                .usage = "",
-               .chain = stm32x_exec_command_handlers,
+               .chain = stm32f2x_exec_command_handlers,
        },
        COMMAND_REGISTRATION_DONE
 };
 
 const struct flash_driver stm32f2x_flash = {
        .name = "stm32f2x",
-       .commands = stm32x_command_handlers,
+       .commands = stm32f2x_command_handlers,
        .flash_bank_command = stm32x_flash_bank_command,
        .erase = stm32x_erase,
        .protect = stm32x_protect,