]> git.sur5r.net Git - openocd/blobdiff - src/flash/at91sam7.c
target read/write is no longer attempted for target_xxx() functions when the target...
[openocd] / src / flash / at91sam7.c
index cf3547942d39638ac95dd4162327c762b2c67b5c..7aba6db44d638754956361893911e67095d3b6f9 100644 (file)
@@ -57,6 +57,7 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last);
 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last);
 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
 int at91sam7_probe(struct flash_bank_s *bank);
+int at91sam7_auto_probe(struct flash_bank_s *bank);
 int at91sam7_erase_check(struct flash_bank_s *bank);
 int at91sam7_protect_check(struct flash_bank_s *bank);
 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size);
@@ -76,6 +77,7 @@ flash_driver_t at91sam7_flash =
        .protect = at91sam7_protect,
        .write = at91sam7_write,
        .probe = at91sam7_probe,
+       .auto_probe = at91sam7_probe,
        .erase_check = at91sam7_erase_check,
        .protect_check = at91sam7_protect_check,
        .info = at91sam7_info
@@ -143,7 +145,7 @@ u32 at91sam7_get_flash_status(flash_bank_t *bank, u8 flashplane)
        return fsr;
 }
 
-/** Read clock configuration and set at91sam7_info->usec_clocks*/ 
+/* Read clock configuration and set at91sam7_info->usec_clocks*/
 void at91sam7_read_clock_info(flash_bank_t *bank)
 {
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
@@ -178,7 +180,7 @@ void at91sam7_read_clock_info(flash_bank_t *bank)
 
                case 2:                 /* Reserved */
                        break;
-               case 3:         /* PLL Clock */
+               case 3:                 /* PLL Clock */
                        if (mcfr & CKGR_MCFR_MAINRDY) 
                        {
                                target_read_u32(target, CKGR_PLLR, &pllr);
@@ -241,7 +243,7 @@ void at91sam7_set_flash_mode(flash_bank_t *bank, u8 flashplane, int mode)
                if (at91sam7_info->mck_freq > 30000000ul)
                        fws = 1;
 
-               DEBUG("fmcn[%i]: %i", flashplane, fmcn); 
+               LOG_DEBUG("fmcn[%i]: %i", flashplane, fmcn); 
                fmr = fmcn << 16 | fws << 8;
                target_write_u32(target, MC_FMR[flashplane], fmr);
        }
@@ -255,21 +257,21 @@ u32 at91sam7_wait_status_busy(flash_bank_t *bank, u8 flashplane, u32 waitbits, i
        
        while ((!((status = at91sam7_get_flash_status(bank,flashplane)) & waitbits)) && (timeout-- > 0))
        {
-               DEBUG("status[%i]: 0x%x", flashplane, status);
+               LOG_DEBUG("status[%i]: 0x%x", flashplane, status);
                usleep(1000);
        }
        
-       DEBUG("status[%i]: 0x%x", flashplane, status);
+       LOG_DEBUG("status[%i]: 0x%x", flashplane, status);
 
        if (status & 0x0C)
        {
-               ERROR("status register: 0x%x", status);
+               LOG_ERROR("status register: 0x%x", status);
                if (status & 0x4)
-                       ERROR("Lock Error Bit Detected, Operation Abort");
+                       LOG_ERROR("Lock Error Bit Detected, Operation Abort");
                if (status & 0x8)
-                       ERROR("Invalid command and/or bad keyword, Operation Abort");
+                       LOG_ERROR("Invalid command and/or bad keyword, Operation Abort");
                if (status & 0x10)
-                       ERROR("Security Bit Set, Operation Abort");
+                       LOG_ERROR("Security Bit Set, Operation Abort");
        }
        
        return status;
@@ -285,7 +287,7 @@ int at91sam7_flash_command(struct flash_bank_s *bank, u8 flashplane, u8 cmd, u16
 
        fcr = (0x5A<<24) | ((pagen&0x3FF)<<8) | cmd; 
        target_write_u32(target, MC_FCR[flashplane], fcr);
-       DEBUG("Flash command: 0x%x, flashplane: %i, pagenumber:%u", fcr, flashplane, pagen);
+       LOG_DEBUG("Flash command: 0x%x, flashplane: %i, pagenumber:%u", fcr, flashplane, pagen);
 
        if ((at91sam7_info->cidr_arch == 0x60)&&((cmd==SLB)|(cmd==CLB)))
        {
@@ -311,18 +313,16 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
        target_t *target = bank->target;
        u32 cidr, status;
        int sectornum;
-       
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
+
+       if (at91sam7_info->cidr != 0)
+               return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
        
        /* Read and parse chip identification register */
        target_read_u32(target, DBGU_CIDR, &cidr);
        
        if (cidr == 0)
        {
-               WARNING("Cannot identify target as an AT91SAM");
+               LOG_WARNING("Cannot identify target as an AT91SAM");
                return ERROR_FLASH_OPERATION_FAILED;
        }
        
@@ -363,7 +363,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
                
        
 
-       DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch );
+       LOG_DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch );
 
        /* Read main and master clock freqency register */
        at91sam7_read_clock_info(bank);
@@ -384,7 +384,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
                        at91sam7_info->target_name = "AT91SAM7S512";
                        at91sam7_info->num_planes = 2;
                        if (at91sam7_info->num_planes != bank->num_sectors)
-                               WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
+                               LOG_WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
                        at91sam7_info->num_lockbits = 2*16;
                        at91sam7_info->pagesize = 256;
                        at91sam7_info->pages_in_lockregion = 64;
@@ -437,7 +437,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
                        at91sam7_info->target_name = "AT91SAM7XC512";
                        at91sam7_info->num_planes = 2;
                        if (at91sam7_info->num_planes != bank->num_sectors)
-                               WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
+                               LOG_WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
                        at91sam7_info->num_lockbits = 2*16;
                        at91sam7_info->pagesize = 256;
                        at91sam7_info->pages_in_lockregion = 64;
@@ -465,8 +465,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
        
        if (at91sam7_info->cidr_arch == 0x72 )
        {
-               at91sam7_info->num_nvmbits = 2;
-               at91sam7_info->nvmbits = (status>>8)&0x03;
+               at91sam7_info->num_nvmbits = 3;
+               at91sam7_info->nvmbits = (status>>8)&0x07;
                bank->base = 0x100000;
                bank->bus_width = 4;
                if (bank->size==0x80000) /* AT91SAM7SE512 */
@@ -474,7 +474,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
                        at91sam7_info->target_name = "AT91SAM7SE512";
                        at91sam7_info->num_planes = 2;
                        if (at91sam7_info->num_planes != bank->num_sectors)
-                               WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
+                               LOG_WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
                        at91sam7_info->num_lockbits = 32;
                        at91sam7_info->pagesize = 256;
                        at91sam7_info->pages_in_lockregion = 64;
@@ -511,12 +511,12 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
                        at91sam7_info->target_name = "AT91SAM7X512";
                        at91sam7_info->num_planes = 2;
                        if (at91sam7_info->num_planes != bank->num_sectors)
-                               WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
+                               LOG_WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
                        at91sam7_info->num_lockbits = 32;
                        at91sam7_info->pagesize = 256;
                        at91sam7_info->pages_in_lockregion = 64;
                        at91sam7_info->num_pages = 2*16*64;
-                       DEBUG("Support for AT91SAM7X512 is experimental in this version!");
+                       LOG_DEBUG("Support for AT91SAM7X512 is experimental in this version!");
                }
                if (bank->size==0x40000)  /* AT91SAM7X256 */
                {
@@ -556,9 +556,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
                return ERROR_OK;
        }
        
-   WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
-       
-   return ERROR_OK;
+       LOG_WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
+       return ERROR_OK;
 }
 
 int at91sam7_erase_check(struct flash_bank_s *bank)
@@ -584,13 +583,12 @@ int at91sam7_protect_check(struct flash_bank_s *bank)
 
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
+               return ERROR_TARGET_NOT_HALTED;
        }
 
        for (flashplane=0;flashplane<at91sam7_info->num_planes;flashplane++)
@@ -611,7 +609,7 @@ int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, ch
        
        if (argc < 6)
        {
-               WARNING("incomplete flash_bank at91sam7 configuration");
+               LOG_WARNING("incomplete flash_bank at91sam7 configuration");
                return ERROR_FLASH_BANK_INVALID;
        }
        
@@ -631,27 +629,21 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last)
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
        u8 flashplane;
 
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-       
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
-       }       
+               return ERROR_TARGET_NOT_HALTED;
+       }
        
        if ((first < 0) || (last < first) || (last >= bank->num_sectors))
        {
                if ((first == 0) && (last == (at91sam7_info->num_lockbits-1)))
                {
-                       WARNING("Sector numbers based on lockbit count, probably a deprecated script");
+                       LOG_WARNING("Sector numbers based on lockbit count, probably a deprecated script");
                        last = bank->num_sectors-1;
                }
                else return ERROR_FLASH_SECTOR_INVALID;
@@ -680,6 +672,11 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
        
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
        
+       if (at91sam7_info->cidr == 0)
+       {
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
        if (bank->target->state != TARGET_HALTED)
        {
                return ERROR_TARGET_NOT_HALTED;
@@ -690,17 +687,6 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
                return ERROR_FLASH_SECTOR_INVALID;
        }
        
-       if (at91sam7_info->cidr == 0)
-       {
-               at91sam7_read_part_info(bank);
-       }
-
-       if (at91sam7_info->cidr == 0)
-       {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
-       }
-       
        at91sam7_read_clock_info(bank); 
        
        for (lockregion=first;lockregion<=last;lockregion++) 
@@ -735,22 +721,16 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
        u32 first_page, last_page, pagen, buffer_pos;
        u8 flashplane;
        
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-       
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
+               return ERROR_TARGET_NOT_HALTED;
        }
-       
+
        if (offset + count > bank->size)
                return ERROR_FLASH_DST_OUT_OF_BANK;
        
@@ -758,7 +738,7 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 
        if (offset % dst_min_alignment)
        {
-               WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
+               LOG_WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
                return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
        }
        
@@ -768,7 +748,7 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
        first_page = offset/dst_min_alignment;
        last_page = CEIL(offset + count, dst_min_alignment);
        
-       DEBUG("first_page: %i, last_page: %i, count %i", first_page, last_page, count);
+       LOG_DEBUG("first_page: %i, last_page: %i, count %i", first_page, last_page, count);
        
        at91sam7_read_clock_info(bank); 
 
@@ -793,7 +773,7 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
                {
                                return ERROR_FLASH_OPERATION_FAILED;
                }
-               DEBUG("Write flash plane:%i page number:%i", flashplane, pagen);
+               LOG_DEBUG("Write flash plane:%i page number:%i", flashplane, pagen);
        }
        
        return ERROR_OK;
@@ -806,34 +786,34 @@ int at91sam7_probe(struct flash_bank_s *bank)
         * if this is an at91sam7, it has the configured flash
         */
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
+       int retval;
        
-       if (at91sam7_info->cidr == 0)
+       if (at91sam7_info->cidr != 0)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_OK; /* already probed */
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
+               return ERROR_TARGET_NOT_HALTED;
        }
+
+       retval = at91sam7_read_part_info(bank);
+       if (retval != ERROR_OK)
+               return retval;
        
        return ERROR_OK;
 }
 
+
 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
 {
        int printed, flashplane;
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
        
-       at91sam7_read_part_info(bank);
-
        if (at91sam7_info->cidr == 0)
        {
-               printed = snprintf(buf, buf_size, "Cannot identify target as an AT91SAM\n");
-               buf += printed;
-               buf_size -= printed;
-               return ERROR_FLASH_OPERATION_FAILED;
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
        
        printed = snprintf(buf, buf_size, "\nat91sam7 information: Chip is %s\n",at91sam7_info->target_name);
@@ -869,7 +849,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
                buf_size -= printed;
        }
                        
-       printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->nvmbits);
+       printed = snprintf(buf, buf_size, "securitybit: %i,  nvmbits(%i): 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->num_nvmbits, at91sam7_info->nvmbits);
        buf += printed;
        buf_size -= printed;
 
@@ -877,7 +857,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
 }
 
 /* 
-* On AT91SAM7S: When the gpnmv bits are set with 
+* On AT91SAM7S: When the gpnvm bits are set with 
 * > at91sam7 gpnvm 0 bitnr set
 * the changes are not visible in the flash controller status register MC_FSR 
 * until the processor has been reset.
@@ -894,6 +874,7 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd,
        u32 status;
        char *value;
        at91sam7_flash_bank_t *at91sam7_info;
+       int retval;
 
        if (argc < 3)
        {
@@ -901,32 +882,48 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd,
                return ERROR_OK;
        }
        
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       bank = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0));
        bit = atoi(args[1]);
        value = args[2];
 
-       if (!bank)
+       if (bank ==  NULL)
        {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if (bank->driver != &at91sam7_flash)
+       {
+               command_print(cmd_ctx, "not an at91sam7 flash bank '%s'", args[0]);
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if (strcmp(value, "set") == 0)
+       {
+               flashcmd = SGPB;
+       }
+       else if (strcmp(value, "clear") == 0)
+       {
+               flashcmd = CGPB;
+       }
+       else
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        at91sam7_info = bank->driver_priv;
 
        if (bank->target->state != TARGET_HALTED)
        {
+               LOG_ERROR("target has to be halted to perform flash operation");
                return ERROR_TARGET_NOT_HALTED;
        }
        
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
-       }
-
-       if (at91sam7_info->cidr == 0)
-       {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
+               retval = at91sam7_read_part_info(bank);
+               if (retval != ERROR_OK) {
+                       return retval;
+               }
        }
 
        if ((bit<0) || (at91sam7_info->num_nvmbits <= bit))
@@ -935,20 +932,6 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd,
                return ERROR_OK;
        }
 
-       if (strcmp(value, "set") == 0)
-       {
-               flashcmd = SGPB;
-       }
-       else if (strcmp(value, "clear") == 0)
-       {
-               flashcmd = CGPB;
-       }
-       else
-       {
-               command_print(cmd_ctx, "usage: at91sam7 gpnvm <num> <bit> <set|clear>");
-               return ERROR_OK;
-       }
-
        /* Configure the flash controller timing */
        at91sam7_read_clock_info(bank); 
        at91sam7_set_flash_mode(bank, 0, FMR_TIMING_NVBITS);
@@ -959,7 +942,7 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd,
        }       
 
        status = at91sam7_get_flash_status(bank, 0);
-       DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value 0x%x, status 0x%x \n",flashcmd,bit,status);
+       LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value 0x%x, status 0x%x \n",flashcmd,bit,status);
        at91sam7_info->nvmbits = (status>>8)&((1<<at91sam7_info->num_nvmbits)-1);
 
        return ERROR_OK;