Browse Source

build: cleanup src/flash/nor directory

Change-Id: Ic299de969ce566282c055ba4dd8b94892c4c4311
Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk>
Reviewed-on: http://openocd.zylin.com/420
Tested-by: jenkins
tags/v0.6.0-rc1
Spencer Oliver 12 years ago
parent
commit
9f0cba528a
36 changed files with 4919 additions and 6584 deletions
  1. +169
    -174
      src/flash/nor/aduc702x.c
  2. +1536
    -1683
      src/flash/nor/at91sam3.c
  3. +174
    -275
      src/flash/nor/at91sam7.c
  4. +100
    -129
      src/flash/nor/avrf.c
  5. +767
    -933
      src/flash/nor/cfi.c
  6. +7
    -12
      src/flash/nor/cfi.h
  7. +104
    -162
      src/flash/nor/core.c
  8. +11
    -11
      src/flash/nor/core.h
  9. +5
    -4
      src/flash/nor/driver.h
  10. +2
    -2
      src/flash/nor/drivers.c
  11. +49
    -53
      src/flash/nor/dsp5680xx_flash.c
  12. +92
    -109
      src/flash/nor/ecos.c
  13. +108
    -156
      src/flash/nor/em357.c
  14. +7
    -14
      src/flash/nor/faux.c
  15. +3
    -6
      src/flash/nor/fm3.c
  16. +4
    -3
      src/flash/nor/imp.h
  17. +97
    -118
      src/flash/nor/kinetis.c
  18. +137
    -164
      src/flash/nor/lpc2000.c
  19. +84
    -128
      src/flash/nor/lpc288x.c
  20. +381
    -614
      src/flash/nor/lpc2900.c
  21. +53
    -87
      src/flash/nor/non_cfi.c
  22. +2
    -2
      src/flash/nor/non_cfi.h
  23. +57
    -61
      src/flash/nor/ocl.c
  24. +1
    -0
      src/flash/nor/ocl.h
  25. +54
    -98
      src/flash/nor/pic32mx.c
  26. +75
    -132
      src/flash/nor/stellaris.c
  27. +101
    -221
      src/flash/nor/stm32f1x.c
  28. +43
    -69
      src/flash/nor/stm32f2x.c
  29. +85
    -147
      src/flash/nor/stm32lx.c
  30. +56
    -80
      src/flash/nor/stmsmi.c
  31. +49
    -105
      src/flash/nor/str7x.c
  32. +74
    -137
      src/flash/nor/str9x.c
  33. +49
    -134
      src/flash/nor/str9xpec.c
  34. +144
    -213
      src/flash/nor/tcl.c
  35. +207
    -307
      src/flash/nor/tms470.c
  36. +32
    -41
      src/flash/nor/virtual.c

+ 169
- 174
src/flash/nor/aduc702x.c View File

@@ -29,20 +29,19 @@
#include <target/algorithm.h>
#include <target/arm.h>


static int aduc702x_build_sector_list(struct flash_bank *bank);
static int aduc702x_check_flash_completion(struct target* target, unsigned int timeout_ms);
static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms);
static int aduc702x_set_write_enable(struct target *target, int enable);

#define ADUC702x_FLASH 0xfffff800
#define ADUC702x_FLASH_FEESTA (0*4)
#define ADUC702x_FLASH_FEEMOD (1*4)
#define ADUC702x_FLASH_FEECON (2*4)
#define ADUC702x_FLASH_FEEDAT (3*4)
#define ADUC702x_FLASH_FEEADR (4*4)
#define ADUC702x_FLASH_FEESIGN (5*4)
#define ADUC702x_FLASH_FEEPRO (6*4)
#define ADUC702x_FLASH_FEEHIDE (7*4)
#define ADUC702x_FLASH 0xfffff800
#define ADUC702x_FLASH_FEESTA (0*4)
#define ADUC702x_FLASH_FEEMOD (1*4)
#define ADUC702x_FLASH_FEECON (2*4)
#define ADUC702x_FLASH_FEEDAT (3*4)
#define ADUC702x_FLASH_FEEADR (4*4)
#define ADUC702x_FLASH_FEESIGN (5*4)
#define ADUC702x_FLASH_FEEPRO (6*4)
#define ADUC702x_FLASH_FEEHIDE (7*4)

struct aduc702x_flash_bank {
struct working_area *write_algorithm;
@@ -56,33 +55,32 @@ FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)

nbank = malloc(sizeof(struct aduc702x_flash_bank));

bank->base = 0x80000;
bank->size = 0xF800; // top 4k not accessible
bank->base = 0x80000;
bank->size = 0xF800; /* top 4k not accessible */
bank->driver_priv = nbank;

aduc702x_build_sector_list(bank);
aduc702x_build_sector_list(bank);

return ERROR_OK;
return ERROR_OK;
}

static int aduc702x_build_sector_list(struct flash_bank *bank)
{
//aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv;

int i = 0;
uint32_t offset = 0;

// sector size is 512
bank->num_sectors = bank->size / 512;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
for (i = 0; i < bank->num_sectors; ++i)
{
bank->sectors[i].offset = offset;
bank->sectors[i].size = 512;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;
}
/* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */

int i = 0;
uint32_t offset = 0;

/* sector size is 512 */
bank->num_sectors = bank->size / 512;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
for (i = 0; i < bank->num_sectors; ++i) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 512;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;
}

return ERROR_OK;
}
@@ -95,13 +93,13 @@ static int aduc702x_protect_check(struct flash_bank *bank)

static int aduc702x_erase(struct flash_bank *bank, int first, int last)
{
//int res;
/* int res; */
int x;
int count;
//uint32_t v;
/* uint32_t v; */
struct target *target = bank->target;

aduc702x_set_write_enable(target, 1);
aduc702x_set_write_enable(target, 1);

/* mass erase */
if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
@@ -110,38 +108,35 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);

if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK)
{
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) {
LOG_ERROR("mass erase failed");
aduc702x_set_write_enable(target, 0);
aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_OPERATION_FAILED;
}

LOG_DEBUG("mass erase successful.");
return ERROR_OK;
} else {
unsigned long adr;
unsigned long adr;

count = last - first + 1;
for (x = 0; x < count; ++x)
{
adr = bank->base + ((first + x) * 512);
count = last - first + 1;
for (x = 0; x < count; ++x) {
adr = bank->base + ((first + x) * 512);

target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);

if (aduc702x_check_flash_completion(target, 50) != ERROR_OK)
{
LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_SECTOR_NOT_ERASED;
}
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) {
LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_SECTOR_NOT_ERASED;
}

LOG_DEBUG("erased sector at address 0x%08lX", adr);
}
}
LOG_DEBUG("erased sector at address 0x%08lX", adr);
}
}

aduc702x_set_write_enable(target, 0);
aduc702x_set_write_enable(target, 0);

return ERROR_OK;
}
@@ -157,7 +152,10 @@ static int aduc702x_protect(struct flash_bank *bank, int set, int first, int las
*
* Caller should not check for other return values specifically
*/
static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
static int aduc702x_write_block(struct flash_bank *bank,
uint8_t *buffer,
uint32_t offset,
uint32_t count)
{
struct aduc702x_flash_bank *aduc702x_info = bank->driver_priv;
struct target *target = bank->target;
@@ -168,71 +166,66 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
struct arm_algorithm armv4_5_info;
int retval = ERROR_OK;

if (((count%2)!=0)||((offset%2)!=0))
{
if (((count%2) != 0) || ((offset%2) != 0)) {
LOG_ERROR("write block must be multiple of two bytes in offset & length");
return ERROR_FAIL;
}

/* parameters:
r0 - address of source data (absolute)
r1 - number of halfwords to be copied
r2 - start address in flash (offset from beginning of flash memory)
r3 - exit code
r4 - base address of flash controller (0xFFFFF800)
registers:
r5 - scratch
r6 - set to 2, used to write flash command
*/
static const uint32_t aduc702x_flash_write_code[] = {
//<_start>:
0xe3a05008, // mov r5, #8 ; 0x8
0xe5845004, // str r5, [r4, #4]
0xe3a06002, // mov r6, #2 ; 0x2
//<next>:
0xe1c421b0, // strh r2, [r4, #16]
0xe0d050b2, // ldrh r5, [r0], #2
0xe1c450bc, // strh r5, [r4, #12]
0xe5c46008, // strb r6, [r4, #8]
//<wait_complete>:
0xe1d430b0, // ldrh r3, [r4]
0xe3130004, // tst r3, #4 ; 0x4
0x1afffffc, // bne 1001c <wait_complete>
0xe2822002, // add r2, r2, #2 ; 0x2
0xe2511001, // subs r1, r1, #1 ; 0x1
0x0a000001, // beq 1003c <done>
0xe3130001, // tst r3, #1 ; 0x1
0x1afffff3, // bne 1000c <next>
//<done>:
0xeafffffe // b 1003c <done>
/* parameters:
r0 - address of source data (absolute)
r1 - number of halfwords to be copied
r2 - start address in flash (offset from beginning of flash memory)
r3 - exit code
r4 - base address of flash controller (0xFFFFF800)
registers:
r5 - scratch
r6 - set to 2, used to write flash command
*/
static const uint32_t aduc702x_flash_write_code[] = {
/* <_start>: */
0xe3a05008, /* mov r5, #8 ; 0x8 */
0xe5845004, /* str r5, [r4, #4] */
0xe3a06002, /* mov r6, #2 ; 0x2 */
/* <next>: */
0xe1c421b0, /* strh r2, [r4, #16] */
0xe0d050b2, /* ldrh r5, [r0], #2 */
0xe1c450bc, /* strh r5, [r4, #12] */
0xe5c46008, /* strb r6, [r4, #8] */
/* <wait_complete>: */
0xe1d430b0, /* ldrh r3, [r4] */
0xe3130004, /* tst r3, #4 ; 0x4 */
0x1afffffc, /* bne 1001c <wait_complete> */
0xe2822002, /* add r2, r2, #2 ; 0x2 */
0xe2511001, /* subs r1, r1, #1 ; 0x1 */
0x0a000001, /* beq 1003c <done> */
0xe3130001, /* tst r3, #1 ; 0x1 */
0x1afffff3, /* bne 1000c <next> */
/* <done>: */
0xeafffffe /* b 1003c <done> */
};

/* flash write code */
if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
&aduc702x_info->write_algorithm) != ERROR_OK)
{
&aduc702x_info->write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};
}

retval=target_write_buffer(target, aduc702x_info->write_algorithm->address,
sizeof(aduc702x_flash_write_code), (uint8_t*)aduc702x_flash_write_code);
if (retval!=ERROR_OK)
{
retval = target_write_buffer(target, aduc702x_info->write_algorithm->address,
sizeof(aduc702x_flash_write_code), (uint8_t *)aduc702x_flash_write_code);
if (retval != ERROR_OK)
return retval;
}

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= 256)
{
/* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a buffer,
*free the algorithm */
if (aduc702x_info->write_algorithm)
target_free_working_area(target, aduc702x_info->write_algorithm);

@@ -251,32 +244,29 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);

while (count > 0)
{
while (count > 0) {
uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;

retval=target_write_buffer(target, source->address, thisrun_count, buffer);
if (retval!=ERROR_OK)
{
retval = target_write_buffer(target, source->address, thisrun_count, buffer);
if (retval != ERROR_OK)
break;
}

buf_set_u32(reg_params[0].value, 0, 32, source->address);
buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
buf_set_u32(reg_params[2].value, 0, 32, address);
buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);

if ((retval = target_run_algorithm(target, 0, NULL, 5,
reg_params, aduc702x_info->write_algorithm->address,
aduc702x_info->write_algorithm->address + sizeof(aduc702x_flash_write_code) - 4,
10000, &armv4_5_info)) != ERROR_OK)
{
retval = target_run_algorithm(target, 0, NULL, 5,
reg_params, aduc702x_info->write_algorithm->address,
aduc702x_info->write_algorithm->address +
sizeof(aduc702x_flash_write_code) - 4,
10000, &armv4_5_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing aduc702x flash write algorithm");
break;
}

if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1)
{
if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) {
/* FIX!!!! what does this mean??? replace w/sensible error message */
LOG_ERROR("aduc702x detected error writing flash");
retval = ERROR_FAIL;
@@ -302,43 +292,44 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32

/* All-JTAG, single-access method. Very slow. Used only if there is no
* working area available. */
static int aduc702x_write_single(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
static int aduc702x_write_single(struct flash_bank *bank,
uint8_t *buffer,
uint32_t offset,
uint32_t count)
{
uint32_t x;
uint8_t b;
uint8_t b;
struct target *target = bank->target;

aduc702x_set_write_enable(target, 1);
aduc702x_set_write_enable(target, 1);

for (x = 0; x < count; x += 2) {
// FEEADR = address
/* FEEADR = address */
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x);

// set up data
if ((x + 1) == count)
{
// last byte
target_read_u8(target, offset + x + 1, &b);
}
else
b = buffer[x + 1];
/* set up data */
if ((x + 1) == count) {
/* last byte */
target_read_u8(target, offset + x + 1, &b);
} else
b = buffer[x + 1];

target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8));
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8));

// do single-write command
/* do single-write command */
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02);

if (aduc702x_check_flash_completion(target, 1) != ERROR_OK)
{
LOG_ERROR("single write failed for address 0x%08lX", (unsigned long)(offset + x));
aduc702x_set_write_enable(target, 0);
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) {
LOG_ERROR("single write failed for address 0x%08lX",
(unsigned long)(offset + x));
aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_OPERATION_FAILED;
}

}
LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x));
LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x));

aduc702x_set_write_enable(target, 0);
aduc702x_set_write_enable(target, 0);

return ERROR_OK;
}
@@ -347,24 +338,23 @@ static int aduc702x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
{
int retval;

/* try using a block write */
if ((retval = aduc702x_write_block(bank, buffer, offset, count)) != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
/* if block write failed (no sufficient working area),
* use normal (slow) JTAG method */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");

if ((retval = aduc702x_write_single(bank, buffer, offset, count)) != ERROR_OK)
{
LOG_ERROR("slow write failed");
return ERROR_FLASH_OPERATION_FAILED;
}
}
}

return retval;
/* try using a block write */
retval = aduc702x_write_block(bank, buffer, offset, count);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* use normal (slow) JTAG method */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");

retval = aduc702x_write_single(bank, buffer, offset, count);
if (retval != ERROR_OK) {
LOG_ERROR("slow write failed");
return ERROR_FLASH_OPERATION_FAILED;
}
}
}

return retval;
}

static int aduc702x_probe(struct flash_bank *bank)
@@ -382,10 +372,10 @@ static int aduc702x_info(struct flash_bank *bank, char *buf, int buf_size)
* enable = 1 enables writes & erases, 0 disables them */
static int aduc702x_set_write_enable(struct target *target, int enable)
{
// don't bother to preserve int enable bit here
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);
/* don't bother to preserve int enable bit here */
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);

return ERROR_OK;
return ERROR_OK;
}

/* wait up to timeout_ms for controller to not be busy,
@@ -393,22 +383,27 @@ static int aduc702x_set_write_enable(struct target *target, int enable)
*
* this function sleeps 1ms between checks (after the first one),
* so in some cases may slow things down without a usleep after the first read */
static int aduc702x_check_flash_completion(struct target* target, unsigned int timeout_ms)
static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms)
{
uint8_t v = 4;

long long endtime = timeval_ms() + timeout_ms;
while (1) {
target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
if ((v & 4) == 0) break;
alive_sleep(1);
if (timeval_ms() >= endtime) break;
}

if (v & 2) return ERROR_FAIL;
// if a command is ignored, both the success and fail bits may be 0
else if ((v & 3) == 0) return ERROR_FAIL;
else return ERROR_OK;
uint8_t v = 4;

long long endtime = timeval_ms() + timeout_ms;
while (1) {
target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
if ((v & 4) == 0)
break;
alive_sleep(1);
if (timeval_ms() >= endtime)
break;
}

if (v & 2)
return ERROR_FAIL;
/* if a command is ignored, both the success and fail bits may be 0 */
else if ((v & 3) == 0)
return ERROR_FAIL;
else
return ERROR_OK;
}

struct flash_driver aduc702x_flash = {


+ 1536
- 1683
src/flash/nor/at91sam3.c
File diff suppressed because it is too large
View File


+ 174
- 275
src/flash/nor/at91sam7.c View File

@@ -52,55 +52,54 @@
#include "imp.h"
#include <helper/binarybuffer.h>


/* AT91SAM7 control registers */
#define DBGU_CIDR 0xFFFFF240
#define CKGR_MCFR 0xFFFFFC24
#define CKGR_MOR 0xFFFFFC20
#define CKGR_MCFR_MAINRDY 0x10000
#define CKGR_PLLR 0xFFFFFC2c
#define CKGR_PLLR_DIV 0xff
#define CKGR_PLLR_MUL 0x07ff0000
#define PMC_MCKR 0xFFFFFC30
#define PMC_MCKR_CSS 0x03
#define PMC_MCKR_PRES 0x1c
#define DBGU_CIDR 0xFFFFF240
#define CKGR_MCFR 0xFFFFFC24
#define CKGR_MOR 0xFFFFFC20
#define CKGR_MCFR_MAINRDY 0x10000
#define CKGR_PLLR 0xFFFFFC2c
#define CKGR_PLLR_DIV 0xff
#define CKGR_PLLR_MUL 0x07ff0000
#define PMC_MCKR 0xFFFFFC30
#define PMC_MCKR_CSS 0x03
#define PMC_MCKR_PRES 0x1c

/* Flash Controller Commands */
#define WP 0x01
#define SLB 0x02
#define WPL 0x03
#define CLB 0x04
#define EA 0x08
#define SGPB 0x0B
#define CGPB 0x0D
#define SSB 0x0F
#define WP 0x01
#define SLB 0x02
#define WPL 0x03
#define CLB 0x04
#define EA 0x08
#define SGPB 0x0B
#define CGPB 0x0D
#define SSB 0x0F

/* MC_FSR bit definitions */
#define MC_FSR_FRDY 1
#define MC_FSR_EOL 2
#define MC_FSR_FRDY 1
#define MC_FSR_EOL 2

/* AT91SAM7 constants */
#define RC_FREQ 32000
#define RC_FREQ 32000

/* Flash timing modes */
#define FMR_TIMING_NONE 0
#define FMR_TIMING_NVBITS 1
#define FMR_TIMING_FLASH 2
#define FMR_TIMING_NONE 0
#define FMR_TIMING_NVBITS 1
#define FMR_TIMING_FLASH 2

/* Flash size constants */
#define FLASH_SIZE_8KB 1
#define FLASH_SIZE_16KB 2
#define FLASH_SIZE_32KB 3
#define FLASH_SIZE_64KB 5
#define FLASH_SIZE_128KB 7
#define FLASH_SIZE_256KB 9
#define FLASH_SIZE_512KB 10
#define FLASH_SIZE_1024KB 12
#define FLASH_SIZE_2048KB 14

#define FLASH_SIZE_8KB 1
#define FLASH_SIZE_16KB 2
#define FLASH_SIZE_32KB 3
#define FLASH_SIZE_64KB 5
#define FLASH_SIZE_128KB 7
#define FLASH_SIZE_256KB 9
#define FLASH_SIZE_512KB 10
#define FLASH_SIZE_1024KB 12
#define FLASH_SIZE_2048KB 14

static int at91sam7_protect_check(struct flash_bank *bank);
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
uint32_t count);

static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number);
static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode);
@@ -111,10 +110,11 @@ static uint32_t MC_FMR[4] = { 0xFFFFFF60, 0xFFFFFF70, 0xFFFFFF80, 0xFFFFFF90 };
static uint32_t MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 };
static uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };

static char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
static char *EPROC[8] = {
"Unknown", "ARM946-E", "ARM7TDMI", "Unknown", "ARM920T", "ARM926EJ-S", "Unknown", "Unknown"
};

struct at91sam7_flash_bank
{
struct at91sam7_flash_bank {
/* chip id register */
uint32_t cidr;
uint16_t cidr_ext;
@@ -128,7 +128,7 @@ struct at91sam7_flash_bank
const char *target_name;

/* flash auto-detection */
uint8_t flash_autodetection;
uint8_t flash_autodetection;

/* flash geometry */
uint16_t pages_per_sector;
@@ -141,15 +141,15 @@ struct at91sam7_flash_bank
uint16_t num_nvmbits;
uint16_t num_nvmbits_on;
uint16_t nvmbits;
uint8_t securitybit;
uint8_t securitybit;

/* 0: not init
* 1: fmcn for nvbits (1uS)
* 2: fmcn for flash (1.5uS) */
uint8_t flashmode;
uint8_t flashmode;

/* main clock status */
uint8_t mck_valid;
uint8_t mck_valid;
uint32_t mck_freq;

/* external clock frequency */
@@ -178,7 +178,6 @@ static long SRAMSIZ[16] = {
};
#endif


static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number)
{
uint32_t fsr;
@@ -206,8 +205,7 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)

at91sam7_info->mck_valid = 0;
at91sam7_info->mck_freq = 0;
switch (mckr & PMC_MCKR_CSS)
{
switch (mckr & PMC_MCKR_CSS) {
case 0: /* Slow Clock */
at91sam7_info->mck_valid = 1;
tmp = RC_FREQ;
@@ -215,13 +213,10 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)

case 1: /* Main Clock */
if ((mcfr & CKGR_MCFR_MAINRDY) &&
(at91sam7_info->ext_freq == 0))
{
(at91sam7_info->ext_freq == 0)) {
at91sam7_info->mck_valid = 1;
tmp = RC_FREQ / 16ul * (mcfr & 0xffff);
}
else if (at91sam7_info->ext_freq != 0)
{
} else if (at91sam7_info->ext_freq != 0) {
at91sam7_info->mck_valid = 1;
tmp = at91sam7_info->ext_freq;
}
@@ -232,35 +227,30 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)

case 3: /* PLL Clock */
if ((mcfr & CKGR_MCFR_MAINRDY) &&
(at91sam7_info->ext_freq == 0))
{
(at91sam7_info->ext_freq == 0)) {
target_read_u32(target, CKGR_PLLR, &pllr);
if (!(pllr & CKGR_PLLR_DIV))
break; /* 0 Hz */
break; /* 0 Hz */
at91sam7_info->mck_valid = 1;
mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
/* Integer arithmetic should have sufficient precision
* as long as PLL is properly configured. */
tmp = mainfreq / (pllr & CKGR_PLLR_DIV)*
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
}
else if ((at91sam7_info->ext_freq != 0) &&
((pllr&CKGR_PLLR_DIV) != 0))
{
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
} else if ((at91sam7_info->ext_freq != 0) &&
((pllr&CKGR_PLLR_DIV) != 0)) {
at91sam7_info->mck_valid = 1;
tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)*
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
}
break;
}

/* Prescaler adjust */
if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0))
{
if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0)) {
at91sam7_info->mck_valid = 0;
at91sam7_info->mck_freq = 0;
}
else if (((mckr & PMC_MCKR_PRES) >> 2) != 0)
} else if (((mckr & PMC_MCKR_PRES) >> 2) != 0)
at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
else
at91sam7_info->mck_freq = tmp;
@@ -273,24 +263,17 @@ static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode)
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
struct target *target = bank->target;

if (mode && (mode != at91sam7_info->flashmode))
{
if (mode && (mode != at91sam7_info->flashmode)) {
/* Always round up (ceil) */
if (mode == FMR_TIMING_NVBITS)
{
if (at91sam7_info->cidr_arch == 0x60)
{
if (mode == FMR_TIMING_NVBITS) {
if (at91sam7_info->cidr_arch == 0x60) {
/* AT91SAM7A3 uses master clocks in 100 ns */
fmcn = (at91sam7_info->mck_freq/10000000ul) + 1;
}
else
{
} else {
/* master clocks in 1uS for ARCH 0x7 types */
fmcn = (at91sam7_info->mck_freq/1000000ul) + 1;
}
}
else if (mode == FMR_TIMING_FLASH)
{
} else if (mode == FMR_TIMING_FLASH) {
/* main clocks in 1.5uS */
fmcn = (at91sam7_info->mck_freq/1000000ul)+
(at91sam7_info->mck_freq/2000000ul) + 1;
@@ -319,16 +302,15 @@ static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t wait
{
uint32_t status;

while ((!((status = at91sam7_get_flash_status(bank->target, bank->bank_number)) & waitbits)) && (timeout-- > 0))
{
while ((!((status = at91sam7_get_flash_status(bank->target,
bank->bank_number)) & waitbits)) && (timeout-- > 0)) {
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status);
alive_sleep(1);
}

LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status);

if (status & 0x0C)
{
if (status & 0x0C) {
LOG_ERROR("status register: 0x%" PRIx32 "", status);
if (status & 0x4)
LOG_ERROR("Lock Error Bit Detected, Operation Abort");
@@ -350,22 +332,20 @@ static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t

fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd;
target_write_u32(target, MC_FCR[bank->bank_number], fcr);
LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u", fcr, bank->bank_number + 1, pagen);
LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u",
fcr,
bank->bank_number + 1,
pagen);

if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB)))
{
if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB))) {
/* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */
if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C)
{
return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK;
}

if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C)
{
return ERROR_FLASH_OPERATION_FAILED;
}

return ERROR_OK;
}
@@ -392,14 +372,12 @@ static int at91sam7_read_part_info(struct flash_bank *bank)

at91sam7_info = t_bank->driver_priv;

if (at91sam7_info->cidr != 0)
{
if (at91sam7_info->cidr != 0) {
/* flash already configured, update clock and check for protected sectors */
struct flash_bank *fb = bank;
t_bank = fb;

while (t_bank)
{
while (t_bank) {
/* re-calculate master clock frequency */
at91sam7_read_clock_info(t_bank);

@@ -418,19 +396,16 @@ static int at91sam7_read_part_info(struct flash_bank *bank)

/* Read and parse chip identification register */
target_read_u32(target, DBGU_CIDR, &cidr);
if (cidr == 0)
{
if (cidr == 0) {
LOG_WARNING("Cannot identify target as an AT91SAM");
return ERROR_FLASH_OPERATION_FAILED;
}

if (at91sam7_info->flash_autodetection == 0)
{
if (at91sam7_info->flash_autodetection == 0) {
/* banks and sectors are already created, based on data from input file */
struct flash_bank *fb = bank;
t_bank = fb;
while (t_bank)
{
while (t_bank) {
at91sam7_info = t_bank->driver_priv;

at91sam7_info->cidr = cidr;
@@ -462,8 +437,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
arch = (cidr >> 20)&0x00FF;

/* check flash size */
switch ((cidr >> 8)&0x000F)
{
switch ((cidr >> 8)&0x000F) {
case FLASH_SIZE_8KB:
break;

@@ -473,8 +447,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 32;
page_size = 64;
base_address = 0x00100000;
if (arch == 0x70)
{
if (arch == 0x70) {
num_nvmbits = 2;
target_name_t = "AT91SAM7S161/16";
}
@@ -486,13 +459,11 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 32;
page_size = 128;
base_address = 0x00100000;
if (arch == 0x70)
{
if (arch == 0x70) {
num_nvmbits = 2;
target_name_t = "AT91SAM7S321/32";
}
if (arch == 0x72)
{
if (arch == 0x72) {
num_nvmbits = 3;
target_name_t = "AT91SAM7SE32";
}
@@ -504,8 +475,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 32;
page_size = 128;
base_address = 0x00100000;
if (arch == 0x70)
{
if (arch == 0x70) {
num_nvmbits = 2;
target_name_t = "AT91SAM7S64";
}
@@ -517,23 +487,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 64;
page_size = 256;
base_address = 0x00100000;
if (arch == 0x70)
{
if (arch == 0x70) {
num_nvmbits = 2;
target_name_t = "AT91SAM7S128";
}
if (arch == 0x71)
{
if (arch == 0x71) {
num_nvmbits = 3;
target_name_t = "AT91SAM7XC128";
}
if (arch == 0x72)
{
if (arch == 0x72) {
num_nvmbits = 3;
target_name_t = "AT91SAM7SE128";
}
if (arch == 0x75)
{
if (arch == 0x75) {
num_nvmbits = 3;
target_name_t = "AT91SAM7X128";
}
@@ -545,28 +511,23 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 64;
page_size = 256;
base_address = 0x00100000;
if (arch == 0x60)
{
if (arch == 0x60) {
num_nvmbits = 3;
target_name_t = "AT91SAM7A3";
}
if (arch == 0x70)
{
if (arch == 0x70) {
num_nvmbits = 2;
target_name_t = "AT91SAM7S256";
}
if (arch == 0x71)
{
if (arch == 0x71) {
num_nvmbits = 3;
target_name_t = "AT91SAM7XC256";
}
if (arch == 0x72)
{
if (arch == 0x72) {
num_nvmbits = 3;
target_name_t = "AT91SAM7SE256";
}
if (arch == 0x75)
{
if (arch == 0x75) {
num_nvmbits = 3;
target_name_t = "AT91SAM7X256";
}
@@ -578,23 +539,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 64;
page_size = 256;
base_address = 0x00100000;
if (arch == 0x70)
{
if (arch == 0x70) {
num_nvmbits = 2;
target_name_t = "AT91SAM7S512";
}
if (arch == 0x71)
{
if (arch == 0x71) {
num_nvmbits = 3;
target_name_t = "AT91SAM7XC512";
}
if (arch == 0x72)
{
if (arch == 0x72) {
num_nvmbits = 3;
target_name_t = "AT91SAM7SE512";
}
if (arch == 0x75)
{
if (arch == 0x75) {
num_nvmbits = 3;
target_name_t = "AT91SAM7X512";
}
@@ -607,9 +564,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
break;
}

if (strcmp(target_name_t, "Unknown") == 0)
{
LOG_ERROR("Target autodetection failed! Please specify target parameters in configuration file");
if (strcmp(target_name_t, "Unknown") == 0) {
LOG_ERROR(
"Target autodetection failed! Please specify target parameters in configuration file");
return ERROR_FLASH_OPERATION_FAILED;
}

@@ -618,10 +575,8 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
/* calculate bank size */
bank_size = sectors_num * pages_per_sector * page_size;

for (bnk = 0; bnk < banks_num; bnk++)
{
if (bnk > 0)
{
for (bnk = 0; bnk < banks_num; bnk++) {
if (bnk > 0) {
if (!t_bank->next) {
/* create a new flash bank element */
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
@@ -646,8 +601,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)

/* allocate sectors */
t_bank->sectors = malloc(sectors_num * sizeof(struct flash_sector));
for (sec = 0; sec < sectors_num; sec++)
{
for (sec = 0; sec < sectors_num; sec++) {
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
t_bank->sectors[sec].size = pages_per_sector * page_size;
t_bank->sectors[sec].is_erased = -1;
@@ -684,7 +638,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
at91sam7_protect_check(t_bank);
}

LOG_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);

return ERROR_OK;
}
@@ -699,8 +655,7 @@ static int at91sam7_erase_check(struct flash_bank *bank)
uint16_t nSector;
uint16_t nByte;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -710,12 +665,12 @@ static int at91sam7_erase_check(struct flash_bank *bank)
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);

fast_check = 1;
for (nSector = 0; nSector < bank->num_sectors; nSector++)
{
retval = target_blank_check_memory(target, bank->base + bank->sectors[nSector].offset,
bank->sectors[nSector].size, &blank);
if (retval != ERROR_OK)
{
for (nSector = 0; nSector < bank->num_sectors; nSector++) {
retval = target_blank_check_memory(target,
bank->base + bank->sectors[nSector].offset,
bank->sectors[nSector].size,
&blank);
if (retval != ERROR_OK) {
fast_check = 0;
break;
}
@@ -726,25 +681,20 @@ static int at91sam7_erase_check(struct flash_bank *bank)
}

if (fast_check)
{
return ERROR_OK;
}

LOG_USER("Running slow fallback erase check - add working memory");

buffer = malloc(bank->sectors[0].size);
for (nSector = 0; nSector < bank->num_sectors; nSector++)
{
for (nSector = 0; nSector < bank->num_sectors; nSector++) {
bank->sectors[nSector].is_erased = 1;
retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4,
bank->sectors[nSector].size/4, buffer);
bank->sectors[nSector].size/4, buffer);
if (retval != ERROR_OK)
return retval;

for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++)
{
if (buffer[nByte] != 0xFF)
{
for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) {
if (buffer[nByte] != 0xFF) {
bank->sectors[nSector].is_erased = 0;
break;
}
@@ -763,11 +713,8 @@ static int at91sam7_protect_check(struct flash_bank *bank)
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;

if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED;
}
if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -776,14 +723,11 @@ static int at91sam7_protect_check(struct flash_bank *bank)
at91sam7_info->lockbits = (status >> 16);

at91sam7_info->num_lockbits_on = 0;
for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++)
{
if (((status >> (16 + lock_pos))&(0x0001)) == 1)
{
for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) {
if (((status >> (16 + lock_pos))&(0x0001)) == 1) {
at91sam7_info->num_lockbits_on++;
bank->sectors[lock_pos].is_protected = 1;
}
else
} else
bank->sectors[lock_pos].is_protected = 0;
}

@@ -794,12 +738,9 @@ static int at91sam7_protect_check(struct flash_bank *bank)
at91sam7_info->nvmbits = (status >> 8)&0xFF;

at91sam7_info->num_nvmbits_on = 0;
for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++)
{
for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++) {
if (((status >> (8 + gpnvm_pos))&(0x01)) == 1)
{
at91sam7_info->num_nvmbits_on++;
}
}

return ERROR_OK;
@@ -837,8 +778,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
at91sam7_info->ext_freq = 0;
at91sam7_info->flash_autodetection = 0;

if (CMD_ARGC < 13)
{
if (CMD_ARGC < 13) {
at91sam7_info->flash_autodetection = 1;
return ERROR_OK;
}
@@ -862,8 +802,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
}

if ((bus_width == 0) || (banks_num == 0) || (num_sectors == 0) ||
(pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0))
{
(pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0)) {
at91sam7_info->flash_autodetection = 1;
return ERROR_OK;
}
@@ -874,10 +813,8 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
/* calculate bank size */
bank_size = num_sectors * pages_per_sector * page_size;

for (bnk = 0; bnk < banks_num; bnk++)
{
if (bnk > 0)
{
for (bnk = 0; bnk < banks_num; bnk++) {
if (bnk > 0) {
if (!t_bank->next) {
/* create a new bank element */
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
@@ -902,8 +839,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)

/* allocate sectors */
t_bank->sectors = malloc(num_sectors * sizeof(struct flash_sector));
for (sec = 0; sec < num_sectors; sec++)
{
for (sec = 0; sec < num_sectors; sec++) {
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
t_bank->sectors[sec].size = pages_per_sector * page_size;
t_bank->sectors[sec].is_erased = -1;
@@ -933,61 +869,43 @@ static int at91sam7_erase(struct flash_bank *bank, int first, int last)
uint8_t erase_all;

if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED;
}

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((first < 0) || (last < first) || (last >= bank->num_sectors))
{
return ERROR_FLASH_SECTOR_INVALID;
}

erase_all = 0;
if ((first == 0) && (last == (bank->num_sectors-1)))
{
erase_all = 1;
}

/* Configure the flash controller timing */
at91sam7_read_clock_info(bank);
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);

if (erase_all)
{
if (erase_all) {
if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}
}
else
{
} else {
/* allocate and clean buffer */
nbytes = (last - first + 1) * bank->sectors[first].size;
buffer = malloc(nbytes * sizeof(uint8_t));
for (pos = 0; pos < nbytes; pos++)
{
buffer[pos] = 0xFF;
}

if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}

free(buffer);
}

/* mark erased sectors */
for (sec = first; sec <= last; sec++)
{
bank->sectors[sec].is_erased = 1;
}

return ERROR_OK;
}
@@ -1001,27 +919,21 @@ static int at91sam7_protect(struct flash_bank *bank, int set, int first, int las
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;

if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED;
}

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((first < 0) || (last < first) || (last >= bank->num_sectors))
{
return ERROR_FLASH_SECTOR_INVALID;
}

/* Configure the flash controller timing */
at91sam7_read_clock_info(bank);
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);

for (sector = first; sector <= last; sector++)
{
for (sector = first; sector <= last; sector++) {
if (set)
cmd = SLB;
else
@@ -1032,9 +944,7 @@ static int at91sam7_protect(struct flash_bank *bank, int set, int first, int las
pagen = sector * at91sam7_info->pages_per_sector;

if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}
}

at91sam7_protect_check(bank);
@@ -1051,12 +961,9 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
uint32_t first_page, last_page, pagen, buffer_pos;

if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED;
}

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1066,9 +973,10 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off

dst_min_alignment = at91sam7_info->pagesize;

if (offset % dst_min_alignment)
{
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, dst_min_alignment);
if (offset % dst_min_alignment) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
offset,
dst_min_alignment);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

@@ -1078,14 +986,16 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
first_page = offset/dst_min_alignment;
last_page = DIV_ROUND_UP(offset + count, dst_min_alignment);

LOG_DEBUG("first_page: %i, last_page: %i, count %i", (int)first_page, (int)last_page, (int)count);
LOG_DEBUG("first_page: %i, last_page: %i, count %i",
(int)first_page,
(int)last_page,
(int)count);

/* Configure the flash controller timing */
at91sam7_read_clock_info(bank);
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);

for (pagen = first_page; pagen < last_page; pagen++)
{
for (pagen = first_page; pagen < last_page; pagen++) {
if (bytes_remaining < dst_min_alignment)
count = bytes_remaining;
else
@@ -1094,17 +1004,15 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off

/* Write one block to the PageWriteBuffer */
buffer_pos = (pagen-first_page)*dst_min_alignment;
wcount = DIV_ROUND_UP(count,4);
if ((retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4, wcount, buffer + buffer_pos)) != ERROR_OK)
{
wcount = DIV_ROUND_UP(count, 4);
retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4,
wcount, buffer + buffer_pos);
if (retval != ERROR_OK)
return retval;
}

/* Send Write Page command to Flash Controller */
if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}
LOG_DEBUG("Write flash bank:%i page number:%" PRIi32 "", bank->bank_number, pagen);
}

@@ -1117,8 +1025,7 @@ static int at91sam7_probe(struct flash_bank *bank)
* if this is an at91sam7, it has the configured flash */
int retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1136,40 +1043,44 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;

if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED;
}

printed = snprintf(buf, buf_size,
"\n at91sam7 driver information: Chip is %s\n",
at91sam7_info->target_name);
"\n at91sam7 driver information: Chip is %s\n",
at91sam7_info->target_name);

buf += printed;
buf_size -= printed;

printed = snprintf(buf,
buf_size,
" Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | Flashsize: 0x%8.8" PRIx32 "\n",
at91sam7_info->cidr,
at91sam7_info->cidr_arch,
EPROC[at91sam7_info->cidr_eproc],
at91sam7_info->cidr_version,
bank->size);
buf_size,
" Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | "
"Flashsize: 0x%8.8" PRIx32 "\n",
at91sam7_info->cidr,
at91sam7_info->cidr_arch,
EPROC[at91sam7_info->cidr_eproc],
at91sam7_info->cidr_version,
bank->size);

buf += printed;
buf_size -= printed;

printed = snprintf(buf, buf_size,
" Master clock (estimated): %u KHz | External clock: %u KHz\n",
(unsigned)(at91sam7_info->mck_freq / 1000), (unsigned)(at91sam7_info->ext_freq / 1000));
" Master clock (estimated): %u KHz | External clock: %u KHz\n",
(unsigned)(at91sam7_info->mck_freq / 1000),
(unsigned)(at91sam7_info->ext_freq / 1000));

buf += printed;
buf_size -= printed;

printed = snprintf(buf, buf_size,
" Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i \n",
at91sam7_info->pagesize, bank->num_sectors, at91sam7_info->num_lockbits_on,
at91sam7_info->lockbits, at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on);
printed = snprintf(buf,
buf_size,
" Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i\n",
at91sam7_info->pagesize,
bank->num_sectors,
at91sam7_info->num_lockbits_on,
at91sam7_info->lockbits,
at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on);

buf += printed;
buf_size -= printed;
@@ -1196,59 +1107,46 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
{
struct flash_bank *bank;
int bit;
uint8_t flashcmd;
uint8_t flashcmd;
uint32_t status;
struct at91sam7_flash_bank *at91sam7_info;
int retval;

if (CMD_ARGC != 2)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

bank = get_flash_bank_by_num_noprobe(0);
if (bank == NULL)
{
return ERROR_FLASH_BANK_INVALID;
}
if (strcmp(bank->driver->name, "at91sam7"))
{
if (strcmp(bank->driver->name, "at91sam7")) {
command_print(CMD_CTX, "not an at91sam7 flash bank '%s'", CMD_ARGV[0]);
return ERROR_FLASH_BANK_INVALID;
}
if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("target has to be halted to perform flash operation");
return ERROR_TARGET_NOT_HALTED;
}

if (strcmp(CMD_ARGV[1], "set") == 0)
{
flashcmd = SGPB;
}
else if (strcmp(CMD_ARGV[1], "clear") == 0)
{
flashcmd = CGPB;
}
else
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

at91sam7_info = bank->driver_priv;
if (at91sam7_info->cidr == 0)
{
if (at91sam7_info->cidr == 0) {
retval = at91sam7_read_part_info(bank);
if (retval != ERROR_OK)
{
return retval;
}
}

COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit);
if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits))
{
command_print(CMD_CTX, "gpnvm bit '#%s' is out of bounds for target %s", CMD_ARGV[0], at91sam7_info->target_name);
if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) {
command_print(CMD_CTX,
"gpnvm bit '#%s' is out of bounds for target %s",
CMD_ARGV[0],
at91sam7_info->target_name);
return ERROR_OK;
}

@@ -1257,13 +1155,14 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);

if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}

/* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
status = at91sam7_get_flash_status(bank->target, 0);
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32, flashcmd, bit, status);
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32,
flashcmd,
bit,
status);

/* check protect state */
at91sam7_protect_check(bank);


+ 100
- 129
src/flash/nor/avrf.c View File

@@ -17,6 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -24,33 +25,31 @@
#include "imp.h"
#include <target/avrt.h>


/* AVR_JTAG_Instructions */
#define AVR_JTAG_INS_LEN 4
// Public Instructions:
#define AVR_JTAG_INS_EXTEST 0x00
#define AVR_JTAG_INS_IDCODE 0x01
#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02
#define AVR_JTAG_INS_BYPASS 0x0F
// AVR Specified Public Instructions:
#define AVR_JTAG_INS_AVR_RESET 0x0C
#define AVR_JTAG_INS_PROG_ENABLE 0x04
#define AVR_JTAG_INS_PROG_COMMANDS 0x05
#define AVR_JTAG_INS_PROG_PAGELOAD 0x06
#define AVR_JTAG_INS_PROG_PAGEREAD 0x07

// Data Registers:
#define AVR_JTAG_REG_Bypass_Len 1
#define AVR_JTAG_REG_DeviceID_Len 32

#define AVR_JTAG_REG_Reset_Len 1
#define AVR_JTAG_REG_JTAGID_Len 32
#define AVR_JTAG_REG_ProgrammingEnable_Len 16
#define AVR_JTAG_REG_ProgrammingCommand_Len 15
#define AVR_JTAG_REG_FlashDataByte_Len 16

struct avrf_type
{
#define AVR_JTAG_INS_LEN 4
/* Public Instructions: */
#define AVR_JTAG_INS_EXTEST 0x00
#define AVR_JTAG_INS_IDCODE 0x01
#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02
#define AVR_JTAG_INS_BYPASS 0x0F
/* AVR Specified Public Instructions: */
#define AVR_JTAG_INS_AVR_RESET 0x0C
#define AVR_JTAG_INS_PROG_ENABLE 0x04
#define AVR_JTAG_INS_PROG_COMMANDS 0x05
#define AVR_JTAG_INS_PROG_PAGELOAD 0x06
#define AVR_JTAG_INS_PROG_PAGEREAD 0x07

/* Data Registers: */
#define AVR_JTAG_REG_Bypass_Len 1
#define AVR_JTAG_REG_DeviceID_Len 32

#define AVR_JTAG_REG_Reset_Len 1
#define AVR_JTAG_REG_JTAGID_Len 32
#define AVR_JTAG_REG_ProgrammingEnable_Len 16
#define AVR_JTAG_REG_ProgrammingCommand_Len 15
#define AVR_JTAG_REG_FlashDataByte_Len 16

struct avrf_type {
char name[15];
uint16_t chip_id;
int flash_page_size;
@@ -59,26 +58,24 @@ struct avrf_type
int eeprom_page_num;
};

struct avrf_flash_bank
{
struct avrf_flash_bank {
int ppage_size;
int probed;
};

static struct avrf_type avft_chips_info[] =
{
static struct avrf_type avft_chips_info[] = {
/* name, chip_id, flash_page_size, flash_page_num,
* eeprom_page_size, eeprom_page_num
*/
{"atmega128", 0x9702, 256, 512, 8, 512},
{"at90can128", 0x9781, 256, 512, 8, 512},
{"atmega128", 0x9702, 256, 512, 8, 512},
{"at90can128", 0x9781, 256, 512, 8, 512},
};

/* avr program functions */
static int avr_jtag_reset(struct avr_common *avr, uint32_t reset)
{
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_AVR_RESET);
avr_jtag_senddat(avr->jtag_info.tap, NULL, reset ,AVR_JTAG_REG_Reset_Len);
avr_jtag_senddat(avr->jtag_info.tap, NULL, reset, AVR_JTAG_REG_Reset_Len);

return ERROR_OK;
}
@@ -127,42 +124,48 @@ static int avr_jtagprg_chiperase(struct avr_common *avr)

do {
poll_value = 0;
avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len);
avr_jtag_senddat(avr->jtag_info.tap,
&poll_value,
0x3380,
AVR_JTAG_REG_ProgrammingCommand_Len);
if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL;
}
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
} while (!(poll_value & 0x0200));

return ERROR_OK;
}

static int avr_jtagprg_writeflashpage(struct avr_common *avr, uint8_t *page_buf, uint32_t buf_size, uint32_t addr, uint32_t page_size)
static int avr_jtagprg_writeflashpage(struct avr_common *avr,
uint8_t *page_buf,
uint32_t buf_size,
uint32_t addr,
uint32_t page_size)
{
uint32_t i, poll_value;

avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len);

// load addr high byte
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0700 | ((addr >> 9) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len);
/* load addr high byte */
avr_jtag_senddat(avr->jtag_info.tap,
NULL,
0x0700 | ((addr >> 9) & 0xFF),
AVR_JTAG_REG_ProgrammingCommand_Len);

// load addr low byte
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0300 | ((addr >> 1) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len);
/* load addr low byte */
avr_jtag_senddat(avr->jtag_info.tap,
NULL,
0x0300 | ((addr >> 1) & 0xFF),
AVR_JTAG_REG_ProgrammingCommand_Len);

avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGELOAD);

for (i = 0; i < page_size; i++)
{
for (i = 0; i < page_size; i++) {
if (i < buf_size)
{
avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8);
}
else
{
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8);
}
}

avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
@@ -174,11 +177,12 @@ static int avr_jtagprg_writeflashpage(struct avr_common *avr, uint8_t *page_buf,

do {
poll_value = 0;
avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len);
avr_jtag_senddat(avr->jtag_info.tap,
&poll_value,
0x3700,
AVR_JTAG_REG_ProgrammingCommand_Len);
if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL;
}
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
} while (!(poll_value & 0x0200));

@@ -190,9 +194,7 @@ FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command)
struct avrf_flash_bank *avrf_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

avrf_info = malloc(sizeof(struct avrf_flash_bank));
bank->driver_priv = avrf_info;
@@ -208,10 +210,9 @@ static int avrf_erase(struct flash_bank *bank, int first, int last)
struct avr_common *avr = target->arch_info;
int status;

LOG_DEBUG("%s", __FUNCTION__);
LOG_DEBUG("%s", __func__);

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -229,7 +230,7 @@ static int avrf_erase(struct flash_bank *bank, int first, int last)

static int avrf_protect(struct flash_bank *bank, int set, int first, int last)
{
LOG_INFO("%s", __FUNCTION__);
LOG_INFO("%s", __func__);
return ERROR_OK;
}

@@ -239,16 +240,16 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
struct avr_common *avr = target->arch_info;
uint32_t cur_size, cur_buffer_size, page_size;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

page_size = bank->sectors[0].size;
if ((offset % page_size) != 0)
{
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment", offset, page_size);
if ((offset % page_size) != 0) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
offset,
page_size);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

@@ -256,22 +257,19 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
LOG_DEBUG("count is %" PRId32 "", count);

if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
{
return ERROR_FAIL;
}

cur_size = 0;
while (count > 0)
{
while (count > 0) {
if (count > page_size)
{
cur_buffer_size = page_size;
}
else
{
cur_buffer_size = count;
}
avr_jtagprg_writeflashpage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size);
avr_jtagprg_writeflashpage(avr,
buffer + cur_size,
cur_buffer_size,
offset + cur_size,
page_size);
count -= cur_buffer_size;
cur_size += cur_buffer_size;

@@ -284,6 +282,7 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)

static int avrf_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
@@ -293,8 +292,7 @@ static int avrf_probe(struct flash_bank *bank)
int i;
uint32_t device_id;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -303,42 +301,35 @@ static int avrf_probe(struct flash_bank *bank)

avr_jtag_read_jtagid(avr, &device_id);
if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL;
}

LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
if (EXTRACT_MFG(device_id) != 0x1F)
{
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F);
}
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
EXTRACT_MFG(device_id),
0x1F);

for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++)
{
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id))
{
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
avr_info = &avft_chips_info[i];
LOG_INFO("target device is %s", avr_info->name);
break;
}
}

if (avr_info != NULL)
{
if (bank->sectors)
{
if (avr_info != NULL) {
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}

// chip found
/* chip found */
bank->base = 0x00000000;
bank->size = (avr_info->flash_page_size * avr_info->flash_page_num);
bank->num_sectors = avr_info->flash_page_num;
bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num);

for (i = 0; i < avr_info->flash_page_num; i++)
{
for (i = 0; i < avr_info->flash_page_num; i++) {
bank->sectors[i].offset = i * avr_info->flash_page_size;
bank->sectors[i].size = avr_info->flash_page_size;
bank->sectors[i].is_erased = -1;
@@ -347,10 +338,8 @@ static int avrf_probe(struct flash_bank *bank)

avrf_info->probed = 1;
return ERROR_OK;
}
else
{
// chip not supported
} else {
/* chip not supported */
LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id));

avrf_info->probed = 1;
@@ -368,7 +357,7 @@ static int avrf_auto_probe(struct flash_bank *bank)

static int avrf_protect_check(struct flash_bank *bank)
{
LOG_INFO("%s", __FUNCTION__);
LOG_INFO("%s", __func__);
return ERROR_OK;
}

@@ -380,28 +369,23 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
int i;
uint32_t device_id;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

avr_jtag_read_jtagid(avr, &device_id);
if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL;
}

LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
if (EXTRACT_MFG(device_id) != 0x1F)
{
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F);
}
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
EXTRACT_MFG(device_id),
0x1F);

for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++)
{
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id))
{
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
avr_info = &avft_chips_info[i];
LOG_INFO("target device is %s", avr_info->name);

@@ -409,15 +393,13 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
}
}

if (avr_info != NULL)
{
// chip found
snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name, EXTRACT_VER(device_id));
if (avr_info != NULL) {
/* chip found */
snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name,
EXTRACT_VER(device_id));
return ERROR_OK;
}
else
{
// chip not supported
} else {
/* chip not supported */
snprintf(buf, buf_size, "Cannot identify target as a avr\n");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -428,18 +410,15 @@ static int avrf_mass_erase(struct flash_bank *bank)
struct target *target = bank->target;
struct avr_common *avr = target->arch_info;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((ERROR_OK != avr_jtagprg_enterprogmode(avr))
|| (ERROR_OK != avr_jtagprg_chiperase(avr))
|| (ERROR_OK != avr_jtagprg_leaveprogmode(avr)))
{
|| (ERROR_OK != avr_jtagprg_chiperase(avr))
|| (ERROR_OK != avr_jtagprg_leaveprogmode(avr)))
return ERROR_FAIL;
}

return ERROR_OK;
}
@@ -449,31 +428,23 @@ COMMAND_HANDLER(avrf_handle_mass_erase_command)
int i;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (ERROR_OK != retval)
return retval;

if (avrf_mass_erase(bank) == ERROR_OK)
{
if (avrf_mass_erase(bank) == ERROR_OK) {
/* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1;
}

command_print(CMD_CTX, "avr mass erase complete");
}
else
{
} else
command_print(CMD_CTX, "avr mass erase failed");
}

LOG_DEBUG("%s", __FUNCTION__);
LOG_DEBUG("%s", __func__);
return ERROR_OK;
}



+ 767
- 933
src/flash/nor/cfi.c
File diff suppressed because it is too large
View File


+ 7
- 12
src/flash/nor/cfi.h View File

@@ -17,14 +17,14 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifndef CFI_H
#define CFI_H

#define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */
#define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */

struct cfi_flash_bank
{
struct cfi_flash_bank {
struct working_area *write_algorithm;

int x16_as_x8;
@@ -80,8 +80,7 @@ struct cfi_flash_bank
* as defined for the Advanced+ Boot Block Flash Memory (C3)
* and used by the linux kernel cfi driver (as of 2.6.14)
*/
struct cfi_intel_pri_ext
{
struct cfi_intel_pri_ext {
uint8_t pri[3];
uint8_t major_version;
uint8_t minor_version;
@@ -100,8 +99,7 @@ struct cfi_intel_pri_ext
/* Spansion primary extended query table as defined for and used by
* the linux kernel cfi driver (as of 2.6.15)
*/
struct cfi_spansion_pri_ext
{
struct cfi_spansion_pri_ext {
uint8_t pri[3];
uint8_t major_version;
uint8_t minor_version;
@@ -124,8 +122,7 @@ struct cfi_spansion_pri_ext
/* Atmel primary extended query table as defined for and used by
* the linux kernel cfi driver (as of 2.6.20+)
*/
struct cfi_atmel_pri_ext
{
struct cfi_atmel_pri_ext {
uint8_t pri[3];
uint8_t major_version;
uint8_t minor_version;
@@ -140,14 +137,12 @@ enum {
CFI_UNLOCK_5555_2AAA,
};

struct cfi_unlock_addresses
{
struct cfi_unlock_addresses {
uint32_t unlock1;
uint32_t unlock2;
};

struct cfi_fixup
{
struct cfi_fixup {
uint16_t mfr;
uint16_t id;
void (*fixup)(struct flash_bank *bank, void *param);


+ 104
- 162
src/flash/nor/core.c View File

@@ -29,7 +29,6 @@
#include <flash/nor/imp.h>
#include <target/image.h>


/**
* @file
* Upper level of NOR flash framework.
@@ -45,9 +44,7 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last)

retval = bank->driver->erase(bank, first, last);
if (retval != ERROR_OK)
{
LOG_ERROR("failed erasing sectors %d to %d", first, last);
}

return retval;
}
@@ -57,8 +54,7 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
int retval;

/* callers may not supply illegal parameters ... */
if (first < 0 || first > last || last >= bank->num_sectors)
{
if (first < 0 || first > last || last >= bank->num_sectors) {
LOG_ERROR("illegal sector range");
return ERROR_FAIL;
}
@@ -79,47 +75,47 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
*/
retval = bank->driver->protect(bank, set, first, last);
if (retval != ERROR_OK)
{
LOG_ERROR("failed setting protection for areas %d to %d", first, last);
}

return retval;
}

int flash_driver_write(struct flash_bank *bank,
uint8_t *buffer, uint32_t offset, uint32_t count)
uint8_t *buffer, uint32_t offset, uint32_t count)
{
int retval;

retval = bank->driver->write(bank, buffer, offset, count);
if (retval != ERROR_OK)
{
LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
bank->base, offset);
if (retval != ERROR_OK) {
LOG_ERROR(
"error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
bank->base,
offset);
}

return retval;
}

int flash_driver_read(struct flash_bank *bank,
uint8_t *buffer, uint32_t offset, uint32_t count)
uint8_t *buffer, uint32_t offset, uint32_t count)
{
int retval;

LOG_DEBUG("call flash_driver_read()");

retval = bank->driver->read(bank, buffer, offset, count);
if (retval != ERROR_OK)
{
LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
bank->base, offset);
if (retval != ERROR_OK) {
LOG_ERROR(
"error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
bank->base,
offset);
}

return retval;
}

int default_flash_read(struct flash_bank *bank,
uint8_t *buffer, uint32_t offset, uint32_t count)
uint8_t *buffer, uint32_t offset, uint32_t count)
{
return target_read_buffer(bank->target, offset + bank->base, count, buffer);
}
@@ -128,19 +124,16 @@ void flash_bank_add(struct flash_bank *bank)
{
/* put flash bank in linked list */
unsigned bank_num = 0;
if (flash_banks)
{
if (flash_banks) {
/* find last flash bank */
struct flash_bank *p = flash_banks;
while (NULL != p->next)
{
while (NULL != p->next) {
bank_num += 1;
p = p->next;
}
p->next = bank;
bank_num += 1;
}
else
} else
flash_banks = bank;

bank->bank_number = bank_num;
@@ -156,12 +149,9 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num)
struct flash_bank *p;
int i = 0;

for (p = flash_banks; p; p = p->next)
{
for (p = flash_banks; p; p = p->next) {
if (i++ == num)
{
return p;
}
}
LOG_ERROR("flash bank %d does not exist", num);
return NULL;
@@ -172,9 +162,7 @@ int flash_get_bank_count(void)
struct flash_bank *p;
int i = 0;
for (p = flash_banks; p; p = p->next)
{
i++;
}
return i;
}

@@ -184,8 +172,7 @@ struct flash_bank *get_flash_bank_by_name_noprobe(const char *name)
unsigned found = 0;

struct flash_bank *bank;
for (bank = flash_banks; NULL != bank; bank = bank->next)
{
for (bank = flash_banks; NULL != bank; bank = bank->next) {
if (strcmp(bank->name, name) == 0)
return bank;
if (!flash_driver_name_matches(bank->driver->name, name))
@@ -203,12 +190,10 @@ int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result)
int retval;

bank = get_flash_bank_by_name_noprobe(name);
if (bank != NULL)
{
if (bank != NULL) {
retval = bank->driver->auto_probe(bank);

if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
LOG_ERROR("auto_probe failed");
return retval;
}
@@ -224,14 +209,11 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank)
int retval;

if (p == NULL)
{
return ERROR_FAIL;
}

retval = p->driver->auto_probe(p);

if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
LOG_ERROR("auto_probe failed");
return retval;
}
@@ -241,31 +223,30 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank)

/* lookup flash bank by address, bank not found is success, but
* result_bank is set to NULL. */
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank)
int get_flash_bank_by_addr(struct target *target,
uint32_t addr,
bool check,
struct flash_bank **result_bank)
{
struct flash_bank *c;

/* cycle through bank list */
for (c = flash_banks; c; c = c->next)
{
for (c = flash_banks; c; c = c->next) {
int retval;
retval = c->driver->auto_probe(c);

if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
LOG_ERROR("auto_probe failed");
return retval;
}
/* check whether address belongs to this flash bank */
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target)
{
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target) {
*result_bank = c;
return ERROR_OK;
}
}
*result_bank = NULL;
if (check)
{
if (check) {
LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
return ERROR_FAIL;
}
@@ -280,38 +261,33 @@ int default_flash_mem_blank_check(struct flash_bank *bank)
uint32_t nBytes;
int retval = ERROR_OK;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

uint8_t *buffer = malloc(buffer_size);

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
uint32_t j;
bank->sectors[i].is_erased = 1;

for (j = 0; j < bank->sectors[i].size; j += buffer_size)
{
for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
uint32_t chunk;
chunk = buffer_size;
if (chunk > (j - bank->sectors[i].size))
{
chunk = (j - bank->sectors[i].size);
}

retval = target_read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk/4, buffer);
retval = target_read_memory(target,
bank->base + bank->sectors[i].offset + j,
4,
chunk/4,
buffer);
if (retval != ERROR_OK)
{
goto done;
}

for (nBytes = 0; nBytes < chunk; nBytes++)
{
if (buffer[nBytes] != 0xFF)
{
for (nBytes = 0; nBytes < chunk; nBytes++) {
if (buffer[nBytes] != 0xFF) {
bank->sectors[i].is_erased = 0;
break;
}
@@ -319,7 +295,7 @@ int default_flash_mem_blank_check(struct flash_bank *bank)
}
}

done:
done:
free(buffer);

return retval;
@@ -333,20 +309,17 @@ int default_flash_blank_check(struct flash_bank *bank)
int fast_check = 0;
uint32_t blank;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
uint32_t address = bank->base + bank->sectors[i].offset;
uint32_t size = bank->sectors[i].size;

retval = target_blank_check_memory(target, address, size, &blank);
if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
fast_check = 0;
break;
}
@@ -357,8 +330,7 @@ int default_flash_blank_check(struct flash_bank *bank)
fast_check = 1;
}

if (!fast_check)
{
if (!fast_check) {
LOG_USER("Running slow fallback erase check - add working memory");
return default_flash_mem_blank_check(bank);
}
@@ -381,8 +353,8 @@ int default_flash_blank_check(struct flash_bank *bank)
* warning about those additions.
*/
static int flash_iterate_address_range_inner(struct target *target,
char *pad_reason, uint32_t addr, uint32_t length,
int (*callback)(struct flash_bank *bank, int first, int last))
char *pad_reason, uint32_t addr, uint32_t length,
int (*callback)(struct flash_bank *bank, int first, int last))
{
struct flash_bank *c;
uint32_t last_addr = addr + length; /* first address AFTER end */
@@ -394,17 +366,14 @@ static int flash_iterate_address_range_inner(struct target *target,
if (retval != ERROR_OK)
return retval;

if (c->size == 0 || c->num_sectors == 0)
{
if (c->size == 0 || c->num_sectors == 0) {
LOG_ERROR("Bank is invalid");
return ERROR_FLASH_BANK_INVALID;
}

if (length == 0)
{
if (length == 0) {
/* special case, erase whole bank when length is zero */
if (addr != c->base)
{
if (addr != c->base) {
LOG_ERROR("Whole bank access must start at beginning of bank.");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
@@ -413,8 +382,7 @@ static int flash_iterate_address_range_inner(struct target *target,
}

/* check whether it all fits in this bank */
if (addr + length - 1 > c->base + c->size - 1)
{
if (addr + length - 1 > c->base + c->size - 1) {
LOG_ERROR("Flash access does not fit into bank.");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
@@ -424,8 +392,7 @@ static int flash_iterate_address_range_inner(struct target *target,
addr -= c->base;
last_addr -= c->base;

for (i = 0; i < c->num_sectors; i++)
{
for (i = 0; i < c->num_sectors; i++) {
struct flash_sector *f = c->sectors + i;
uint32_t end = f->offset + f->size;

@@ -449,7 +416,7 @@ static int flash_iterate_address_range_inner(struct target *target,
else if (addr < end && pad_reason) {
/* FIXME say how many bytes (e.g. 80 KB) */
LOG_WARNING("Adding extra %s range, "
"%#8.8x to %#8.8x",
"%#8.8x to %#8.8x",
pad_reason,
(unsigned) f->offset,
(unsigned) addr - 1);
@@ -470,7 +437,7 @@ static int flash_iterate_address_range_inner(struct target *target,
if (last_addr < end && pad_reason) {
/* FIXME say how many bytes (e.g. 80 KB) */
LOG_WARNING("Adding extra %s range, "
"%#8.8x to %#8.8x",
"%#8.8x to %#8.8x",
pad_reason,
(unsigned) last_addr,
(unsigned) end - 1);
@@ -486,9 +453,9 @@ static int flash_iterate_address_range_inner(struct target *target,
/* invalid start or end address? */
if (first == -1 || last == -1) {
LOG_ERROR("address range 0x%8.8x .. 0x%8.8x "
"is not sector-aligned",
(unsigned) (c->base + addr),
(unsigned) (c->base + last_addr - 1));
"is not sector-aligned",
(unsigned) (c->base + addr),
(unsigned) (c->base + last_addr - 1));
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

@@ -503,23 +470,21 @@ static int flash_iterate_address_range_inner(struct target *target,
* multiple chips.
*/
static int flash_iterate_address_range(struct target *target,
char *pad_reason, uint32_t addr, uint32_t length,
int (*callback)(struct flash_bank *bank, int first, int last))
char *pad_reason, uint32_t addr, uint32_t length,
int (*callback)(struct flash_bank *bank, int first, int last))
{
struct flash_bank *c;
int retval = ERROR_OK;

/* Danger! zero-length iterations means entire bank! */
do
{
do {
retval = get_flash_bank_by_addr(target, addr, true, &c);
if (retval != ERROR_OK)
return retval;

uint32_t cur_length = length;
/* check whether it all fits in this bank */
if (addr + length - 1 > c->base + c->size - 1)
{
if (addr + length - 1 > c->base + c->size - 1) {
LOG_DEBUG("iterating over more than one flash bank.");
cur_length = c->base + c->size - addr;
}
@@ -537,10 +502,10 @@ static int flash_iterate_address_range(struct target *target,
}

int flash_erase_address_range(struct target *target,
bool pad, uint32_t addr, uint32_t length)
bool pad, uint32_t addr, uint32_t length)
{
return flash_iterate_address_range(target, pad ? "erase" : NULL,
addr, length, &flash_driver_erase);
addr, length, &flash_driver_erase);
}

static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
@@ -555,30 +520,25 @@ int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t le
* and doesn't restore it.
*/
return flash_iterate_address_range(target, "unprotect",
addr, length, &flash_driver_unprotect);
addr, length, &flash_driver_unprotect);
}

static int compare_section (const void * a, const void * b)
static int compare_section(const void *a, const void *b)
{
struct imagesection *b1, *b2;
b1=*((struct imagesection **)a);
b2=*((struct imagesection **)b);
b1 = *((struct imagesection **)a);
b2 = *((struct imagesection **)b);

if (b1->base_address == b2->base_address)
{
return 0;
} else if (b1->base_address > b2->base_address)
{
else if (b1->base_address > b2->base_address)
return 1;
} else
{
else
return -1;
}
}


int flash_write_unlock(struct target *target, struct image *image,
uint32_t *written, int erase, bool unlock)
uint32_t *written, int erase, bool unlock)
{
int retval = ERROR_OK;

@@ -593,8 +553,7 @@ int flash_write_unlock(struct target *target, struct image *image,
if (written)
*written = 0;

if (erase)
{
if (erase) {
/* assume all sectors need erasing - stops any problems
* when flash_write is called multiple times */

@@ -610,16 +569,13 @@ int flash_write_unlock(struct target *target, struct image *image,
image->num_sections);
int i;
for (i = 0; i < image->num_sections; i++)
{
sections[i] = &image->sections[i];
}

qsort(sections, image->num_sections, sizeof(struct imagesection *),
compare_section);
compare_section);

/* loop until we reach end of the image */
while (section < image->num_sections)
{
while (section < image->num_sections) {
uint32_t buffer_size;
uint8_t *buffer;
int section_last;
@@ -627,8 +583,7 @@ int flash_write_unlock(struct target *target, struct image *image,
uint32_t run_size = sections[section]->size - section_offset;
int pad_bytes = 0;

if (sections[section]->size == 0)
{
if (sections[section]->size == 0) {
LOG_WARNING("empty section %d", section);
section++;
section_offset = 0;
@@ -638,12 +593,9 @@ int flash_write_unlock(struct target *target, struct image *image,
/* find the corresponding flash bank */
retval = get_flash_bank_by_addr(target, run_address, false, &c);
if (retval != ERROR_OK)
{
goto done;
}
if (c == NULL)
{
section++; /* and skip it */
if (c == NULL) {
section++; /* and skip it */
section_offset = 0;
continue;
}
@@ -651,15 +603,13 @@ int flash_write_unlock(struct target *target, struct image *image,
/* collect consecutive sections which fall into the same bank */
section_last = section;
padding[section] = 0;
while ((run_address + run_size - 1 < c->base + c->size - 1)
&& (section_last + 1 < image->num_sections))
{
while ((run_address + run_size - 1 < c->base + c->size - 1) &&
(section_last + 1 < image->num_sections)) {
/* sections are sorted */
assert(sections[section_last + 1]->base_address >= c->base);
if (sections[section_last + 1]->base_address >= (c->base + c->size))
{
/* Done with this bank */
break;
if (sections[section_last + 1]->base_address >= (c->base + c->size)) {
/* Done with this bank */
break;
}

/* FIXME This needlessly touches sectors BETWEEN the
@@ -685,11 +635,12 @@ int flash_write_unlock(struct target *target, struct image *image,
run_size += pad_bytes;

if (pad_bytes > 0)
LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
LOG_INFO("Padding image section %d with %d bytes",
section_last-1,
pad_bytes);
}

if (run_address + run_size - 1 > c->base + c->size - 1)
{
if (run_address + run_size - 1 > c->base + c->size - 1) {
/* If we have more than one flash chip back to back, then we limit
* the current write operation to the current chip.
*/
@@ -710,7 +661,7 @@ int flash_write_unlock(struct target *target, struct image *image,

for (sector = 0; sector < c->num_sectors; sector++) {
end = c->sectors[sector].offset
+ c->sectors[sector].size;
+ c->sectors[sector].size;
if (offset_end <= end)
break;
}
@@ -722,8 +673,7 @@ int flash_write_unlock(struct target *target, struct image *image,

/* allocate buffer */
buffer = malloc(run_size);
if (buffer == NULL)
{
if (buffer == NULL) {
LOG_ERROR("Out of memory for flash bank buffer");
retval = ERROR_FAIL;
goto done;
@@ -731,13 +681,12 @@ int flash_write_unlock(struct target *target, struct image *image,
buffer_size = 0;

/* read sections to the buffer */
while (buffer_size < run_size)
{
while (buffer_size < run_size) {
size_t size_read;

size_read = run_size - buffer_size;
if (size_read > sections[section]->size - section_offset)
size_read = sections[section]->size - section_offset;
size_read = sections[section]->size - section_offset;

/* KLUDGE!
*
@@ -747,25 +696,25 @@ int flash_write_unlock(struct target *target, struct image *image,
intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
int t_section_num = diff / sizeof(struct imagesection);

LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d",
(int)section,
(int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read);
if ((retval = image_read_section(image, t_section_num, section_offset,
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
{
LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, "
"section_offset = %d, buffer_size = %d, size_read = %d",
(int)section, (int)t_section_num, (int)section_offset,
(int)buffer_size, (int)size_read);
retval = image_read_section(image, t_section_num, section_offset,
size_read, buffer + buffer_size, &size_read);
if (retval != ERROR_OK || size_read == 0) {
free(buffer);
goto done;
}

/* see if we need to pad the section */
while (padding[section]--)
(buffer + buffer_size)[size_read++] = 0xff;
(buffer + buffer_size)[size_read++] = 0xff;

buffer_size += size_read;
section_offset += size_read;

if (section_offset >= sections[section]->size)
{
if (section_offset >= sections[section]->size) {
section++;
section_offset = 0;
}
@@ -774,38 +723,31 @@ int flash_write_unlock(struct target *target, struct image *image,
retval = ERROR_OK;

if (unlock)
{
retval = flash_unlock_address_range(target, run_address, run_size);
}
if (retval == ERROR_OK)
{
if (erase)
{
if (retval == ERROR_OK) {
if (erase) {
/* calculate and erase sectors */
retval = flash_erase_address_range(target,
true, run_address, run_size);
}
}

if (retval == ERROR_OK)
{
if (retval == ERROR_OK) {
/* write flash sectors */
retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
}

free(buffer);

if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
/* abort operation */
goto done;
}

if (written != NULL)
*written += run_size; /* add run size to total written counter */
*written += run_size; /* add run size to total written counter */
}


done:
free(sections);
free(padding);
@@ -814,7 +756,7 @@ done:
}

int flash_write(struct target *target, struct image *image,
uint32_t *written, int erase)
uint32_t *written, int erase)
{
return flash_write_unlock(target, image, written, erase, false);
}

+ 11
- 11
src/flash/nor/core.h View File

@@ -20,6 +20,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifndef FLASH_NOR_CORE_H
#define FLASH_NOR_CORE_H

@@ -39,11 +40,10 @@ struct image;
* within a flash bank. A single bank typically consists of multiple
* sectors, each of which can be erased and protected independently.
*/
struct flash_sector
{
/// Bus offset from start of the flash chip (in bytes).
struct flash_sector {
/** Bus offset from start of the flash chip (in bytes). */
uint32_t offset;
/// Number of bytes in this flash sector.
/** Number of bytes in this flash sector. */
uint32_t size;
/**
* Indication of erasure status: 0 = not erased, 1 = erased,
@@ -72,8 +72,7 @@ struct flash_sector
* may use the @c driver_priv member to store additional data on a
* per-bank basis, if required.
*/
struct flash_bank
{
struct flash_bank {
const char *name;

struct target *target; /**< Target to which this bank belongs. */
@@ -94,13 +93,13 @@ struct flash_bank
* some non-zero value during "probe()" or "auto_probe()".
*/
int num_sectors;
/// Array of sectors, allocated and initilized by the flash driver
/** Array of sectors, allocated and initilized by the flash driver */
struct flash_sector *sectors;

struct flash_bank *next; /**< The next flash bank on this chip */
};

/// Registers the 'flash' subsystem commands
/** Registers the 'flash' subsystem commands */
int flash_register_commands(struct command_context *cmd_ctx);

/**
@@ -134,7 +133,7 @@ int flash_write(struct target *target,
* This routine must be called when the system may modify the status.
*/
void flash_set_dirty(void);
/// @returns The number of flash banks currently defined.
/** @returns The number of flash banks currently defined. */
int flash_get_bank_count(void);
/**
* Provides default read implementation for flash memory.
@@ -209,6 +208,7 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num);
* @param check return ERROR_OK and result_bank NULL if the bank does not exist
* @returns The struct flash_bank located at @a addr, or NULL.
*/
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank);
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check,
struct flash_bank **result_bank);

#endif // FLASH_NOR_CORE_H
#endif /* FLASH_NOR_CORE_H */

+ 5
- 4
src/flash/nor/driver.h View File

@@ -20,6 +20,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifndef FLASH_NOR_DRIVER_H
#define FLASH_NOR_DRIVER_H

@@ -48,8 +49,7 @@ struct flash_bank;
* corresponding static <code>flash_driver_<i>callback</i>()</code>
* routine in flash.c.
*/
struct flash_driver
{
struct flash_driver {
/**
* Gives a human-readable name of this flash driver,
* This field is used to select and initialize the driver.
@@ -213,7 +213,8 @@ struct flash_driver
int (*auto_probe)(struct flash_bank *bank);
};

#define FLASH_BANK_COMMAND_HANDLER(name) static __FLASH_BANK_COMMAND(name)
#define FLASH_BANK_COMMAND_HANDLER(name) \
static __FLASH_BANK_COMMAND(name)

/**
* Find a NOR flash driver by its name.
@@ -222,4 +223,4 @@ struct flash_driver
*/
struct flash_driver *flash_driver_find_by_name(const char *name);

#endif // FLASH_NOR_DRIVER_H
#endif /* FLASH_NOR_DRIVER_H */

+ 2
- 2
src/flash/nor/drivers.c View File

@@ -16,6 +16,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -84,8 +85,7 @@ static struct flash_driver *flash_drivers[] = {

struct flash_driver *flash_driver_find_by_name(const char *name)
{
for (unsigned i = 0; flash_drivers[i]; i++)
{
for (unsigned i = 0; flash_drivers[i]; i++) {
if (strcmp(name, flash_drivers[i]->name) == 0)
return flash_drivers[i];
}


+ 49
- 53
src/flash/nor/dsp5680xx_flash.c View File

@@ -27,12 +27,12 @@
* @file dsp5680xx_flash.c
* @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com>
* @date Thu Jun 9 18:21:58 2011
*
*
* @brief This file implements the basic functions to run flashing commands
* from the TCL interface.
* It allows the user to flash the Freescale 5680xx DSP.
*
*
*
*
*/

#ifdef HAVE_CONFIG_H
@@ -84,14 +84,14 @@ FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command)
return ERROR_OK;
}

/**
/**
* A memory mapped register (PROT) holds information regarding sector protection.
* Protection refers to undesired core access.
* The value in this register is loaded from flash upon reset.
*
* @param bank
*
* @return
*
* @param bank
*
* @return
*/
static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
{
@@ -118,17 +118,18 @@ static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
return retval;
}

/**
/**
* Protection funcionality is not implemented.
* The current implementation applies/removes security on the chip.
* The chip is effectively secured/unsecured after the first reset following the execution of this function.
*
* @param bank
* The chip is effectively secured/unsecured after the first reset
* following the execution of this function.
*
* @param bank
* @param set Apply or remove security on the chip.
* @param first This parameter is ignored.
* @param last This parameter is ignored.
*
* @return
*
* @return
*/
static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
int last)
@@ -153,15 +154,16 @@ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
return retval;
}

/**
* The dsp5680xx use word addressing. The "/2" that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing.
*
* @param bank
/**
* The dsp5680xx use word addressing. The "/2" that appear in the following code
* are a workaround for the fact that OpenOCD uses byte addressing.
*
* @param bank
* @param buffer Data to write to flash.
* @param offset
* @param offset
* @param count In bytes (2 bytes per address).
*
* @return
*
* @return
*/
static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t * buffer,
uint32_t offset, uint32_t count)
@@ -178,24 +180,18 @@ static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t * buffer,
* This chip uses word addressing, Openocd only supports byte addressing.
* The workaround results in disabling writing to odd byte addresses
*/
LOG_ERROR
("%s: Writing to odd addresses not supported for this target",
__func__);
LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
return ERROR_FAIL;
}
retval =
dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count,
0);
retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
uint32_t addr_word;

for (addr_word = bank->base + offset / 2; addr_word < count / 2;
addr_word += (HFM_SECTOR_SIZE / 2)) {
addr_word += (HFM_SECTOR_SIZE / 2)) {
if (retval == ERROR_OK)
bank->sectors[addr_word /
(HFM_SECTOR_SIZE / 2)].is_erased = 0;
bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0;
else
bank->sectors[addr_word /
(HFM_SECTOR_SIZE / 2)].is_erased = -1;
bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1;
}
return retval;
}
@@ -207,31 +203,32 @@ static int dsp5680xx_probe(struct flash_bank *bank)
}

static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf,
int buf_size)
int buf_size)
{
snprintf(buf, buf_size,
"\ndsp5680xx flash driver info:\n - See comments in code.");
return ERROR_OK;
}

/**
* The flash module (FM) on the dsp5680xx supports both individual sector and mass erase of the flash memory.
* If this function is called with @first == @last == 0 or if @first is the first sector (#0) and @last is the last sector then the mass erase command is executed (much faster than erasing each sector individually).
*
* @param bank
* @param first
* @param last
*
* @return
/**
* The flash module (FM) on the dsp5680xx supports both individual sector
* and mass erase of the flash memory.
* If this function is called with @first == @last == 0 or if @first is the
* first sector (#0) and @last is the last sector then the mass erase command
* is executed (much faster than erasing each sector individually).
*
* @param bank
* @param first
* @param last
*
* @return
*/
static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
{
int retval;

retval =
dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
if ((!(first | last))
|| ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
last = HFM_SECTOR_COUNT - 1;
if (retval == ERROR_OK)
for (int i = first; i <= last; i++)
@@ -246,13 +243,13 @@ static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
return retval;
}

/**
/**
* The flash module (FM) on the dsp5680xx support a blank check function.
* This function executes the FM's blank check functionality on each and every sector.
*
* @param bank
*
* @return
*
* @param bank
*
* @return
*/
static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
{
@@ -264,8 +261,7 @@ static int dsp5680xx_flash_erase_check(struct flash_bank *bank)

for (i = 0; i < HFM_SECTOR_COUNT; i++) {
if (bank->sectors[i].is_erased == -1) {
retval =
dsp5680xx_f_erase_check(bank->target, &erased, i);
retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
if (retval != ERROR_OK) {
bank->sectors[i].is_erased = -1;
} else {


+ 92
- 109
src/flash/nor/ecos.c View File

@@ -17,6 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -26,16 +27,15 @@
#include <target/algorithm.h>
#include <target/image.h>


#if 0
static uint32_t ecosflash_get_flash_status(struct flash_bank *bank);
static void ecosflash_set_flash_mode(struct flash_bank *bank,int mode);
static void ecosflash_set_flash_mode(struct flash_bank *bank, int mode);
static uint32_t ecosflash_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout);
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc);
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx,
char *cmd, char **args, int argc);
#endif

struct ecosflash_flash_bank
{
struct ecosflash_flash_bank {
struct target *target;
struct working_area *write_algorithm;
struct working_area *erase_check_algorithm;
@@ -45,60 +45,58 @@ struct ecosflash_flash_bank

static const int sectorSize = 0x10000;

char *
flash_errmsg(int err);
char *flash_errmsg(int err);

#ifndef __ECOS
#define FLASH_ERR_OK 0x00 /* No error - operation complete */
#define FLASH_ERR_INVALID 0x01 /* Invalid FLASH address */
#define FLASH_ERR_ERASE 0x02 /* Error trying to erase */
#define FLASH_ERR_LOCK 0x03 /* Error trying to lock/unlock */
#define FLASH_ERR_PROGRAM 0x04 /* Error trying to program */
#define FLASH_ERR_PROTOCOL 0x05 /* Generic error */
#define FLASH_ERR_PROTECT 0x06 /* Device/region is write-protected */
#define FLASH_ERR_NOT_INIT 0x07 /* FLASH info not yet initialized */
#define FLASH_ERR_HWR 0x08 /* Hardware (configuration?) problem */
#define FLASH_ERR_ERASE_SUSPEND 0x09 /* Device is in erase suspend mode */
#define FLASH_ERR_PROGRAM_SUSPEND 0x0a /* Device is in in program suspend mode */
#define FLASH_ERR_DRV_VERIFY 0x0b /* Driver failed to verify data */
#define FLASH_ERR_DRV_TIMEOUT 0x0c /* Driver timed out waiting for device */
#define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support device */
#define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */

char *
flash_errmsg(int err)
#define FLASH_ERR_OK 0x00 /* No error - operation complete */
#define FLASH_ERR_INVALID 0x01 /* Invalid FLASH address */
#define FLASH_ERR_ERASE 0x02 /* Error trying to erase */
#define FLASH_ERR_LOCK 0x03 /* Error trying to lock/unlock */
#define FLASH_ERR_PROGRAM 0x04 /* Error trying to program */
#define FLASH_ERR_PROTOCOL 0x05 /* Generic error */
#define FLASH_ERR_PROTECT 0x06 /* Device/region is write-protected */
#define FLASH_ERR_NOT_INIT 0x07 /* FLASH info not yet initialized */
#define FLASH_ERR_HWR 0x08 /* Hardware (configuration?) problem */
#define FLASH_ERR_ERASE_SUSPEND 0x09 /* Device is in erase suspend mode */
#define FLASH_ERR_PROGRAM_SUSPEND 0x0a /* Device is in in program suspend mode */
#define FLASH_ERR_DRV_VERIFY 0x0b /* Driver failed to verify data */
#define FLASH_ERR_DRV_TIMEOUT 0x0c /* Driver timed out waiting for device */
#define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support device */
#define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */

char *flash_errmsg(int err)
{
switch (err) {
case FLASH_ERR_OK:
return "No error - operation complete";
case FLASH_ERR_ERASE_SUSPEND:
return "Device is in erase suspend state";
case FLASH_ERR_PROGRAM_SUSPEND:
return "Device is in program suspend state";
case FLASH_ERR_INVALID:
return "Invalid FLASH address";
case FLASH_ERR_ERASE:
return "Error trying to erase";
case FLASH_ERR_LOCK:
return "Error trying to lock/unlock";
case FLASH_ERR_PROGRAM:
return "Error trying to program";
case FLASH_ERR_PROTOCOL:
return "Generic error";
case FLASH_ERR_PROTECT:
return "Device/region is write-protected";
case FLASH_ERR_NOT_INIT:
return "FLASH sub-system not initialized";
case FLASH_ERR_DRV_VERIFY:
return "Data verify failed after operation";
case FLASH_ERR_DRV_TIMEOUT:
return "Driver timed out waiting for device";
case FLASH_ERR_DRV_WRONG_PART:
return "Driver does not support device";
case FLASH_ERR_LOW_VOLTAGE:
return "Device reports low voltage";
default:
return "Unknown error";
case FLASH_ERR_OK:
return "No error - operation complete";
case FLASH_ERR_ERASE_SUSPEND:
return "Device is in erase suspend state";
case FLASH_ERR_PROGRAM_SUSPEND:
return "Device is in program suspend state";
case FLASH_ERR_INVALID:
return "Invalid FLASH address";
case FLASH_ERR_ERASE:
return "Error trying to erase";
case FLASH_ERR_LOCK:
return "Error trying to lock/unlock";
case FLASH_ERR_PROGRAM:
return "Error trying to program";
case FLASH_ERR_PROTOCOL:
return "Generic error";
case FLASH_ERR_PROTECT:
return "Device/region is write-protected";
case FLASH_ERR_NOT_INIT:
return "FLASH sub-system not initialized";
case FLASH_ERR_DRV_VERIFY:
return "Data verify failed after operation";
case FLASH_ERR_DRV_TIMEOUT:
return "Driver timed out waiting for device";
case FLASH_ERR_DRV_WRONG_PART:
return "Driver does not support device";
case FLASH_ERR_LOW_VOLTAGE:
return "Device reports low voltage";
default:
return "Unknown error";
}
}
#endif
@@ -110,13 +108,10 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
struct ecosflash_flash_bank *info;

if (CMD_ARGC < 7)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

info = malloc(sizeof(struct ecosflash_flash_bank));
if (info == NULL)
{
if (info == NULL) {
LOG_ERROR("no memory for flash bank info");
exit(-1);
}
@@ -131,8 +126,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
uint32_t offset = 0;
bank->num_sectors = bank->size/sectorSize;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = sectorSize;
offset += bank->sectors[i].size;
@@ -141,8 +135,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
}

info->target = get_target(CMD_ARGV[5]);
if (info->target == NULL)
{
if (info->target == NULL) {
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
return ERROR_FAIL;
}
@@ -160,20 +153,18 @@ static int loadDriver(struct ecosflash_flash_bank *info)
struct target *target = info->target;
int retval;

if ((retval = image_open(&image, info->driverPath, NULL)) != ERROR_OK)
{
retval = image_open(&image, info->driverPath, NULL);
if (retval != ERROR_OK)
return retval;
}

info->start_address = image.start_address;

image_size = 0x0;
int i;
for (i = 0; i < image.num_sections; i++)
{
for (i = 0; i < image.num_sections; i++) {
void *buffer = malloc(image.sections[i].size);
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
{
retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
if (retval != ERROR_OK) {
free(buffer);
image_close(&image);
return retval;
@@ -181,7 +172,7 @@ static int loadDriver(struct ecosflash_flash_bank *info)
target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
image_size += buf_cnt;
LOG_DEBUG("%zu bytes written at address 0x%8.8" PRIx32 "",
buf_cnt, image.sections[i].base_address);
buf_cnt, image.sections[i].base_address);

free(buffer);
}
@@ -191,7 +182,7 @@ static int loadDriver(struct ecosflash_flash_bank *info)
return ERROR_OK;
}

static int const OFFSET_ERASE = 0x0;
static int const OFFSET_ERASE;
static int const OFFSET_ERASE_SIZE = 0x8;
static int const OFFSET_FLASH = 0xc;
static int const OFFSET_FLASH_SIZE = 0x8;
@@ -199,10 +190,10 @@ static int const OFFSET_GET_WORKAREA = 0x18;
static int const OFFSET_GET_WORKAREA_SIZE = 0x4;

static int runCode(struct ecosflash_flash_bank *info,
uint32_t codeStart, uint32_t codeStop, uint32_t r0, uint32_t r1, uint32_t r2,
uint32_t *result,
/* timeout in ms */
int timeout)
uint32_t codeStart, uint32_t codeStop, uint32_t r0, uint32_t r1, uint32_t r2,
uint32_t *result,
/* timeout in ms */
int timeout)
{
struct target *target = info->target;

@@ -220,12 +211,9 @@ static int runCode(struct ecosflash_flash_bank *info,
buf_set_u32(reg_params[1].value, 0, 32, r1);
buf_set_u32(reg_params[2].value, 0, 32, r2);

int retval;
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
codeStart,
codeStop, timeout,
&armv4_5_info)) != ERROR_OK)
{
int retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
codeStart, codeStop, timeout, &armv4_5_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing eCos flash algorithm");
return retval;
}
@@ -242,7 +230,7 @@ static int runCode(struct ecosflash_flash_bank *info,
static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address, uint32_t len)
{
int retval;
int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/
int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/

retval = loadDriver(info);
if (retval != ERROR_OK)
@@ -257,12 +245,11 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address,
0,
&flashErr,
timeout
);
);
if (retval != ERROR_OK)
return retval;

if (flashErr != 0x0)
{
if (flashErr != 0x0) {
LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
return ERROR_FAIL;
}
@@ -270,12 +257,15 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address,
return ERROR_OK;
}

static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32_t address, uint32_t len)
static int eCosBoard_flash(struct ecosflash_flash_bank *info,
void *data,
uint32_t address,
uint32_t len)
{
struct target *target = info->target;
const int chunk = 8192;
int retval = ERROR_OK;
int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/
int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/

retval = loadDriver(info);
if (retval != ERROR_OK)
@@ -295,13 +285,10 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32


uint32_t i;
for (i = 0; i < len; i += chunk)
{
for (i = 0; i < len; i += chunk) {
int t = len-i;
if (t > chunk)
{
t = chunk;
}

retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
if (retval != ERROR_OK)
@@ -319,9 +306,9 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32
if (retval != ERROR_OK)
return retval;

if (flashErr != 0x0)
{
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
if (flashErr != 0x0) {
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr,
flash_errmsg(flashErr));
return ERROR_FAIL;
}
}
@@ -339,19 +326,12 @@ static void command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
struct ecosflash_flash_bank *info = bank->driver_priv;
int i;

if (info->target->endianness == TARGET_LITTLE_ENDIAN)
{
if (info->target->endianness == TARGET_LITTLE_ENDIAN) {
for (i = bank->bus_width; i > 0; i--)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
}
}
else
{
} else {
for (i = 1; i <= bank->bus_width; i++)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
}
}
}
#endif
@@ -360,8 +340,7 @@ static void command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
static uint32_t ecosflash_address(struct flash_bank *bank, uint32_t address)
{
uint32_t retval = 0;
switch (bank->bus_width)
{
switch (bank->bus_width) {
case 4:
retval = address & 0xfffffffc;
case 2:
@@ -386,7 +365,8 @@ static int ecosflash_protect(struct flash_bank *bank, int set, int first, int la
return ERROR_OK;
}

static int ecosflash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
static int ecosflash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
uint32_t count)
{
struct ecosflash_flash_bank *info = bank->driver_priv;
struct flash_bank *c = bank;
@@ -411,7 +391,7 @@ static uint32_t ecosflash_get_flash_status(struct flash_bank *bank)
return ERROR_OK;
}

static void ecosflash_set_flash_mode(struct flash_bank *bank,int mode)
static void ecosflash_set_flash_mode(struct flash_bank *bank, int mode)
{

}
@@ -421,7 +401,10 @@ static uint32_t ecosflash_wait_status_busy(struct flash_bank *bank, uint32_t wai
return ERROR_OK;
}

static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc)
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx,
char *cmd,
char **args,
int argc)
{
return ERROR_OK;
}


+ 108
- 156
src/flash/nor/em357.c View File

@@ -7,7 +7,7 @@
*
* Copyright (C) 2011 by Erik Botö
* erik.boto@pelagicore.com
*
*
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
@@ -23,6 +23,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -34,60 +35,58 @@

/* em357 register locations */

#define EM357_FLASH_ACR 0x40008000
#define EM357_FLASH_KEYR 0x40008004
#define EM357_FLASH_OPTKEYR 0x40008008
#define EM357_FLASH_SR 0x4000800C
#define EM357_FLASH_CR 0x40008010
#define EM357_FLASH_AR 0x40008014
#define EM357_FLASH_OBR 0x4000801C
#define EM357_FLASH_WRPR 0x40008020
#define EM357_FLASH_ACR 0x40008000
#define EM357_FLASH_KEYR 0x40008004
#define EM357_FLASH_OPTKEYR 0x40008008
#define EM357_FLASH_SR 0x4000800C
#define EM357_FLASH_CR 0x40008010
#define EM357_FLASH_AR 0x40008014
#define EM357_FLASH_OBR 0x4000801C
#define EM357_FLASH_WRPR 0x40008020

#define EM357_FPEC_CLK 0x4000402c
#define EM357_FPEC_CLK 0x4000402c
/* option byte location */

#define EM357_OB_RDP 0x08040800
#define EM357_OB_WRP0 0x08040808
#define EM357_OB_WRP1 0x0804080A
#define EM357_OB_WRP2 0x0804080C
#define EM357_OB_RDP 0x08040800
#define EM357_OB_WRP0 0x08040808
#define EM357_OB_WRP1 0x0804080A
#define EM357_OB_WRP2 0x0804080C

/* FLASH_CR register bits */

#define FLASH_PG (1 << 0)
#define FLASH_PER (1 << 1)
#define FLASH_MER (1 << 2)
#define FLASH_OPTPG (1 << 4)
#define FLASH_OPTER (1 << 5)
#define FLASH_STRT (1 << 6)
#define FLASH_LOCK (1 << 7)
#define FLASH_OPTWRE (1 << 9)
#define FLASH_PG (1 << 0)
#define FLASH_PER (1 << 1)
#define FLASH_MER (1 << 2)
#define FLASH_OPTPG (1 << 4)
#define FLASH_OPTER (1 << 5)
#define FLASH_STRT (1 << 6)
#define FLASH_LOCK (1 << 7)
#define FLASH_OPTWRE (1 << 9)

/* FLASH_SR register bits */

#define FLASH_BSY (1 << 0)
#define FLASH_PGERR (1 << 2)
#define FLASH_WRPRTERR (1 << 4)
#define FLASH_EOP (1 << 5)
#define FLASH_BSY (1 << 0)
#define FLASH_PGERR (1 << 2)
#define FLASH_WRPRTERR (1 << 4)
#define FLASH_EOP (1 << 5)

/* EM357_FLASH_OBR bit definitions (reading) */

#define OPT_ERROR 0
#define OPT_READOUT 1
#define OPT_ERROR 0
#define OPT_READOUT 1

/* register unlock keys */

#define KEY1 0x45670123
#define KEY2 0xCDEF89AB
#define KEY1 0x45670123
#define KEY2 0xCDEF89AB

struct em357_options
{
struct em357_options {
uint16_t RDP;
uint16_t user_options;
uint16_t protection[3];
};

struct em357_flash_bank
{
struct em357_flash_bank {
struct em357_options option_bytes;
struct working_area *write_algorithm;
int ppage_size;
@@ -103,9 +102,7 @@ FLASH_BANK_COMMAND_HANDLER(em357_flash_bank_command)
struct em357_flash_bank *em357_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

em357_info = malloc(sizeof(struct em357_flash_bank));
bank->driver_priv = em357_info;
@@ -129,37 +126,32 @@ static int em357_wait_status_busy(struct flash_bank *bank, int timeout)
int retval = ERROR_OK;

/* wait for busy to clear */
for (;;)
{
for (;; ) {
retval = em357_get_flash_status(bank, &status);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("status: 0x%" PRIx32 "", status);
if ((status & FLASH_BSY) == 0)
break;
if (timeout-- <= 0)
{
if (timeout-- <= 0) {
LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL;
}
alive_sleep(1);
}

if (status & FLASH_WRPRTERR)
{
if (status & FLASH_WRPRTERR) {
LOG_ERROR("em357 device protected");
retval = ERROR_FAIL;
}

if (status & FLASH_PGERR)
{
if (status & FLASH_PGERR) {
LOG_ERROR("em357 device programming failed");
retval = ERROR_FAIL;
}

/* Clear but report errors */
if (status & (FLASH_WRPRTERR | FLASH_PGERR))
{
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) {
/* If this operation fails, we ignore it and report the original
* retval
*/
@@ -330,8 +322,7 @@ static int em357_protect_check(struct flash_bank *bank)
int num_bits;
int set;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -344,8 +335,7 @@ static int em357_protect_check(struct flash_bank *bank)
/* each protection bit is for 4 * 2K pages */
num_bits = (bank->num_sectors / em357_info->ppage_size);

for (i = 0; i < num_bits; i++)
{
for (i = 0; i < num_bits; i++) {
set = 1;
if (protection & (1 << i))
set = 0;
@@ -362,16 +352,13 @@ static int em357_erase(struct flash_bank *bank, int first, int last)
struct target *target = bank->target;
int i;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((first == 0) && (last == (bank->num_sectors - 1)))
{
return em357_mass_erase(bank);
}

/* unlock flash registers */
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
@@ -381,8 +368,7 @@ static int em357_erase(struct flash_bank *bank, int first, int last)
if (retval != ERROR_OK)
return retval;

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER);
if (retval != ERROR_OK)
return retval;
@@ -419,22 +405,19 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)

em357_info = bank->driver_priv;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((first % em357_info->ppage_size) != 0)
{
if ((first % em357_info->ppage_size) != 0) {
LOG_WARNING("aligned start protect sector to a %d sector boundary",
em357_info->ppage_size);
em357_info->ppage_size);
first = first - (first % em357_info->ppage_size);
}
if (((last + 1) % em357_info->ppage_size) != 0)
{
if (((last + 1) % em357_info->ppage_size) != 0) {
LOG_WARNING("aligned end protect sector to a %d sector boundary",
em357_info->ppage_size);
em357_info->ppage_size);
last++;
last = last - (last % em357_info->ppage_size);
last--;
@@ -449,8 +432,7 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)
prot_reg[1] = (uint16_t)(protection >> 8);
prot_reg[2] = (uint16_t)(protection >> 16);

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
reg = (i / em357_info->ppage_size) / 8;
bit = (i / em357_info->ppage_size) - (reg * 8);

@@ -461,7 +443,8 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)
prot_reg[reg] |= (1 << bit);
}

if ((status = em357_erase_options(bank)) != ERROR_OK)
status = em357_erase_options(bank);
if (retval != ERROR_OK)
return status;

em357_info->option_bytes.protection[0] = prot_reg[0];
@@ -472,7 +455,7 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)
}

static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
uint32_t offset, uint32_t count)
uint32_t offset, uint32_t count)
{
struct em357_flash_bank *em357_info = bank->driver_priv;
struct target *target = bank->target;
@@ -483,61 +466,63 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;

/* see contib/loaders/flash/stm32x.s for src, the same is used here except for
/* see contib/loaders/flash/stm32x.s for src, the same is used here except for
* a modified *_FLASH_BASE */

static const uint8_t em357_flash_write_code[] = {
/* #define EM357_FLASH_CR_OFFSET 0x10 */
/* #define EM357_FLASH_SR_OFFSET 0x0C */
/* write: */
/* #define EM357_FLASH_CR_OFFSET 0x10
* #define EM357_FLASH_SR_OFFSET 0x0C
* write: */
0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */
0x1c, 0x44, /* add r4, r3 */
/* write_half_word: */
/* write_half_word: */
0x01, 0x23, /* movs r3, #0x01 */
0x23, 0x61, /* str r3, [r4, #EM357_FLASH_CR_OFFSET] */
0x23, 0x61, /* str r3, [r4,
*#EM357_FLASH_CR_OFFSET] */
0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
/* busy: */
0xe3, 0x68, /* ldr r3, [r4, #EM357_FLASH_SR_OFFSET] */
/* busy: */
0xe3, 0x68, /* ldr r3, [r4,
*#EM357_FLASH_SR_OFFSET] */
0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
0xfb, 0xd0, /* beq busy */
0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
0x01, 0xd1, /* bne exit */
0x01, 0x3a, /* subs r2, r2, #0x01 */
0xf0, 0xd1, /* bne write_half_word */
/* exit: */
/* exit: */
0x00, 0xbe, /* bkpt #0x00 */
0x00, 0x80, 0x00, 0x40, /* EM357_FLASH_BASE: .word 0x40008000 */
};

/* flash write code */
if (target_alloc_working_area(target, sizeof(em357_flash_write_code),
&em357_info->write_algorithm) != ERROR_OK)
{
&em357_info->write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};
}
;

if ((retval = target_write_buffer(target, em357_info->write_algorithm->address,
sizeof(em357_flash_write_code),
(uint8_t*)em357_flash_write_code)) != ERROR_OK)
retval = target_write_buffer(target, em357_info->write_algorithm->address,
sizeof(em357_flash_write_code), (uint8_t *)em357_flash_write_code);
if (retval != ERROR_OK)
return retval;

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= 256)
{
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
if (em357_info->write_algorithm)
target_free_working_area(target, em357_info->write_algorithm);

LOG_WARNING("no large enough working area available, can't do block memory writes");
LOG_WARNING(
"no large enough working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
};
}
;

armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARMV7M_MODE_ANY;
@@ -547,13 +532,12 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_OUT);

while (count > 0)
{
while (count > 0) {
uint32_t thisrun_count = (count > (buffer_size / 2)) ?
(buffer_size / 2) : count;
(buffer_size / 2) : count;

if ((retval = target_write_buffer(target, source->address,
thisrun_count * 2, buffer)) != ERROR_OK)
retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
if (retval != ERROR_OK)
break;

buf_set_u32(reg_params[0].value, 0, 32, source->address);
@@ -561,17 +545,14 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
buf_set_u32(reg_params[3].value, 0, 32, 0);

if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
em357_info->write_algorithm->address,
0,
10000, &armv7m_info)) != ERROR_OK)
{
retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
em357_info->write_algorithm->address, 0, 10000, &armv7m_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing em357 flash write algorithm");
break;
}

if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR)
{
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, EM357_FLASH_SR, FLASH_PGERR);
@@ -579,8 +560,7 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
break;
}

if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR)
{
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, EM357_FLASH_SR, FLASH_WRPRTERR);
@@ -605,7 +585,7 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
}

static int em357_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t offset, uint32_t count)
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
uint32_t words_remaining = (count / 2);
@@ -614,14 +594,12 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t bytes_written = 0;
int retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (offset & 0x1)
{
if (offset & 0x1) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
@@ -635,20 +613,17 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
return retval;

/* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0)
{
if (words_remaining > 0) {
/* try using a block write */
if ((retval = em357_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
retval = em357_write_block(bank, buffer, offset, words_remaining);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
LOG_WARNING(
"couldn't use block writes, falling back to single memory accesses");
}
}
else
{
} else {
buffer += words_remaining * 2;
address += words_remaining * 2;
words_remaining = 0;
@@ -658,8 +633,7 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
return retval;

while (words_remaining > 0)
{
while (words_remaining > 0) {
uint16_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));

@@ -679,8 +653,7 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
address += 2;
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint16_t value = 0xffff;
memcpy(&value, buffer + bytes_written, bytes_remaining);

@@ -721,8 +694,7 @@ static int em357_probe(struct flash_bank *bank)

LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024);

if (bank->sectors)
{
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
@@ -732,8 +704,7 @@ static int em357_probe(struct flash_bank *bank)
bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);

for (i = 0; i < num_pages; i++)
{
for (i = 0; i < num_pages; i++) {
bank->sectors[i].offset = i * page_size;
bank->sectors[i].size = page_size;
bank->sectors[i].is_erased = -1;
@@ -766,9 +737,7 @@ COMMAND_HANDLER(em357_handle_lock_command)
struct em357_flash_bank *em357_info = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -779,14 +748,12 @@ COMMAND_HANDLER(em357_handle_lock_command)

target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (em357_erase_options(bank) != ERROR_OK)
{
if (em357_erase_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "em357 failed to erase options");
return ERROR_OK;
}
@@ -794,8 +761,7 @@ COMMAND_HANDLER(em357_handle_lock_command)
/* set readout protection */
em357_info->option_bytes.RDP = 0;

if (em357_write_options(bank) != ERROR_OK)
{
if (em357_write_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "em357 failed to lock device");
return ERROR_OK;
}
@@ -810,9 +776,7 @@ COMMAND_HANDLER(em357_handle_unlock_command)
struct target *target = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -821,27 +785,24 @@ COMMAND_HANDLER(em357_handle_unlock_command)

target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (em357_erase_options(bank) != ERROR_OK)
{
if (em357_erase_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "em357 failed to unlock device");
return ERROR_OK;
}

if (em357_write_options(bank) != ERROR_OK)
{
if (em357_write_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "em357 failed to lock device");
return ERROR_OK;
}

command_print(CMD_CTX, "em357 unlocked.\n"
"INFO: a reset or power cycle is required "
"for the new settings to take effect.");
"INFO: a reset or power cycle is required "
"for the new settings to take effect.");

return ERROR_OK;
}
@@ -850,8 +811,7 @@ static int em357_mass_erase(struct flash_bank *bank)
{
struct target *target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -888,9 +848,7 @@ COMMAND_HANDLER(em357_handle_mass_erase_command)
int i;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -898,20 +856,14 @@ COMMAND_HANDLER(em357_handle_mass_erase_command)
return retval;

retval = em357_mass_erase(bank);
if (retval == ERROR_OK)
{
if (retval == ERROR_OK) {
/* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1;
}

command_print(CMD_CTX, "em357 mass erase complete");
}
else
{
} else
command_print(CMD_CTX, "em357 mass erase failed");
}

return retval;
}


+ 7
- 14
src/flash/nor/faux.c View File

@@ -17,6 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -25,9 +26,7 @@
#include <target/image.h>
#include "hello.h"


struct faux_flash_bank
{
struct faux_flash_bank {
struct target *target;
uint8_t *memory;
uint32_t start_address;
@@ -43,19 +42,15 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
struct faux_flash_bank *info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

info = malloc(sizeof(struct faux_flash_bank));
if (info == NULL)
{
if (info == NULL) {
LOG_ERROR("no memory for flash bank info");
return ERROR_FAIL;
}
info->memory = malloc(bank->size);
if (info == NULL)
{
if (info == NULL) {
free(info);
LOG_ERROR("no memory for flash bank info");
return ERROR_FAIL;
@@ -67,8 +62,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
uint32_t offset = 0;
bank->num_sectors = bank->size/sectorSize;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = sectorSize;
offset += bank->sectors[i].size;
@@ -77,8 +71,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
}

info->target = get_target(CMD_ARGV[5]);
if (info->target == NULL)
{
if (info->target == NULL) {
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
free(info->memory);
free(info);
@@ -96,7 +89,7 @@ static int faux_erase(struct flash_bank *bank, int first, int last)

static int faux_protect(struct flash_bank *bank, int set, int first, int last)
{
LOG_USER("set protection sector %d to %d to %s", first, last, set?"on":"off");
LOG_USER("set protection sector %d to %d to %s", first, last, set ? "on" : "off");
return ERROR_OK;
}



+ 3
- 6
src/flash/nor/fm3.c View File

@@ -31,8 +31,7 @@
#define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */
#define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */

enum fm3_variant
{
enum fm3_variant {
mb9bfxx1, /* Flash Type '1' */
mb9bfxx2,
mb9bfxx3,
@@ -47,15 +46,13 @@ enum fm3_variant
mb9afxx6
};

enum fm3_flash_type
{
enum fm3_flash_type {
fm3_no_flash_type = 0,
fm3_flash_type1 = 1,
fm3_flash_type2 = 2
};

struct fm3_flash_bank
{
struct fm3_flash_bank {
struct working_area *write_algorithm;
enum fm3_variant variant;
enum fm3_flash_type flashtype;


+ 4
- 3
src/flash/nor/imp.h View File

@@ -16,13 +16,14 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifndef FLASH_NOR_IMP_H
#define FLASH_NOR_IMP_H

// this is an internal header
/* this is an internal header */
#include "core.h"
#include "driver.h"
// almost all drivers will need this file
/* almost all drivers will need this file */
#include <target/target.h>

/**
@@ -47,4 +48,4 @@ int flash_driver_read(struct flash_bank *bank,
int flash_write_unlock(struct target *target, struct image *image,
uint32_t *written, int erase, bool unlock);

#endif // FLASH_NOR_IMP_H
#endif /* FLASH_NOR_IMP_H */

+ 97
- 118
src/flash/nor/kinetis.c View File

@@ -20,6 +20,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -32,12 +33,12 @@ struct kinetis_flash_bank {
};

static int kinetis_get_master_bank(struct flash_bank *bank,
struct flash_bank **master_bank)
struct flash_bank **master_bank)
{
*master_bank = get_flash_bank_by_name_noprobe(bank->name);
if (*master_bank == NULL) {
LOG_ERROR("master flash bank '%s' does not exist",
(char *)bank->driver_priv);
(char *)bank->driver_priv);
return ERROR_FLASH_OPERATION_FAILED;
}

@@ -51,9 +52,8 @@ static int kinetis_update_bank_info(struct flash_bank *bank)

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

/* update the info we do not have */
bank->size = master_bank->size;
@@ -69,9 +69,8 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
{
struct kinetis_flash_bank *bank_info;

if (CMD_ARGC < 6) {
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
}

LOG_INFO("add flash_bank kinetis %s", bank->name);

@@ -85,16 +84,15 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
}

static int kinetis_protect(struct flash_bank *bank, int set, int first,
int last)
int last)
{
int result;
struct flash_bank *master_bank;

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

LOG_WARNING("kinetis_protect not supported yet");

@@ -121,16 +119,14 @@ static int kinetis_protect_check(struct flash_bank *bank)

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

/* read protection register FTFL_FPROT */
result = target_read_memory(bank->target, 0x40020010, 1, 4, buffer);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

fprot = target_buffer_get_u32(bank->target, buffer);

@@ -157,7 +153,7 @@ static int kinetis_protect_check(struct flash_bank *bank)
}

static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
uint32_t w1, uint32_t w2)
uint32_t w1, uint32_t w2)
{
uint8_t buffer[12];
int result, i;
@@ -165,11 +161,10 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
/* wait for done */
for (i = 0; i < 50; i++) {
result =
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

if (buffer[0] & 0x80)
break;
@@ -181,10 +176,9 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
/* reset error flags */
buffer[0] = 0x30;
result =
target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
if (result != ERROR_OK) {
target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
if (result != ERROR_OK)
return result;
}
}

target_buffer_set_u32(bank->target, buffer, w0);
@@ -193,25 +187,22 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,

result = target_write_memory(bank->target, 0x40020004, 4, 3, buffer);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

/* start command */
buffer[0] = 0x80;
result = target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

/* wait for done */
for (i = 0; i < 50; i++) {
result =
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

if (buffer[0] & 0x80)
break;
@@ -221,8 +212,8 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,

if (buffer[0] != 0x80) {
LOG_ERROR
("ftfl command failed FSTAT: %02X W0: %08X W1: %08X W2: %08X",
buffer[0], w0, w1, w2);
("ftfl command failed FSTAT: %02X W0: %08X W1: %08X W2: %08X",
buffer[0], w0, w1, w2);

return ERROR_FLASH_OPERATION_FAILED;
}
@@ -243,13 +234,11 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

if ((first > bank->num_sectors) || (last > bank->num_sectors)) {
if ((first > bank->num_sectors) || (last > bank->num_sectors))
return ERROR_FLASH_OPERATION_FAILED;
}

for (i = first; i <= last; i++) {
/* set command and sector address */
@@ -267,20 +256,20 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)

if (first == 0) {
LOG_WARNING
("flash configuration field erased, please reset the device");
("flash configuration field erased, please reset the device");
}

return ERROR_OK;
}

static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
uint32_t offset, uint32_t count)
static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct flash_bank *master_bank;
unsigned int i, result, fallback = 0, nvm = 0;
uint8_t buf[8];
uint32_t wc, w0 = 0, w1 = 0, w2 = 0;
struct kinetis_flash_bank * kbank = (struct kinetis_flash_bank *)
struct kinetis_flash_bank *kbank = (struct kinetis_flash_bank *)
bank->driver_priv;

if (bank->target->state != TARGET_HALTED) {
@@ -290,9 +279,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

if (offset >= kbank->nvm_start)
nvm = 1;
@@ -327,8 +315,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
/* fallback to longword write */
fallback = 1;

LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)",
buf[0]);
LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)",
buf[0]);
}
} else {
LOG_DEBUG("flash write into PFLASH @08%X", offset);
@@ -347,12 +335,12 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
}

LOG_DEBUG("write section @ %08X with length %d",
offset + i, wc * 4);
offset + i, wc * 4);

/* write data to flexram */
result =
target_write_memory(bank->target, 0x14000000, 4, wc,
buffer + i);
target_write_memory(bank->target, 0x14000000, 4, wc,
buffer + i);

if (result != ERROR_OK) {
LOG_ERROR("target_write_memory failed");
@@ -366,9 +354,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,

result = kinetis_ftfl_command(bank, w0, w1, w2);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return ERROR_FLASH_OPERATION_FAILED;
}
}
}
/* program longword command */
@@ -381,9 +368,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,

result = kinetis_ftfl_command(bank, w0, w1, w2);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return ERROR_FLASH_OPERATION_FAILED;
}
}
}

@@ -405,97 +391,93 @@ static int kinetis_probe(struct flash_bank *bank)

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

result = target_read_memory(bank->target, 0x40048024, 1, 4, buf);
if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}
sim_sdid = target_buffer_get_u32(bank->target, buf);
result = target_read_memory(bank->target, 0x4004804c, 1, 4, buf);
if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}
sim_fcfg1 = target_buffer_get_u32(bank->target, buf);
result = target_read_memory(bank->target, 0x40048050, 1, 4, buf);
if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}
sim_fcfg2 = target_buffer_get_u32(bank->target, buf);

LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", sim_sdid, sim_fcfg1,
sim_fcfg2);
sim_fcfg2);

switch ((sim_fcfg1 >> 28) & 0x0f) {
case 0x07:
nvm_size = 128 * 1024;
break;
case 0x09:
case 0x0f:
nvm_size = 256 * 1024;
break;
default:
nvm_size = 0;
break;
case 0x07:
nvm_size = 128 * 1024;
break;
case 0x09:
case 0x0f:
nvm_size = 256 * 1024;
break;
default:
nvm_size = 0;
break;
}

switch ((sim_fcfg1 >> 24) & 0x0f) {
case 0x07:
pf_size = 128 * 1024;
break;
case 0x09:
pf_size = 256 * 1024;
break;
case 0x0b:
case 0x0f:
pf_size = 512 * 1024;
break;
default:
pf_size = 0;
break;
case 0x07:
pf_size = 128 * 1024;
break;
case 0x09:
pf_size = 256 * 1024;
break;
case 0x0b:
case 0x0f:
pf_size = 512 * 1024;
break;
default:
pf_size = 0;
break;
}

switch ((sim_fcfg1 >> 16) & 0x0f) {
case 0x02:
ee_size = 4 * 1024;
break;
case 0x03:
ee_size = 2 * 1024;
break;
case 0x04:
ee_size = 1 * 1024;
break;
case 0x05:
ee_size = 512;
break;
case 0x06:
ee_size = 256;
break;
case 0x07:
ee_size = 128;
break;
case 0x08:
ee_size = 64;
break;
case 0x09:
ee_size = 32;
break;
default:
ee_size = 0;
break;
case 0x02:
ee_size = 4 * 1024;
break;
case 0x03:
ee_size = 2 * 1024;
break;
case 0x04:
ee_size = 1 * 1024;
break;
case 0x05:
ee_size = 512;
break;
case 0x06:
ee_size = 256;
break;
case 0x07:
ee_size = 128;
break;
case 0x08:
ee_size = 64;
break;
case 0x09:
ee_size = 32;
break;
default:
ee_size = 0;
break;
}

((struct kinetis_flash_bank *) bank->driver_priv)->nvm_start =
pf_size - nvm_size;

LOG_DEBUG("NVM: %d PF: %d EE: %d BL1: %d", nvm_size, pf_size, ee_size,
(sim_fcfg2 >> 23) & 1);
(sim_fcfg2 >> 23) & 1);

if (pf_size != bank->size) {
LOG_WARNING("flash size is different %d != %d", pf_size,
bank->size);
bank->size);
}

bank->num_sectors = bank->size / (2 * 1024);
@@ -526,13 +508,12 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size)

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

snprintf(buf, buf_size,
"%s driver for flash bank %s at 0x%8.8" PRIx32 "",
bank->driver->name, master_bank->name, master_bank->base);
"%s driver for flash bank %s at 0x%8.8" PRIx32 "",
bank->driver->name, master_bank->name, master_bank->base);

return ERROR_OK;
}
@@ -551,15 +532,14 @@ static int kinetis_blank_check(struct flash_bank *bank)

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

return ERROR_OK;
}

static int kinetis_flash_read(struct flash_bank *bank,
uint8_t * buffer, uint32_t offset, uint32_t count)
uint8_t *buffer, uint32_t offset, uint32_t count)
{
int result;
struct flash_bank *master_bank;
@@ -573,9 +553,8 @@ static int kinetis_flash_read(struct flash_bank *bank,

result = kinetis_get_master_bank(bank, &master_bank);

if (result != ERROR_OK) {
if (result != ERROR_OK)
return result;
}

return ERROR_OK;
}


+ 137
- 164
src/flash/nor/lpc2000.c View File

@@ -61,15 +61,13 @@
* - 176x (tested with LPC1768)
*/

typedef enum
{
typedef enum {
lpc2000_v1,
lpc2000_v2,
lpc1700
} lpc2000_variant;

struct lpc2000_flash_bank
{
struct lpc2000_flash_bank {
lpc2000_variant variant;
struct working_area *iap_working_area;
uint32_t cclk;
@@ -81,8 +79,7 @@ struct lpc2000_flash_bank
int checksum_vector;
};

enum lpc2000_status_codes
{
enum lpc2000_status_codes {
LPC2000_CMD_SUCCESS = 0,
LPC2000_INVALID_COMMAND = 1,
LPC2000_SRC_ADDR_ERROR = 2,
@@ -114,63 +111,50 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
/* default to a 4096 write buffer */
lpc2000_info->cmd51_max_buffer = 4096;

if (lpc2000_info->variant == lpc2000_v1)
{
if (lpc2000_info->variant == lpc2000_v1) {
/* variant 1 has different layout for 128kb and 256kb flashes */
if (bank->size == 128 * 1024)
{
if (bank->size == 128 * 1024) {
bank->num_sectors = 16;
bank->sectors = malloc(sizeof(struct flash_sector) * 16);
for (i = 0; i < 16; i++)
{
for (i = 0; i < 16; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
}
else if (bank->size == 256 * 1024)
{
} else if (bank->size == 256 * 1024) {
bank->num_sectors = 18;
bank->sectors = malloc(sizeof(struct flash_sector) * 18);

for (i = 0; i < 8; i++)
{
for (i = 0; i < 8; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
for (i = 8; i < 10; i++)
{
for (i = 8; i < 10; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 64 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
for (i = 10; i < 18; i++)
{
for (i = 10; i < 18; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
}
else
{
} else {
LOG_ERROR("BUG: unknown bank->size encountered");
exit(-1);
}
}
else if (lpc2000_info->variant == lpc2000_v2)
{
} else if (lpc2000_info->variant == lpc2000_v2) {
/* variant 2 has a uniform layout, only number of sectors differs */
switch (bank->size)
{
switch (bank->size) {
case 4 * 1024:
lpc2000_info->cmd51_max_buffer = 1024;
bank->num_sectors = 1;
@@ -209,26 +193,20 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)

bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);

for (i = 0; i < bank->num_sectors; i++)
{
if (i < 8)
{
for (i = 0; i < bank->num_sectors; i++) {
if (i < 8) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 4 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
else if (i < 22)
{
} else if (i < 22) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 32 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
else if (i < 28)
{
} else if (i < 28) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 4 * 1024;
offset += bank->sectors[i].size;
@@ -236,11 +214,8 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
bank->sectors[i].is_protected = 1;
}
}
}
else if (lpc2000_info->variant == lpc1700)
{
switch(bank->size)
{
} else if (lpc2000_info->variant == lpc1700) {
switch (bank->size) {
case 32 * 1024:
bank->num_sectors = 8;
break;
@@ -249,7 +224,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
break;
case 128 * 1024:
bank->num_sectors = 18;
break;
break;
case 256 * 1024:
bank->num_sectors = 22;
break;
@@ -263,18 +238,16 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)

bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);

for(i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = offset;
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
bank->sectors[i].size = (i < 16)? 4 * 1024 : 32 * 1024;
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx
*devices */
bank->sectors[i].size = (i < 16) ? 4 * 1024 : 32 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
}
else
{
} else {
LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
exit(-1);
}
@@ -289,38 +262,37 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
* 0x20 to 0x33: command result table (1+4 words)
* 0x34 to 0xb3: stack (only 128b needed)
*/
static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_table[5], uint32_t result_table[4])
static int lpc2000_iap_call(struct flash_bank *bank,
int code,
uint32_t param_table[5],
uint32_t result_table[4])
{
int retval;
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
struct target *target = bank->target;
struct mem_param mem_params[2];
struct reg_param reg_params[5];
struct arm_algorithm armv4_5_info; /* for LPC2000 */
struct armv7m_algorithm armv7m_info; /* for LPC1700 */
uint32_t status_code;
uint32_t iap_entry_point = 0; /* to make compiler happier */
struct arm_algorithm armv4_5_info; /* for LPC2000 */
struct armv7m_algorithm armv7m_info; /* for LPC1700 */
uint32_t status_code;
uint32_t iap_entry_point = 0; /* to make compiler happier */

/* regrab previously allocated working_area, or allocate a new one */
if (!lpc2000_info->iap_working_area)
{
if (!lpc2000_info->iap_working_area) {
uint8_t jump_gate[8];

/* make sure we have a working area */
if (target_alloc_working_area(target, 180, &lpc2000_info->iap_working_area) != ERROR_OK)
{
if (target_alloc_working_area(target, 180,
&lpc2000_info->iap_working_area) != ERROR_OK) {
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
return ERROR_FLASH_OPERATION_FAILED;
}

/* write IAP code to working area */
switch(lpc2000_info->variant)
{
switch (lpc2000_info->variant) {
case lpc1700:
target_buffer_set_u32(target, jump_gate,
ARMV4_5_T_BX(12));
target_buffer_set_u32(target, jump_gate + 4,
ARMV5_T_BKPT(0));
target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
break;
case lpc2000_v1:
case lpc2000_v2:
@@ -332,15 +304,17 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
exit(-1);
}

if ((retval = target_write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK)
{
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", lpc2000_info->iap_working_area->address);
retval = target_write_memory(target,
lpc2000_info->iap_working_area->address, 4, 2, jump_gate);
if (retval != ERROR_OK) {
LOG_ERROR(
"Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)",
lpc2000_info->iap_working_area->address);
return retval;
}
}

switch(lpc2000_info->variant)
{
switch (lpc2000_info->variant) {
case lpc1700:
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARMV7M_MODE_ANY;
@@ -359,7 +333,8 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
}

/* command parameter table */
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4, PARAM_OUT);
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4,
PARAM_OUT);
target_buffer_set_u32(target, mem_params[0].value, code);
target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
@@ -371,7 +346,10 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);

/* command result table */
init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 5 * 4, PARAM_IN);
init_mem_param(&mem_params[1],
lpc2000_info->iap_working_area->address + 0x20,
5 * 4,
PARAM_IN);

init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
@@ -380,44 +358,55 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);

switch(lpc2000_info->variant)
{
switch (lpc2000_info->variant) {
case lpc1700:
/* IAP stack */
init_reg_param(&reg_params[3], "sp", 32, PARAM_OUT);
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
buf_set_u32(reg_params[3].value, 0, 32,
lpc2000_info->iap_working_area->address + 0xb4);

/* return address */
init_reg_param(&reg_params[4], "lr", 32, PARAM_OUT);
buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */
buf_set_u32(reg_params[4].value, 0, 32,
(lpc2000_info->iap_working_area->address + 0x04) | 1);
/* bit0 of LR = 1 to return in Thumb mode */

target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info);
target_run_algorithm(target, 2, mem_params, 5, reg_params,
lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info);
break;
case lpc2000_v1:
case lpc2000_v2:
/* IAP stack */
init_reg_param(&reg_params[3], "sp_svc", 32, PARAM_OUT);
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
buf_set_u32(reg_params[3].value, 0, 32,
lpc2000_info->iap_working_area->address + 0xb4);

/* return address */
init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x04);
buf_set_u32(reg_params[4].value, 0, 32,
lpc2000_info->iap_working_area->address + 0x04);

target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv4_5_info);
target_run_algorithm(target, 2, mem_params, 5, reg_params,
lpc2000_info->iap_working_area->address,
lpc2000_info->iap_working_area->address + 0x4,
10000, &armv4_5_info);
break;
default:
LOG_ERROR("BUG: unknown lpc2000->variant encountered");
exit(-1);
}

status_code = target_buffer_get_u32(target, mem_params[1].value);
status_code = target_buffer_get_u32(target, mem_params[1].value);
result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04);
result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08);
result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);

LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32") completed with result = %8.8" PRIx32,
code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code);
LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32
", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8"
PRIx32 ") completed with result = %8.8" PRIx32,
code, param_table[0], param_table[1], param_table[2],
param_table[3], param_table[4], status_code);

destroy_mem_param(&mem_params[0]);
destroy_mem_param(&mem_params[1]);
@@ -441,14 +430,12 @@ static int lpc2000_iap_blank_check(struct flash_bank *bank, int first, int last)
if ((first < 0) || (last >= bank->num_sectors))
return ERROR_FLASH_SECTOR_INVALID;

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
/* check single sector */
param_table[0] = param_table[1] = i;
status_code = lpc2000_iap_call(bank, 53, param_table, result_table);

switch (status_code)
{
switch (status_code) {
case ERROR_FLASH_OPERATION_FAILED:
return ERROR_FLASH_OPERATION_FAILED;
case LPC2000_CMD_SUCCESS:
@@ -480,39 +467,30 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
struct lpc2000_flash_bank *lpc2000_info;

if (CMD_ARGC < 8)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

lpc2000_info = malloc(sizeof(struct lpc2000_flash_bank));
bank->driver_priv = lpc2000_info;

if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0)
{
if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0) {
lpc2000_info->variant = lpc2000_v1;
lpc2000_info->cmd51_dst_boundary = 512;
lpc2000_info->cmd51_can_256b = 0;
lpc2000_info->cmd51_can_8192b = 1;
lpc2000_info->checksum_vector = 5;
}
else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0)
{
} else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0) {
lpc2000_info->variant = lpc2000_v2;
lpc2000_info->cmd51_dst_boundary = 256;
lpc2000_info->cmd51_can_256b = 1;
lpc2000_info->cmd51_can_8192b = 0;
lpc2000_info->checksum_vector = 5;
}
else if (strcmp(CMD_ARGV[6], "lpc1700") == 0)
{
} else if (strcmp(CMD_ARGV[6], "lpc1700") == 0) {
lpc2000_info->variant = lpc1700;
lpc2000_info->cmd51_dst_boundary = 256;
lpc2000_info->cmd51_can_256b = 1;
lpc2000_info->cmd51_can_8192b = 0;
lpc2000_info->checksum_vector = 7;
}
else
{
} else {
LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]);
free(lpc2000_info);
return ERROR_FLASH_BANK_INVALID;
@@ -523,8 +501,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
lpc2000_info->calc_checksum = 0;
lpc2000_build_sector_list(bank);

if (CMD_ARGC >= 9)
{
if (CMD_ARGC >= 9) {
if (strcmp(CMD_ARGV[8], "calc_checksum") == 0)
lpc2000_info->calc_checksum = 1;
}
@@ -539,8 +516,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)
uint32_t result_table[4];
int status_code;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -551,8 +527,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)

/* Prepare sectors */
status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
switch (status_code)
{
switch (status_code) {
case ERROR_FLASH_OPERATION_FAILED:
return ERROR_FLASH_OPERATION_FAILED;
case LPC2000_CMD_SUCCESS:
@@ -567,8 +542,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)

/* Erase sectors */
status_code = lpc2000_iap_call(bank, 52, param_table, result_table);
switch (status_code)
{
switch (status_code) {
case ERROR_FLASH_OPERATION_FAILED:
return ERROR_FLASH_OPERATION_FAILED;
case LPC2000_CMD_SUCCESS:
@@ -606,8 +580,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
struct working_area *download_area;
int retval = ERROR_OK;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -617,55 +590,56 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs

dst_min_alignment = lpc2000_info->cmd51_dst_boundary;

if (offset % dst_min_alignment)
{
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, offset, dst_min_alignment);
if (offset % dst_min_alignment) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32,
offset,
dst_min_alignment);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
if (offset >= bank->sectors[i].offset)
first_sector = i;
if (offset + DIV_ROUND_UP(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset)
if (offset + DIV_ROUND_UP(count, dst_min_alignment)
* dst_min_alignment > bank->sectors[i].offset)
last_sector = i;
}

LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);

/* check if exception vectors should be flashed */
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
{
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) {
uint32_t checksum = 0;
for (i = 0; i < 8; i++)
{
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
for (i = 0; i < 8; i++) {
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4,
buf_get_u32(buffer + (i * 4), 0, 32));
if (i != lpc2000_info->checksum_vector)
checksum += buf_get_u32(buffer + (i * 4), 0, 32);
}
checksum = 0 - checksum;
LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);

uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32);
if (original_value != checksum)
{
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is different from calculated vector checksum (0x%8.8" PRIx32 ").",
original_value, checksum);
LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
uint32_t original_value = buf_get_u32(buffer +
(lpc2000_info->checksum_vector * 4), 0, 32);
if (original_value != checksum) {
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") "
"to be written to flash is different from calculated vector "
"checksum (0x%8.8" PRIx32 ").", original_value, checksum);
LOG_WARNING("To remove this warning modify build tools on developer PC "
"to inject correct LPC vector checksum.");
}

buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
}

/* allocate a working area */
if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, &download_area) != ERROR_OK)
{
if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer,
&download_area) != ERROR_OK) {
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
return ERROR_FLASH_OPERATION_FAILED;
}

while (bytes_remaining > 0)
{
while (bytes_remaining > 0) {
uint32_t thisrun_bytes;
if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
thisrun_bytes = lpc2000_info->cmd51_max_buffer;
@@ -680,8 +654,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
param_table[0] = first_sector;
param_table[1] = last_sector;
status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
switch (status_code)
{
switch (status_code) {
case ERROR_FLASH_OPERATION_FAILED:
retval = ERROR_FLASH_OPERATION_FAILED;
break;
@@ -700,24 +673,28 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
if (retval != ERROR_OK)
break;

if (bytes_remaining >= thisrun_bytes)
{
if ((retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written)) != ERROR_OK)
{
if (bytes_remaining >= thisrun_bytes) {
retval = target_write_buffer(bank->target, download_area->address,
thisrun_bytes, buffer + bytes_written);
if (retval != ERROR_OK) {
retval = ERROR_FLASH_OPERATION_FAILED;
break;
}
}
else
{
} else {
uint8_t *last_buffer = malloc(thisrun_bytes);
memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining);
target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer);
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes -
bytes_remaining);
target_write_buffer(bank->target,
download_area->address,
thisrun_bytes,
last_buffer);
free(last_buffer);
}

LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32 , thisrun_bytes, bank->base + offset + bytes_written);
LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32,
thisrun_bytes,
bank->base + offset + bytes_written);

/* Write data */
param_table[0] = bank->base + offset + bytes_written;
@@ -725,8 +702,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
param_table[2] = thisrun_bytes;
param_table[3] = lpc2000_info->cclk;
status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
switch (status_code)
{
switch (status_code) {
case ERROR_FLASH_OPERATION_FAILED:
retval = ERROR_FLASH_OPERATION_FAILED;
break;
@@ -767,8 +743,7 @@ static int lpc2000_probe(struct flash_bank *bank)

static int lpc2000_erase_check(struct flash_bank *bank)
{
if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -786,7 +761,11 @@ static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;

snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz" , lpc2000_info->variant, lpc2000_info->cclk);
snprintf(buf,
buf_size,
"lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz",
lpc2000_info->variant,
lpc2000_info->cclk);

return ERROR_OK;
}
@@ -798,34 +777,28 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command)
int status_code;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (ERROR_OK != retval)
return retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0)
{
if (status_code == ERROR_FLASH_OPERATION_FAILED)
{
command_print(CMD_CTX, "no sufficient working area specified, can't access LPC2000 IAP interface");
status_code = lpc2000_iap_call(bank, 54, param_table, result_table);
if (status_code != 0x0) {
if (status_code == ERROR_FLASH_OPERATION_FAILED) {
command_print(CMD_CTX,
"no sufficient working area specified, can't access LPC2000 IAP interface");
return ERROR_OK;
}
command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code);
}
else
{
command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32 , result_table[0]);
}
} else
command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, result_table[0]);

return ERROR_OK;
}


+ 84
- 128
src/flash/nor/lpc288x.c View File

@@ -34,64 +34,65 @@
#include "imp.h"
#include <helper/binarybuffer.h>

#define LOAD_TIMER_ERASE 0
#define LOAD_TIMER_WRITE 1

#define LOAD_TIMER_ERASE 0
#define LOAD_TIMER_WRITE 1

#define FLASH_PAGE_SIZE 512
#define FLASH_PAGE_SIZE 512

/* LPC288X control registers */
#define DBGU_CIDR 0x8000507C
#define DBGU_CIDR 0x8000507C
/* LPC288X flash registers */
#define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
#define F_STAT 0x80102004 /* Flash status register RO 0x45 */
#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
#define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
#define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 */
#define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
#define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
#define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
#define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
#define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
#define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
#define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power savings. R/W 1*/
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from Power Down mode. R/W -*/
#define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
#define F_STAT 0x80102004 /* Flash status register RO 0x45 */
#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
#define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
#define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0
**/
#define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
#define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
#define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
#define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
#define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
#define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
#define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power
*savings. R/W 1*/
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from
*Power Down mode. R/W -*/

/* F_CTRL bits */
#define FC_CS 0x0001
#define FC_FUNC 0x0002
#define FC_WEN 0x0004
#define FC_RD_LATCH 0x0020
#define FC_PROTECT 0x0080
#define FC_SET_DATA 0x0400
#define FC_RSSL 0x0800
#define FC_PROG_REQ 0x1000
#define FC_CLR_BUF 0x4000
#define FC_LOAD_REQ 0x8000
#define FC_CS 0x0001
#define FC_FUNC 0x0002
#define FC_WEN 0x0004
#define FC_RD_LATCH 0x0020
#define FC_PROTECT 0x0080
#define FC_SET_DATA 0x0400
#define FC_RSSL 0x0800
#define FC_PROG_REQ 0x1000
#define FC_CLR_BUF 0x4000
#define FC_LOAD_REQ 0x8000
/* F_STAT bits */
#define FS_DONE 0x0001
#define FS_PROGGNT 0x0002
#define FS_RDY 0x0004
#define FS_ERR 0x0020
#define FS_DONE 0x0001
#define FS_PROGGNT 0x0002
#define FS_RDY 0x0004
#define FS_ERR 0x0020
/* F_PROG_TIME */
#define FPT_TIME_MASK 0x7FFF
#define FPT_TIME_MASK 0x7FFF

#define FPT_ENABLE 0x8000
#define FPT_ENABLE 0x8000
/* F_WAIT */
#define FW_WAIT_STATES_MASK 0x00FF
#define FW_SET_MASK 0xC000
#define FW_WAIT_STATES_MASK 0x00FF
#define FW_SET_MASK 0xC000

/* F_CLK_TIME */
#define FCT_CLK_DIV_MASK 0x0FFF

struct lpc288x_flash_bank
{
struct lpc288x_flash_bank {
uint32_t working_area;
uint32_t working_area_size;

/* chip id register */
uint32_t cidr;
const char * target_name;
const char *target_name;
uint32_t cclk;

uint32_t sector_size_break;
@@ -106,15 +107,13 @@ static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout)
{
uint32_t status;
struct target *target = bank->target;
do
{
do {
alive_sleep(1);
timeout--;
target_read_u32(target, F_STAT, &status);
} while (((status & FS_DONE) == 0) && timeout);

if (timeout == 0)
{
if (timeout == 0) {
LOG_DEBUG("Timedout!");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -132,14 +131,14 @@ static int lpc288x_read_part_info(struct flash_bank *bank)
uint32_t offset;

if (lpc288x_info->cidr == 0x0102100A)
return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
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 != 0x0102100A)
{
LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")",cidr);
if (cidr != 0x0102100A) {
LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr);
return ERROR_FLASH_OPERATION_FAILED;
}

@@ -152,16 +151,14 @@ static int lpc288x_read_part_info(struct flash_bank *bank)
bank->num_sectors = 23;
bank->sectors = malloc(sizeof(struct flash_sector) * 23);

for (i = 0; i < 15; i++)
{
for (i = 0; i < 15; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 64 * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
for (i = 15; i < 23; i++)
{
for (i = 15; i < 23; i++) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size;
@@ -183,9 +180,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command)
struct lpc288x_flash_bank *lpc288x_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank));
bank->driver_priv = lpc288x_info;
@@ -220,25 +215,18 @@ static void lpc288x_set_flash_clk(struct flash_bank *bank)
static void lpc288x_load_timer(int erase, struct target *target)
{
if (erase == LOAD_TIMER_ERASE)
{
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
}
else
{
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
}
}

static uint32_t lpc288x_system_ready(struct flash_bank *bank)
{
struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
if (lpc288x_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED;
}

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -248,8 +236,7 @@ static uint32_t lpc288x_system_ready(struct flash_bank *bank)
static int lpc288x_erase_check(struct flash_bank *bank)
{
uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
if (status != ERROR_OK)
{
if (status != ERROR_OK) {
LOG_INFO("Processor not halted/not probed");
return status;
}
@@ -263,14 +250,11 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last)
int sector;
struct target *target = bank->target;

status = lpc288x_system_ready(bank); /* probed? halted? */
status = lpc288x_system_ready(bank); /* probed? halted? */
if (status != ERROR_OK)
{
return status;
}

if ((first < 0) || (last < first) || (last >= bank->num_sectors))
{
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
LOG_INFO("Bad sector range");
return ERROR_FLASH_SECTOR_INVALID;
}
@@ -278,30 +262,25 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last)
/* Configure the flash controller timing */
lpc288x_set_flash_clk(bank);

for (sector = first; sector <= last; sector++)
{
for (sector = first; sector <= last; sector++) {
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}

lpc288x_load_timer(LOAD_TIMER_ERASE,target);
lpc288x_load_timer(LOAD_TIMER_ERASE, target);

target_write_u32(target, bank->sectors[sector].offset, 0x00);

target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
}
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK;
}

static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
uint8_t page_buffer[FLASH_PAGE_SIZE];
uint32_t status, source_offset,dest_offset;
uint32_t status, source_offset, dest_offset;
struct target *target = bank->target;
uint32_t bytes_remaining = count;
uint32_t first_sector, last_sector, sector, page;
@@ -310,39 +289,34 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
/* probed? halted? */
status = lpc288x_system_ready(bank);
if (status != ERROR_OK)
{
return status;
}

/* Initialise search indices */
first_sector = last_sector = 0xffffffff;

/* validate the write range... */
for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
if ((offset >= bank->sectors[i].offset) &&
(offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
(first_sector == 0xffffffff))
{
(offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
(first_sector == 0xffffffff)) {
first_sector = i;
/* all writes must start on a sector boundary... */
if (offset % bank->sectors[i].size)
{
LOG_INFO("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, bank->sectors[i].size);
if (offset % bank->sectors[i].size) {
LOG_INFO(
"offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
offset,
bank->sectors[i].size);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
}
if (((offset + count) > bank->sectors[i].offset) &&
((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
(last_sector == 0xffffffff))
{
((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
(last_sector == 0xffffffff))
last_sector = i;
}
}

/* Range check... */
if (first_sector == 0xffffffff || last_sector == 0xffffffff)
{
if (first_sector == 0xffffffff || last_sector == 0xffffffff) {
LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
return ERROR_FLASH_DST_OUT_OF_BANK;
}
@@ -354,32 +328,23 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
source_offset = 0;
dest_offset = 0;

for (sector = first_sector; sector <= last_sector; sector++)
{
for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++)
{
if (bytes_remaining == 0)
{
for (sector = first_sector; sector <= last_sector; sector++) {
for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) {
if (bytes_remaining == 0) {
count = 0;
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
}
else if (bytes_remaining < FLASH_PAGE_SIZE)
{
} else if (bytes_remaining < FLASH_PAGE_SIZE) {
count = bytes_remaining;
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
memcpy(page_buffer, &buffer[source_offset], count);
}
else
{
} else {
count = FLASH_PAGE_SIZE;
memcpy(page_buffer, &buffer[source_offset], count);
}

/* Wait for flash to become ready */
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED;
}

/* fill flash data latches with 1's */
target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
@@ -389,14 +354,14 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
* it seems not to be a LOT slower....
* bulk_write_memory() is no quicker :(*/
#if 1
if (target_write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK)
{
if (target_write_memory(target, offset + dest_offset, 4, 128,
page_buffer) != ERROR_OK) {
LOG_ERROR("Write failed s %" PRIx32 " p %" PRIx32 "", sector, page);
return ERROR_FLASH_OPERATION_FAILED;
}
#else
if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK)
{
if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE,
page_buffer) != ERROR_OK) {
LOG_INFO("Write to flash buffer failed");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -407,7 +372,8 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs

lpc288x_load_timer(LOAD_TIMER_WRITE, target);

target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | FC_CS);
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC |
FC_CS);
}
}

@@ -421,12 +387,9 @@ static int lpc288x_probe(struct flash_bank *bank)
int retval;

if (lpc288x_info->cidr != 0)
{
return ERROR_OK; /* already probed */
}
return ERROR_OK;/* already probed */

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -452,32 +415,25 @@ static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last
/* probed? halted? */
status = lpc288x_system_ready(bank);
if (status != ERROR_OK)
{
return status;
}

if ((first < 0) || (last < first) || (last >= bank->num_sectors))
{
return ERROR_FLASH_SECTOR_INVALID;
}

/* Configure the flash controller timing */
lpc288x_set_flash_clk(bank);

for (lockregion = first; lockregion <= last; lockregion++)
{
if (set)
{
for (lockregion = first; lockregion <= last; lockregion++) {
if (set) {
/* write an odd value to base addy to protect... */
value = 0x01;
}
else
{
} else {
/* write an even value to base addy to unprotect... */
value = 0x00;
}
target_write_u32(target, bank->sectors[lockregion].offset, value);
target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | FC_CS);
target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC |
FC_CS);
}

return ERROR_OK;


+ 381
- 614
src/flash/nor/lpc2900.c
File diff suppressed because it is too large
View File


+ 53
- 87
src/flash/nor/non_cfi.c View File

@@ -19,6 +19,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -27,7 +28,6 @@
#include "cfi.h"
#include "non_cfi.h"


#define KB 1024
#define MB (1024*1024)
#define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
@@ -43,8 +43,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(16, 4*KB)
}
},
@@ -57,8 +56,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(32, 4*KB)
}
},
@@ -71,8 +69,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(64, 4*KB)
}
},
@@ -85,8 +82,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(128, 4*KB)
}
},
@@ -99,8 +95,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(8, 64*KB)
}
},
@@ -113,8 +108,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(128, 4*KB)
}
},
@@ -127,8 +121,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -144,8 +137,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(7, 64*KB),
ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB),
@@ -156,9 +148,9 @@ static struct non_cfi non_cfi_flashes[] = {
/* SST 39VF* do not support DQ5 status polling - this currently is
only supported by the host algorithm, not by the target code using
the work area.
Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
without DQ5 status polling are supported by the target code.
*/
Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
without DQ5 status polling are supported by the target code.
*/
{
.mfr = CFI_MFR_SST,
.id = 0x2782, /* SST39xF160 */
@@ -168,8 +160,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(512, 4*KB)
}
},
@@ -182,8 +173,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1024, 4*KB)
}
},
@@ -196,8 +186,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(512, 4*KB)
}
},
@@ -210,8 +199,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(512, 4*KB)
}
},
@@ -224,8 +212,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(512, 4*KB)
}
},
@@ -238,8 +225,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1024, 4*KB)
}
},
@@ -252,26 +238,24 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1024, 4*KB)
}
},
{
.mfr = CFI_MFR_SST,
.id = 0x236d, /* SST39VF6401B */
.pri_id = 0x02,
.dev_size = 8*MB,
.interface_desc = 0x2, /* x8 or x16 device with nBYTE */
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info =
{
ERASE_REGION(2048, 4*KB)
}
},
{
.mfr = CFI_MFR_SST,
.id = 0x236d, /* SST39VF6401B */
.pri_id = 0x02,
.dev_size = 8*MB,
.interface_desc = 0x2, /* x8 or x16 device with nBYTE */
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1,
.erase_region_info = {
ERASE_REGION(2048, 4*KB)
}
},
{
.mfr = CFI_MFR_AMD,
.id = 0x22ab, /* AM29F400BB */
.pri_id = 0x02,
@@ -280,8 +264,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -297,8 +280,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(7, 64*KB),
ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB),
@@ -314,15 +296,14 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
ERASE_REGION(15, 64*KB)
}
},
{
{
.mfr = CFI_MFR_FUJITSU,
.id = 0x22ea, /* MBM29SL800TE */
.pri_id = 0x02,
@@ -331,8 +312,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(15, 64*KB),
ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB),
@@ -348,8 +328,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x00,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -365,8 +344,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -382,8 +360,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -400,8 +377,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -417,8 +393,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(31, 64*KB),
ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB),
@@ -434,8 +409,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -451,8 +425,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 3,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(8, 8*KB),
ERASE_REGION(2, 32*KB),
ERASE_REGION(30, 64*KB)
@@ -467,8 +440,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 3,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(30, 64*KB),
ERASE_REGION(2, 32*KB),
ERASE_REGION(8, 8*KB)
@@ -483,8 +455,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4,
.erase_region_info =
{
.erase_region_info = {
ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB),
@@ -503,18 +474,15 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
struct cfi_flash_bank *cfi_info = bank->driver_priv;
struct non_cfi *non_cfi = non_cfi_flashes;

if(cfi_info->x16_as_x8)
if (cfi_info->x16_as_x8)
mask = 0xFF;
else
mask = 0xFFFF;

for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++)
{
for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++) {
if ((cfi_info->manufacturer == non_cfi->mfr)
&& (cfi_info->device_id == (non_cfi->id & mask)))
{
&& (cfi_info->device_id == (non_cfi->id & mask)))
break;
}
}

/* only fixup jedec flashs found in table */
@@ -554,14 +522,13 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
cfi_info->status_poll_mask = non_cfi->status_poll_mask;
cfi_info->num_erase_regions = non_cfi->num_erase_regions;
size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) *
cfi_info->num_erase_regions;
cfi_info->num_erase_regions;
cfi_info->erase_region_info = malloc(erase_region_info_size);
memcpy(cfi_info->erase_region_info,
non_cfi->erase_region_info, erase_region_info_size);
non_cfi->erase_region_info, erase_region_info_size);
cfi_info->dev_size = non_cfi->dev_size;

if (cfi_info->pri_id == 0x2)
{
if (cfi_info->pri_id == 0x2) {
struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));

pri_ext->pri[0] = 'P';
@@ -589,8 +556,7 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
pri_ext->_reversed_geometry = 0;

cfi_info->pri_ext = pri_ext;
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3))
{
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3)) {
LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
exit(-1);
}


+ 2
- 2
src/flash/nor/non_cfi.h View File

@@ -17,11 +17,11 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifndef NON_CFI_H
#define NON_CFI_H

struct non_cfi
{
struct non_cfi {
uint16_t mfr;
uint16_t id;
uint16_t pri_id;


+ 57
- 61
src/flash/nor/ocl.c View File

@@ -17,6 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -25,9 +26,7 @@
#include "ocl.h"
#include <target/embeddedice.h>


struct ocl_priv
{
struct ocl_priv {
struct arm_jtag *jtag_info;
unsigned int buflen;
unsigned int bufalign;
@@ -50,9 +49,7 @@ FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
struct ocl_priv *ocl;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

arm7_9 = target_to_arm7_9(bank->target);
if (!is_arm7_9(arm7_9))
@@ -76,39 +73,36 @@ static int ocl_erase(struct flash_bank *bank, int first, int last)
if (bank->num_sectors == 0)
return ERROR_FLASH_BANK_NOT_PROBED;

if (bank->target->state != TARGET_RUNNING)
{
if (bank->target->state != TARGET_RUNNING) {
LOG_ERROR("target has to be running to communicate with the loader");
return ERROR_TARGET_NOT_RUNNING;
}

if ((first == 0) && (last == bank->num_sectors - 1))
{
if ((first == 0) && (last == bank->num_sectors - 1)) {
dcc_buffer[0] = OCL_ERASE_ALL;
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval;
}
else
{
} else {
dcc_buffer[0] = OCL_ERASE_BLOCK;
dcc_buffer[1] = first;
dcc_buffer[2] = last;
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK))
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3);
if (retval != ERROR_OK)
return retval;
}

/* wait for response, fixed timeout of 1 s */
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
{
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
if (retval != ERROR_OK)
return retval;
}

/* receive response */
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1) != ERROR_OK))
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1);
if (retval != ERROR_OK)
return retval;

if (dcc_buffer[1] != OCL_CMD_DONE)
{
if (dcc_buffer[1] != OCL_CMD_DONE) {
if (dcc_buffer[0] == OCL_ERASE_ALL)
LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
else
@@ -140,8 +134,7 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
if (ocl->buflen == 0 || ocl->bufalign == 0)
return ERROR_FLASH_BANK_NOT_PROBED;

if (bank->target->state != TARGET_RUNNING)
{
if (bank->target->state != TARGET_RUNNING) {
LOG_ERROR("target has to be running to communicate with the loader");
return ERROR_TARGET_NOT_RUNNING;
}
@@ -149,8 +142,7 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
/* allocate buffer for max. ocl buffer + overhead */
dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));

while (count)
{
while (count) {
if (count + (offset % ocl->bufalign) > ocl->buflen)
runlen = ocl->buflen - (offset % ocl->bufalign);
else
@@ -165,10 +157,8 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
chksum = OCL_CHKS_INIT;

/* copy data to DCC buffer in proper byte order and properly aligned */
for (i = 0; i < runlen; i++)
{
switch (byteofs++)
{
for (i = 0; i < runlen; i++) {
switch (byteofs++) {
case 0:
*dcc_bufptr &= *(buffer++) | 0xffffff00;
break;
@@ -194,28 +184,27 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
*(dcc_bufptr++) = chksum;

/* send the data */
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK)
{
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer);
if (retval != ERROR_OK) {
free(dcc_buffer);
return retval;
}

/* wait for response, fixed timeout of 1 s */
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
{
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
if (retval != ERROR_OK) {
free(dcc_buffer);
return retval;
}

/* receive response */
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
{
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK) {
free(dcc_buffer);
return retval;
}

if (dcc_buffer[0] != OCL_CMD_DONE)
{
if (dcc_buffer[0] != OCL_CMD_DONE) {
LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
free(dcc_buffer);
return ERROR_FLASH_OPERATION_FAILED;
@@ -241,50 +230,61 @@ static int ocl_probe(struct flash_bank *bank)
embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);

dcc_buffer[0] = OCL_PROBE;
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval;

/* wait for response, fixed timeout of 1 s */
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
{
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
if (retval != ERROR_OK)
return retval;
}

/* receive response */
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval;

if (dcc_buffer[0] != OCL_CMD_DONE)
{
if (dcc_buffer[0] != OCL_CMD_DONE) {
LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
return ERROR_FLASH_OPERATION_FAILED;
}

/* receive and fill in parameters, detection of loader is important, receive it one by one */
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval;
bank->base = dcc_buffer[0];

if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval;
bank->size = dcc_buffer[0];

if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval;
bank->num_sectors = dcc_buffer[0];

if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval;
ocl->buflen = dcc_buffer[0] & 0xffff;
ocl->bufalign = dcc_buffer[0] >> 16;

bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
if (bank->num_sectors == 0)
{
if (bank->num_sectors == 0) {
LOG_ERROR("number of sectors shall be non zero value");
return ERROR_FLASH_BANK_INVALID;
}
@@ -293,8 +293,7 @@ static int ocl_probe(struct flash_bank *bank)
return ERROR_FLASH_BANK_INVALID;
}
sectsize = bank->size / bank->num_sectors;
for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = i * sectsize;
bank->sectors[i].size = sectsize;
bank->sectors[i].is_erased = -1;
@@ -304,20 +303,17 @@ static int ocl_probe(struct flash_bank *bank)
if (ocl->bufalign == 0)
ocl->bufalign = 1;

if (ocl->buflen == 0)
{
if (ocl->buflen == 0) {
LOG_ERROR("buflen shall be non zero value");
return ERROR_FLASH_BANK_INVALID;
}

if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign))
{
if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) {
LOG_ERROR("buflen is not multiple of bufalign");
return ERROR_FLASH_BANK_INVALID;
}

if (ocl->buflen % 4)
{
if (ocl->buflen % 4) {
LOG_ERROR("buflen shall be divisible by 4");
return ERROR_FLASH_BANK_INVALID;
}


+ 1
- 0
src/flash/nor/ocl.h View File

@@ -17,6 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifndef OCL_H
#define OCL_H



+ 54
- 98
src/flash/nor/pic32mx.c View File

@@ -23,6 +23,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -46,7 +47,7 @@
* Note: These macros only work for KSEG0/KSEG1 addresses.
*/

#define Virt2Phys(v) ((v) & 0x1FFFFFFF)
#define Virt2Phys(v) ((v) & 0x1FFFFFFF)

/* pic32mx configuration register locations */

@@ -90,8 +91,7 @@
#define NVMKEY1 0xAA996655
#define NVMKEY2 0x556699AA

struct pic32mx_flash_bank
{
struct pic32mx_flash_bank {
struct working_area *write_algorithm;
int probed;
};
@@ -171,9 +171,7 @@ FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
struct pic32mx_flash_bank *pic32mx_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
bank->driver_priv = pic32mx_info;
@@ -199,8 +197,7 @@ static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout)
uint32_t status;

/* wait for busy to clear */
while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0))
{
while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) {
LOG_DEBUG("status: 0x%" PRIx32, status);
alive_sleep(1);
}
@@ -240,8 +237,7 @@ static int pic32mx_protect_check(struct flash_bank *bank)
int s;
int num_pages;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -249,15 +245,13 @@ static int pic32mx_protect_check(struct flash_bank *bank)
target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0);

if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
num_pages = 0xffff; /* All pages protected */
else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH)
{
num_pages = 0xffff; /* All pages protected */
else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
if (devcfg0 & (1 << 24))
num_pages = 0; /* All pages unprotected */
num_pages = 0; /* All pages unprotected */
else
num_pages = 0xffff; /* All pages protected */
}
else /* pgm flash */
num_pages = 0xffff; /* All pages protected */
} else /* pgm flash */
num_pages = (~devcfg0 >> 12) & 0xff;

for (s = 0; s < bank->num_sectors && s < num_pages; s++)
@@ -274,15 +268,13 @@ static int pic32mx_erase(struct flash_bank *bank, int first, int last)
int i;
uint32_t status;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((first == 0) && (last == (bank->num_sectors - 1))
&& (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH))
{
&& (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) {
/* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
* we need to use the MTAP to perform a full erase */
LOG_DEBUG("Erasing entire program flash");
@@ -294,8 +286,7 @@ static int pic32mx_erase(struct flash_bank *bank, int first, int last)
return ERROR_OK;
}

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset));

status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
@@ -314,8 +305,7 @@ static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last
{
struct target *target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -381,7 +371,7 @@ static const uint32_t pic32mx_flash_write_code[] = {
0x1600FFFD, /* bne $s0, $zero, waitflash */
0x00000000, /* nop */
0x00000000, /* nop */
0x00000000, /* nop */
0x00000000, /* nop */
0x00000000, /* nop */
0x00000000, /* nop */
0x8D510000, /* lw $s1, 0($t2) */
@@ -407,24 +397,20 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,

/* flash write code */
if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code),
&pic32mx_info->write_algorithm) != ERROR_OK)
{
&pic32mx_info->write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};

if ((retval = target_write_buffer(target,
pic32mx_info->write_algorithm->address,
sizeof(pic32mx_flash_write_code),
(uint8_t*)pic32mx_flash_write_code)) != ERROR_OK)
retval = target_write_buffer(target, pic32mx_info->write_algorithm->address,
sizeof(pic32mx_flash_write_code), (uint8_t *)pic32mx_flash_write_code);
if (retval != ERROR_OK)
return retval;

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= 256)
{
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
if (pic32mx_info->write_algorithm)
@@ -442,25 +428,24 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,
init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "a2", 32, PARAM_OUT);

while (count > 0)
{
while (count > 0) {
uint32_t status;
uint32_t thisrun_count = (count > (buffer_size / 4)) ?
(buffer_size / 4) : count;

if ((retval = target_write_buffer(target, source->address,
thisrun_count * 4, buffer)) != ERROR_OK)
retval = target_write_buffer(target, source->address,
thisrun_count * 4, buffer);
if (retval != ERROR_OK)
break;

buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address));
buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address));
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);

if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
pic32mx_info->write_algorithm->address,
0,
10000, &mips32_info)) != ERROR_OK)
{
0, 10000, &mips32_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing pic32mx flash write algorithm");
retval = ERROR_FLASH_OPERATION_FAILED;
break;
@@ -468,15 +453,13 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,

status = buf_get_u32(reg_params[0].value, 0, 32);

if (status & NVMCON_NVMERR)
{
if (status & NVMCON_NVMERR) {
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
retval = ERROR_FLASH_OPERATION_FAILED;
break;
}

if (status & NVMCON_LVDERR)
{
if (status & NVMCON_LVDERR) {
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
retval = ERROR_FLASH_OPERATION_FAILED;
break;
@@ -516,8 +499,7 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
uint32_t status;
int retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -525,53 +507,43 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32
" count: 0x%8.8" PRIx32 "", bank->base, offset, count);

if (offset & 0x3)
{
if (offset & 0x3) {
LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

/* multiple words (4-byte) to be programmed? */
if (words_remaining > 0)
{
if (words_remaining > 0) {
/* try using a block write */
if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
retval = pic32mx_write_block(bank, buffer, offset, words_remaining);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
}
else if (retval == ERROR_FLASH_OPERATION_FAILED)
{
} else if (retval == ERROR_FLASH_OPERATION_FAILED) {
LOG_ERROR("flash writing failed");
return retval;
}
}
else
{
} else {
buffer += words_remaining * 4;
address += words_remaining * 4;
words_remaining = 0;
}
}

while (words_remaining > 0)
{
while (words_remaining > 0) {
uint32_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint32_t));

status = pic32mx_write_word(bank, address, value);

if (status & NVMCON_NVMERR)
{
if (status & NVMCON_NVMERR) {
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED;
}

if (status & NVMCON_LVDERR)
{
if (status & NVMCON_LVDERR) {
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -581,21 +553,18 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
address += 4;
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint32_t value = 0xffffffff;
memcpy(&value, buffer + bytes_written, bytes_remaining);

status = pic32mx_write_word(bank, address, value);

if (status & NVMCON_NVMERR)
{
if (status & NVMCON_NVMERR) {
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED;
}

if (status & NVMCON_LVDERR)
{
if (status & NVMCON_LVDERR) {
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -631,8 +600,7 @@ static int pic32mx_probe(struct flash_bank *bank)

page_size = 4096;

if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH)
{
if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
/* 0x1FC00000: Boot flash size */
#if 0
/* for some reason this register returns 8k for the boot bank size
@@ -646,9 +614,7 @@ static int pic32mx_probe(struct flash_bank *bank)
/* fixed 12k boot bank - see comments above */
num_pages = (12 * 1024);
#endif
}
else
{
} else {
/* read the flash size from the device */
if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
@@ -658,8 +624,7 @@ static int pic32mx_probe(struct flash_bank *bank)

LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024);

if (bank->sectors)
{
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
@@ -670,8 +635,7 @@ static int pic32mx_probe(struct flash_bank *bank)
bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);

for (i = 0; i < (int)num_pages; i++)
{
for (i = 0; i < (int)num_pages; i++) {
bank->sectors[i].offset = i * page_size;
bank->sectors[i].size = page_size;
bank->sectors[i].is_erased = -1;
@@ -709,17 +673,15 @@ static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size)
return ERROR_FLASH_OPERATION_FAILED;
}

for (i = 0; pic32mx_devs[i].name != NULL; i++)
{
for (i = 0; pic32mx_devs[i].name != NULL; i++) {
if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
break;
}
}

if (pic32mx_devs[i].name == NULL) {
if (pic32mx_devs[i].name == NULL)
printed = snprintf(buf, buf_size, "Unknown");
}

buf += printed;
buf_size -= printed;
@@ -735,9 +697,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
int status, res;

if (CMD_ARGC != 3)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
@@ -747,8 +707,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
if (ERROR_OK != retval)
return retval;

if (address < bank->base || address >= (bank->base + bank->size))
{
if (address < bank->base || address >= (bank->base + bank->size)) {
command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
return ERROR_OK;
}
@@ -776,8 +735,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
struct mips_ejtag *ejtag_info;
int timeout = 10;

if (CMD_ARGC < 1)
{
if (CMD_ARGC < 1) {
command_print(CMD_CTX, "pic32mx unlock <bank>");
return ERROR_COMMAND_SYNTAX_ERROR;
}
@@ -798,8 +756,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
/* first check status of device */
mchip_cmd = MCHP_STATUS;
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
if (mchip_cmd & (1 << 7))
{
if (mchip_cmd & (1 << 7)) {
/* device is not locked */
command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway");
}
@@ -812,8 +769,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
do {
mchip_cmd = MCHP_STATUS;
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
if (timeout-- == 0)
{
if (timeout-- == 0) {
LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd);
break;
}


+ 75
- 132
src/flash/nor/stellaris.c View File

@@ -91,15 +91,14 @@
static void stellaris_read_clock_info(struct flash_bank *bank);
static int stellaris_mass_erase(struct flash_bank *bank);

struct stellaris_flash_bank
{
struct stellaris_flash_bank {
/* chip id register */
uint32_t did0;
uint32_t did1;
uint32_t dc0;
uint32_t dc1;

const char * target_name;
const char *target_name;
uint8_t target_class;

uint32_t sramsiz;
@@ -123,8 +122,8 @@ struct stellaris_flash_bank
const char *mck_desc;
};

// Autogenerated by contrib/gen-stellaris-part-header.pl
// From Stellaris Firmware Development Package revision 8049
/* Autogenerated by contrib/gen-stellaris-part-header.pl */
/* From Stellaris Firmware Development Package revision 8049 */
static struct {
uint8_t class;
uint8_t partno;
@@ -415,8 +414,7 @@ static struct {
{0xFF, 0x00, "Unknown Part"}
};

static char * StellarisClassname[7] =
{
static char *StellarisClassname[7] = {
"Sandstorm",
"Fury",
"Unknown",
@@ -437,9 +435,7 @@ FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
struct stellaris_flash_bank *stellaris_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
bank->base = 0x0;
@@ -503,8 +499,7 @@ static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

if (stellaris_info->num_lockbits > 0)
{
if (stellaris_info->num_lockbits > 0) {
snprintf(buf,
buf_size,
"pagesize: %" PRIi32 ", pages: %d, "
@@ -532,7 +527,7 @@ static void stellaris_set_flash_timing(struct flash_bank *bank)
if (stellaris_info->target_class > 1)
return;

LOG_DEBUG("usecrl = %i",(int)(usecrl));
LOG_DEBUG("usecrl = %i", (int)(usecrl));
target_write_u32(target, SCB_BASE | USECRL, usecrl);
}

@@ -613,8 +608,7 @@ static void stellaris_read_clock_info(struct flash_bank *bank)

stellaris_info->mck_desc = "";

switch (oscsrc)
{
switch (oscsrc) {
case 0: /* MOSC */
mainfreq = rcc_xtal[xtal];
break;
@@ -670,22 +664,19 @@ static int stellaris_read_part_info(struct flash_bank *bank)
did0, did1, stellaris_info->dc0, stellaris_info->dc1);

ver = did0 >> 28;
if ((ver != 0) && (ver != 1))
{
if ((ver != 0) && (ver != 1)) {
LOG_WARNING("Unknown did0 version, cannot identify target");
return ERROR_FLASH_OPERATION_FAILED;
}

if (did1 == 0)
{
if (did1 == 0) {
LOG_WARNING("Cannot identify target as a Stellaris");
return ERROR_FLASH_OPERATION_FAILED;
}

ver = did1 >> 28;
fam = (did1 >> 24) & 0xF;
if (((ver != 0) && (ver != 1)) || (fam != 0))
{
if (((ver != 0) && (ver != 1)) || (fam != 0)) {
LOG_WARNING("Unknown did1 version/family.");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -754,7 +745,7 @@ static int stellaris_read_part_info(struct flash_bank *bank)
stellaris_info->did1 = did1;

stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
stellaris_info->num_pages = 2 *(1 + (stellaris_info->dc0 & 0xFFFF));
stellaris_info->num_pages = 2 * (1 + (stellaris_info->dc0 & 0xFFFF));
stellaris_info->pagesize = 1024;
stellaris_info->pages_in_lockregion = 2;

@@ -823,8 +814,7 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last)
struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
struct target *target = bank->target;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -833,14 +823,10 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last)
return ERROR_FLASH_BANK_NOT_PROBED;

if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
{
return ERROR_FLASH_SECTOR_INVALID;
}

if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
{
return stellaris_mass_erase(bank);
}

/* Refresh flash controller timing */
stellaris_read_clock_info(bank);
@@ -854,24 +840,21 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last)
* it might want to process those IRQs.
*/

for (banknr = first; banknr <= last; banknr++)
{
for (banknr = first; banknr <= last; banknr++) {
/* Address is first word in page */
target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
/* Write erase command */
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
/* Wait until erase complete */
do
{
do {
target_read_u32(target, FLASH_FMC, &flash_fmc);
}
while (flash_fmc & FMC_ERASE);
} while (flash_fmc & FMC_ERASE);

/* Check acess violations */
target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK))
{
LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
if (flash_cris & (AMASK)) {
LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "",
banknr, flash_cris);
target_write_u32(target, FLASH_CRIS, 0);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -890,14 +873,12 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
struct target *target = bank->target;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (!set)
{
if (!set) {
LOG_ERROR("Hardware doesn't support page-level unprotect. "
"Try the 'recover' command.");
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -909,8 +890,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
/* lockregions are 2 pages ... must protect [even..odd] */
if ((first < 0) || (first & 1)
|| (last < first) || !(last & 1)
|| (last >= 2 * stellaris_info->num_lockbits))
{
|| (last >= 2 * stellaris_info->num_lockbits)) {
LOG_ERROR("Can't protect unaligned or out-of-range pages.");
return ERROR_FLASH_SECTOR_INVALID;
}
@@ -944,7 +924,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
* it might want to process those IRQs.
*/

LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
LOG_DEBUG("fmppe 0x%" PRIx32 "", fmppe);
target_write_u32(target, SCB_BASE | FMPPE, fmppe);

/* Commit FMPPE */
@@ -960,16 +940,13 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
/* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */

/* Wait until erase complete */
do
{
do {
target_read_u32(target, FLASH_FMC, &flash_fmc);
}
while (flash_fmc & FMC_COMT);
} while (flash_fmc & FMC_COMT);

/* Check acess violations */
target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK))
{
if (flash_cris & (AMASK)) {
LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
target_write_u32(target, FLASH_CRIS, 0);
return ERROR_FLASH_OPERATION_FAILED;
@@ -980,8 +957,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la

/* see contib/loaders/flash/stellaris.s for src */

static const uint8_t stellaris_write_code[] =
{
static const uint8_t stellaris_write_code[] = {
/*
Call with :
r0 = buffer address
@@ -995,28 +971,28 @@ static const uint8_t stellaris_write_code[] =
r6 = bytes written
r7 = temp reg
*/
0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
0x08,0x4C, /* ldr r4,FLASHWRITECMD */
0x01,0x25, /* movs r5, 1 */
0x00,0x26, /* movs r6, #0 */
0x07, 0x4B, /* ldr r3,pFLASH_CTRL_BASE */
0x08, 0x4C, /* ldr r4,FLASHWRITECMD */
0x01, 0x25, /* movs r5, 1 */
0x00, 0x26, /* movs r6, #0 */
/* mainloop: */
0x19,0x60, /* str r1, [r3, #0] */
0x87,0x59, /* ldr r7, [r0, r6] */
0x5F,0x60, /* str r7, [r3, #4] */
0x9C,0x60, /* str r4, [r3, #8] */
0x19, 0x60, /* str r1, [r3, #0] */
0x87, 0x59, /* ldr r7, [r0, r6] */
0x5F, 0x60, /* str r7, [r3, #4] */
0x9C, 0x60, /* str r4, [r3, #8] */
/* waitloop: */
0x9F,0x68, /* ldr r7, [r3, #8] */
0x2F,0x42, /* tst r7, r5 */
0xFC,0xD1, /* bne waitloop */
0x04,0x31, /* adds r1, r1, #4 */
0x04,0x36, /* adds r6, r6, #4 */
0x96,0x42, /* cmp r6, r2 */
0xF4,0xD1, /* bne mainloop */
0x00,0xBE, /* bkpt #0 */
0x9F, 0x68, /* ldr r7, [r3, #8] */
0x2F, 0x42, /* tst r7, r5 */
0xFC, 0xD1, /* bne waitloop */
0x04, 0x31, /* adds r1, r1, #4 */
0x04, 0x36, /* adds r6, r6, #4 */
0x96, 0x42, /* cmp r6, r2 */
0xF4, 0xD1, /* bne mainloop */
0x00, 0xBE, /* bkpt #0 */
/* pFLASH_CTRL_BASE: */
0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
/* FLASHWRITECMD: */
0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
};

static int stellaris_write_block(struct flash_bank *bank,
@@ -1042,8 +1018,8 @@ static int stellaris_write_block(struct flash_bank *bank,
bank, buffer, offset, wcount);

/* flash write code */
if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
{
if (target_alloc_working_area(target, sizeof(stellaris_write_code),
&write_algorithm) != ERROR_OK) {
LOG_DEBUG("no working area for block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};
@@ -1053,11 +1029,9 @@ static int stellaris_write_block(struct flash_bank *bank,
buffer_size = wcount * 4;

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= buf_min)
{
if (buffer_size <= buf_min) {
target_free_working_area(target, write_algorithm);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
@@ -1076,8 +1050,7 @@ static int stellaris_write_block(struct flash_bank *bank,
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);

while (wcount > 0)
{
while (wcount > 0) {
uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;

target_write_buffer(target, source->address, thisrun_count * 4, buffer);
@@ -1093,8 +1066,7 @@ static int stellaris_write_block(struct flash_bank *bank,
write_algorithm->address,
0,
10000, &armv7m_info);
if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
LOG_ERROR("error %d executing stellaris "
"flash write algorithm",
retval);
@@ -1121,7 +1093,8 @@ static int stellaris_write_block(struct flash_bank *bank,
return retval;
}

static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
static int stellaris_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
struct target *target = bank->target;
@@ -1132,8 +1105,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
uint32_t bytes_written = 0;
int retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1144,8 +1116,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
if (stellaris_info->did1 == 0)
return ERROR_FLASH_BANK_NOT_PROBED;

if (offset & 0x3)
{
if (offset & 0x3) {
LOG_WARNING("offset size must be word aligned");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
@@ -1166,36 +1137,28 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
*/

/* multiple words to be programmed? */
if (words_remaining > 0)
{
if (words_remaining > 0) {
/* try using a block write */
retval = stellaris_write_block(bank, buffer, offset,
words_remaining);
if (retval != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
LOG_DEBUG("writing flash word-at-a-time");
}
else if (retval == ERROR_FLASH_OPERATION_FAILED)
{
} else if (retval == ERROR_FLASH_OPERATION_FAILED) {
/* if an error occured, we examine the reason, and quit */
target_read_u32(target, FLASH_CRIS, &flash_cris);

LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
return ERROR_FLASH_OPERATION_FAILED;
}
}
else
{
} else {
buffer += words_remaining * 4;
address += words_remaining * 4;
words_remaining = 0;
}
}

while (words_remaining > 0)
{
while (words_remaining > 0) {
if (!(address & 0xff))
LOG_DEBUG("0x%" PRIx32 "", address);

@@ -1205,8 +1168,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
/* Wait until write complete */
do
{
do {
target_read_u32(target, FLASH_FMC, &flash_fmc);
} while (flash_fmc & FMC_WRITE);

@@ -1215,8 +1177,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
words_remaining--;
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};

/* copy the last remaining bytes into the write buffer */
@@ -1231,16 +1192,14 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
/* Wait until write complete */
do
{
do {
target_read_u32(target, FLASH_FMC, &flash_fmc);
} while (flash_fmc & FMC_WRITE);
}

/* Check access violations */
target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK))
{
if (flash_cris & (AMASK)) {
LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -1266,8 +1225,7 @@ static int stellaris_probe(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;

if (bank->sectors)
{
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
@@ -1276,8 +1234,7 @@ static int stellaris_probe(struct flash_bank *bank)
bank->size = 1024 * stellaris_info->num_pages;
bank->num_sectors = stellaris_info->num_pages;
bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
for (int i = 0; i < bank->num_sectors; i++)
{
for (int i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = i * stellaris_info->pagesize;
bank->sectors[i].size = stellaris_info->pagesize;
bank->sectors[i].is_erased = -1;
@@ -1296,8 +1253,7 @@ static int stellaris_mass_erase(struct flash_bank *bank)
stellaris_info = bank->driver_priv;
target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1320,24 +1276,19 @@ static int stellaris_mass_erase(struct flash_bank *bank)
target_write_u32(target, FLASH_FMA, 0);
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
/* Wait until erase complete */
do
{
do {
target_read_u32(target, FLASH_FMC, &flash_fmc);
}
while (flash_fmc & FMC_MERASE);
} while (flash_fmc & FMC_MERASE);

/* if device has > 128k, then second erase cycle is needed
* this is only valid for older devices, but will not hurt */
if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
{
if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) {
target_write_u32(target, FLASH_FMA, 0x20000);
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
/* Wait until erase complete */
do
{
do {
target_read_u32(target, FLASH_FMC, &flash_fmc);
}
while (flash_fmc & FMC_MERASE);
} while (flash_fmc & FMC_MERASE);
}

return ERROR_OK;
@@ -1348,29 +1299,21 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command)
int i;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (ERROR_OK != retval)
return retval;

if (stellaris_mass_erase(bank) == ERROR_OK)
{
if (stellaris_mass_erase(bank) == ERROR_OK) {
/* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1;
}

command_print(CMD_CTX, "stellaris mass erase complete");
}
else
{
} else
command_print(CMD_CTX, "stellaris mass erase failed");
}

return ERROR_OK;
}


+ 101
- 221
src/flash/nor/stm32f1x.c View File

@@ -23,6 +23,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -101,15 +102,13 @@
#define KEY1 0x45670123
#define KEY2 0xCDEF89AB

struct stm32x_options
{
struct stm32x_options {
uint16_t RDP;
uint16_t user_options;
uint16_t protection[4];
};

struct stm32x_flash_bank
{
struct stm32x_flash_bank {
struct stm32x_options option_bytes;
struct working_area *write_algorithm;
int ppage_size;
@@ -129,9 +128,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
struct stm32x_flash_bank *stm32x_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
bank->driver_priv = stm32x_info;
@@ -163,37 +160,32 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
int retval = ERROR_OK;

/* wait for busy to clear */
for (;;)
{
for (;;) {
retval = stm32x_get_flash_status(bank, &status);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("status: 0x%" PRIx32 "", status);
if ((status & FLASH_BSY) == 0)
break;
if (timeout-- <= 0)
{
if (timeout-- <= 0) {
LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL;
}
alive_sleep(1);
}

if (status & FLASH_WRPRTERR)
{
if (status & FLASH_WRPRTERR) {
LOG_ERROR("stm32x device protected");
retval = ERROR_FAIL;
}

if (status & FLASH_PGERR)
{
if (status & FLASH_PGERR) {
LOG_ERROR("stm32x device programming failed");
retval = ERROR_FAIL;
}

/* Clear but report errors */
if (status & (FLASH_WRPRTERR | FLASH_PGERR))
{
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) {
/* If this operation fails, we ignore it and report the original
* retval
*/
@@ -209,8 +201,7 @@ int stm32x_check_operation_supported(struct flash_bank *bank)

/* if we have a dual flash bank device then
* we need to perform option byte stuff on bank0 only */
if (stm32x_info->register_base != FLASH_REG_BASE_B0)
{
if (stm32x_info->register_base != FLASH_REG_BASE_B0) {
LOG_ERROR("Option Byte Operation's must use bank0");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -395,8 +386,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
int num_bits;
int set;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -415,8 +405,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
* high density - each protection bit is for 2 * 2K pages */
num_bits = (bank->num_sectors / stm32x_info->ppage_size);

if (stm32x_info->ppage_size == 2)
{
if (stm32x_info->ppage_size == 2) {
/* high density flash/connectivity line protection */

set = 1;
@@ -427,15 +416,12 @@ static int stm32x_protect_check(struct flash_bank *bank)
/* bit 31 controls sector 62 - 255 protection for high density
* bit 31 controls sector 62 - 127 protection for connectivity line */
for (s = 62; s < bank->num_sectors; s++)
{
bank->sectors[s].is_protected = set;
}

if (bank->num_sectors > 61)
num_bits = 31;

for (i = 0; i < num_bits; i++)
{
for (i = 0; i < num_bits; i++) {
set = 1;

if (protection & (1 << i))
@@ -444,12 +430,9 @@ static int stm32x_protect_check(struct flash_bank *bank)
for (s = 0; s < stm32x_info->ppage_size; s++)
bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
}
}
else
{
} else {
/* low/medium density flash protection */
for (i = 0; i < num_bits; i++)
{
for (i = 0; i < num_bits; i++) {
set = 1;

if (protection & (1 << i))
@@ -468,16 +451,13 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
struct target *target = bank->target;
int i;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((first == 0) && (last == (bank->num_sectors - 1)))
{
return stm32x_mass_erase(bank);
}

/* unlock flash registers */
int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
@@ -487,8 +467,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
if (retval != ERROR_OK)
return retval;

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
if (retval != ERROR_OK)
return retval;
@@ -526,8 +505,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)

stm32x_info = bank->driver_priv;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -536,14 +514,12 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
if (ERROR_OK != retval)
return retval;

if ((first % stm32x_info->ppage_size) != 0)
{
if ((first % stm32x_info->ppage_size) != 0) {
LOG_WARNING("aligned start protect sector to a %d sector boundary",
stm32x_info->ppage_size);
first = first - (first % stm32x_info->ppage_size);
}
if (((last + 1) % stm32x_info->ppage_size) != 0)
{
if (((last + 1) % stm32x_info->ppage_size) != 0) {
LOG_WARNING("aligned end protect sector to a %d sector boundary",
stm32x_info->ppage_size);
last++;
@@ -562,13 +538,11 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
prot_reg[2] = (uint16_t)(protection >> 16);
prot_reg[3] = (uint16_t)(protection >> 24);

if (stm32x_info->ppage_size == 2)
{
if (stm32x_info->ppage_size == 2) {
/* high density flash */

/* bit 7 controls sector 62 - 255 protection */
if (last > 61)
{
if (last > 61) {
if (set)
prot_reg[3] &= ~(1 << 7);
else
@@ -580,8 +554,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
if (last > 61)
last = 61;

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
reg = (i / stm32x_info->ppage_size) / 8;
bit = (i / stm32x_info->ppage_size) - (reg * 8);

@@ -590,12 +563,9 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
else
prot_reg[reg] |= (1 << bit);
}
}
else
{
} else {
/* medium density flash */
for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
reg = (i / stm32x_info->ppage_size) / 8;
bit = (i / stm32x_info->ppage_size) - (reg * 8);

@@ -606,7 +576,8 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
}
}

if ((status = stm32x_erase_options(bank)) != ERROR_OK)
status = stm32x_erase_options(bank);
if (status != ERROR_OK)
return status;

stm32x_info->option_bytes.protection[0] = prot_reg[0];
@@ -675,24 +646,21 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,

/* flash write code */
if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
&stm32x_info->write_algorithm) != ERROR_OK)
{
&stm32x_info->write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};

if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
sizeof(stm32x_flash_write_code),
(uint8_t*)stm32x_flash_write_code)) != ERROR_OK)
retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
sizeof(stm32x_flash_write_code), (uint8_t *)stm32x_flash_write_code);
if (retval != ERROR_OK)
return retval;

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
buffer_size &= ~3UL; // Make sure it's 4 byte aligned
if (buffer_size <= 256)
{
buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
if (stm32x_info->write_algorithm)
@@ -736,35 +704,31 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
armv7m_info.core_mode = ARMV7M_MODE_ANY;

/* Start up algorithm on target and let it idle while writing the first chunk */
if ((retval = target_start_algorithm(target, 0, NULL, 5, reg_params,
retval = target_start_algorithm(target, 0, NULL, 5, reg_params,
stm32x_info->write_algorithm->address,
0,
&armv7m_info)) != ERROR_OK)
{
&armv7m_info);
if (retval != ERROR_OK) {
LOG_ERROR("error starting stm32x flash write algorithm");
goto cleanup;
}

while (count > 0)
{
while (count > 0) {
retval = target_read_u32(target, rp_addr, &rp);
if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
LOG_ERROR("failed to get read pointer");
break;
}

LOG_DEBUG("count 0x%"PRIx32" wp 0x%"PRIx32" rp 0x%"PRIx32, count, wp, rp);

if (rp == 0)
{
if (rp == 0) {
LOG_ERROR("flash write algorithm aborted by target");
retval = ERROR_FLASH_OPERATION_FAILED;
break;
}

if ((rp & 1) || rp < fifo_start_addr || rp >= fifo_end_addr)
{
if ((rp & 1) || rp < fifo_start_addr || rp >= fifo_end_addr) {
LOG_ERROR("corrupted fifo read pointer 0x%"PRIx32, rp);
break;
}
@@ -780,8 +744,7 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
else
thisrun_bytes = fifo_end_addr - wp - 2;

if (thisrun_bytes == 0)
{
if (thisrun_bytes == 0) {
/* Throttle polling a bit if transfer is (much) faster than flash
* programming. The exact delay shouldn't matter as long as it's
* less than buffer size / flash speed. This is very unlikely to
@@ -812,36 +775,29 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
break;
}

if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
/* abort flash write algorithm on target */
target_write_u32(target, wp_addr, 0);
}

int retval2;
if ((retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params,
0,
10000,
&armv7m_info)) != ERROR_OK)
{
int retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params,
0, 10000, &armv7m_info);
if (retval2 != ERROR_OK) {
LOG_ERROR("error waiting for stm32x flash write algorithm");
retval = retval2;
}

if (retval == ERROR_FLASH_OPERATION_FAILED)
{
if (retval == ERROR_FLASH_OPERATION_FAILED) {
LOG_ERROR("flash write failed at address 0x%"PRIx32,
buf_get_u32(reg_params[4].value, 0, 32));

if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR)
{
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) {
LOG_ERROR("flash memory not erased before writing");
/* Clear but report errors */
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_PGERR);
}

if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR)
{
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) {
LOG_ERROR("flash memory write protected");
/* Clear but report errors */
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_WRPRTERR);
@@ -871,14 +827,12 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t bytes_written = 0;
int retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (offset & 0x1)
{
if (offset & 0x1) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
@@ -892,20 +846,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
return retval;

/* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0)
{
if (words_remaining > 0) {
/* try using a block write */
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
retval = stm32x_write_block(bank, buffer, offset, words_remaining);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
}
}
else
{
} else {
buffer += words_remaining * 2;
address += words_remaining * 2;
words_remaining = 0;
@@ -915,8 +865,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
return retval;

while (words_remaining > 0)
{
while (words_remaining > 0) {
uint16_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));

@@ -936,8 +885,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
address += 2;
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint16_t value = 0xffff;
memcpy(&value, buffer + bytes_written, bytes_remaining);

@@ -977,8 +925,7 @@ static int stm32x_probe(struct flash_bank *bank)

/* get flash size from target. */
retval = target_read_u16(target, 0x1FFFF7E0, &flash_size_in_kb);
if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
LOG_WARNING("failed reading flash size, default to max target family");
/* failed reading flash size, default to max target family */
flash_size_in_kb = 0xffff;
@@ -991,8 +938,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4;

/* check for early silicon */
if (flash_size_in_kb == 0xffff)
{
if (flash_size_in_kb == 0xffff) {
/* number of sectors incorrect on revA */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
flash_size_in_kb = 128;
@@ -1004,8 +950,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4;

/* check for early silicon */
if (flash_size_in_kb == 0xffff)
{
if (flash_size_in_kb == 0xffff) {
/* number of sectors incorrect on revA */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash");
flash_size_in_kb = 32;
@@ -1017,8 +962,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 2;

/* check for early silicon */
if (flash_size_in_kb == 0xffff)
{
if (flash_size_in_kb == 0xffff) {
/* number of sectors incorrect on revZ */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash");
flash_size_in_kb = 512;
@@ -1030,8 +974,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 2;

/* check for early silicon */
if (flash_size_in_kb == 0xffff)
{
if (flash_size_in_kb == 0xffff) {
/* number of sectors incorrect on revZ */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash");
flash_size_in_kb = 256;
@@ -1043,8 +986,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4;

/* check for early silicon */
if (flash_size_in_kb == 0xffff)
{
if (flash_size_in_kb == 0xffff) {
/* number of sectors may be incorrrect on early silicon */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
flash_size_in_kb = 128;
@@ -1056,8 +998,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4;

/* check for early silicon */
if (flash_size_in_kb == 0xffff)
{
if (flash_size_in_kb == 0xffff) {
/* number of sectors may be incorrrect on early silicon */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
flash_size_in_kb = 128;
@@ -1070,29 +1011,23 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->has_dual_banks = true;

/* check for early silicon */
if (flash_size_in_kb == 0xffff)
{
if (flash_size_in_kb == 0xffff) {
/* number of sectors may be incorrrect on early silicon */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 1024k flash");
flash_size_in_kb = 1024;
}

/* split reported size into matching bank */
if (bank->base != 0x08080000)
{
if (bank->base != 0x08080000) {
/* bank 0 will be fixed 512k */
flash_size_in_kb = 512;
}
else
{
} else {
flash_size_in_kb -= 512;
/* bank1 also uses a register offset */
stm32x_info->register_base = FLASH_REG_BASE_B1;
base_address = 0x08080000;
}
}
else
{
} else {
LOG_WARNING("Cannot identify target as a STM32 family.");
return ERROR_FAIL;
}
@@ -1108,8 +1043,7 @@ static int stm32x_probe(struct flash_bank *bank)
/* check that calculation result makes sense */
assert(num_pages > 0);

if (bank->sectors)
{
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
@@ -1119,8 +1053,7 @@ static int stm32x_probe(struct flash_bank *bank)
bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);

for (i = 0; i < num_pages; i++)
{
for (i = 0; i < num_pages; i++) {
bank->sectors[i].offset = i * page_size;
bank->sectors[i].size = page_size;
bank->sectors[i].is_erased = -1;
@@ -1163,8 +1096,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x0000:
snprintf(buf, buf_size, "A");
break;
@@ -1190,8 +1122,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x1000:
snprintf(buf, buf_size, "A");
break;
@@ -1205,8 +1136,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x1000:
snprintf(buf, buf_size, "A");
break;
@@ -1224,8 +1154,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x1000:
snprintf(buf, buf_size, "A");
break;
@@ -1243,8 +1172,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x1000:
snprintf(buf, buf_size, "A");
break;
@@ -1262,8 +1190,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x1000:
snprintf(buf, buf_size, "A");
break;
@@ -1281,8 +1208,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x1000:
snprintf(buf, buf_size, "A");
break;
@@ -1291,9 +1217,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
snprintf(buf, buf_size, "unknown");
break;
}
}
else
{
} else {
snprintf(buf, buf_size, "Cannot identify target as a stm32x\n");
return ERROR_FAIL;
}
@@ -1307,9 +1231,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
struct stm32x_flash_bank *stm32x_info = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1320,8 +1242,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)

target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1330,8 +1251,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
if (ERROR_OK != retval)
return retval;

if (stm32x_erase_options(bank) != ERROR_OK)
{
if (stm32x_erase_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to erase options");
return ERROR_OK;
}
@@ -1339,8 +1259,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
/* set readout protection */
stm32x_info->option_bytes.RDP = 0;

if (stm32x_write_options(bank) != ERROR_OK)
{
if (stm32x_write_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to lock device");
return ERROR_OK;
}
@@ -1355,9 +1274,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
struct target *target = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1366,8 +1283,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)

target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1376,14 +1292,12 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
if (ERROR_OK != retval)
return retval;

if (stm32x_erase_options(bank) != ERROR_OK)
{
if (stm32x_erase_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to unlock device");
return ERROR_OK;
}

if (stm32x_write_options(bank) != ERROR_OK)
{
if (stm32x_write_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to lock device");
return ERROR_OK;
}
@@ -1402,9 +1316,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
struct stm32x_flash_bank *stm32x_info = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1415,8 +1327,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)

target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1430,32 +1341,31 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
return retval;
command_print(CMD_CTX, "Option Byte: 0x%" PRIx32 "", optionbyte);

if (buf_get_u32((uint8_t*)&optionbyte, OPT_ERROR, 1))
if (buf_get_u32((uint8_t *)&optionbyte, OPT_ERROR, 1))
command_print(CMD_CTX, "Option Byte Complement Error");

if (buf_get_u32((uint8_t*)&optionbyte, OPT_READOUT, 1))
if (buf_get_u32((uint8_t *)&optionbyte, OPT_READOUT, 1))
command_print(CMD_CTX, "Readout Protection On");
else
command_print(CMD_CTX, "Readout Protection Off");

if (buf_get_u32((uint8_t*)&optionbyte, OPT_RDWDGSW, 1))
if (buf_get_u32((uint8_t *)&optionbyte, OPT_RDWDGSW, 1))
command_print(CMD_CTX, "Software Watchdog");
else
command_print(CMD_CTX, "Hardware Watchdog");

if (buf_get_u32((uint8_t*)&optionbyte, OPT_RDRSTSTOP, 1))
if (buf_get_u32((uint8_t *)&optionbyte, OPT_RDRSTSTOP, 1))
command_print(CMD_CTX, "Stop: No reset generated");
else
command_print(CMD_CTX, "Stop: Reset generated");

if (buf_get_u32((uint8_t*)&optionbyte, OPT_RDRSTSTDBY, 1))
if (buf_get_u32((uint8_t *)&optionbyte, OPT_RDRSTSTDBY, 1))
command_print(CMD_CTX, "Standby: No reset generated");
else
command_print(CMD_CTX, "Standby: Reset generated");

if (stm32x_info->has_dual_banks)
{
if (buf_get_u32((uint8_t*)&optionbyte, OPT_BFB2, 1))
if (stm32x_info->has_dual_banks) {
if (buf_get_u32((uint8_t *)&optionbyte, OPT_BFB2, 1))
command_print(CMD_CTX, "Boot: Bank 0");
else
command_print(CMD_CTX, "Boot: Bank 1");
@@ -1471,9 +1381,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
uint16_t optionbyte = 0xF8;

if (CMD_ARGC < 4)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1484,8 +1392,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)

target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1500,57 +1407,38 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)

/* 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)
{
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);
}
}

if (stm32x_erase_options(bank) != ERROR_OK)
{
if (stm32x_erase_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to erase options");
return ERROR_OK;
}

stm32x_info->option_bytes.user_options = optionbyte;

if (stm32x_write_options(bank) != ERROR_OK)
{
if (stm32x_write_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to write options");
return ERROR_OK;
}
@@ -1566,8 +1454,7 @@ static int stm32x_mass_erase(struct flash_bank *bank)
{
struct target *target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1584,7 +1471,8 @@ static int stm32x_mass_erase(struct flash_bank *bank)
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER);
if (retval != ERROR_OK)
return retval;
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER | FLASH_STRT);
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
FLASH_MER | FLASH_STRT);
if (retval != ERROR_OK)
return retval;

@@ -1604,9 +1492,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
int i;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1614,20 +1500,14 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
return retval;

retval = stm32x_mass_erase(bank);
if (retval == ERROR_OK)
{
if (retval == ERROR_OK) {
/* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1;
}

command_print(CMD_CTX, "stm32x mass erase complete");
}
else
{
} else
command_print(CMD_CTX, "stm32x mass erase failed");
}

return retval;
}


+ 43
- 69
src/flash/nor/stm32f2x.c View File

@@ -23,6 +23,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -70,7 +71,8 @@
* http://www.st.com/internet/mcu/product/250192.jsp
*
* PM0059
* www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/PROGRAMMING_MANUAL/CD00233952.pdf
* www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/
* PROGRAMMING_MANUAL/CD00233952.pdf
*
* STM32F1x series - notice that this code was copy, pasted and knocked
* into a stm32f2x driver, so in case something has been converted or
@@ -85,11 +87,10 @@
*
*/

// Erase time can be as high as 1000ms, 10x this and it's toast...
/* Erase time can be as high as 1000ms, 10x this and it's toast... */
#define FLASH_ERASE_TIMEOUT 10000
#define FLASH_WRITE_TIMEOUT 5


#define STM32_FLASH_BASE 0x40023c00
#define STM32_FLASH_ACR 0x40023c00
#define STM32_FLASH_KEYR 0x40023c04
@@ -99,8 +100,6 @@
#define STM32_FLASH_OPTCR 0x40023c14
#define STM32_FLASH_OBR 0x40023c1C



/* option byte location */

#define STM32_OB_RDP 0x1FFFF800
@@ -122,19 +121,19 @@
#define FLASH_PSIZE_16 (1 << 8)
#define FLASH_PSIZE_32 (2 << 8)
#define FLASH_PSIZE_64 (3 << 8)
#define FLASH_SNB(a) ((a) << 3)
#define FLASH_SNB(a) ((a) << 3)
#define FLASH_LOCK (1 << 31)

/* FLASH_SR register bits */

#define FLASH_BSY (1 << 16)
#define FLASH_PGSERR (1 << 7) // Programming sequence error
#define FLASH_PGPERR (1 << 6) // Programming parallelism error
#define FLASH_PGAERR (1 << 5) // Programming alignment error
#define FLASH_WRPERR (1 << 4) // Write protection error
#define FLASH_OPERR (1 << 1) // Operation error
#define FLASH_PGSERR (1 << 7) /* Programming sequence error */
#define FLASH_PGPERR (1 << 6) /* Programming parallelism error */
#define FLASH_PGAERR (1 << 5) /* Programming alignment error */
#define FLASH_WRPERR (1 << 4) /* Write protection error */
#define FLASH_OPERR (1 << 1) /* Operation error */

#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR| FLASH_WRPERR| FLASH_OPERR)
#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR)

/* STM32_FLASH_OBR bit definitions (reading) */

@@ -150,8 +149,7 @@
#define KEY1 0x45670123
#define KEY2 0xCDEF89AB

struct stm32x_flash_bank
{
struct stm32x_flash_bank {
struct working_area *write_algorithm;
int probed;
};
@@ -164,9 +162,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
struct stm32x_flash_bank *stm32x_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
bank->driver_priv = stm32x_info;
@@ -195,16 +191,14 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
int retval = ERROR_OK;

/* wait for busy to clear */
for (;;)
{
for (;;) {
retval = stm32x_get_flash_status(bank, &status);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("status: 0x%" PRIx32 "", status);
if ((status & FLASH_BSY) == 0)
break;
if (timeout-- <= 0)
{
if (timeout-- <= 0) {
LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL;
}
@@ -212,15 +206,13 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
}


if (status & FLASH_WRPERR)
{
if (status & FLASH_WRPERR) {
LOG_ERROR("stm32x device protected");
retval = ERROR_FAIL;
}

/* Clear but report errors */
if (status & FLASH_ERROR)
{
if (status & FLASH_ERROR) {
/* If this operation fails, we ignore it and report the original
* retval
*/
@@ -275,8 +267,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
struct target *target = bank->target;
int i;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -297,8 +288,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
4. Wait for the BSY bit to be cleared
*/

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
retval = target_write_u32(target,
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT);
if (retval != ERROR_OK)
@@ -361,30 +351,27 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,

/* Flip endian */
uint8_t stm32x_flash_write_code[sizeof(stm32x_flash_write_code_16)*2];
for (unsigned i = 0; i < sizeof(stm32x_flash_write_code_16) / 2; i++)
{
for (unsigned i = 0; i < sizeof(stm32x_flash_write_code_16) / 2; i++) {
stm32x_flash_write_code[i*2 + 0] = stm32x_flash_write_code_16[i] & 0xff;
stm32x_flash_write_code[i*2 + 1] = (stm32x_flash_write_code_16[i] >> 8) & 0xff;
}

if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
&stm32x_info->write_algorithm) != ERROR_OK)
{
&stm32x_info->write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};

if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
sizeof(stm32x_flash_write_code),
(uint8_t*)stm32x_flash_write_code)) != ERROR_OK)
(uint8_t *)stm32x_flash_write_code);
if (retval != ERROR_OK)
return retval;

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= 256)
{
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
if (stm32x_info->write_algorithm)
@@ -404,28 +391,27 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);

while (count > 0)
{
while (count > 0) {
uint32_t thisrun_count = (count > (buffer_size / 2)) ?
(buffer_size / 2) : count;

if ((retval = target_write_buffer(target, source->address,
thisrun_count * 2, buffer)) != ERROR_OK)
retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
if (retval != ERROR_OK)
break;

buf_set_u32(reg_params[0].value, 0, 32, source->address);
buf_set_u32(reg_params[1].value, 0, 32, address);
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
// R3 is a return value only
/* R3 is a return value only */
buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE);

if ((retval = target_run_algorithm(target, 0, NULL,
retval = target_run_algorithm(target, 0, NULL,
sizeof(reg_params) / sizeof(*reg_params),
reg_params,
stm32x_info->write_algorithm->address,
0,
10000, &armv7m_info)) != ERROR_OK)
{
10000, &armv7m_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing stm32x flash write algorithm");
break;
}
@@ -433,12 +419,9 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
uint32_t error = buf_get_u32(reg_params[3].value, 0, 32) & FLASH_ERROR;

if (error & FLASH_WRPERR)
{
LOG_ERROR("flash memory write protected");
}

if (error != 0)
{
if (error != 0) {
LOG_ERROR("flash write failed = %08x", error);
/* Clear but report errors */
target_write_u32(target, STM32_FLASH_SR, error);
@@ -473,14 +456,12 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t bytes_written = 0;
int retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (offset & 0x1)
{
if (offset & 0x1) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
@@ -490,20 +471,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
return retval;

/* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0)
{
if (words_remaining > 0) {
/* try using a block write */
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
retval = stm32x_write_block(bank, buffer, offset, words_remaining);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
}
}
else
{
} else {
buffer += words_remaining * 2;
address += words_remaining * 2;
words_remaining = 0;
@@ -529,8 +506,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
Double word access in case of x64 parallelism
Wait for the BSY bit to be cleared
*/
while (words_remaining > 0)
{
while (words_remaining > 0) {
uint16_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));

@@ -552,8 +528,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
address += 2;
}

if (bytes_remaining)
{
if (bytes_remaining) {
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
FLASH_PG | FLASH_PSIZE_8);
if (retval != ERROR_OK)
@@ -572,8 +547,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,

static void setup_sector(struct flash_bank *bank, int start, int num, int size)
{
for (int i = start; i < (start + num) ; i++)
{
for (int i = start; i < (start + num) ; i++) {
bank->sectors[i].offset = bank->size;
bank->sectors[i].size = size;
bank->size += bank->sectors[i].size;


+ 85
- 147
src/flash/nor/stm32lx.c View File

@@ -23,6 +23,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -117,8 +118,7 @@ static int stm32lx_enable_write_half_page(struct flash_bank *bank);
static int stm32lx_erase_sector(struct flash_bank *bank, int sector);
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank);

struct stm32lx_flash_bank
{
struct stm32lx_flash_bank {
struct working_area *write_algorithm;
int probed;
};
@@ -129,16 +129,13 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
{
struct stm32lx_flash_bank *stm32lx_info;
if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

// Create the bank structure
/* Create the bank structure */
stm32lx_info = malloc(sizeof(struct stm32lx_flash_bank));

// Check allocation
if (stm32lx_info == NULL)
{
/* Check allocation */
if (stm32lx_info == NULL) {
LOG_ERROR("failed to allocate bank structure");
return ERROR_FAIL;
}
@@ -158,8 +155,7 @@ static int stm32lx_protect_check(struct flash_bank *bank)

uint32_t wrpr;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -172,16 +168,11 @@ static int stm32lx_protect_check(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;

for (int i = 0; i < 32; i++)
{
for (int i = 0; i < 32; i++) {
if (wrpr & (1 << i))
{
bank->sectors[i].is_protected = 1;
}
else
{
bank->sectors[i].is_protected = 0;
}
}
return ERROR_OK;
}
@@ -195,8 +186,7 @@ static int stm32lx_erase(struct flash_bank *bank, int first, int last)
* erased, but it is not implemented yet.
*/

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -204,8 +194,7 @@ static int stm32lx_erase(struct flash_bank *bank, int first, int last)
/*
* Loop over the selected sectors and erase them
*/
for (int i = first; i <= last; i++)
{
for (int i = first; i <= last; i++) {
retval = stm32lx_erase_sector(bank, i);
if (retval != ERROR_OK)
return retval;
@@ -238,72 +227,66 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer,

/* see contib/loaders/flash/stm32lx.s for src */

static const uint16_t stm32lx_flash_write_code_16[] =
{
// 00000000 <write_word-0x4>:
0x2300, // 0: 2300 movs r3, #0
0xe004, // 2: e004 b.n e <test_done>
static const uint16_t stm32lx_flash_write_code_16[] = {
/* 00000000 <write_word-0x4>: */
0x2300, /* 0: 2300 movs r3, #0 */
0xe004, /* 2: e004 b.n e <test_done> */

// 00000004 <write_word>:
0xf851, 0xcb04, // 4: f851 cb04 ldr.w ip, [r1], #4
0xf840, 0xcb04, // 8: f840 cb04 str.w ip, [r0], #4
0x3301, // c: 3301 adds r3, #1
/* 00000004 <write_word>: */
0xf851, 0xcb04, /* 4: f851 cb04 ldr.w ip, [r1], #4 */
0xf840, 0xcb04, /* 8: f840 cb04 str.w ip, [r0], #4 */
0x3301, /* c: 3301 adds r3, #1 */

// 0000000e <test_done>:
0x4293, // e: 4293 cmp r3, r2
0xd3f8, // 10: d3f8 bcc.n 4 <write_word>
0xbe00, // 12: be00 bkpt 0x0000
/* 0000000e <test_done>: */
0x4293, /* e: 4293 cmp r3, r2 */
0xd3f8, /* 10: d3f8 bcc.n 4 <write_word> */
0xbe00, /* 12: be00 bkpt 0x0000 */

};

// Flip endian
/* Flip endian */
uint8_t stm32lx_flash_write_code[sizeof(stm32lx_flash_write_code_16)];
for (unsigned int i = 0; i < sizeof(stm32lx_flash_write_code_16) / 2; i++)
{
for (unsigned int i = 0; i < sizeof(stm32lx_flash_write_code_16) / 2; i++) {
stm32lx_flash_write_code[i * 2 + 0] = stm32lx_flash_write_code_16[i]
& 0xff;
stm32lx_flash_write_code[i * 2 + 1] = (stm32lx_flash_write_code_16[i]
>> 8) & 0xff;
}
// Check if there is an even number of half pages (128bytes)
if (count % 128)
{
/* Check if there is an even number of half pages (128bytes) */
if (count % 128) {
LOG_ERROR("there should be an even number "
"of half pages = 128 bytes (count = %" PRIi32 " bytes)", count);
return ERROR_FAIL;
}

// Allocate working area
/* Allocate working area */
reg32 = sizeof(stm32lx_flash_write_code);
// Add bytes to make 4byte aligned
/* Add bytes to make 4byte aligned */
reg32 += (4 - (reg32 % 4)) % 4;
retval = target_alloc_working_area(target, reg32,
&stm32lx_info->write_algorithm);
if (retval != ERROR_OK)
return retval;

// Write the flashing code
/* Write the flashing code */
retval = target_write_buffer(target,
stm32lx_info->write_algorithm->address,
sizeof(stm32lx_flash_write_code),
(uint8_t*) stm32lx_flash_write_code);
if (retval != ERROR_OK)
{
(uint8_t *)stm32lx_flash_write_code);
if (retval != ERROR_OK) {
target_free_working_area(target, stm32lx_info->write_algorithm);
return retval;
}

// Allocate half pages memory
/* Allocate half pages memory */
while (target_alloc_working_area_try(target, buffer_size, &source)
!= ERROR_OK)
{
!= ERROR_OK) {
if (buffer_size > 1024)
buffer_size -= 1024;
else
buffer_size /= 2;

if (buffer_size <= 256)
{
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
if (stm32lx_info->write_algorithm)
@@ -323,11 +306,9 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer,
init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);

// Enable half-page write
/* Enable half-page write */
retval = stm32lx_enable_write_half_page(bank);
if (retval != ERROR_OK)
{

if (retval != ERROR_OK) {
target_free_working_area(target, source);
target_free_working_area(target, stm32lx_info->write_algorithm);

@@ -335,38 +316,36 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer,
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);

return retval;
}

// Loop while there are bytes to write
while (count > 0)
{
/* Loop while there are bytes to write */
while (count > 0) {
uint32_t this_count;
this_count = (count > buffer_size) ? buffer_size : count;

// Write the next half pages
/* Write the next half pages */
retval = target_write_buffer(target, source->address, this_count,
buffer);
if (retval != ERROR_OK)
break;

// 4: Store useful information in the registers
// the destination address of the copy (R0)
/* 4: Store useful information in the registers */
/* the destination address of the copy (R0) */
buf_set_u32(reg_params[0].value, 0, 32, address);
// The source address of the copy (R1)
/* The source address of the copy (R1) */
buf_set_u32(reg_params[1].value, 0, 32, source->address);
// The length of the copy (R2)
/* The length of the copy (R2) */
buf_set_u32(reg_params[2].value, 0, 32, this_count / 4);

// 5: Execute the bunch of code
/* 5: Execute the bunch of code */
retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params)
/ sizeof(*reg_params), reg_params,
stm32lx_info->write_algorithm->address, 0, 20000, &armv7m_info);
if (retval != ERROR_OK)
break;

// 6: Wait while busy
/* 6: Wait while busy */
retval = stm32lx_wait_until_bsy_clear(bank);
if (retval != ERROR_OK)
break;
@@ -401,34 +380,28 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t bytes_written = 0;
int retval;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (offset & 0x1)
{
if (offset & 0x1) {
LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

// Check if there are some full half pages
if (((offset % 128) == 0) && (count >= 128))
{
/* Check if there are some full half pages */
if (((offset % 128) == 0) && (count >= 128)) {
halfpages_number = count / 128;
words_remaining = (count - 128 * halfpages_number) / 4;
bytes_remaining = (count & 0x3);
}
else
{
} else {
halfpages_number = 0;
words_remaining = (count / 4);
bytes_remaining = (count & 0x3);
}

if (halfpages_number)
{
if (halfpages_number) {
retval = stm32lx_write_half_pages(bank, buffer, offset, 128
* halfpages_number);
if (retval != ERROR_OK)
@@ -441,12 +414,11 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
if (retval != ERROR_OK)
return retval;

while (words_remaining > 0)
{
while (words_remaining > 0) {
uint32_t value;
uint8_t* p = buffer + bytes_written;
uint8_t *p = buffer + bytes_written;

// Prepare the word, Little endian conversion
/* Prepare the word, Little endian conversion */
value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);

retval = target_write_u32(target, address, value);
@@ -462,8 +434,7 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
return retval;
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};

/* copy the last remaining bytes into the write buffer */
@@ -508,14 +479,13 @@ static int stm32lx_probe(struct flash_bank *bank)
return ERROR_FAIL;
}

// Read the RDP byte and check if it is 0xAA
/* Read the RDP byte and check if it is 0xAA */
uint8_t rdp;
retval = target_read_u32(target, FLASH_OBR, &reg32);
if (retval != ERROR_OK)
return retval;
rdp = reg32 & 0xFF;
if (rdp != 0xAA)
{
if (rdp != 0xAA) {
/*
* Unlocking the option byte is done by unlocking the PECR, then
* by writing the 2 option byte keys to OPTKEYR
@@ -549,19 +519,18 @@ static int stm32lx_probe(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;

if (reg32 & FLASH_PECR__OPTLOCK)
{
if (reg32 & FLASH_PECR__OPTLOCK) {
LOG_ERROR("OPTLOCK is not cleared");
return ERROR_FLASH_OPERATION_FAILED;
}

// Then, write RDP to 0x00 to set level 1
/* Then, write RDP to 0x00 to set level 1 */
reg32 = ((~0xAA) << 16) | (0xAA);
retval = target_write_u32(target, OB_RDP, reg32);
if (retval != ERROR_OK)
return retval;

// Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR
/* Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR */
reg32 = FLASH_PECR__OBL_LAUNCH;
retval = target_write_u32(target, FLASH_PECR, reg32);
if (retval != ERROR_OK)
@@ -574,8 +543,7 @@ static int stm32lx_probe(struct flash_bank *bank)
return retval;

/* check for valid flash size */
if (flash_size == 0xffff)
{
if (flash_size == 0xffff) {
/* number of sectors incorrect on revA */
LOG_ERROR("STM32 flash size failed, probe inaccurate");
return ERROR_FAIL;
@@ -588,8 +556,7 @@ static int stm32lx_probe(struct flash_bank *bank)
int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE;
LOG_INFO("flash size = %dkbytes", flash_size);

if (bank->sectors)
{
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
@@ -598,14 +565,12 @@ static int stm32lx_probe(struct flash_bank *bank)
bank->size = flash_size * 1024;
bank->num_sectors = num_sectors;
bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
if (bank->sectors == NULL)
{
if (bank->sectors == NULL) {
LOG_ERROR("failed to allocate bank sectors");
return ERROR_FAIL;
}

for (i = 0; i < num_sectors; i++)
{
for (i = 0; i < num_sectors; i++) {
bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
bank->sectors[i].size = FLASH_SECTOR_SIZE;
bank->sectors[i].is_erased = -1;
@@ -622,9 +587,7 @@ static int stm32lx_auto_probe(struct flash_bank *bank)
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;

if (stm32lx_info->probed)
{
return ERROR_OK;
}

return stm32lx_probe(bank);
}
@@ -637,60 +600,51 @@ static int stm32lx_erase_check(struct flash_bank *bank)
uint32_t nBytes;
int retval = ERROR_OK;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

uint8_t *buffer = malloc(buffer_size);
if (buffer == NULL)
{
if (buffer == NULL) {
LOG_ERROR("failed to allocate read buffer");
return ERROR_FAIL;
}

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
uint32_t j;
bank->sectors[i].is_erased = 1;

// Loop chunk by chunk over the sector
for (j = 0; j < bank->sectors[i].size; j += buffer_size)
{
/* Loop chunk by chunk over the sector */
for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
uint32_t chunk;
chunk = buffer_size;
if (chunk > (j - bank->sectors[i].size))
{
chunk = (j - bank->sectors[i].size);
}

retval = target_read_memory(target, bank->base
+ bank->sectors[i].offset + j, 4, chunk / 4, buffer);
if (retval != ERROR_OK)
break;

for (nBytes = 0; nBytes < chunk; nBytes++)
{
if (buffer[nBytes] != 0x00)
{
for (nBytes = 0; nBytes < chunk; nBytes++) {
if (buffer[nBytes] != 0x00) {
bank->sectors[i].is_erased = 0;
break;
}
}
}
if (retval != ERROR_OK)
{
break;
}
}
free(buffer);

return retval;
}

static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
{
// This method must return a string displaying information about the bank
/* This method must return a string displaying information about the bank */

struct target *target = bank->target;
uint32_t device_id;
@@ -706,8 +660,7 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed;
buf_size -= printed;

switch (device_id >> 16)
{
switch (device_id >> 16) {
case 0x1000:
snprintf(buf, buf_size, "A");
break;
@@ -719,9 +672,7 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
snprintf(buf, buf_size, "unknown");
break;
}
}
else
{
} else {
snprintf(buf, buf_size, "Cannot identify target as a stm32lx");
return ERROR_FAIL;
}
@@ -729,13 +680,11 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
return ERROR_OK;
}

static const struct command_registration stm32lx_exec_command_handlers[] =
{
static const struct command_registration stm32lx_exec_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};

static const struct command_registration stm32lx_command_handlers[] =
{
static const struct command_registration stm32lx_command_handlers[] = {
{
.name = "stm32lx",
.mode = COMMAND_ANY,
@@ -746,8 +695,7 @@ static const struct command_registration stm32lx_command_handlers[] =
COMMAND_REGISTRATION_DONE
};

struct flash_driver stm32lx_flash =
{
struct flash_driver stm32lx_flash = {
.name = "stm32lx",
.commands = stm32lx_command_handlers,
.flash_bank_command = stm32lx_flash_bank_command,
@@ -762,8 +710,7 @@ struct flash_driver stm32lx_flash =
.info = stm32lx_get_info,
};

// Static methods implementation

/* Static methods implementation */
static int stm32lx_unlock_program_memory(struct flash_bank *bank)
{
struct target *target = bank->target;
@@ -789,8 +736,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;

if (reg32 & FLASH_PECR__PELOCK)
{
if (reg32 & FLASH_PECR__PELOCK) {
LOG_ERROR("PELOCK is not cleared :(");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -807,8 +753,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;

if (reg32 & FLASH_PECR__PRGLOCK)
{
if (reg32 & FLASH_PECR__PRGLOCK) {
LOG_ERROR("PRGLOCK is not cleared :(");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -892,8 +837,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
if (retval != ERROR_OK)
return retval;

for (int page = 0; page < FLASH_PAGES_PER_SECTOR; page++)
{
for (int page = 0; page < FLASH_PAGES_PER_SECTOR; page++) {
reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
retval = target_write_u32(target, FLASH_PECR, reg32);
if (retval != ERROR_OK)
@@ -929,32 +873,26 @@ static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank)
int timeout = 100;

/* wait for busy to clear */
for (;;)
{
for (;;) {
retval = target_read_u32(target, FLASH_SR, &status);
if (retval != ERROR_OK)
return retval;

if ((status & FLASH_SR__BSY) == 0)
{
break;
}
if (timeout-- <= 0)
{
if (timeout-- <= 0) {
LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL;
}
alive_sleep(1);
}

if (status & FLASH_SR__WRPERR)
{
if (status & FLASH_SR__WRPERR) {
LOG_ERROR("access denied / write protected");
retval = ERROR_FAIL;
}

if (status & FLASH_SR__PGAERR)
{
if (status & FLASH_SR__PGAERR) {
LOG_ERROR("invalid program address");
retval = ERROR_FAIL;
}


+ 56
- 80
src/flash/nor/stmsmi.c View File

@@ -43,33 +43,33 @@
#include <helper/time_support.h>

#define SMI_READ_REG(a) (_SMI_READ_REG(a))
#define _SMI_READ_REG(a) \
{ \
int __a; \
uint32_t __v; \
\
#define _SMI_READ_REG(a) \
{ \
int __a; \
uint32_t __v; \
\
__a = target_read_u32(target, io_base + (a), &__v); \
if (__a != ERROR_OK) \
return __a; \
__v; \
if (__a != ERROR_OK) \
return __a; \
__v; \
}

#define SMI_WRITE_REG(a,v) \
{ \
int __r; \
\
#define SMI_WRITE_REG(a, v) \
{ \
int __r; \
\
__r = target_write_u32(target, io_base + (a), (v)); \
if (__r != ERROR_OK) \
return __r; \
if (__r != ERROR_OK) \
return __r; \
}

#define SMI_POLL_TFF(timeout) \
{ \
int __r; \
\
#define SMI_POLL_TFF(timeout) \
{ \
int __r; \
\
__r = poll_tff(target, io_base, timeout); \
if (__r != ERROR_OK) \
return __r; \
if (__r != ERROR_OK) \
return __r; \
}

#define SMI_SET_SW_MODE() SMI_WRITE_REG(SMI_CR1, \
@@ -117,8 +117,7 @@
#define SMI_PROBE_TIMEOUT (100)
#define SMI_MAX_TIMEOUT (3000)

struct stmsmi_flash_bank
{
struct stmsmi_flash_bank {
int probed;
uint32_t io_base;
uint32_t bank_num;
@@ -202,16 +201,13 @@ FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command)
{
struct stmsmi_flash_bank *stmsmi_info;

LOG_DEBUG("%s", __FUNCTION__);
LOG_DEBUG("%s", __func__);

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}
return ERROR_COMMAND_SYNTAX_ERROR;

stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank));
if (stmsmi_info == NULL)
{
if (stmsmi_info == NULL) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
@@ -279,17 +275,17 @@ static int wait_till_ready(struct flash_bank *bank, int timeout)
int retval;
long long endtime;

endtime = timeval_ms() + timeout;
do {
/* read flash status register */
retval = read_status_reg(bank, &status);
if (retval != ERROR_OK)
return retval;
endtime = timeval_ms() + timeout;
do {
/* read flash status register */
retval = read_status_reg(bank, &status);
if (retval != ERROR_OK)
return retval;

if ((status & SMI_WIP_BIT) == 0)
return ERROR_OK;
alive_sleep(1);
} while (timeval_ms() < endtime);
} while (timeval_ms() < endtime);

LOG_ERROR("timeout");
return ERROR_FAIL;
@@ -324,8 +320,7 @@ static int smi_write_enable(struct flash_bank *bank)
return retval;

/* Check write enabled */
if ((status & SMI_WEL_BIT) == 0)
{
if ((status & SMI_WEL_BIT) == 0) {
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
return ERROR_FAIL;
}
@@ -391,37 +386,31 @@ static int stmsmi_erase(struct flash_bank *bank, int first, int last)
int retval = ERROR_OK;
int sector;

LOG_DEBUG("%s: from sector %d to sector %d", __FUNCTION__, first, last);
LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if ((first < 0) || (last < first) || (last >= bank->num_sectors))
{
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
LOG_ERROR("Flash sector invalid");
return ERROR_FLASH_SECTOR_INVALID;
}

if (!(stmsmi_info->probed))
{
if (!(stmsmi_info->probed)) {
LOG_ERROR("Flash bank not probed");
return ERROR_FLASH_BANK_NOT_PROBED;
}

for (sector = first; sector <= last; sector++)
{
if (bank->sectors[sector].is_protected)
{
for (sector = first; sector <= last; sector++) {
if (bank->sectors[sector].is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
}

for (sector = first; sector <= last; sector++)
{
for (sector = first; sector <= last; sector++) {
retval = smi_erase_sector(bank, sector);
if (retval != ERROR_OK)
break;
@@ -452,7 +441,7 @@ static int smi_write_buffer(struct flash_bank *bank, uint8_t *buffer,
int retval;

LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
__FUNCTION__, address, len);
__func__, address, len);

retval = smi_write_enable(bank);
if (retval != ERROR_OK)
@@ -479,30 +468,26 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,
int retval = ERROR_OK;

LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__FUNCTION__, offset, count);
__func__, offset, count);

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (offset + count > stmsmi_info->dev->size_in_bytes)
{
if (offset + count > stmsmi_info->dev->size_in_bytes) {
LOG_WARNING("Write pasts end of flash. Extra data discarded.");
count = stmsmi_info->dev->size_in_bytes - offset;
}

/* Check sector protection */
for (sector = 0; sector < bank->num_sectors; sector++)
{
for (sector = 0; sector < bank->num_sectors; sector++) {
/* Start offset in or before this sector? */
/* End offset in or behind this sector? */
if ( (offset <
if ((offset <
(bank->sectors[sector].offset + bank->sectors[sector].size))
&& ((offset + count - 1) >= bank->sectors[sector].offset)
&& bank->sectors[sector].is_protected )
{
&& bank->sectors[sector].is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
@@ -511,8 +496,7 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,
page_size = stmsmi_info->dev->pagesize;

/* unaligned buffer head */
if (count > 0 && (offset & 3) != 0)
{
if (count > 0 && (offset & 3) != 0) {
cur_count = 4 - (offset & 3);
if (cur_count > count)
cur_count = count;
@@ -527,8 +511,7 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,

page_offset = offset % page_size;
/* central part, aligned words */
while (count >= 4)
{
while (count >= 4) {
/* clip block at page boundary */
if (page_offset + count > page_size)
cur_count = page_size - page_offset;
@@ -567,8 +550,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id)
uint32_t io_base = stmsmi_info->io_base;
int retval;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -614,18 +596,16 @@ static int stmsmi_probe(struct flash_bank *bank)
free(bank->sectors);
stmsmi_info->probed = 0;

for (target_device=target_devices ; target_device->name ; ++target_device)
for (target_device = target_devices ; target_device->name ; ++target_device)
if (target_device->tap_idcode == target->tap->idcode)
break;
if (!target_device->name)
{
if (!target_device->name) {
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable",
target->tap->idcode);
return ERROR_FAIL;
}

switch (bank->base - target_device->smi_base)
{
switch (bank->base - target_device->smi_base) {
case 0:
stmsmi_info->bank_num = SMI_SEL_BANK0;
break;
@@ -661,8 +641,7 @@ static int stmsmi_probe(struct flash_bank *bank)
break;
}

if (!stmsmi_info->dev)
{
if (!stmsmi_info->dev) {
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
return ERROR_FAIL;
}
@@ -677,14 +656,12 @@ static int stmsmi_probe(struct flash_bank *bank)
bank->num_sectors =
stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
if (sectors == NULL)
{
if (sectors == NULL) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}

for (int sector = 0; sector < bank->num_sectors; sector++)
{
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * stmsmi_info->dev->sectorsize;
sectors[sector].size = stmsmi_info->dev->sectorsize;
sectors[sector].is_erased = -1;
@@ -714,8 +691,7 @@ static int get_stmsmi_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;

if (!(stmsmi_info->probed))
{
if (!(stmsmi_info->probed)) {
snprintf(buf, buf_size,
"\nSMI flash bank not probed yet\n");
return ERROR_OK;


+ 49
- 105
src/flash/nor/str7x.c View File

@@ -23,6 +23,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -32,7 +33,6 @@
#include <helper/binarybuffer.h>
#include <target/algorithm.h>


/* Flash registers */

#define FLASH_CR0 0x00000000
@@ -85,8 +85,7 @@
#define FLASH_ERR 0x00000001


struct str7x_flash_bank
{
struct str7x_flash_bank {
uint32_t *sector_bits;
uint32_t disable_bit;
uint32_t busy_bits;
@@ -100,8 +99,7 @@ struct str7x_mem_layout {
uint32_t sector_bit;
};

enum str7x_status_codes
{
enum str7x_status_codes {
STR7X_CMD_SUCCESS = 0,
STR7X_INVALID_COMMAND = 1,
STR7X_SRC_ADDR_ERROR = 2,
@@ -135,7 +133,7 @@ static struct str7x_mem_layout mem_layout_str7bank1[] = {
static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
{
struct str7x_flash_bank *str7x_info = bank->driver_priv;
return (str7x_info->register_base | reg);
return str7x_info->register_base | reg;
}

static int str7x_build_block_list(struct flash_bank *bank)
@@ -146,8 +144,7 @@ static int str7x_build_block_list(struct flash_bank *bank)
int num_sectors;
int b0_sectors = 0, b1_sectors = 0;

switch (bank->size)
{
switch (bank->size) {
case 16 * 1024:
b1_sectors = 2;
break;
@@ -173,8 +170,7 @@ static int str7x_build_block_list(struct flash_bank *bank)

num_sectors = 0;

for (i = 0; i < b0_sectors; i++)
{
for (i = 0; i < b0_sectors; i++) {
bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
bank->sectors[num_sectors].is_erased = -1;
@@ -185,8 +181,7 @@ static int str7x_build_block_list(struct flash_bank *bank)
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
}

for (i = 0; i < b1_sectors; i++)
{
for (i = 0; i < b1_sectors; i++) {
bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
bank->sectors[num_sectors].is_erased = -1;
@@ -207,9 +202,7 @@ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
struct str7x_flash_bank *str7x_info;

if (CMD_ARGC < 7)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

str7x_info = malloc(sizeof(struct str7x_flash_bank));
bank->driver_priv = str7x_info;
@@ -219,21 +212,14 @@ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
str7x_info->disable_bit = (1 << 1);

if (strcmp(CMD_ARGV[6], "STR71x") == 0)
{
str7x_info->register_base = 0x40100000;
}
else if (strcmp(CMD_ARGV[6], "STR73x") == 0)
{
else if (strcmp(CMD_ARGV[6], "STR73x") == 0) {
str7x_info->register_base = 0x80100000;
str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0);
}
else if (strcmp(CMD_ARGV[6], "STR75x") == 0)
{
} else if (strcmp(CMD_ARGV[6], "STR75x") == 0) {
str7x_info->register_base = 0x20100000;
str7x_info->disable_bit = (1 << 0);
}
else
{
} else {
LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]);
free(str7x_info);
return ERROR_FLASH_BANK_INVALID;
@@ -263,8 +249,7 @@ static int str7x_waitbusy(struct flash_bank *bank)
struct target *target = bank->target;
struct str7x_flash_bank *str7x_info = bank->driver_priv;

for (i = 0 ; i < 10000; i++)
{
for (i = 0 ; i < 10000; i++) {
uint32_t retval;
err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
if (err != ERROR_OK)
@@ -290,35 +275,28 @@ static int str7x_result(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;

if (flash_flags & FLASH_WPF)
{
if (flash_flags & FLASH_WPF) {
LOG_ERROR("str7x hw write protection set");
retval = ERROR_FAIL;
}
if (flash_flags & FLASH_RESER)
{
if (flash_flags & FLASH_RESER) {
LOG_ERROR("str7x suspended program erase not resumed");
retval = ERROR_FAIL;
}
if (flash_flags & FLASH_10ER)
{
if (flash_flags & FLASH_10ER) {
LOG_ERROR("str7x trying to set bit to 1 when it is already 0");
retval = ERROR_FAIL;
}
if (flash_flags & FLASH_PGER)
{
if (flash_flags & FLASH_PGER) {
LOG_ERROR("str7x program error");
retval = ERROR_FAIL;
}
if (flash_flags & FLASH_ERER)
{
if (flash_flags & FLASH_ERER) {
LOG_ERROR("str7x erase error");
retval = ERROR_FAIL;
}
if (retval == ERROR_OK)
{
if (flash_flags & FLASH_ERR)
{
if (retval == ERROR_OK) {
if (flash_flags & FLASH_ERR) {
/* this should always be set if one of the others are set... */
LOG_ERROR("str7x write operation failed / bad setup");
retval = ERROR_FAIL;
@@ -336,8 +314,7 @@ static int str7x_protect_check(struct flash_bank *bank)
int i;
uint32_t flash_flags;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -347,8 +324,7 @@ static int str7x_protect_check(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
if (flash_flags & str7x_info->sector_bits[i])
bank->sectors[i].is_protected = 0;
else
@@ -368,16 +344,13 @@ static int str7x_erase(struct flash_bank *bank, int first, int last)
uint32_t sectors = 0;
int err;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

for (i = first; i <= last; i++)
{
sectors |= str7x_info->sector_bits[i];
}

LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);

@@ -423,16 +396,14 @@ static int str7x_protect(struct flash_bank *bank, int set, int first, int last)
uint32_t cmd;
uint32_t protect_blocks;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

protect_blocks = 0xFFFFFFFF;

if (set)
{
if (set) {
for (i = first; i <= last; i++)
protect_blocks &= ~(str7x_info->sector_bits[i]);
}
@@ -499,7 +470,7 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
0xe582400c, /* str r4, [r2, #0xc] */
0xe3a04209, /* mov r4, #0x90000000 */
0xe5824000, /* str r4, [r2, #0x0] */
/* busy: */
/* busy: */
0xe5924000, /* ldr r4, [r2, #0x0] */
0xe1140005, /* tst r4, r5 */
0x1afffffc, /* bne busy */
@@ -516,21 +487,18 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,

/* flash write code */
if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code),
&str7x_info->write_algorithm) != ERROR_OK)
{
&str7x_info->write_algorithm) != ERROR_OK) {
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};

target_write_buffer(target, str7x_info->write_algorithm->address,
sizeof(str7x_flash_write_code),
(uint8_t*)str7x_flash_write_code);
(uint8_t *)str7x_flash_write_code);

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= 256)
{
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
if (str7x_info->write_algorithm)
@@ -552,8 +520,7 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);

while (count > 0)
{
while (count > 0) {
uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;

target_write_buffer(target, source->address, thisrun_count * 8, buffer);
@@ -564,16 +531,14 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);

if ((retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
str7x_info->write_algorithm->address,
str7x_info->write_algorithm->address + (sizeof(str7x_flash_write_code) - 4),
10000, &armv4_5_info)) != ERROR_OK)
{
10000, &armv4_5_info);
if (retval != ERROR_OK)
break;
}

if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
{
if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00) {
retval = str7x_result(bank);
break;
}
@@ -609,26 +574,22 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t check_address = offset;
int i;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (offset & 0x7)
{
if (offset & 0x7) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
uint32_t sec_start = bank->sectors[i].offset;
uint32_t sec_end = sec_start + bank->sectors[i].size;

/* check if destination falls within the current sector */
if ((check_address >= sec_start) && (check_address < sec_end))
{
if ((check_address >= sec_start) && (check_address < sec_end)) {
/* check if destination ends in the current sector */
if (offset + count < sec_end)
check_address = offset + count;
@@ -644,32 +605,25 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);

/* multiple dwords (8-byte) to be programmed? */
if (dwords_remaining > 0)
{
if (dwords_remaining > 0) {
/* try using a block write */
if ((retval = str7x_write_block(bank, buffer, offset,
dwords_remaining)) != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
retval = str7x_write_block(bank, buffer, offset, dwords_remaining);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
} else
{
} else {
return retval;
}
}
else
{
} else {
buffer += dwords_remaining * 8;
address += dwords_remaining * 8;
dwords_remaining = 0;
}
}

while (dwords_remaining > 0)
{
while (dwords_remaining > 0) {
/* command */
cmd = FLASH_DWPG;
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
@@ -704,8 +658,7 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
address += 8;
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

/* copy the last remaining bytes into the write buffer */
@@ -777,9 +730,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
uint16_t ProtectionRegs;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -790,8 +741,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)

target = bank->target;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -801,30 +751,24 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), &reg);

if (!(reg & str7x_info->disable_bit))
{
ProtectionLevel = 1;
}

target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &reg);
ProtectionRegs = ~(reg >> 16);

while (((ProtectionRegs) != 0) && (ProtectionLevel < 16))
{
while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) {
ProtectionRegs >>= 1;
ProtectionLevel++;
}

if (ProtectionLevel == 0)
{
if (ProtectionLevel == 0) {
flash_cmd = FLASH_SPR;
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
flash_cmd = FLASH_SPR | FLASH_WMS;
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
}
else
{
} else {
flash_cmd = FLASH_SPR;
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);


+ 74
- 137
src/flash/nor/str9x.c View File

@@ -23,6 +23,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -31,7 +32,6 @@
#include <target/arm966e.h>
#include <target/algorithm.h>


/* Flash registers */

#define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */
@@ -42,17 +42,14 @@
#define FLASH_SR 0x5400001C /* Status Register */
#define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */


struct str9x_flash_bank
{
struct str9x_flash_bank {
uint32_t *sector_bits;
int variant;
int bank1;
struct working_area *write_algorithm;
};

enum str9x_status_codes
{
enum str9x_status_codes {
STR9X_CMD_SUCCESS = 0,
STR9X_INVALID_COMMAND = 1,
STR9X_SRC_ADDR_ERROR = 2,
@@ -82,8 +79,7 @@ static int str9x_build_block_list(struct flash_bank *bank)
str9x_info->variant = 0;
str9x_info->bank1 = 0;

switch (bank->size)
{
switch (bank->size) {
case (256 * 1024):
b0_sectors = 4;
break;
@@ -124,8 +120,7 @@ static int str9x_build_block_list(struct flash_bank *bank)

num_sectors = 0;

for (i = 0; i < b0_sectors; i++)
{
for (i = 0; i < b0_sectors; i++) {
bank->sectors[num_sectors].offset = offset;
bank->sectors[num_sectors].size = 0x10000;
offset += bank->sectors[i].size;
@@ -134,8 +129,7 @@ static int str9x_build_block_list(struct flash_bank *bank)
str9x_info->sector_bits[num_sectors++] = (1 << i);
}

for (i = 0; i < b1_sectors; i++)
{
for (i = 0; i < b1_sectors; i++) {
bank->sectors[num_sectors].offset = offset;
bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
offset += bank->sectors[i].size;
@@ -157,9 +151,7 @@ FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command)
struct str9x_flash_bank *str9x_info;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

str9x_info = malloc(sizeof(struct str9x_flash_bank));
bank->driver_priv = str9x_info;
@@ -182,64 +174,49 @@ static int str9x_protect_check(struct flash_bank *bank)
uint32_t status = 0;
uint16_t hstatus = 0;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

/* read level one protection */

if (str9x_info->variant)
{
if (str9x_info->bank1)
{
if (str9x_info->variant) {
if (str9x_info->bank1) {
adr = bank1start + 0x18;
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0x90);
if (retval != ERROR_OK)
return retval;
}
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
{
retval = target_read_u16(target, adr, &hstatus);
if (retval != ERROR_OK)
return retval;
}
status = hstatus;
}
else
{
} else {
adr = bank1start + 0x14;
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0x90);
if (retval != ERROR_OK)
return retval;
}
if ((retval = target_read_u32(target, adr, &status)) != ERROR_OK)
{
retval = target_read_u32(target, adr, &status);
if (retval != ERROR_OK)
return retval;
}
}
}
else
{
} else {
adr = bank1start + 0x10;
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0x90);
if (retval != ERROR_OK)
return retval;
}
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
{
retval = target_read_u16(target, adr, &hstatus);
if (retval != ERROR_OK)
return retval;
}
status = hstatus;
}

/* read array command */
if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0xFF);
if (retval != ERROR_OK)
return retval;
}

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
if (status & str9x_info->sector_bits[i])
bank->sectors[i].is_protected = 1;
else
@@ -258,22 +235,18 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
uint8_t erase_cmd;
int total_timeout;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

/* Check if we can erase whole bank */
if ((first == 0) && (last == (bank->num_sectors - 1)))
{
if ((first == 0) && (last == (bank->num_sectors - 1))) {
/* Optimize to run erase bank command instead of sector */
erase_cmd = 0x80;
/* Add timeout duration since erase bank takes more time */
/* Add timeout duration since erase bank takes more time */
total_timeout = 1000 * bank->num_sectors;
}
else
{
} else {
/* Erase sector command */
erase_cmd = 0x20;
total_timeout = 1000;
@@ -282,58 +255,48 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
/* this is so the compiler can *know* */
assert(total_timeout > 0);

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
int retval;
adr = bank->base + bank->sectors[i].offset;

/* erase sectors or block */
if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK)
{
retval = target_write_u16(target, adr, erase_cmd);
if (retval != ERROR_OK)
return retval;
}
if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0xD0);
if (retval != ERROR_OK)
return retval;
}

/* get status */
if ((retval = target_write_u16(target, adr, 0x70)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0x70);
if (retval != ERROR_OK)
return retval;
}

int timeout;
for (timeout = 0; timeout < total_timeout; timeout++)
{
if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK)
{
for (timeout = 0; timeout < total_timeout; timeout++) {
retval = target_read_u8(target, adr, &status);
if (retval != ERROR_OK)
return retval;
}
if (status & 0x80)
break;
alive_sleep(1);
}
if (timeout == total_timeout)
{
if (timeout == total_timeout) {
LOG_ERROR("erase timed out");
return ERROR_FAIL;
}

/* clear status, also clear read array */
if ((retval = target_write_u16(target, adr, 0x50)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0x50);
if (retval != ERROR_OK)
return retval;
}

/* read array command */
if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
{
retval = target_write_u16(target, adr, 0xFF);
if (retval != ERROR_OK)
return retval;
}

if (status & 0x22)
{
if (status & 0x22) {
LOG_ERROR("error erasing flash bank, status: 0x%x", status);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -357,14 +320,12 @@ static int str9x_protect(struct flash_bank *bank,
uint32_t adr;
uint8_t status;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
/* Level One Protection */

adr = bank->base + bank->sectors[i].offset;
@@ -429,22 +390,19 @@ static int str9x_write_block(struct flash_bank *bank,

/* flash write code */
if (target_alloc_working_area(target, sizeof(str9x_flash_write_code),
&str9x_info->write_algorithm) != ERROR_OK)
{
&str9x_info->write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};

target_write_buffer(target, str9x_info->write_algorithm->address,
sizeof(str9x_flash_write_code),
(uint8_t*)str9x_flash_write_code);
(uint8_t *)str9x_flash_write_code);

/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
{
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= 256)
{
if (buffer_size <= 256) {
/* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
if (str9x_info->write_algorithm)
@@ -464,8 +422,7 @@ static int str9x_write_block(struct flash_bank *bank,
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);

while (count > 0)
{
while (count > 0) {
uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;

target_write_buffer(target, source->address, thisrun_count * 2, buffer);
@@ -474,17 +431,16 @@ static int str9x_write_block(struct flash_bank *bank,
buf_set_u32(reg_params[1].value, 0, 32, address);
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);

if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
str9x_info->write_algorithm->address,
0, 10000, &armv4_5_info)) != ERROR_OK)
{
0, 10000, &armv4_5_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing str9x flash write algorithm");
retval = ERROR_FLASH_OPERATION_FAILED;
break;
}

if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
{
if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80) {
retval = ERROR_FLASH_OPERATION_FAILED;
break;
}
@@ -519,26 +475,22 @@ static int str9x_write(struct flash_bank *bank,
uint32_t bank_adr;
int i;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (offset & 0x1)
{
if (offset & 0x1) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
uint32_t sec_start = bank->sectors[i].offset;
uint32_t sec_end = sec_start + bank->sectors[i].size;

/* check if destination falls within the current sector */
if ((check_address >= sec_start) && (check_address < sec_end))
{
if ((check_address >= sec_start) && (check_address < sec_end)) {
/* check if destination ends in the current sector */
if (offset + count < sec_end)
check_address = offset + count;
@@ -551,33 +503,26 @@ static int str9x_write(struct flash_bank *bank,
return ERROR_FLASH_DST_OUT_OF_BANK;

/* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0)
{
if (words_remaining > 0) {
/* try using a block write */
if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
retval = str9x_write_block(bank, buffer, offset, words_remaining);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
}
else if (retval == ERROR_FLASH_OPERATION_FAILED)
{
} else if (retval == ERROR_FLASH_OPERATION_FAILED) {
LOG_ERROR("flash writing failed");
return ERROR_FLASH_OPERATION_FAILED;
}
}
else
{
} else {
buffer += words_remaining * 2;
address += words_remaining * 2;
words_remaining = 0;
}
}

while (words_remaining > 0)
{
while (words_remaining > 0) {
bank_adr = address & ~0x03;

/* write data command */
@@ -588,15 +533,13 @@ static int str9x_write(struct flash_bank *bank,
target_write_u16(target, bank_adr, 0x70);

int timeout;
for (timeout = 0; timeout < 1000; timeout++)
{
for (timeout = 0; timeout < 1000; timeout++) {
target_read_u8(target, bank_adr, &status);
if (status & 0x80)
break;
alive_sleep(1);
}
if (timeout == 1000)
{
if (timeout == 1000) {
LOG_ERROR("write timed out");
return ERROR_FAIL;
}
@@ -615,8 +558,7 @@ static int str9x_write(struct flash_bank *bank,
address += 2;
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint8_t last_halfword[2] = {0xff, 0xff};

/* copy the last remaining bytes into the write buffer */
@@ -632,15 +574,13 @@ static int str9x_write(struct flash_bank *bank,
target_write_u16(target, bank_adr, 0x70);

int timeout;
for (timeout = 0; timeout < 1000; timeout++)
{
for (timeout = 0; timeout < 1000; timeout++) {
target_read_u8(target, bank_adr, &status);
if (status & 0x80)
break;
alive_sleep(1);
}
if (timeout == 1000)
{
if (timeout == 1000) {
LOG_ERROR("write timed out");
return ERROR_FAIL;
}
@@ -681,9 +621,7 @@ COMMAND_HANDLER(str9x_handle_flash_config_command)
struct target *target = NULL;

if (CMD_ARGC < 5)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -698,8 +636,7 @@ COMMAND_HANDLER(str9x_handle_flash_config_command)

target = bank->target;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}


+ 49
- 134
src/flash/nor/str9xpec.c View File

@@ -20,6 +20,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -27,7 +28,6 @@
#include "imp.h"
#include <target/arm7_9_common.h>


/* ISC commands */

#define ISC_IDCODE 0xFE
@@ -61,16 +61,14 @@
#define STR9XPEC_OPT_LVDWARNBIT 51
#define STR9XPEC_OPT_OTPBIT 63

enum str9xpec_status_codes
{
enum str9xpec_status_codes {
STR9XPEC_INVALID_COMMAND = 1,
STR9XPEC_ISC_SUCCESS = 2,
STR9XPEC_ISC_DISABLED = 3,
STR9XPEC_ISC_INTFAIL = 32,
};

struct str9xpec_flash_controller
{
struct str9xpec_flash_controller {
struct jtag_tap *tap;
uint32_t *sector_bits;
int chain_pos;
@@ -84,16 +82,14 @@ static int str9xpec_write_options(struct flash_bank *bank);

static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state)
{
if (tap == NULL) {
if (tap == NULL)
return ERROR_TARGET_INVALID;
}

if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
{
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
struct scan_field field;

field.num_bits = tap->ir_length;
void * t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
@@ -147,8 +143,7 @@ static int str9xpec_isc_enable(struct flash_bank *bank)

/* check ISC status */
status = str9xpec_isc_status(tap);
if (status & ISC_STATUS_MODE)
{
if (status & ISC_STATUS_MODE) {
/* we have entered isc mode */
str9xpec_info->isc_enable = 1;
LOG_DEBUG("ISC_MODE Enabled");
@@ -176,8 +171,7 @@ static int str9xpec_isc_disable(struct flash_bank *bank)

/* check ISC status */
status = str9xpec_isc_status(tap);
if (!(status & ISC_STATUS_MODE))
{
if (!(status & ISC_STATUS_MODE)) {
/* we have left isc mode */
str9xpec_info->isc_enable = 0;
LOG_DEBUG("ISC_MODE Disabled");
@@ -224,8 +218,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
uint32_t offset = 0;
int b1_size = 0x2000;

switch (bank->size)
{
switch (bank->size) {
case (256 * 1024):
b0_sectors = 4;
break;
@@ -258,8 +251,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)

num_sectors = 0;

for (i = 0; i < b0_sectors; i++)
{
for (i = 0; i < b0_sectors; i++) {
bank->sectors[num_sectors].offset = offset;
bank->sectors[num_sectors].size = 0x10000;
offset += bank->sectors[i].size;
@@ -268,8 +260,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
str9xpec_info->sector_bits[num_sectors++] = i;
}

for (i = 0; i < b1_sectors; i++)
{
for (i = 0; i < b1_sectors; i++) {
bank->sectors[num_sectors].offset = offset;
bank->sectors[num_sectors].size = b1_size;
offset += bank->sectors[i].size;
@@ -291,9 +282,7 @@ FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command)
struct arm_jtag *jtag_info = NULL;

if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller));
bank->driver_priv = str9xpec_info;
@@ -329,21 +318,18 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last)

tap = str9xpec_info->tap;

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank);
}

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
return ERROR_FLASH_OPERATION_FAILED;
}

buffer = calloc(DIV_ROUND_UP(64, 8), 1);

LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);

for (i = first; i <= last; i++) {
for (i = first; i <= last; i++)
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
}

/* execute ISC_BLANK_CHECK command */
str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE);
@@ -365,8 +351,7 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last)

status = str9xpec_isc_status(tap);

for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
bank->sectors[i].is_erased = 0;
else
@@ -391,8 +376,7 @@ static int str9xpec_protect_check(struct flash_bank *bank)

status = str9xpec_read_config(bank);

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
bank->sectors[i].is_protected = 1;
else
@@ -416,13 +400,11 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)

tap = str9xpec_info->tap;

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank);
}

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
return ISC_STATUS_ERROR;
}

buffer = calloc(DIV_ROUND_UP(64, 8), 1);

@@ -430,21 +412,14 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)

/* last bank: 0xFF signals a full erase (unlock complete device) */
/* last bank: 0xFE signals a option byte erase */
if (last == 0xFF)
{
for (i = 0; i < 64; i++) {
if (last == 0xFF) {
for (i = 0; i < 64; i++)
buf_set_u32(buffer, i, 1, 1);
}
}
else if (last == 0xFE)
{
} else if (last == 0xFE)
buf_set_u32(buffer, 49, 1, 1);
}
else
{
for (i = first; i <= last; i++) {
else {
for (i = first; i <= last; i++)
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
}
}

LOG_DEBUG("ISC_ERASE");
@@ -462,9 +437,8 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
jtag_add_sleep(10);

/* wait for erase completion */
while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) {
while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY))
alive_sleep(1);
}

free(buffer);

@@ -495,13 +469,11 @@ static int str9xpec_lock_device(struct flash_bank *bank)
str9xpec_info = bank->driver_priv;
tap = str9xpec_info->tap;

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank);
}

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
return ISC_STATUS_ERROR;
}

/* set security address */
str9xpec_set_address(bank, 0x80);
@@ -550,22 +522,15 @@ static int str9xpec_protect(struct flash_bank *bank, int set, int first, int las
LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last);

/* last bank: 0xFF signals a full device protect */
if (last == 0xFF)
{
if (last == 0xFF) {
if (set)
{
status = str9xpec_lock_device(bank);
}
else
{
else {
/* perform full erase to unlock device */
status = str9xpec_unlock_device(bank);
}
}
else
{
for (i = first; i <= last; i++)
{
} else {
for (i = first; i <= last; i++) {
if (set)
buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
else
@@ -619,28 +584,23 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,

tap = str9xpec_info->tap;

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank);
}

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
return ERROR_FLASH_OPERATION_FAILED;
}

if (offset & 0x7)
{
if (offset & 0x7) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}

for (i = 0; i < bank->num_sectors; i++)
{
for (i = 0; i < bank->num_sectors; i++) {
uint32_t sec_start = bank->sectors[i].offset;
uint32_t sec_end = sec_start + bank->sectors[i].size;

/* check if destination falls within the current sector */
if ((check_address >= sec_start) && (check_address < sec_end))
{
if ((check_address >= sec_start) && (check_address < sec_end)) {
/* check if destination ends in the current sector */
if (offset + count < sec_end)
check_address = offset + count;
@@ -648,13 +608,11 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
check_address = sec_end;
}

if ((offset >= sec_start) && (offset < sec_end)) {
if ((offset >= sec_start) && (offset < sec_end))
first_sector = i;
}

if ((offset + count >= sec_start) && (offset + count < sec_end)) {
if ((offset + count >= sec_start) && (offset + count < sec_end))
last_sector = i;
}
}

if (check_address != offset + count)
@@ -666,15 +624,13 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,

LOG_DEBUG("ISC_PROGRAM");

for (i = first_sector; i <= last_sector; i++)
{
for (i = first_sector; i <= last_sector; i++) {
str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);

dwords_remaining = dwords_remaining < (bank->sectors[i].size/8)
? dwords_remaining : (bank->sectors[i].size/8);

while (dwords_remaining > 0)
{
while (dwords_remaining > 0) {
str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);

field.num_bits = 64;
@@ -711,8 +667,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
}
}

if (bytes_remaining)
{
if (bytes_remaining) {
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

/* copy the last remaining bytes into the write buffer */
@@ -818,9 +773,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_read_command)
struct str9xpec_flash_controller *str9xpec_info = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -883,13 +836,11 @@ static int str9xpec_write_options(struct flash_bank *bank)
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
return status;

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank);
}

if (!str9xpec_info->isc_enable) {
if (!str9xpec_info->isc_enable)
return ISC_STATUS_ERROR;
}

/* according to data 64th bit has to be set */
buf_set_u32(str9xpec_info->options, 63, 1, 1);
@@ -931,9 +882,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
uint8_t status;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -957,9 +906,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
struct str9xpec_flash_controller *str9xpec_info = NULL;

if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -969,13 +916,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
str9xpec_info = bank->driver_priv;

if (strcmp(CMD_ARGV[1], "bank1") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
}
else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
}

return ERROR_OK;
}
@@ -985,9 +928,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
struct str9xpec_flash_controller *str9xpec_info = NULL;

if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -997,13 +938,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
str9xpec_info = bank->driver_priv;

if (strcmp(CMD_ARGV[1], "2.7v") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
}
else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
}

return ERROR_OK;
}
@@ -1013,9 +950,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
struct str9xpec_flash_controller *str9xpec_info = NULL;

if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1025,13 +960,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
str9xpec_info = bank->driver_priv;

if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
}
else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
}

return ERROR_OK;
}
@@ -1041,9 +972,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
struct str9xpec_flash_controller *str9xpec_info = NULL;

if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1053,13 +982,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
str9xpec_info = bank->driver_priv;

if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
}
else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
}

return ERROR_OK;
}
@@ -1069,9 +994,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_lock_command)
uint8_t status;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1091,9 +1014,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
uint8_t status;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1120,9 +1041,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
struct str9xpec_flash_controller *str9xpec_info = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1135,23 +1054,22 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)

/* remove arm core from chain - enter turbo mode */
tap1 = tap0->next_tap;
if (tap1 == NULL)
{
if (tap1 == NULL) {
/* things are *WRONG* */
command_print(CMD_CTX,"**STR9FLASH** (tap1) invalid chain?");
command_print(CMD_CTX, "**STR9FLASH** (tap1) invalid chain?");
return ERROR_OK;
}
tap2 = tap1->next_tap;
if (tap2 == NULL)
{
if (tap2 == NULL) {
/* things are *WRONG* */
command_print(CMD_CTX,"**STR9FLASH** (tap2) invalid chain?");
command_print(CMD_CTX, "**STR9FLASH** (tap2) invalid chain?");
return ERROR_OK;
}

/* enable turbo mode - TURBO-PROG-ENABLE */
str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
if ((retval = jtag_execute_queue()) != ERROR_OK)
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;

/* modify scan chain - str9 core has been removed */
@@ -1166,9 +1084,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
struct str9xpec_flash_controller *str9xpec_info = NULL;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1187,9 +1103,8 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
jtag_execute_queue();

/* restore previous scan chain */
if (tap->next_tap) {
if (tap->next_tap)
tap->next_tap->enabled = 1;
}

return ERROR_OK;
}


+ 144
- 213
src/flash/nor/tcl.c View File

@@ -32,7 +32,7 @@
*/

COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
struct flash_bank **bank)
struct flash_bank **bank)
{
const char *name = CMD_ARGV[name_index];
int retval = get_flash_bank_by_name(name, bank);
@@ -47,7 +47,6 @@ COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
return get_flash_bank_by_num(bank_num, bank);
}


COMMAND_HANDLER(handle_flash_info_command)
{
struct flash_bank *p;
@@ -61,12 +60,12 @@ COMMAND_HANDLER(handle_flash_info_command)
if (retval != ERROR_OK)
return retval;

if (p != NULL)
{
if (p != NULL) {
char buf[1024];

/* attempt auto probe */
if ((retval = p->driver->auto_probe(p)) != ERROR_OK)
retval = p->driver->auto_probe(p);
if (retval != ERROR_OK)
return retval;

/* We must query the hardware to avoid printing stale information! */
@@ -75,15 +74,15 @@ COMMAND_HANDLER(handle_flash_info_command)
return retval;

command_print(CMD_CTX,
"#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", buswidth %i, chipwidth %i",
p->bank_number,
p->driver->name,
p->base,
p->size,
p->bus_width,
p->chip_width);
for (j = 0; j < p->num_sectors; j++)
{
"#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32
", buswidth %i, chipwidth %i",
p->bank_number,
p->driver->name,
p->base,
p->size,
p->bus_width,
p->chip_width);
for (j = 0; j < p->num_sectors; j++) {
char *protect_state;

if (p->sectors[j].is_protected == 0)
@@ -94,15 +93,16 @@ COMMAND_HANDLER(handle_flash_info_command)
protect_state = "protection state unknown";

command_print(CMD_CTX,
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
j,
p->sectors[j].offset,
p->sectors[j].size,
p->sectors[j].size >> 10,
protect_state);
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
j,
p->sectors[j].offset,
p->sectors[j].size,
p->sectors[j].size >> 10,
protect_state);
}

*buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
*buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver
*function fails */
retval = p->driver->info(p, buf, sizeof(buf));
command_print(CMD_CTX, "%s", buf);
if (retval != ERROR_OK)
@@ -118,23 +118,20 @@ COMMAND_HANDLER(handle_flash_probe_command)
int retval;

if (CMD_ARGC != 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
if (retval != ERROR_OK)
return retval;

if (p)
{
if ((retval = p->driver->probe(p)) == ERROR_OK)
{
command_print(CMD_CTX, "flash '%s' found at 0x%8.8" PRIx32, p->driver->name, p->base);
}
}
else
{
if (p) {
retval = p->driver->probe(p);
if (retval == ERROR_OK)
command_print(CMD_CTX,
"flash '%s' found at 0x%8.8" PRIx32,
p->driver->name,
p->base);
} else {
command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
retval = ERROR_FAIL;
}
@@ -145,9 +142,7 @@ COMMAND_HANDLER(handle_flash_probe_command)
COMMAND_HANDLER(handle_flash_erase_check_command)
{
if (CMD_ARGC != 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

struct flash_bank *p;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
@@ -155,18 +150,17 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
return retval;

int j;
if ((retval = p->driver->erase_check(p)) == ERROR_OK)
{
retval = p->driver->erase_check(p);
if (retval == ERROR_OK)
command_print(CMD_CTX, "successfully checked erase state");
}
else
{
command_print(CMD_CTX, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
CMD_ARGV[0], p->base);
else {
command_print(CMD_CTX,
"unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
CMD_ARGV[0],
p->base);
}

for (j = 0; j < p->num_sectors; j++)
{
for (j = 0; j < p->num_sectors; j++) {
char *erase_state;

if (p->sectors[j].is_erased == 0)
@@ -177,12 +171,12 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
erase_state = "erase state unknown";

command_print(CMD_CTX,
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
j,
p->sectors[j].offset,
p->sectors[j].size,
p->sectors[j].size >> 10,
erase_state);
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
j,
p->sectors[j].offset,
p->sectors[j].size,
p->sectors[j].size >> 10,
erase_state);
}

return retval;
@@ -198,35 +192,27 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
bool do_unlock = false;
struct target *target = get_current_target(CMD_CTX);

while (CMD_ARGC >= 3)
{
while (CMD_ARGC >= 3) {
/* Optionally pad out the address range to block/sector
* boundaries. We can't know if there's data in that part
* of the flash; only do padding if we're told to.
*/
if (strcmp("pad", CMD_ARGV[0]) == 0)
{
do_pad = true;
} else if (strcmp("unlock", CMD_ARGV[0]) == 0)
{
else if (strcmp("unlock", CMD_ARGV[0]) == 0)
do_unlock = true;
} else
{
else
return ERROR_COMMAND_SYNTAX_ERROR;
}
CMD_ARGC--;
CMD_ARGV++;
}
if (CMD_ARGC != 2)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);

if (length <= 0)
{
if (length <= 0) {
command_print(CMD_CTX, "Length must be >0");
return ERROR_COMMAND_SYNTAX_ERROR;
}
@@ -235,44 +221,40 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
if (retval != ERROR_OK)
return retval;

/* We can't know if we did a resume + halt, in which case we no longer know the erased state */
/* We can't know if we did a resume + halt, in which case we no longer know the erased state
**/
flash_set_dirty();

struct duration bench;
duration_start(&bench);

if (do_unlock)
{
retval = flash_unlock_address_range(target, address, length);
}

if (retval == ERROR_OK)
{
retval = flash_erase_address_range(target, do_pad, address, length);
}

if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
{
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
command_print(CMD_CTX, "erased address 0x%8.8x (length %i)"
" in %fs (%0.3f KiB/s)", address, length,
duration_elapsed(&bench), duration_kbps(&bench, length));
" in %fs (%0.3f KiB/s)", address, length,
duration_elapsed(&bench), duration_kbps(&bench, length));
}

return retval;
}

static int flash_check_sector_parameters(struct command_context *cmd_ctx,
uint32_t first, uint32_t last, uint32_t num_sectors)
uint32_t first, uint32_t last, uint32_t num_sectors)
{
if (!(first <= last)) {
command_print(cmd_ctx, "ERROR: "
"first sector must be <= last sector");
"first sector must be <= last sector");
return ERROR_FAIL;
}

if (!(last <= (num_sectors - 1))) {
command_print(cmd_ctx, "ERROR: last sector must be <= %d",
(int) num_sectors - 1);
(int) num_sectors - 1);
return ERROR_FAIL;
}

@@ -300,8 +282,8 @@ COMMAND_HANDLER(handle_flash_erase_command)
else
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);

if ((retval = flash_check_sector_parameters(CMD_CTX,
first, last, p->num_sectors)) != ERROR_OK)
retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
if (retval != ERROR_OK)
return retval;

struct duration bench;
@@ -309,11 +291,10 @@ COMMAND_HANDLER(handle_flash_erase_command)

retval = flash_driver_erase(p, first, last);

if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
{
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
command_print(CMD_CTX, "erased sectors %" PRIu32 " "
"through %" PRIu32" on flash bank %" PRIu32 " "
"in %fs", first, last, p->bank_number, duration_elapsed(&bench));
"through %" PRIu32 " on flash bank %" PRIu32 " "
"in %fs", first, last, p->bank_number, duration_elapsed(&bench));
}

return ERROR_OK;
@@ -343,14 +324,14 @@ COMMAND_HANDLER(handle_flash_protect_command)
bool set;
COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);

if ((retval = flash_check_sector_parameters(CMD_CTX,
first, last, p->num_sectors)) != ERROR_OK)
retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
if (retval != ERROR_OK)
return retval;

retval = flash_driver_protect(p, set, first, last);
if (retval == ERROR_OK) {
command_print(CMD_CTX, "%s protection for sectors %i "
"through %i on flash bank %" PRIu32 "",
"through %i on flash bank %" PRIu32 "",
(set) ? "set" : "cleared", (int) first,
(int) last, p->bank_number);
}
@@ -368,41 +349,31 @@ COMMAND_HANDLER(handle_flash_write_image_command)
int retval;

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

/* flash auto-erase is disabled by default*/
int auto_erase = 0;
bool auto_unlock = false;

for (;;)
{
if (strcmp(CMD_ARGV[0], "erase") == 0)
{
for (;; ) {
if (strcmp(CMD_ARGV[0], "erase") == 0) {
auto_erase = 1;
CMD_ARGV++;
CMD_ARGC--;
command_print(CMD_CTX, "auto erase enabled");
} else if (strcmp(CMD_ARGV[0], "unlock") == 0)
{
} else if (strcmp(CMD_ARGV[0], "unlock") == 0) {
auto_unlock = true;
CMD_ARGV++;
CMD_ARGC--;
command_print(CMD_CTX, "auto unlock enabled");
} else
{
break;
}
}

if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

if (!target)
{
if (!target) {
LOG_ERROR("no target selected");
return ERROR_FAIL;
}
@@ -410,13 +381,10 @@ COMMAND_HANDLER(handle_flash_write_image_command)
struct duration bench;
duration_start(&bench);

if (CMD_ARGC >= 2)
{
if (CMD_ARGC >= 2) {
image.base_address_set = 1;
COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
}
else
{
} else {
image.base_address_set = 0;
image.base_address = 0x0;
}
@@ -425,22 +393,18 @@ COMMAND_HANDLER(handle_flash_write_image_command)

retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
if (retval != ERROR_OK)
{
return retval;
}

retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
image_close(&image);
return retval;
}

if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
{
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
"in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
duration_elapsed(&bench), duration_kbps(&bench, written));
"in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
duration_elapsed(&bench), duration_kbps(&bench, written));
}

image_close(&image);
@@ -468,20 +432,17 @@ COMMAND_HANDLER(handle_flash_fill_command)
return ERROR_FAIL;

uint8_t *readback = malloc(chunksize);
if (readback == NULL)
{
if (readback == NULL) {
free(chunk);
return ERROR_FAIL;
}


if (CMD_ARGC != 3)
{
if (CMD_ARGC != 3) {
retval = ERROR_COMMAND_SYNTAX_ERROR;
goto done;
}


COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
@@ -489,88 +450,79 @@ COMMAND_HANDLER(handle_flash_fill_command)
if (count == 0)
goto done;

switch (CMD_NAME[4])
{
case 'w':
wordsize = 4;
break;
case 'h':
wordsize = 2;
break;
case 'b':
wordsize = 1;
break;
default:
retval = ERROR_COMMAND_SYNTAX_ERROR;
goto done;
switch (CMD_NAME[4]) {
case 'w':
wordsize = 4;
break;
case 'h':
wordsize = 2;
break;
case 'b':
wordsize = 1;
break;
default:
retval = ERROR_COMMAND_SYNTAX_ERROR;
goto done;
}

chunk_count = MIN(count, (chunksize / wordsize));
switch (wordsize)
{
case 4:
for (i = 0; i < chunk_count; i++)
{
target_buffer_set_u32(target, chunk + i * wordsize, pattern);
}
break;
case 2:
for (i = 0; i < chunk_count; i++)
{
target_buffer_set_u16(target, chunk + i * wordsize, pattern);
}
break;
case 1:
memset(chunk, pattern, chunk_count);
break;
default:
LOG_ERROR("BUG: can't happen");
exit(-1);
switch (wordsize) {
case 4:
for (i = 0; i < chunk_count; i++)
target_buffer_set_u32(target, chunk + i * wordsize, pattern);
break;
case 2:
for (i = 0; i < chunk_count; i++)
target_buffer_set_u16(target, chunk + i * wordsize, pattern);
break;
case 1:
memset(chunk, pattern, chunk_count);
break;
default:
LOG_ERROR("BUG: can't happen");
exit(-1);
}

struct duration bench;
duration_start(&bench);

for (wrote = 0; wrote < (count*wordsize); wrote += cur_size)
{
for (wrote = 0; wrote < (count*wordsize); wrote += cur_size) {
struct flash_bank *bank;

retval = get_flash_bank_by_addr(target, address, true, &bank );
retval = get_flash_bank_by_addr(target, address, true, &bank);
if (retval != ERROR_OK)
goto done;

cur_size = MIN((count * wordsize - wrote), chunksize);
err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size);
if (err != ERROR_OK)
{
if (err != ERROR_OK) {
retval = err;
goto done;
}

err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size);
if (err != ERROR_OK)
{
if (err != ERROR_OK) {
retval = err;
goto done;
}

for (i = 0; i < cur_size; i++)
{
if (readback[i]!=chunk[i])
{
LOG_ERROR("Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
address + wrote + i, readback[i], chunk[i]);
for (i = 0; i < cur_size; i++) {
if (readback[i] != chunk[i]) {
LOG_ERROR(
"Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
address + wrote + i,
readback[i],
chunk[i]);
retval = ERROR_FAIL;
goto done;
}
}
}

if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK))
{
if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) {
command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)", wrote, address,
duration_elapsed(&bench), duration_kbps(&bench, wrote));
" in %fs (%0.3f KiB/s)", wrote, address,
duration_elapsed(&bench), duration_kbps(&bench, wrote));
}

done:
@@ -600,28 +552,23 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);

if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
{
return ERROR_OK;
}

int filesize;
retval = fileio_size(&fileio, &filesize);
if (retval != ERROR_OK)
{
if (retval != ERROR_OK) {
fileio_close(&fileio);
return retval;
}

buffer = malloc(filesize);
if (buffer == NULL)
{
if (buffer == NULL) {
fileio_close(&fileio);
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
size_t buf_cnt;
if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK)
{
if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) {
free(buffer);
fileio_close(&fileio);
return ERROR_OK;
@@ -632,12 +579,11 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
free(buffer);
buffer = NULL;

if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
{
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u"
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
(long)filesize, CMD_ARGV[1], p->bank_number, offset,
duration_elapsed(&bench), duration_kbps(&bench, filesize));
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
(long)filesize, CMD_ARGV[1], p->bank_number, offset,
duration_elapsed(&bench), duration_kbps(&bench, filesize));
}

fileio_close(&fileio);
@@ -651,12 +597,9 @@ void flash_set_dirty(void)
int i;

/* set all flash to require erasing */
for (c = flash_bank_list(); c; c = c->next)
{
for (c = flash_bank_list(); c; c = c->next) {
for (i = 0; i < c->num_sectors; i++)
{
c->sectors[i].is_erased = 0;
}
}
}

@@ -770,49 +713,43 @@ static int flash_init_drivers(struct command_context *cmd_ctx)

COMMAND_HANDLER(handle_flash_bank_command)
{
if (CMD_ARGC < 7)
{
if (CMD_ARGC < 7) {
LOG_ERROR("usage: flash bank <name> <driver> "
"<base> <size> <chip_width> <bus_width> <target>");
"<base> <size> <chip_width> <bus_width> <target>");
return ERROR_COMMAND_SYNTAX_ERROR;
}
// save bank name and advance arguments for compatibility
/* save bank name and advance arguments for compatibility */
const char *bank_name = *CMD_ARGV++;
CMD_ARGC--;

struct target *target;
if ((target = get_target(CMD_ARGV[5])) == NULL)
{
struct target *target = get_target(CMD_ARGV[5]);
if (target == NULL) {
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
return ERROR_FAIL;
}

const char *driver_name = CMD_ARGV[0];
struct flash_driver *driver = flash_driver_find_by_name(driver_name);
if (NULL == driver)
{
if (NULL == driver) {
/* no matching flash driver found */
LOG_ERROR("flash driver '%s' not found", driver_name);
return ERROR_FAIL;
}

/* check the flash bank name is unique */
if (get_flash_bank_by_name_noprobe(bank_name) != NULL)
{
if (get_flash_bank_by_name_noprobe(bank_name) != NULL) {
/* flash bank name already exists */
LOG_ERROR("flash bank name '%s' already exists", bank_name);
return ERROR_FAIL;
}

/* register flash specific commands */
if (NULL != driver->commands)
{
if (NULL != driver->commands) {
int retval = register_commands(CMD_CTX, NULL,
driver->commands);
if (ERROR_OK != retval)
{
if (ERROR_OK != retval) {
LOG_ERROR("couldn't register '%s' commands",
driver_name);
driver_name);
return ERROR_FAIL;
}
}
@@ -832,10 +769,9 @@ COMMAND_HANDLER(handle_flash_bank_command)

int retval;
retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
if (ERROR_OK != retval)
{
if (ERROR_OK != retval) {
LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "Usage %s",
driver_name, c->base, driver->usage);
driver_name, c->base, driver->usage);
free(c);
return retval;
}
@@ -854,8 +790,7 @@ COMMAND_HANDLER(handle_flash_banks_command)
return ERROR_COMMAND_SYNTAX_ERROR;

unsigned n = 0;
for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++)
{
for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) {
LOG_USER("#%" PRIu32 " : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
"buswidth %u, chipwidth %u", p->bank_number,
p->name, p->driver->name, p->base, p->size,
@@ -864,19 +799,17 @@ COMMAND_HANDLER(handle_flash_banks_command)
return ERROR_OK;
}

static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{
if (argc != 1)
{
if (argc != 1) {
Jim_WrongNumArgs(interp, 1, argv,
"no arguments to 'flash list' command");
"no arguments to 'flash list' command");
return JIM_ERR;
}

Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);

for (struct flash_bank *p = flash_bank_list(); p; p = p->next)
{
for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);

Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
@@ -898,15 +831,13 @@ static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}


COMMAND_HANDLER(handle_flash_init_command)
{
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;

static bool flash_initialized = false;
if (flash_initialized)
{
static bool flash_initialized;
if (flash_initialized) {
LOG_INFO("'flash init' has already been called");
return ERROR_OK;
}


+ 207
- 307
src/flash/nor/tms470.c View File

@@ -17,19 +17,18 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "imp.h"


/* ----------------------------------------------------------------------
Internal Support, Helpers
---------------------------------------------------------------------- */
* Internal Support, Helpers
* ---------------------------------------------------------------------- */

struct tms470_flash_bank
{
struct tms470_flash_bank {
unsigned ordinal;

/* device identification register */
@@ -38,7 +37,7 @@ struct tms470_flash_bank
uint32_t technology_family;
uint32_t rom_flash;
uint32_t part_number;
const char * part_name;
const char *part_name;

};

@@ -134,15 +133,14 @@ static int tms470_read_part_info(struct flash_bank *bank)
/* we shall not rely on the caller in this test, this function allocates memory,
thus and executing the code more than once may cause memory leak */
if (tms470_info->device_ident_reg)
return ERROR_OK;
return ERROR_OK;

/* read and parse the device identification register */
target_read_u32(target, 0xFFFFFFF0, &device_ident_reg);

LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg);

if ((device_ident_reg & 7) == 0)
{
if ((device_ident_reg & 7) == 0) {
LOG_WARNING("Cannot identify target as a TMS470 family.");
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -152,8 +150,7 @@ static int tms470_read_part_info(struct flash_bank *bank)
rom_flash = (device_ident_reg >> 10) & 1;
part_number = (device_ident_reg >> 3) & 0x7f;

if (bank->sectors)
{
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
@@ -164,116 +161,100 @@ static int tms470_read_part_info(struct flash_bank *bank)
* ranges. Then fixup/complete the remaining fields of the flash
* bank structure.
*/
switch (part_number)
{
case 0x0a:
part_name = "TMS470R1A256";

if (bank->base >= 0x00040000)
{
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED;
}
tms470_info->ordinal = 0;
bank->base = 0x00000000;
bank->size = 256 * 1024;
bank->num_sectors = TMS470R1A256_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED;
}
(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
break;

case 0x2b:
part_name = "TMS470R1A288";

if (bank->base < 0x00008000)
{
tms470_info->ordinal = 0;
bank->base = 0x00000000;
bank->size = 32 * 1024;
bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED;
}
(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS, sizeof(TMS470R1A288_BANK0_SECTORS));
}
else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000))
{
tms470_info->ordinal = 1;
bank->base = 0x00040000;
bank->size = 256 * 1024;
bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
if (!bank->sectors)
{
switch (part_number) {
case 0x0a:
part_name = "TMS470R1A256";

if (bank->base >= 0x00040000) {
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
part_name,
bank->base);
return ERROR_FLASH_OPERATION_FAILED;
}
(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, sizeof(TMS470R1A288_BANK1_SECTORS));
}
else
{
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED;
}
break;

case 0x2d:
part_name = "TMS470R1A384";

if (bank->base < 0x00020000)
{
tms470_info->ordinal = 0;
bank->base = 0x00000000;
bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
bank->size = 256 * 1024;
bank->num_sectors = TMS470R1A256_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED;
}
(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS, sizeof(TMS470R1A384_BANK0_SECTORS));
}
else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000))
{
tms470_info->ordinal = 1;
bank->base = 0x00020000;
bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
if (!bank->sectors)
{
(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
break;

case 0x2b:
part_name = "TMS470R1A288";

if (bank->base < 0x00008000) {
tms470_info->ordinal = 0;
bank->base = 0x00000000;
bank->size = 32 * 1024;
bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
if (!bank->sectors)
return ERROR_FLASH_OPERATION_FAILED;
(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS,
sizeof(TMS470R1A288_BANK0_SECTORS));
} else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
tms470_info->ordinal = 1;
bank->base = 0x00040000;
bank->size = 256 * 1024;
bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
if (!bank->sectors)
return ERROR_FLASH_OPERATION_FAILED;
(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS,
sizeof(TMS470R1A288_BANK1_SECTORS));
} else {
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED;
}
(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS, sizeof(TMS470R1A384_BANK1_SECTORS));
}
else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000))
{
tms470_info->ordinal = 2;
bank->base = 0x00040000;
bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
if (!bank->sectors)
{
break;

case 0x2d:
part_name = "TMS470R1A384";

if (bank->base < 0x00020000) {
tms470_info->ordinal = 0;
bank->base = 0x00000000;
bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
if (!bank->sectors)
return ERROR_FLASH_OPERATION_FAILED;
(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS,
sizeof(TMS470R1A384_BANK0_SECTORS));
} else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
tms470_info->ordinal = 1;
bank->base = 0x00020000;
bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
if (!bank->sectors)
return ERROR_FLASH_OPERATION_FAILED;
(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS,
sizeof(TMS470R1A384_BANK1_SECTORS));
} else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
tms470_info->ordinal = 2;
bank->base = 0x00040000;
bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
if (!bank->sectors)
return ERROR_FLASH_OPERATION_FAILED;
(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS,
sizeof(TMS470R1A384_BANK2_SECTORS));
} else {
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED;
}
(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, sizeof(TMS470R1A384_BANK2_SECTORS));
}
else
{
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED;
}
break;
break;

default:
LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", (unsigned)part_number);
return ERROR_FLASH_OPERATION_FAILED;
default:
LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.",
(unsigned)part_number);
return ERROR_FLASH_OPERATION_FAILED;
}

/* turn off memory selects */
@@ -284,10 +265,10 @@ static int tms470_read_part_info(struct flash_bank *bank)
bank->bus_width = 32;

LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.",
part_name,
(int)(silicon_version),
(technology_family ? "1.8v" : "3.3v"),
(rom_flash ? "rom" : "flash"));
part_name,
(int)(silicon_version),
(technology_family ? "1.8v" : "3.3v"),
(rom_flash ? "rom" : "flash"));

tms470_info->device_ident_reg = device_ident_reg;
tms470_info->silicon_version = silicon_version;
@@ -306,67 +287,57 @@ static int tms470_read_part_info(struct flash_bank *bank)

/* ---------------------------------------------------------------------- */

static uint32_t keysSet = 0;
static uint32_t keysSet;
static uint32_t flashKeys[4];

COMMAND_HANDLER(tms470_handle_flash_keyset_command)
{
if (CMD_ARGC > 4)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}
else if (CMD_ARGC == 4)
{
else if (CMD_ARGC == 4) {
int i;

for (i = 0; i < 4; i++)
{
for (i = 0; i < 4; i++) {
int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;

if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i]))
{
command_print(CMD_CTX, "could not process flash key %s", CMD_ARGV[i]);
if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) {
command_print(CMD_CTX, "could not process flash key %s",
CMD_ARGV[i]);
LOG_ERROR("could not process flash key %s", CMD_ARGV[i]);
return ERROR_COMMAND_SYNTAX_ERROR;
}
}

keysSet = 1;
}
else if (CMD_ARGC != 0)
{
} else if (CMD_ARGC != 0) {
command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
return ERROR_COMMAND_SYNTAX_ERROR;
}

if (keysSet)
{
command_print(CMD_CTX, "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3]);
}
else
{
if (keysSet) {
command_print(CMD_CTX,
"using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
flashKeys[0],
flashKeys[1],
flashKeys[2],
flashKeys[3]);
} else
command_print(CMD_CTX, "flash keys not set");
}

return ERROR_OK;
}

static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
};
0xFFFFFFFF, 0xFFFFFFFF,};

static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
0x00000000, 0x00000000,
};
0x00000000, 0x00000000,};

static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
0xf0fff0ff, 0xf0fff0ff
};
0xf0fff0ff, 0xf0fff0ff};

static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
0x0000ffff, 0x0000ffff
};
0x0000ffff, 0x0000ffff};

/* ---------------------------------------------------------------------- */

@@ -375,16 +346,11 @@ static int oscMHz = 12;
COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
{
if (CMD_ARGC > 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}
else if (CMD_ARGC == 1)
{
sscanf(CMD_ARGV[0], "%d", &oscMHz);
}

if (oscMHz <= 0)
{
if (oscMHz <= 0) {
LOG_ERROR("osc_megahertz must be positive and non-zero!");
command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!");
oscMHz = 12;
@@ -398,16 +364,13 @@ COMMAND_HANDLER(tms470_handle_osc_megahertz_command)

/* ---------------------------------------------------------------------- */

static int plldis = 0;
static int plldis;

COMMAND_HANDLER(tms470_handle_plldis_command)
{
if (CMD_ARGC > 1)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}
else if (CMD_ARGC == 1)
{
else if (CMD_ARGC == 1) {
sscanf(CMD_ARGV[0], "%d", &plldis);
plldis = plldis ? 1 : 0;
}
@@ -419,18 +382,20 @@ COMMAND_HANDLER(tms470_handle_plldis_command)

/* ---------------------------------------------------------------------- */

static int tms470_check_flash_unlocked(struct target * target)
static int tms470_check_flash_unlocked(struct target *target)
{
uint32_t fmbbusy;

target_read_u32(target, 0xFFE89C08, &fmbbusy);
LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s", fmbbusy, fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s",
fmbbusy,
fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
}

/* ---------------------------------------------------------------------- */

static int tms470_try_flash_keys(struct target * target, const uint32_t * key_set)
static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set)
{
uint32_t glbctrl, fmmstat;
int retval = ERROR_FLASH_OPERATION_FAILED;
@@ -441,20 +406,17 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se

/* only perform the key match when 3VSTAT is clear */
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
if (!(fmmstat & 0x08))
{
if (!(fmmstat & 0x08)) {
unsigned i;
uint32_t fmbptr, fmbac2, orig_fmregopt;

target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);

/* wait for pump ready */
do
{
do {
target_read_u32(target, 0xFFE8A814, &fmbptr);
alive_sleep(1);
}
while (!(fmbptr & 0x0200));
} while (!(fmbptr & 0x0200));

/* force max wait states */
target_read_u32(target, 0xFFE88004, &fmbac2);
@@ -464,8 +426,7 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se
target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
target_write_u32(target, 0xFFE89C00, 0x00);

for (i = 0; i < 4; i++)
{
for (i = 0; i < 4; i++) {
uint32_t tmp;

/* There is no point displaying the value of tmp, it is
@@ -478,15 +439,13 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se
target_write_u32(target, 0xFFE89C0C, key_set[i]);
}

if (ERROR_OK == tms470_check_flash_unlocked(target))
{
if (ERROR_OK == tms470_check_flash_unlocked(target)) {
/*
* There seems to be a side-effect of reading the FMPKEY
* register in that it re-enables the protection. So we
* re-enable it.
*/
for (i = 0; i < 4; i++)
{
for (i = 0; i < 4; i++) {
uint32_t tmp;

target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
@@ -514,17 +473,14 @@ static int tms470_unlock_flash(struct flash_bank *bank)
const uint32_t *p_key_sets[5];
unsigned i, key_set_count;

if (keysSet)
{
if (keysSet) {
key_set_count = 5;
p_key_sets[0] = flashKeys;
p_key_sets[1] = FLASH_KEYS_ALL_ONES;
p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
p_key_sets[3] = FLASH_KEYS_MIX1;
p_key_sets[4] = FLASH_KEYS_MIX2;
}
else
{
} else {
key_set_count = 4;
p_key_sets[0] = FLASH_KEYS_ALL_ONES;
p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
@@ -532,10 +488,8 @@ static int tms470_unlock_flash(struct flash_bank *bank)
p_key_sets[3] = FLASH_KEYS_MIX2;
}

for (i = 0; i < key_set_count; i++)
{
if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK)
{
for (i = 0; i < key_set_count; i++) {
if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) {
LOG_INFO("tms470 flash is unlocked");
return ERROR_OK;
}
@@ -594,14 +548,11 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban
* configure VHV
*/
target_read_u32(target, 0xFFE8A080, &fmmaxep);
if (fmmaxep == 0xf000)
{
if (fmmaxep == 0xf000) {
fmmaxep = 0xf000 + 4095;
target_write_u32(target, 0xFFE8A80C, 0x9964);
LOG_DEBUG("set fmptr3 = 0x9964");
}
else
{
} else {
fmmaxep = 0xa000 + 4095;
target_write_u32(target, 0xFFE8A80C, 0x9b64);
LOG_DEBUG("set fmptr3 = 0x9b64");
@@ -692,44 +643,37 @@ static int tms470_flash_status(struct flash_bank *bank)
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);

if (fmmstat & 0x0080)
{
if (fmmstat & 0x0080) {
LOG_WARNING("tms470 flash command: erase still active after busy clear.");
result = ERROR_FLASH_OPERATION_FAILED;
}

if (fmmstat & 0x0040)
{
if (fmmstat & 0x0040) {
LOG_WARNING("tms470 flash command: program still active after busy clear.");
result = ERROR_FLASH_OPERATION_FAILED;
}

if (fmmstat & 0x0020)
{
if (fmmstat & 0x0020) {
LOG_WARNING("tms470 flash command: invalid data command.");
result = ERROR_FLASH_OPERATION_FAILED;
}

if (fmmstat & 0x0010)
{
if (fmmstat & 0x0010) {
LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
result = ERROR_FLASH_OPERATION_FAILED;
}

if (fmmstat & 0x0008)
{
if (fmmstat & 0x0008) {
LOG_WARNING("tms470 flash command: voltage instability detected.");
result = ERROR_FLASH_OPERATION_FAILED;
}

if (fmmstat & 0x0006)
{
if (fmmstat & 0x0006) {
LOG_WARNING("tms470 flash command: command suspend detected.");
result = ERROR_FLASH_OPERATION_FAILED;
}

if (fmmstat & 0x0001)
{
if (fmmstat & 0x0001) {
LOG_WARNING("tms470 flash command: sector was locked.");
result = ERROR_FLASH_OPERATION_FAILED;
}
@@ -765,14 +709,11 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
* Select one or more bits in FMBSEA or FMBSEB to disable Level 1
* protection for the particular sector to be erased/written.
*/
if (sector < 16)
{
if (sector < 16) {
target_read_u32(target, 0xFFE88008, &fmbsea);
target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
}
else
{
} else {
target_read_u32(target, 0xFFE8800C, &fmbseb);
target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
@@ -793,26 +734,19 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
* Monitor FMMSTAT, busy until clear, then check and other flags for
* ultimate result of the operation.
*/
do
{
do {
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
if (fmmstat & 0x0100)
{
alive_sleep(1);
}
}
while (fmmstat & 0x0100);
} while (fmmstat & 0x0100);

result = tms470_flash_status(bank);

if (sector < 16)
{
if (sector < 16) {
target_write_u32(target, 0xFFE88008, fmbsea);
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
}
else
{
} else {
target_write_u32(target, 0xFFE8800C, fmbseb);
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
@@ -823,16 +757,14 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);

if (result == ERROR_OK)
{
bank->sectors[sector].is_erased = 1;
}

return result;
}

/* ----------------------------------------------------------------------
Implementation of Flash Driver Interfaces
---------------------------------------------------------------------- */
/*----------------------------------------------------------------------
* Implementation of Flash Driver Interfaces
*---------------------------------------------------------------------- */

static const struct command_registration tms470_any_command_handlers[] = {
{
@@ -876,41 +808,33 @@ static int tms470_erase(struct flash_bank *bank, int first, int last)
struct tms470_flash_bank *tms470_info = bank->driver_priv;
int sector, result = ERROR_OK;

if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

tms470_read_part_info(bank);

if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last))
{
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
(last >= bank->num_sectors) || (first > last)) {
LOG_ERROR("Sector range %d to %d invalid.", first, last);
return ERROR_FLASH_SECTOR_INVALID;
}

result = tms470_unlock_flash(bank);
if (result != ERROR_OK)
{
return result;
}

for (sector = first; sector <= last; sector++)
{
for (sector = first; sector <= last; sector++) {
LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector);

result = tms470_erase_sector(bank, sector);

if (result != ERROR_OK)
{
if (result != ERROR_OK) {
LOG_ERROR("tms470 could not erase flash sector.");
break;
}
else
{
} else
LOG_INFO("sector erased successfully.");
}
}

return result;
@@ -925,16 +849,15 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last)
uint32_t fmmac2, fmbsea, fmbseb;
int sector;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

tms470_read_part_info(bank);

if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last))
{
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
(last >= bank->num_sectors) || (first > last)) {
LOG_ERROR("Sector range %d to %d invalid.", first, last);
return ERROR_FLASH_SECTOR_INVALID;
}
@@ -947,16 +870,13 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last)
target_read_u32(target, 0xFFE88008, &fmbsea);
target_read_u32(target, 0xFFE8800C, &fmbseb);

for (sector = 0; sector < bank->num_sectors; sector++)
{
if (sector < 16)
{
for (sector = 0; sector < bank->num_sectors; sector++) {
if (sector < 16) {
fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
bank->sectors[sector].is_protected = set ? 1 : 0;
}
else
{
fmbseb = set ? fmbseb & ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
} else {
fmbseb = set ? fmbseb &
~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
bank->sectors[sector].is_protected = set ? 1 : 0;
}
}
@@ -970,22 +890,22 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last)

/* ---------------------------------------------------------------------- */

static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offset, uint32_t count)
static int tms470_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
int result = ERROR_OK;
uint32_t i;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

tms470_read_part_info(bank);

LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base + offset);
LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base +
offset);

/* set GLBCTRL.4 */
target_read_u32(target, 0xFFFFFFDC, &glbctrl);
@@ -1012,13 +932,11 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs
/* read MAXPP */
target_read_u32(target, 0xFFE8A07C, &fmmaxpp);

for (i = 0; i < count; i += 2)
{
for (i = 0; i < count; i += 2) {
uint32_t addr = bank->base + offset + i;
uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];

if (word != 0xffff)
{
if (word != 0xffff) {
LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);

/* clear status register */
@@ -1032,28 +950,23 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs
* Monitor FMMSTAT, busy until clear, then check and other flags
* for ultimate result of the operation.
*/
do
{
do {
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
if (fmmstat & 0x0100)
{
alive_sleep(1);
}
}
while (fmmstat & 0x0100);
} while (fmmstat & 0x0100);

if (fmmstat & 0x3ff)
{
if (fmmstat & 0x3ff) {
LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat);
LOG_ERROR("Could not program word 0x%04x at address 0x%08" PRIx32 ".", word, addr);
LOG_ERROR(
"Could not program word 0x%04x at address 0x%08" PRIx32 ".",
word,
addr);
result = ERROR_FLASH_OPERATION_FAILED;
break;
}
}
else
{
} else
LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
}
}

/* restore */
@@ -1070,8 +983,7 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs

static int tms470_probe(struct flash_bank *bank)
{
if (bank->target->state != TARGET_HALTED)
{
if (bank->target->state != TARGET_HALTED) {
LOG_WARNING("Cannot communicate... target not halted.");
return ERROR_TARGET_NOT_HALTED;
}
@@ -1098,16 +1010,13 @@ static int tms470_erase_check(struct flash_bank *bank)
uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt;
static uint8_t buffer[64 * 1024];

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (!tms470_info->device_ident_reg)
{
tms470_read_part_info(bank);
}

/* set GLBCTRL.4 */
target_read_u32(target, 0xFFFFFFDC, &glbctrl);
@@ -1136,10 +1045,8 @@ static int tms470_erase_check(struct flash_bank *bank)
* word at a time. Here we read an entire sector and inspect it in
* an attempt to reduce the JTAG overhead.
*/
for (sector = 0; sector < bank->num_sectors; sector++)
{
if (bank->sectors[sector].is_erased != 1)
{
for (sector = 0; sector < bank->num_sectors; sector++) {
if (bank->sectors[sector].is_erased != 1) {
uint32_t i, addr = bank->base + bank->sectors[sector].offset;

LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector);
@@ -1147,27 +1054,26 @@ static int tms470_erase_check(struct flash_bank *bank)
target_read_buffer(target, addr, bank->sectors[sector].size, buffer);

bank->sectors[sector].is_erased = 1;
for (i = 0; i < bank->sectors[sector].size; i++)
{
if (buffer[i] != 0xff)
{
LOG_WARNING("tms470 bank %d, sector %d, not erased.", tms470_info->ordinal, sector);
LOG_WARNING("at location 0x%08" PRIx32 ": flash data is 0x%02x.", addr + i, buffer[i]);
for (i = 0; i < bank->sectors[sector].size; i++) {
if (buffer[i] != 0xff) {
LOG_WARNING("tms470 bank %d, sector %d, not erased.",
tms470_info->ordinal,
sector);
LOG_WARNING(
"at location 0x%08" PRIx32 ": flash data is 0x%02x.",
addr + i,
buffer[i]);

bank->sectors[sector].is_erased = 0;
break;
}
}
}
if (bank->sectors[sector].is_erased != 1)
{
if (bank->sectors[sector].is_erased != 1) {
result = ERROR_FLASH_SECTOR_NOT_ERASED;
break;
}
else
{
} else
LOG_INFO("sector erased");
}
}

/* reset TEZ, wait states, read mode, GLBCTRL.4 */
@@ -1188,16 +1094,13 @@ static int tms470_protect_check(struct flash_bank *bank)
int sector, result = ERROR_OK;
uint32_t fmmac2, fmbsea, fmbseb;

if (target->state != TARGET_HALTED)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}

if (!tms470_info->device_ident_reg)
{
tms470_read_part_info(bank);
}

/* enable the appropriate bank */
target_read_u32(target, 0xFFE8BC04, &fmmac2);
@@ -1206,22 +1109,21 @@ static int tms470_protect_check(struct flash_bank *bank)
target_read_u32(target, 0xFFE88008, &fmbsea);
target_read_u32(target, 0xFFE8800C, &fmbseb);

for (sector = 0; sector < bank->num_sectors; sector++)
{
for (sector = 0; sector < bank->num_sectors; sector++) {
int protected;

if (sector < 16)
{
if (sector < 16) {
protected = fmbsea & (1 << sector) ? 0 : 1;
bank->sectors[sector].is_protected = protected;
}
else
{
} else {
protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
bank->sectors[sector].is_protected = protected;
}

LOG_DEBUG("bank %d sector %d is %s", tms470_info->ordinal, sector, protected ? "protected" : "not protected");
LOG_DEBUG("bank %d sector %d is %s",
tms470_info->ordinal,
sector,
protected ? "protected" : "not protected");
}

return result;
@@ -1235,21 +1137,21 @@ static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size)
struct tms470_flash_bank *tms470_info = bank->driver_priv;

if (!tms470_info->device_ident_reg)
{
tms470_read_part_info(bank);
}

if (!tms470_info->device_ident_reg)
{
if (!tms470_info->device_ident_reg) {
(void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
return ERROR_FLASH_OPERATION_FAILED;
}

used = snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n", tms470_info->part_name);
used =
snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n",
tms470_info->part_name);
buf += used;
buf_size -= used;

snprintf(buf, buf_size, "Flash protection level 2 is %s\n", tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");
snprintf(buf, buf_size, "Flash protection level 2 is %s\n",
tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");

return ERROR_OK;
}
@@ -1266,9 +1168,7 @@ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));

if (!bank->driver_priv)
{
return ERROR_FLASH_OPERATION_FAILED;
}

(void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));



+ 32
- 41
src/flash/nor/virtual.c View File

@@ -17,20 +17,20 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "imp.h"

static struct flash_bank* virtual_get_master_bank(struct flash_bank *bank)
static struct flash_bank *virtual_get_master_bank(struct flash_bank *bank)
{
struct flash_bank* master_bank;
struct flash_bank *master_bank;

master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv);
if (master_bank == NULL) {
LOG_ERROR("master flash bank '%s' does not exist", (char*)bank->driver_priv);
}
if (master_bank == NULL)
LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv);

return master_bank;
}
@@ -39,9 +39,8 @@ static void virtual_update_bank_info(struct flash_bank *bank)
{
struct flash_bank *master_bank = virtual_get_master_bank(bank);

if (master_bank == NULL) {
if (master_bank == NULL)
return;
}

/* update the info we do not have */
bank->size = master_bank->size;
@@ -54,16 +53,13 @@ static void virtual_update_bank_info(struct flash_bank *bank)
FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
{
if (CMD_ARGC < 7)
{
return ERROR_COMMAND_SYNTAX_ERROR;
}

/* get the master flash bank */
const char *bank_name = CMD_ARGV[6];
struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name);

if (master_bank == NULL)
{
if (master_bank == NULL) {
LOG_ERROR("master flash bank '%s' does not exist", bank_name);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -79,13 +75,12 @@ static int virtual_protect(struct flash_bank *bank, int set, int first, int last
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->protect(master_bank, set,
first, last)) != ERROR_OK)
retval = master_bank->driver->protect(master_bank, set, first, last);
if (retval != ERROR_OK)
return retval;

return ERROR_OK;
@@ -96,12 +91,12 @@ static int virtual_protect_check(struct flash_bank *bank)
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->protect_check(master_bank)) != ERROR_OK)
retval = master_bank->driver->protect_check(master_bank);
if (retval != ERROR_OK)
return retval;

return ERROR_OK;
@@ -112,13 +107,12 @@ static int virtual_erase(struct flash_bank *bank, int first, int last)
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->erase(master_bank,
first, last)) != ERROR_OK)
retval = master_bank->driver->erase(master_bank, first, last);
if (retval != ERROR_OK)
return retval;

return ERROR_OK;
@@ -130,13 +124,12 @@ static int virtual_write(struct flash_bank *bank, uint8_t *buffer,
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->write(master_bank, buffer,
offset, count)) != ERROR_OK)
retval = master_bank->driver->write(master_bank, buffer, offset, count);
if (retval != ERROR_OK)
return retval;

return ERROR_OK;
@@ -147,12 +140,12 @@ static int virtual_probe(struct flash_bank *bank)
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->probe(master_bank)) != ERROR_OK)
retval = master_bank->driver->probe(master_bank);
if (retval != ERROR_OK)
return retval;

/* update the info we do not have */
@@ -166,12 +159,12 @@ static int virtual_auto_probe(struct flash_bank *bank)
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->auto_probe(master_bank)) != ERROR_OK)
retval = master_bank->driver->auto_probe(master_bank);
if (retval != ERROR_OK)
return retval;

/* update the info we do not have */
@@ -184,9 +177,8 @@ static int virtual_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct flash_bank *master_bank = virtual_get_master_bank(bank);

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
bank->driver->name, master_bank->name, master_bank->base);
@@ -199,12 +191,12 @@ static int virtual_blank_check(struct flash_bank *bank)
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->erase_check(master_bank)) != ERROR_OK)
retval = master_bank->driver->erase_check(master_bank);
if (retval != ERROR_OK)
return retval;

return ERROR_OK;
@@ -216,13 +208,12 @@ static int virtual_flash_read(struct flash_bank *bank,
struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval;

if (master_bank == NULL) {
if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED;
}

/* call master handler */
if ((retval = master_bank->driver->read(master_bank, buffer,
offset, count)) != ERROR_OK)
retval = master_bank->driver->read(master_bank, buffer, offset, count);
if (retval != ERROR_OK)
return retval;

return ERROR_OK;


Loading…
Cancel
Save