Clear FLASH_SR error flags after flash errors to avoid reset befor further flash...
[openocd.git] / src / flash / stm32x.c
index 1b821059c6fa038b80d9903f4a31189db586e748..8b8723915800b042d15b601fa8722f2650e19c25 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-int stm32x_register_commands(struct command_context_s *cmd_ctx);
-int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
-int stm32x_erase(struct flash_bank_s *bank, int first, int last);
-int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last);
-int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
-int stm32x_probe(struct flash_bank_s *bank);
-int stm32x_auto_probe(struct flash_bank_s *bank);
-int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int stm32x_protect_check(struct flash_bank_s *bank);
-int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size);
+static int stm32x_register_commands(struct command_context_s *cmd_ctx);
+static int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
+static int stm32x_erase(struct flash_bank_s *bank, int first, int last);
+static int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last);
+static int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
+static int stm32x_probe(struct flash_bank_s *bank);
+static int stm32x_auto_probe(struct flash_bank_s *bank);
+//static int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int stm32x_protect_check(struct flash_bank_s *bank);
+static int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size);
 
-int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int stm32x_mass_erase(struct flash_bank_s *bank);
+static int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int stm32x_mass_erase(struct flash_bank_s *bank);
 
 flash_driver_t stm32x_flash =
 {
@@ -70,7 +70,7 @@ flash_driver_t stm32x_flash =
        .info = stm32x_info
 };
 
-int stm32x_register_commands(struct command_context_s *cmd_ctx)
+static int stm32x_register_commands(struct command_context_s *cmd_ctx)
 {
        command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stm32x", NULL, COMMAND_ANY, "stm32x flash specific commands");
        
@@ -89,7 +89,7 @@ int stm32x_register_commands(struct command_context_s *cmd_ctx)
 
 /* flash bank stm32x <base> <size> 0 0 <target#>
  */
-int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
+static int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
 {
        stm32x_flash_bank_t *stm32x_info;
        
@@ -108,7 +108,7 @@ int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char
        return ERROR_OK;
 }
 
-u32 stm32x_get_flash_status(flash_bank_t *bank)
+static u32 stm32x_get_flash_status(flash_bank_t *bank)
 {
        target_t *target = bank->target;
        u32 status;
@@ -118,8 +118,9 @@ u32 stm32x_get_flash_status(flash_bank_t *bank)
        return status;
 }
 
-u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout)
+static u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout)
 {
+       target_t *target = bank->target;
        u32 status;
        
        /* wait for busy to clear */
@@ -128,11 +129,15 @@ u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout)
                LOG_DEBUG("status: 0x%x", status);
                alive_sleep(1);
        }
-       
+       /* Clear but report errors */
+       if (status & (FLASH_WRPRTERR|FLASH_PGERR))
+       {
+               target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR|FLASH_PGERR);   
+       }
        return status;
 }
 
-int stm32x_read_options(struct flash_bank_s *bank)
+static int stm32x_read_options(struct flash_bank_s *bank)
 {
        u32 optiondata;
        stm32x_flash_bank_t *stm32x_info = NULL;
@@ -160,7 +165,7 @@ int stm32x_read_options(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int stm32x_erase_options(struct flash_bank_s *bank)
+static int stm32x_erase_options(struct flash_bank_s *bank)
 {
        stm32x_flash_bank_t *stm32x_info = NULL;
        target_t *target = bank->target;
@@ -197,7 +202,7 @@ int stm32x_erase_options(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int stm32x_write_options(struct flash_bank_s *bank)
+static int stm32x_write_options(struct flash_bank_s *bank)
 {
        stm32x_flash_bank_t *stm32x_info = NULL;
        target_t *target = bank->target;
@@ -281,7 +286,7 @@ int stm32x_write_options(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int stm32x_protect_check(struct flash_bank_s *bank)
+static int stm32x_protect_check(struct flash_bank_s *bank)
 {
        target_t *target = bank->target;
        stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
@@ -352,7 +357,7 @@ int stm32x_protect_check(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int stm32x_erase(struct flash_bank_s *bank, int first, int last)
+static int stm32x_erase(struct flash_bank_s *bank, int first, int last)
 {
        target_t *target = bank->target;
        int i;
@@ -393,7 +398,7 @@ int stm32x_erase(struct flash_bank_s *bank, int first, int last)
        return ERROR_OK;
 }
 
-int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last)
+static int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last)
 {
        stm32x_flash_bank_t *stm32x_info = NULL;
        target_t *target = bank->target;
@@ -480,11 +485,11 @@ int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last)
        return stm32x_write_options(bank);
 }
 
-int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+static int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 {
        stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
        target_t *target = bank->target;
-       u32 buffer_size = 8192;
+       u32 buffer_size = 16384;
        working_area_t *source;
        u32 address = bank->base + offset;
        reg_param_t reg_params[4];
@@ -508,7 +513,7 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co
                0x01, 0x3A,                                     /* subs r2, r2, #1 */
                0xED, 0xD1,                                     /* bne  write */
                                                                        /* exit: */
-               0xFE, 0xE7,                                     /* b exit */                            
+               0xFE, 0xE7,                                     /* b exit */
                0x10, 0x20, 0x02, 0x40,         /* STM32_FLASH_CR:      .word 0x40022010 */
                0x0C, 0x20, 0x02, 0x40          /* STM32_FLASH_SR:      .word 0x4002200C */
        };
@@ -565,8 +570,20 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co
                        break;
                }
                
-               if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14)
+               if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR)
                {
+                       LOG_ERROR("flash memory not erased before writing");
+                       /* Clear but report errors */
+                       target_write_u32(target, STM32_FLASH_SR, FLASH_PGERR);  
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+               
+               if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR)
+               {
+                       LOG_ERROR("flash memory write protected");
+                       /* Clear but report errors */
+                       target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR);       
                        retval = ERROR_FLASH_OPERATION_FAILED;
                        break;
                }
@@ -587,7 +604,7 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co
        return retval;
 }
 
-int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+static int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 {
        target_t *target = bank->target;
        u32 words_remaining = (count / 2);
@@ -595,7 +612,7 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
        u32 address = bank->base + offset;
        u32 bytes_written = 0;
        u8 status;
-       u32 retval;
+       int retval;
        
        if (bank->target->state != TARGET_HALTED)
        {
@@ -647,9 +664,15 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
                status = stm32x_wait_status_busy(bank, 5);
                
                if( status & FLASH_WRPRTERR )
+               {
+                       LOG_ERROR("flash memory not erased before writing");
                        return ERROR_FLASH_OPERATION_FAILED;
+               }
                if( status & FLASH_PGERR )
+               {
+                       LOG_ERROR("flash memory write protected");
                        return ERROR_FLASH_OPERATION_FAILED;
+               }
 
                bytes_written += 2;
                words_remaining--;
@@ -674,9 +697,15 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
                status = stm32x_wait_status_busy(bank, 5);
                
                if( status & FLASH_WRPRTERR )
+               {
+                       LOG_ERROR("flash memory not erased before writing");
                        return ERROR_FLASH_OPERATION_FAILED;
+               }
                if( status & FLASH_PGERR )
+               {
+                       LOG_ERROR("flash memory write protected");
                        return ERROR_FLASH_OPERATION_FAILED;
+               }
        }
        
        target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
@@ -684,7 +713,7 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
        return ERROR_OK;
 }
 
-int stm32x_probe(struct flash_bank_s *bank)
+static int stm32x_probe(struct flash_bank_s *bank)
 {
        target_t *target = bank->target;
        stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
@@ -757,6 +786,21 @@ int stm32x_probe(struct flash_bank_s *bank)
                        num_pages = 512;
                }
        }
+       else if ((device_id & 0x7ff) == 0x418)
+       {
+               /* connectivity line density - we have 1k pages
+                * 4 pages for a protection area */
+               page_size = 1024;
+               stm32x_info->ppage_size = 4;
+               
+               /* check for early silicon */
+               if (num_pages == 0xffff)
+               {
+                       /* number of sectors incorrect on revZ */
+                       LOG_WARNING( "STM32 flash size failed, probe inaccurate - assuming 256k flash" );
+                       num_pages = 256;
+               }
+       }
        else
        {
                LOG_WARNING( "Cannot identify target as a STM32 family." );
@@ -786,7 +830,7 @@ int stm32x_probe(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int stm32x_auto_probe(struct flash_bank_s *bank)
+static int stm32x_auto_probe(struct flash_bank_s *bank)
 {
        stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
        if (stm32x_info->probed)
@@ -794,12 +838,14 @@ int stm32x_auto_probe(struct flash_bank_s *bank)
        return stm32x_probe(bank);
 }
 
-int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+#if 0
+static int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        return ERROR_OK;
 }
+#endif
 
-int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size)
+static int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size)
 {
        target_t *target = bank->target;
        u32 device_id;
@@ -875,6 +921,23 @@ int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size)
                                break;
                }
        }
+       else if ((device_id & 0x7ff) == 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;
+
+                       default:
+                               snprintf(buf, buf_size, "unknown");
+                               break;
+               }
+       }
        else
        {
                snprintf(buf, buf_size, "Cannot identify target as a stm32x\n");
@@ -884,7 +947,7 @@ int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size)
        return ERROR_OK;
 }
 
-int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        flash_bank_t *bank;
        target_t *target = NULL;
@@ -933,7 +996,7 @@ int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, cha
        return ERROR_OK;
 }
 
-int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        flash_bank_t *bank;
        target_t *target = NULL;
@@ -979,7 +1042,7 @@ int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, c
        return ERROR_OK;
 }
 
-int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        flash_bank_t *bank;
        u32 optionbyte;
@@ -1038,7 +1101,7 @@ int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *
        return ERROR_OK;
 }
 
-int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        flash_bank_t *bank;
        target_t *target = NULL;
@@ -1114,7 +1177,7 @@ int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char
        return ERROR_OK;
 }
 
-int stm32x_mass_erase(struct flash_bank_s *bank)
+static int stm32x_mass_erase(struct flash_bank_s *bank)
 {
        target_t *target = bank->target;
        u32 status;
@@ -1152,7 +1215,7 @@ int stm32x_mass_erase(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        flash_bank_t *bank;
        int i;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)