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
__archive__
Spencer Oliver 2012-01-31 17:55:03 +00:00
parent fab0dcd7e6
commit 9f0cba528a
36 changed files with 4895 additions and 6560 deletions

View File

@ -29,7 +29,6 @@
#include <target/algorithm.h> #include <target/algorithm.h>
#include <target/arm.h> #include <target/arm.h>
static int aduc702x_build_sector_list(struct flash_bank *bank); 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); static int aduc702x_set_write_enable(struct target *target, int enable);
@ -57,7 +56,7 @@ FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
nbank = malloc(sizeof(struct aduc702x_flash_bank)); nbank = malloc(sizeof(struct aduc702x_flash_bank));
bank->base = 0x80000; bank->base = 0x80000;
bank->size = 0xF800; // top 4k not accessible bank->size = 0xF800; /* top 4k not accessible */
bank->driver_priv = nbank; bank->driver_priv = nbank;
aduc702x_build_sector_list(bank); aduc702x_build_sector_list(bank);
@ -67,16 +66,15 @@ FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
static int aduc702x_build_sector_list(struct flash_bank *bank) static int aduc702x_build_sector_list(struct flash_bank *bank)
{ {
//aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; /* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */
int i = 0; int i = 0;
uint32_t offset = 0; uint32_t offset = 0;
// sector size is 512 /* sector size is 512 */
bank->num_sectors = bank->size / 512; bank->num_sectors = bank->size / 512;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); 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].offset = offset;
bank->sectors[i].size = 512; bank->sectors[i].size = 512;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
@ -95,10 +93,10 @@ static int aduc702x_protect_check(struct flash_bank *bank)
static int aduc702x_erase(struct flash_bank *bank, int first, int last) static int aduc702x_erase(struct flash_bank *bank, int first, int last)
{ {
//int res; /* int res; */
int x; int x;
int count; int count;
//uint32_t v; /* uint32_t v; */
struct target *target = bank->target; struct target *target = bank->target;
aduc702x_set_write_enable(target, 1); aduc702x_set_write_enable(target, 1);
@ -110,8 +108,7 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06); 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"); LOG_ERROR("mass erase failed");
aduc702x_set_write_enable(target, 0); aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
@ -123,15 +120,13 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
unsigned long adr; unsigned long adr;
count = last - first + 1; count = last - first + 1;
for (x = 0; x < count; ++x) for (x = 0; x < count; ++x) {
{
adr = bank->base + ((first + x) * 512); adr = bank->base + ((first + x) * 512);
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05); target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) {
{
LOG_ERROR("failed to erase sector at address 0x%08lX", adr); LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
aduc702x_set_write_enable(target, 0); aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_SECTOR_NOT_ERASED; return ERROR_FLASH_SECTOR_NOT_ERASED;
@ -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 * 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 aduc702x_flash_bank *aduc702x_info = bank->driver_priv;
struct target *target = bank->target; struct target *target = bank->target;
@ -168,8 +166,7 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
struct arm_algorithm armv4_5_info; struct arm_algorithm armv4_5_info;
int retval = ERROR_OK; 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"); LOG_ERROR("write block must be multiple of two bytes in offset & length");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -189,50 +186,46 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
*/ */
static const uint32_t aduc702x_flash_write_code[] = { static const uint32_t aduc702x_flash_write_code[] = {
//<_start>: /* <_start>: */
0xe3a05008, // mov r5, #8 ; 0x8 0xe3a05008, /* mov r5, #8 ; 0x8 */
0xe5845004, // str r5, [r4, #4] 0xe5845004, /* str r5, [r4, #4] */
0xe3a06002, // mov r6, #2 ; 0x2 0xe3a06002, /* mov r6, #2 ; 0x2 */
//<next>: /* <next>: */
0xe1c421b0, // strh r2, [r4, #16] 0xe1c421b0, /* strh r2, [r4, #16] */
0xe0d050b2, // ldrh r5, [r0], #2 0xe0d050b2, /* ldrh r5, [r0], #2 */
0xe1c450bc, // strh r5, [r4, #12] 0xe1c450bc, /* strh r5, [r4, #12] */
0xe5c46008, // strb r6, [r4, #8] 0xe5c46008, /* strb r6, [r4, #8] */
//<wait_complete>: /* <wait_complete>: */
0xe1d430b0, // ldrh r3, [r4] 0xe1d430b0, /* ldrh r3, [r4] */
0xe3130004, // tst r3, #4 ; 0x4 0xe3130004, /* tst r3, #4 ; 0x4 */
0x1afffffc, // bne 1001c <wait_complete> 0x1afffffc, /* bne 1001c <wait_complete> */
0xe2822002, // add r2, r2, #2 ; 0x2 0xe2822002, /* add r2, r2, #2 ; 0x2 */
0xe2511001, // subs r1, r1, #1 ; 0x1 0xe2511001, /* subs r1, r1, #1 ; 0x1 */
0x0a000001, // beq 1003c <done> 0x0a000001, /* beq 1003c <done> */
0xe3130001, // tst r3, #1 ; 0x1 0xe3130001, /* tst r3, #1 ; 0x1 */
0x1afffff3, // bne 1000c <next> 0x1afffff3, /* bne 1000c <next> */
//<done>: /* <done>: */
0xeafffffe // b 1003c <done> 0xeafffffe /* b 1003c <done> */
}; };
/* flash write code */ /* flash write code */
if (target_alloc_working_area(target, sizeof(aduc702x_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"); LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}; }
retval = target_write_buffer(target, aduc702x_info->write_algorithm->address, retval = target_write_buffer(target, aduc702x_info->write_algorithm->address,
sizeof(aduc702x_flash_write_code), (uint8_t *)aduc702x_flash_write_code); sizeof(aduc702x_flash_write_code), (uint8_t *)aduc702x_flash_write_code);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
/* memory buffer */ /* 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 /= 2;
if (buffer_size <= 256) if (buffer_size <= 256) {
{ /* if we already allocated the writing code, but failed to get a buffer,
/* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ *free the algorithm */
if (aduc702x_info->write_algorithm) if (aduc702x_info->write_algorithm)
target_free_working_area(target, 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[3], "r3", 32, PARAM_IN);
init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); 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; uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
retval = target_write_buffer(target, source->address, thisrun_count, buffer); retval = target_write_buffer(target, source->address, thisrun_count, buffer);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
break; break;
}
buf_set_u32(reg_params[0].value, 0, 32, source->address); 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[1].value, 0, 32, thisrun_count/2);
buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, address);
buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800); buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
if ((retval = target_run_algorithm(target, 0, NULL, 5, retval = target_run_algorithm(target, 0, NULL, 5,
reg_params, aduc702x_info->write_algorithm->address, reg_params, aduc702x_info->write_algorithm->address,
aduc702x_info->write_algorithm->address + sizeof(aduc702x_flash_write_code) - 4, aduc702x_info->write_algorithm->address +
10000, &armv4_5_info)) != ERROR_OK) sizeof(aduc702x_flash_write_code) - 4,
{ 10000, &armv4_5_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing aduc702x flash write algorithm"); LOG_ERROR("error executing aduc702x flash write algorithm");
break; 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 */ /* FIX!!!! what does this mean??? replace w/sensible error message */
LOG_ERROR("aduc702x detected error writing flash"); LOG_ERROR("aduc702x detected error writing flash");
retval = ERROR_FAIL; retval = ERROR_FAIL;
@ -302,7 +292,10 @@ 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 /* All-JTAG, single-access method. Very slow. Used only if there is no
* working area available. */ * 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; uint32_t x;
uint8_t b; uint8_t b;
@ -311,26 +304,24 @@ static int aduc702x_write_single(struct flash_bank *bank, uint8_t *buffer, uint3
aduc702x_set_write_enable(target, 1); aduc702x_set_write_enable(target, 1);
for (x = 0; x < count; x += 2) { for (x = 0; x < count; x += 2) {
// FEEADR = address /* FEEADR = address */
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x);
// set up data /* set up data */
if ((x + 1) == count) if ((x + 1) == count) {
{ /* last byte */
// last byte
target_read_u8(target, offset + x + 1, &b); target_read_u8(target, offset + x + 1, &b);
} } else
else
b = buffer[x + 1]; 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); target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02);
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) {
{ LOG_ERROR("single write failed for address 0x%08lX",
LOG_ERROR("single write failed for address 0x%08lX", (unsigned long)(offset + x)); (unsigned long)(offset + x));
aduc702x_set_write_enable(target, 0); aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -348,16 +339,15 @@ static int aduc702x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
int retval; int retval;
/* try using a block write */ /* try using a block write */
if ((retval = aduc702x_write_block(bank, buffer, offset, count)) != ERROR_OK) retval = aduc702x_write_block(bank, buffer, offset, count);
{ if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
{
/* if block write failed (no sufficient working area), /* if block write failed (no sufficient working area),
* use normal (slow) JTAG method */ * use normal (slow) JTAG method */
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");
if ((retval = aduc702x_write_single(bank, buffer, offset, count)) != ERROR_OK) retval = aduc702x_write_single(bank, buffer, offset, count);
{ if (retval != ERROR_OK) {
LOG_ERROR("slow write failed"); LOG_ERROR("slow write failed");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -382,7 +372,7 @@ static int aduc702x_info(struct flash_bank *bank, char *buf, int buf_size)
* enable = 1 enables writes & erases, 0 disables them */ * enable = 1 enables writes & erases, 0 disables them */
static int aduc702x_set_write_enable(struct target *target, int enable) static int aduc702x_set_write_enable(struct target *target, int enable)
{ {
// don't bother to preserve int enable bit here /* don't bother to preserve int enable bit here */
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);
return ERROR_OK; return ERROR_OK;
@ -400,15 +390,20 @@ static int aduc702x_check_flash_completion(struct target* target, unsigned int t
long long endtime = timeval_ms() + timeout_ms; long long endtime = timeval_ms() + timeout_ms;
while (1) { while (1) {
target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v); target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
if ((v & 4) == 0) break; if ((v & 4) == 0)
break;
alive_sleep(1); alive_sleep(1);
if (timeval_ms() >= endtime) break; if (timeval_ms() >= endtime)
break;
} }
if (v & 2) return ERROR_FAIL; if (v & 2)
// if a command is ignored, both the success and fail bits may be 0 return ERROR_FAIL;
else if ((v & 3) == 0) return ERROR_FAIL; /* if a command is ignored, both the success and fail bits may be 0 */
else return ERROR_OK; else if ((v & 3) == 0)
return ERROR_FAIL;
else
return ERROR_OK;
} }
struct flash_driver aduc702x_flash = { struct flash_driver aduc702x_flash = {

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,6 @@
#include "imp.h" #include "imp.h"
#include <helper/binarybuffer.h> #include <helper/binarybuffer.h>
/* AT91SAM7 control registers */ /* AT91SAM7 control registers */
#define DBGU_CIDR 0xFFFFF240 #define DBGU_CIDR 0xFFFFF240
#define CKGR_MCFR 0xFFFFFC24 #define CKGR_MCFR 0xFFFFFC24
@ -98,9 +97,9 @@
#define FLASH_SIZE_1024KB 12 #define FLASH_SIZE_1024KB 12
#define FLASH_SIZE_2048KB 14 #define FLASH_SIZE_2048KB 14
static int at91sam7_protect_check(struct flash_bank *bank); 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 uint32_t at91sam7_get_flash_status(struct target *target, int bank_number);
static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode); 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_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 };
static uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 }; 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 */ /* chip id register */
uint32_t cidr; uint32_t cidr;
uint16_t cidr_ext; uint16_t cidr_ext;
@ -178,7 +178,6 @@ static long SRAMSIZ[16] = {
}; };
#endif #endif
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number) static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number)
{ {
uint32_t fsr; 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_valid = 0;
at91sam7_info->mck_freq = 0; at91sam7_info->mck_freq = 0;
switch (mckr & PMC_MCKR_CSS) switch (mckr & PMC_MCKR_CSS) {
{
case 0: /* Slow Clock */ case 0: /* Slow Clock */
at91sam7_info->mck_valid = 1; at91sam7_info->mck_valid = 1;
tmp = RC_FREQ; tmp = RC_FREQ;
@ -215,13 +213,10 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
case 1: /* Main Clock */ case 1: /* Main Clock */
if ((mcfr & CKGR_MCFR_MAINRDY) && if ((mcfr & CKGR_MCFR_MAINRDY) &&
(at91sam7_info->ext_freq == 0)) (at91sam7_info->ext_freq == 0)) {
{
at91sam7_info->mck_valid = 1; at91sam7_info->mck_valid = 1;
tmp = RC_FREQ / 16ul * (mcfr & 0xffff); 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; at91sam7_info->mck_valid = 1;
tmp = at91sam7_info->ext_freq; tmp = at91sam7_info->ext_freq;
} }
@ -232,8 +227,7 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
case 3: /* PLL Clock */ case 3: /* PLL Clock */
if ((mcfr & CKGR_MCFR_MAINRDY) && if ((mcfr & CKGR_MCFR_MAINRDY) &&
(at91sam7_info->ext_freq == 0)) (at91sam7_info->ext_freq == 0)) {
{
target_read_u32(target, CKGR_PLLR, &pllr); target_read_u32(target, CKGR_PLLR, &pllr);
if (!(pllr & CKGR_PLLR_DIV)) if (!(pllr & CKGR_PLLR_DIV))
break; /* 0 Hz */ break; /* 0 Hz */
@ -243,10 +237,8 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
* as long as PLL is properly configured. */ * as long as PLL is properly configured. */
tmp = mainfreq / (pllr & CKGR_PLLR_DIV)* tmp = mainfreq / (pllr & CKGR_PLLR_DIV)*
(((pllr & CKGR_PLLR_MUL) >> 16) + 1); (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
} } else if ((at91sam7_info->ext_freq != 0) &&
else if ((at91sam7_info->ext_freq != 0) && ((pllr&CKGR_PLLR_DIV) != 0)) {
((pllr&CKGR_PLLR_DIV) != 0))
{
at91sam7_info->mck_valid = 1; at91sam7_info->mck_valid = 1;
tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)* tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)*
(((pllr & CKGR_PLLR_MUL) >> 16) + 1); (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
@ -255,12 +247,10 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
} }
/* Prescaler adjust */ /* 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_valid = 0;
at91sam7_info->mck_freq = 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); at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
else else
at91sam7_info->mck_freq = tmp; 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 at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
struct target *target = bank->target; struct target *target = bank->target;
if (mode && (mode != at91sam7_info->flashmode)) if (mode && (mode != at91sam7_info->flashmode)) {
{
/* Always round up (ceil) */ /* Always round up (ceil) */
if (mode == FMR_TIMING_NVBITS) if (mode == FMR_TIMING_NVBITS) {
{ if (at91sam7_info->cidr_arch == 0x60) {
if (at91sam7_info->cidr_arch == 0x60)
{
/* AT91SAM7A3 uses master clocks in 100 ns */ /* AT91SAM7A3 uses master clocks in 100 ns */
fmcn = (at91sam7_info->mck_freq/10000000ul) + 1; fmcn = (at91sam7_info->mck_freq/10000000ul) + 1;
} } else {
else
{
/* master clocks in 1uS for ARCH 0x7 types */ /* master clocks in 1uS for ARCH 0x7 types */
fmcn = (at91sam7_info->mck_freq/1000000ul) + 1; fmcn = (at91sam7_info->mck_freq/1000000ul) + 1;
} }
} } else if (mode == FMR_TIMING_FLASH) {
else if (mode == FMR_TIMING_FLASH)
{
/* main clocks in 1.5uS */ /* main clocks in 1.5uS */
fmcn = (at91sam7_info->mck_freq/1000000ul)+ fmcn = (at91sam7_info->mck_freq/1000000ul)+
(at91sam7_info->mck_freq/2000000ul) + 1; (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; 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); LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status);
alive_sleep(1); alive_sleep(1);
} }
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status); LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status);
if (status & 0x0C) if (status & 0x0C) {
{
LOG_ERROR("status register: 0x%" PRIx32 "", status); LOG_ERROR("status register: 0x%" PRIx32 "", status);
if (status & 0x4) if (status & 0x4)
LOG_ERROR("Lock Error Bit Detected, Operation Abort"); 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; fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd;
target_write_u32(target, MC_FCR[bank->bank_number], fcr); 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 */ /* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */
if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C) if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK; return ERROR_OK;
} }
if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C) if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK; return ERROR_OK;
} }
@ -392,14 +372,12 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
at91sam7_info = t_bank->driver_priv; 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 */ /* flash already configured, update clock and check for protected sectors */
struct flash_bank *fb = bank; struct flash_bank *fb = bank;
t_bank = fb; t_bank = fb;
while (t_bank) while (t_bank) {
{
/* re-calculate master clock frequency */ /* re-calculate master clock frequency */
at91sam7_read_clock_info(t_bank); 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 */ /* Read and parse chip identification register */
target_read_u32(target, DBGU_CIDR, &cidr); target_read_u32(target, DBGU_CIDR, &cidr);
if (cidr == 0) if (cidr == 0) {
{
LOG_WARNING("Cannot identify target as an AT91SAM"); LOG_WARNING("Cannot identify target as an AT91SAM");
return ERROR_FLASH_OPERATION_FAILED; 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 */ /* banks and sectors are already created, based on data from input file */
struct flash_bank *fb = bank; struct flash_bank *fb = bank;
t_bank = fb; t_bank = fb;
while (t_bank) while (t_bank) {
{
at91sam7_info = t_bank->driver_priv; at91sam7_info = t_bank->driver_priv;
at91sam7_info->cidr = cidr; at91sam7_info->cidr = cidr;
@ -462,8 +437,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
arch = (cidr >> 20)&0x00FF; arch = (cidr >> 20)&0x00FF;
/* check flash size */ /* check flash size */
switch ((cidr >> 8)&0x000F) switch ((cidr >> 8)&0x000F) {
{
case FLASH_SIZE_8KB: case FLASH_SIZE_8KB:
break; break;
@ -473,8 +447,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 32; pages_per_sector = 32;
page_size = 64; page_size = 64;
base_address = 0x00100000; base_address = 0x00100000;
if (arch == 0x70) if (arch == 0x70) {
{
num_nvmbits = 2; num_nvmbits = 2;
target_name_t = "AT91SAM7S161/16"; target_name_t = "AT91SAM7S161/16";
} }
@ -486,13 +459,11 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 32; pages_per_sector = 32;
page_size = 128; page_size = 128;
base_address = 0x00100000; base_address = 0x00100000;
if (arch == 0x70) if (arch == 0x70) {
{
num_nvmbits = 2; num_nvmbits = 2;
target_name_t = "AT91SAM7S321/32"; target_name_t = "AT91SAM7S321/32";
} }
if (arch == 0x72) if (arch == 0x72) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7SE32"; target_name_t = "AT91SAM7SE32";
} }
@ -504,8 +475,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 32; pages_per_sector = 32;
page_size = 128; page_size = 128;
base_address = 0x00100000; base_address = 0x00100000;
if (arch == 0x70) if (arch == 0x70) {
{
num_nvmbits = 2; num_nvmbits = 2;
target_name_t = "AT91SAM7S64"; target_name_t = "AT91SAM7S64";
} }
@ -517,23 +487,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 64; pages_per_sector = 64;
page_size = 256; page_size = 256;
base_address = 0x00100000; base_address = 0x00100000;
if (arch == 0x70) if (arch == 0x70) {
{
num_nvmbits = 2; num_nvmbits = 2;
target_name_t = "AT91SAM7S128"; target_name_t = "AT91SAM7S128";
} }
if (arch == 0x71) if (arch == 0x71) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7XC128"; target_name_t = "AT91SAM7XC128";
} }
if (arch == 0x72) if (arch == 0x72) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7SE128"; target_name_t = "AT91SAM7SE128";
} }
if (arch == 0x75) if (arch == 0x75) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7X128"; target_name_t = "AT91SAM7X128";
} }
@ -545,28 +511,23 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 64; pages_per_sector = 64;
page_size = 256; page_size = 256;
base_address = 0x00100000; base_address = 0x00100000;
if (arch == 0x60) if (arch == 0x60) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7A3"; target_name_t = "AT91SAM7A3";
} }
if (arch == 0x70) if (arch == 0x70) {
{
num_nvmbits = 2; num_nvmbits = 2;
target_name_t = "AT91SAM7S256"; target_name_t = "AT91SAM7S256";
} }
if (arch == 0x71) if (arch == 0x71) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7XC256"; target_name_t = "AT91SAM7XC256";
} }
if (arch == 0x72) if (arch == 0x72) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7SE256"; target_name_t = "AT91SAM7SE256";
} }
if (arch == 0x75) if (arch == 0x75) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7X256"; target_name_t = "AT91SAM7X256";
} }
@ -578,23 +539,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
pages_per_sector = 64; pages_per_sector = 64;
page_size = 256; page_size = 256;
base_address = 0x00100000; base_address = 0x00100000;
if (arch == 0x70) if (arch == 0x70) {
{
num_nvmbits = 2; num_nvmbits = 2;
target_name_t = "AT91SAM7S512"; target_name_t = "AT91SAM7S512";
} }
if (arch == 0x71) if (arch == 0x71) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7XC512"; target_name_t = "AT91SAM7XC512";
} }
if (arch == 0x72) if (arch == 0x72) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7SE512"; target_name_t = "AT91SAM7SE512";
} }
if (arch == 0x75) if (arch == 0x75) {
{
num_nvmbits = 3; num_nvmbits = 3;
target_name_t = "AT91SAM7X512"; target_name_t = "AT91SAM7X512";
} }
@ -607,9 +564,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
break; break;
} }
if (strcmp(target_name_t, "Unknown") == 0) if (strcmp(target_name_t, "Unknown") == 0) {
{ LOG_ERROR(
LOG_ERROR("Target autodetection failed! Please specify target parameters in configuration file"); "Target autodetection failed! Please specify target parameters in configuration file");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -618,10 +575,8 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
/* calculate bank size */ /* calculate bank size */
bank_size = sectors_num * pages_per_sector * page_size; bank_size = sectors_num * pages_per_sector * page_size;
for (bnk = 0; bnk < banks_num; bnk++) for (bnk = 0; bnk < banks_num; bnk++) {
{ if (bnk > 0) {
if (bnk > 0)
{
if (!t_bank->next) { if (!t_bank->next) {
/* create a new flash bank element */ /* create a new flash bank element */
struct flash_bank *fb = malloc(sizeof(struct flash_bank)); 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 */ /* allocate sectors */
t_bank->sectors = malloc(sectors_num * sizeof(struct flash_sector)); 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].offset = sec * pages_per_sector * page_size;
t_bank->sectors[sec].size = pages_per_sector * page_size; t_bank->sectors[sec].size = pages_per_sector * page_size;
t_bank->sectors[sec].is_erased = -1; 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); 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; return ERROR_OK;
} }
@ -699,8 +655,7 @@ static int at91sam7_erase_check(struct flash_bank *bank)
uint16_t nSector; uint16_t nSector;
uint16_t nByte; uint16_t nByte;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
fast_check = 1; fast_check = 1;
for (nSector = 0; nSector < bank->num_sectors; nSector++) for (nSector = 0; nSector < bank->num_sectors; nSector++) {
{ retval = target_blank_check_memory(target,
retval = target_blank_check_memory(target, bank->base + bank->sectors[nSector].offset, bank->base + bank->sectors[nSector].offset,
bank->sectors[nSector].size, &blank); bank->sectors[nSector].size,
if (retval != ERROR_OK) &blank);
{ if (retval != ERROR_OK) {
fast_check = 0; fast_check = 0;
break; break;
} }
@ -726,25 +681,20 @@ static int at91sam7_erase_check(struct flash_bank *bank)
} }
if (fast_check) if (fast_check)
{
return ERROR_OK; return ERROR_OK;
}
LOG_USER("Running slow fallback erase check - add working memory"); LOG_USER("Running slow fallback erase check - add working memory");
buffer = malloc(bank->sectors[0].size); 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; bank->sectors[nSector].is_erased = 1;
retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4, 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) if (retval != ERROR_OK)
return retval; return retval;
for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) {
{ if (buffer[nByte] != 0xFF) {
if (buffer[nByte] != 0xFF)
{
bank->sectors[nSector].is_erased = 0; bank->sectors[nSector].is_erased = 0;
break; break;
} }
@ -763,11 +713,8 @@ static int at91sam7_protect_check(struct flash_bank *bank)
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
if (at91sam7_info->cidr == 0) if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
} if (bank->target->state != TARGET_HALTED) {
if (bank->target->state != TARGET_HALTED)
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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->lockbits = (status >> 16);
at91sam7_info->num_lockbits_on = 0; at91sam7_info->num_lockbits_on = 0;
for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) {
{ if (((status >> (16 + lock_pos))&(0x0001)) == 1) {
if (((status >> (16 + lock_pos))&(0x0001)) == 1)
{
at91sam7_info->num_lockbits_on++; at91sam7_info->num_lockbits_on++;
bank->sectors[lock_pos].is_protected = 1; bank->sectors[lock_pos].is_protected = 1;
} } else
else
bank->sectors[lock_pos].is_protected = 0; bank->sectors[lock_pos].is_protected = 0;
} }
@ -794,13 +738,10 @@ static int at91sam7_protect_check(struct flash_bank *bank)
at91sam7_info->nvmbits = (status >> 8)&0xFF; at91sam7_info->nvmbits = (status >> 8)&0xFF;
at91sam7_info->num_nvmbits_on = 0; 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) if (((status >> (8 + gpnvm_pos))&(0x01)) == 1)
{
at91sam7_info->num_nvmbits_on++; at91sam7_info->num_nvmbits_on++;
} }
}
return ERROR_OK; return ERROR_OK;
} }
@ -837,8 +778,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
at91sam7_info->ext_freq = 0; at91sam7_info->ext_freq = 0;
at91sam7_info->flash_autodetection = 0; at91sam7_info->flash_autodetection = 0;
if (CMD_ARGC < 13) if (CMD_ARGC < 13) {
{
at91sam7_info->flash_autodetection = 1; at91sam7_info->flash_autodetection = 1;
return ERROR_OK; 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) || 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; at91sam7_info->flash_autodetection = 1;
return ERROR_OK; return ERROR_OK;
} }
@ -874,10 +813,8 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
/* calculate bank size */ /* calculate bank size */
bank_size = num_sectors * pages_per_sector * page_size; bank_size = num_sectors * pages_per_sector * page_size;
for (bnk = 0; bnk < banks_num; bnk++) for (bnk = 0; bnk < banks_num; bnk++) {
{ if (bnk > 0) {
if (bnk > 0)
{
if (!t_bank->next) { if (!t_bank->next) {
/* create a new bank element */ /* create a new bank element */
struct flash_bank *fb = malloc(sizeof(struct flash_bank)); struct flash_bank *fb = malloc(sizeof(struct flash_bank));
@ -902,8 +839,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
/* allocate sectors */ /* allocate sectors */
t_bank->sectors = malloc(num_sectors * sizeof(struct flash_sector)); 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].offset = sec * pages_per_sector * page_size;
t_bank->sectors[sec].size = pages_per_sector * page_size; t_bank->sectors[sec].size = pages_per_sector * page_size;
t_bank->sectors[sec].is_erased = -1; 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; uint8_t erase_all;
if (at91sam7_info->cidr == 0) if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
}
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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))
{
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
}
erase_all = 0; erase_all = 0;
if ((first == 0) && (last == (bank->num_sectors-1))) if ((first == 0) && (last == (bank->num_sectors-1)))
{
erase_all = 1; erase_all = 1;
}
/* Configure the flash controller timing */ /* Configure the flash controller timing */
at91sam7_read_clock_info(bank); at91sam7_read_clock_info(bank);
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
if (erase_all) if (erase_all) {
{
if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK) if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} } else {
}
else
{
/* allocate and clean buffer */ /* allocate and clean buffer */
nbytes = (last - first + 1) * bank->sectors[first].size; nbytes = (last - first + 1) * bank->sectors[first].size;
buffer = malloc(nbytes * sizeof(uint8_t)); buffer = malloc(nbytes * sizeof(uint8_t));
for (pos = 0; pos < nbytes; pos++) for (pos = 0; pos < nbytes; pos++)
{
buffer[pos] = 0xFF; buffer[pos] = 0xFF;
}
if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK) if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
free(buffer); free(buffer);
} }
/* mark erased sectors */ /* mark erased sectors */
for (sec = first; sec <= last; sec++) for (sec = first; sec <= last; sec++)
{
bank->sectors[sec].is_erased = 1; bank->sectors[sec].is_erased = 1;
}
return ERROR_OK; 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; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
if (at91sam7_info->cidr == 0) if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
}
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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))
{
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
}
/* Configure the flash controller timing */ /* Configure the flash controller timing */
at91sam7_read_clock_info(bank); at91sam7_read_clock_info(bank);
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS); at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
for (sector = first; sector <= last; sector++) for (sector = first; sector <= last; sector++) {
{
if (set) if (set)
cmd = SLB; cmd = SLB;
else else
@ -1032,10 +944,8 @@ static int at91sam7_protect(struct flash_bank *bank, int set, int first, int las
pagen = sector * at91sam7_info->pages_per_sector; pagen = sector * at91sam7_info->pages_per_sector;
if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK) if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
}
at91sam7_protect_check(bank); 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; uint32_t first_page, last_page, pagen, buffer_pos;
if (at91sam7_info->cidr == 0) if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
}
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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; dst_min_alignment = at91sam7_info->pagesize;
if (offset % dst_min_alignment) if (offset % dst_min_alignment) {
{ LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, dst_min_alignment); offset,
dst_min_alignment);
return ERROR_FLASH_DST_BREAKS_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; first_page = offset/dst_min_alignment;
last_page = DIV_ROUND_UP(offset + count, 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 */ /* Configure the flash controller timing */
at91sam7_read_clock_info(bank); at91sam7_read_clock_info(bank);
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); 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) if (bytes_remaining < dst_min_alignment)
count = bytes_remaining; count = bytes_remaining;
else else
@ -1095,16 +1005,14 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
/* Write one block to the PageWriteBuffer */ /* Write one block to the PageWriteBuffer */
buffer_pos = (pagen-first_page)*dst_min_alignment; buffer_pos = (pagen-first_page)*dst_min_alignment;
wcount = DIV_ROUND_UP(count, 4); 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) retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4,
{ wcount, buffer + buffer_pos);
if (retval != ERROR_OK)
return retval; return retval;
}
/* Send Write Page command to Flash Controller */ /* Send Write Page command to Flash Controller */
if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK) if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
LOG_DEBUG("Write flash bank:%i page number:%" PRIi32 "", bank->bank_number, pagen); 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 */ * if this is an at91sam7, it has the configured flash */
int retval; int retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -1136,9 +1043,7 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
if (at91sam7_info->cidr == 0) if (at91sam7_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
}
printed = snprintf(buf, buf_size, printed = snprintf(buf, buf_size,
"\n at91sam7 driver information: Chip is %s\n", "\n at91sam7 driver information: Chip is %s\n",
@ -1149,7 +1054,8 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
printed = snprintf(buf, printed = snprintf(buf,
buf_size, buf_size,
" Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | Flashsize: 0x%8.8" PRIx32 "\n", " 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,
at91sam7_info->cidr_arch, at91sam7_info->cidr_arch,
EPROC[at91sam7_info->cidr_eproc], EPROC[at91sam7_info->cidr_eproc],
@ -1161,15 +1067,20 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
printed = snprintf(buf, buf_size, printed = snprintf(buf, buf_size,
" Master clock (estimated): %u KHz | External clock: %u KHz\n", " Master clock (estimated): %u KHz | External clock: %u KHz\n",
(unsigned)(at91sam7_info->mck_freq / 1000), (unsigned)(at91sam7_info->ext_freq / 1000)); (unsigned)(at91sam7_info->mck_freq / 1000),
(unsigned)(at91sam7_info->ext_freq / 1000));
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
printed = snprintf(buf, buf_size, printed = snprintf(buf,
buf_size,
" Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i\n", " 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->pagesize,
at91sam7_info->lockbits, at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on); bank->num_sectors,
at91sam7_info->num_lockbits_on,
at91sam7_info->lockbits,
at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on);
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
@ -1202,53 +1113,40 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
int retval; int retval;
if (CMD_ARGC != 2) if (CMD_ARGC != 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
bank = get_flash_bank_by_num_noprobe(0); bank = get_flash_bank_by_num_noprobe(0);
if (bank == NULL) if (bank == NULL)
{
return ERROR_FLASH_BANK_INVALID; 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]); command_print(CMD_CTX, "not an at91sam7 flash bank '%s'", CMD_ARGV[0]);
return ERROR_FLASH_BANK_INVALID; 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"); LOG_ERROR("target has to be halted to perform flash operation");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (strcmp(CMD_ARGV[1], "set") == 0) if (strcmp(CMD_ARGV[1], "set") == 0)
{
flashcmd = SGPB; flashcmd = SGPB;
}
else if (strcmp(CMD_ARGV[1], "clear") == 0) else if (strcmp(CMD_ARGV[1], "clear") == 0)
{
flashcmd = CGPB; flashcmd = CGPB;
}
else else
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
at91sam7_info = bank->driver_priv; at91sam7_info = bank->driver_priv;
if (at91sam7_info->cidr == 0) if (at91sam7_info->cidr == 0) {
{
retval = at91sam7_read_part_info(bank); retval = at91sam7_read_part_info(bank);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
} }
}
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit); COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit);
if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) {
{ command_print(CMD_CTX,
command_print(CMD_CTX, "gpnvm bit '#%s' is out of bounds for target %s", CMD_ARGV[0], at91sam7_info->target_name); "gpnvm bit '#%s' is out of bounds for target %s",
CMD_ARGV[0],
at91sam7_info->target_name);
return ERROR_OK; return ERROR_OK;
} }
@ -1257,13 +1155,14 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS); at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK) if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */ /* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
status = at91sam7_get_flash_status(bank->target, 0); 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 */ /* check protect state */
at91sam7_protect_check(bank); at91sam7_protect_check(bank);

View File

@ -17,6 +17,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -24,22 +25,21 @@
#include "imp.h" #include "imp.h"
#include <target/avrt.h> #include <target/avrt.h>
/* AVR_JTAG_Instructions */ /* AVR_JTAG_Instructions */
#define AVR_JTAG_INS_LEN 4 #define AVR_JTAG_INS_LEN 4
// Public Instructions: /* Public Instructions: */
#define AVR_JTAG_INS_EXTEST 0x00 #define AVR_JTAG_INS_EXTEST 0x00
#define AVR_JTAG_INS_IDCODE 0x01 #define AVR_JTAG_INS_IDCODE 0x01
#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02 #define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02
#define AVR_JTAG_INS_BYPASS 0x0F #define AVR_JTAG_INS_BYPASS 0x0F
// AVR Specified Public Instructions: /* AVR Specified Public Instructions: */
#define AVR_JTAG_INS_AVR_RESET 0x0C #define AVR_JTAG_INS_AVR_RESET 0x0C
#define AVR_JTAG_INS_PROG_ENABLE 0x04 #define AVR_JTAG_INS_PROG_ENABLE 0x04
#define AVR_JTAG_INS_PROG_COMMANDS 0x05 #define AVR_JTAG_INS_PROG_COMMANDS 0x05
#define AVR_JTAG_INS_PROG_PAGELOAD 0x06 #define AVR_JTAG_INS_PROG_PAGELOAD 0x06
#define AVR_JTAG_INS_PROG_PAGEREAD 0x07 #define AVR_JTAG_INS_PROG_PAGEREAD 0x07
// Data Registers: /* Data Registers: */
#define AVR_JTAG_REG_Bypass_Len 1 #define AVR_JTAG_REG_Bypass_Len 1
#define AVR_JTAG_REG_DeviceID_Len 32 #define AVR_JTAG_REG_DeviceID_Len 32
@ -49,8 +49,7 @@
#define AVR_JTAG_REG_ProgrammingCommand_Len 15 #define AVR_JTAG_REG_ProgrammingCommand_Len 15
#define AVR_JTAG_REG_FlashDataByte_Len 16 #define AVR_JTAG_REG_FlashDataByte_Len 16
struct avrf_type struct avrf_type {
{
char name[15]; char name[15];
uint16_t chip_id; uint16_t chip_id;
int flash_page_size; int flash_page_size;
@ -59,14 +58,12 @@ struct avrf_type
int eeprom_page_num; int eeprom_page_num;
}; };
struct avrf_flash_bank struct avrf_flash_bank {
{
int ppage_size; int ppage_size;
int probed; 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, /* name, chip_id, flash_page_size, flash_page_num,
* eeprom_page_size, eeprom_page_num * eeprom_page_size, eeprom_page_num
*/ */
@ -127,43 +124,49 @@ static int avr_jtagprg_chiperase(struct avr_common *avr)
do { do {
poll_value = 0; 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()) if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL; return ERROR_FAIL;
}
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value); LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
} while (!(poll_value & 0x0200)); } while (!(poll_value & 0x0200));
return ERROR_OK; 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; uint32_t i, poll_value;
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); 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); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len);
// load addr high byte /* load addr high byte */
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0700 | ((addr >> 9) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len); avr_jtag_senddat(avr->jtag_info.tap,
NULL,
0x0700 | ((addr >> 9) & 0xFF),
AVR_JTAG_REG_ProgrammingCommand_Len);
// load addr low byte /* load addr low byte */
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0300 | ((addr >> 1) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len); 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); 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) if (i < buf_size)
{
avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8); avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8);
}
else else
{
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8);
} }
}
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); 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 { do {
poll_value = 0; 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()) if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL; return ERROR_FAIL;
}
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value); LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
} while (!(poll_value & 0x0200)); } while (!(poll_value & 0x0200));
@ -190,9 +194,7 @@ FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command)
struct avrf_flash_bank *avrf_info; struct avrf_flash_bank *avrf_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
avrf_info = malloc(sizeof(struct avrf_flash_bank)); avrf_info = malloc(sizeof(struct avrf_flash_bank));
bank->driver_priv = avrf_info; 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; struct avr_common *avr = target->arch_info;
int status; 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"); LOG_ERROR("Target not halted");
return 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) 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; 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; struct avr_common *avr = target->arch_info;
uint32_t cur_size, cur_buffer_size, page_size; 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"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
page_size = bank->sectors[0].size; page_size = bank->sectors[0].size;
if ((offset % page_size) != 0) if ((offset % page_size) != 0) {
{ LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment", offset, page_size); offset,
page_size);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; 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); LOG_DEBUG("count is %" PRId32 "", count);
if (ERROR_OK != avr_jtagprg_enterprogmode(avr)) if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
{
return ERROR_FAIL; return ERROR_FAIL;
}
cur_size = 0; cur_size = 0;
while (count > 0) while (count > 0) {
{
if (count > page_size) if (count > page_size)
{
cur_buffer_size = page_size; cur_buffer_size = page_size;
}
else else
{
cur_buffer_size = count; cur_buffer_size = count;
} avr_jtagprg_writeflashpage(avr,
avr_jtagprg_writeflashpage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size); buffer + cur_size,
cur_buffer_size,
offset + cur_size,
page_size);
count -= cur_buffer_size; count -= cur_buffer_size;
cur_size += 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_MFG(X) (((X) & 0xffe) >> 1)
#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12) #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28) #define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
static int avrf_probe(struct flash_bank *bank) static int avrf_probe(struct flash_bank *bank)
{ {
struct target *target = bank->target; struct target *target = bank->target;
@ -293,8 +292,7 @@ static int avrf_probe(struct flash_bank *bank)
int i; int i;
uint32_t device_id; uint32_t device_id;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); avr_jtag_read_jtagid(avr, &device_id);
if (ERROR_OK != mcu_execute_queue()) if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL; return ERROR_FAIL;
}
LOG_INFO("device id = 0x%08" PRIx32 "", device_id); LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
if (EXTRACT_MFG(device_id) != 0x1F) if (EXTRACT_MFG(device_id) != 0x1F)
{ LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); EXTRACT_MFG(device_id),
} 0x1F);
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
{ if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id))
{
avr_info = &avft_chips_info[i]; avr_info = &avft_chips_info[i];
LOG_INFO("target device is %s", avr_info->name); LOG_INFO("target device is %s", avr_info->name);
break; break;
} }
} }
if (avr_info != NULL) if (avr_info != NULL) {
{ if (bank->sectors) {
if (bank->sectors)
{
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL; bank->sectors = NULL;
} }
// chip found /* chip found */
bank->base = 0x00000000; bank->base = 0x00000000;
bank->size = (avr_info->flash_page_size * avr_info->flash_page_num); bank->size = (avr_info->flash_page_size * avr_info->flash_page_num);
bank->num_sectors = 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); 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].offset = i * avr_info->flash_page_size;
bank->sectors[i].size = avr_info->flash_page_size; bank->sectors[i].size = avr_info->flash_page_size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
@ -347,10 +338,8 @@ static int avrf_probe(struct flash_bank *bank)
avrf_info->probed = 1; avrf_info->probed = 1;
return ERROR_OK; return ERROR_OK;
} } else {
else /* chip not supported */
{
// chip not supported
LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id)); LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id));
avrf_info->probed = 1; 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) static int avrf_protect_check(struct flash_bank *bank)
{ {
LOG_INFO("%s", __FUNCTION__); LOG_INFO("%s", __func__);
return ERROR_OK; return ERROR_OK;
} }
@ -380,28 +369,23 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
int i; int i;
uint32_t device_id; uint32_t device_id;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
avr_jtag_read_jtagid(avr, &device_id); avr_jtag_read_jtagid(avr, &device_id);
if (ERROR_OK != mcu_execute_queue()) if (ERROR_OK != mcu_execute_queue())
{
return ERROR_FAIL; return ERROR_FAIL;
}
LOG_INFO("device id = 0x%08" PRIx32 "", device_id); LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
if (EXTRACT_MFG(device_id) != 0x1F) if (EXTRACT_MFG(device_id) != 0x1F)
{ LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); EXTRACT_MFG(device_id),
} 0x1F);
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
{ if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id))
{
avr_info = &avft_chips_info[i]; avr_info = &avft_chips_info[i];
LOG_INFO("target device is %s", avr_info->name); 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) if (avr_info != NULL) {
{ /* chip found */
// chip found snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name,
snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name, EXTRACT_VER(device_id)); EXTRACT_VER(device_id));
return ERROR_OK; return ERROR_OK;
} } else {
else /* chip not supported */
{
// chip not supported
snprintf(buf, buf_size, "Cannot identify target as a avr\n"); snprintf(buf, buf_size, "Cannot identify target as a avr\n");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -428,8 +410,7 @@ static int avrf_mass_erase(struct flash_bank *bank)
struct target *target = bank->target; struct target *target = bank->target;
struct avr_common *avr = target->arch_info; struct avr_common *avr = target->arch_info;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -437,9 +418,7 @@ static int avrf_mass_erase(struct flash_bank *bank)
if ((ERROR_OK != avr_jtagprg_enterprogmode(avr)) if ((ERROR_OK != avr_jtagprg_enterprogmode(avr))
|| (ERROR_OK != avr_jtagprg_chiperase(avr)) || (ERROR_OK != avr_jtagprg_chiperase(avr))
|| (ERROR_OK != avr_jtagprg_leaveprogmode(avr))) || (ERROR_OK != avr_jtagprg_leaveprogmode(avr)))
{
return ERROR_FAIL; return ERROR_FAIL;
}
return ERROR_OK; return ERROR_OK;
} }
@ -449,31 +428,23 @@ COMMAND_HANDLER(avrf_handle_mass_erase_command)
int i; int i;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (avrf_mass_erase(bank) == ERROR_OK) if (avrf_mass_erase(bank) == ERROR_OK) {
{
/* set all sectors as erased */ /* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++) for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1; bank->sectors[i].is_erased = 1;
}
command_print(CMD_CTX, "avr mass erase complete"); command_print(CMD_CTX, "avr mass erase complete");
} } else
else
{
command_print(CMD_CTX, "avr mass erase failed"); command_print(CMD_CTX, "avr mass erase failed");
}
LOG_DEBUG("%s", __FUNCTION__); LOG_DEBUG("%s", __func__);
return ERROR_OK; return ERROR_OK;
} }

File diff suppressed because it is too large Load Diff

View File

@ -17,14 +17,14 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef CFI_H #ifndef CFI_H
#define CFI_H #define CFI_H
#define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */ #define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */
#define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */ #define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */
struct cfi_flash_bank struct cfi_flash_bank {
{
struct working_area *write_algorithm; struct working_area *write_algorithm;
int x16_as_x8; int x16_as_x8;
@ -80,8 +80,7 @@ struct cfi_flash_bank
* as defined for the Advanced+ Boot Block Flash Memory (C3) * as defined for the Advanced+ Boot Block Flash Memory (C3)
* and used by the linux kernel cfi driver (as of 2.6.14) * 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 pri[3];
uint8_t major_version; uint8_t major_version;
uint8_t minor_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 /* Spansion primary extended query table as defined for and used by
* the linux kernel cfi driver (as of 2.6.15) * 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 pri[3];
uint8_t major_version; uint8_t major_version;
uint8_t minor_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 /* Atmel primary extended query table as defined for and used by
* the linux kernel cfi driver (as of 2.6.20+) * 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 pri[3];
uint8_t major_version; uint8_t major_version;
uint8_t minor_version; uint8_t minor_version;
@ -140,14 +137,12 @@ enum {
CFI_UNLOCK_5555_2AAA, CFI_UNLOCK_5555_2AAA,
}; };
struct cfi_unlock_addresses struct cfi_unlock_addresses {
{
uint32_t unlock1; uint32_t unlock1;
uint32_t unlock2; uint32_t unlock2;
}; };
struct cfi_fixup struct cfi_fixup {
{
uint16_t mfr; uint16_t mfr;
uint16_t id; uint16_t id;
void (*fixup)(struct flash_bank *bank, void *param); void (*fixup)(struct flash_bank *bank, void *param);

View File

@ -29,7 +29,6 @@
#include <flash/nor/imp.h> #include <flash/nor/imp.h>
#include <target/image.h> #include <target/image.h>
/** /**
* @file * @file
* Upper level of NOR flash framework. * 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); retval = bank->driver->erase(bank, first, last);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
LOG_ERROR("failed erasing sectors %d to %d", first, last); LOG_ERROR("failed erasing sectors %d to %d", first, last);
}
return retval; return retval;
} }
@ -57,8 +54,7 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
int retval; int retval;
/* callers may not supply illegal parameters ... */ /* 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"); LOG_ERROR("illegal sector range");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -79,9 +75,7 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
*/ */
retval = bank->driver->protect(bank, set, first, last); retval = bank->driver->protect(bank, set, first, last);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
LOG_ERROR("failed setting protection for areas %d to %d", first, last); LOG_ERROR("failed setting protection for areas %d to %d", first, last);
}
return retval; return retval;
} }
@ -92,10 +86,11 @@ int flash_driver_write(struct flash_bank *bank,
int retval; int retval;
retval = bank->driver->write(bank, buffer, offset, count); retval = bank->driver->write(bank, buffer, offset, count);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{ LOG_ERROR(
LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, "error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
bank->base, offset); bank->base,
offset);
} }
return retval; return retval;
@ -109,10 +104,11 @@ int flash_driver_read(struct flash_bank *bank,
LOG_DEBUG("call flash_driver_read()"); LOG_DEBUG("call flash_driver_read()");
retval = bank->driver->read(bank, buffer, offset, count); retval = bank->driver->read(bank, buffer, offset, count);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{ LOG_ERROR(
LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, "error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
bank->base, offset); bank->base,
offset);
} }
return retval; return retval;
@ -128,19 +124,16 @@ void flash_bank_add(struct flash_bank *bank)
{ {
/* put flash bank in linked list */ /* put flash bank in linked list */
unsigned bank_num = 0; unsigned bank_num = 0;
if (flash_banks) if (flash_banks) {
{
/* find last flash bank */ /* find last flash bank */
struct flash_bank *p = flash_banks; struct flash_bank *p = flash_banks;
while (NULL != p->next) while (NULL != p->next) {
{
bank_num += 1; bank_num += 1;
p = p->next; p = p->next;
} }
p->next = bank; p->next = bank;
bank_num += 1; bank_num += 1;
} } else
else
flash_banks = bank; flash_banks = bank;
bank->bank_number = bank_num; bank->bank_number = bank_num;
@ -156,13 +149,10 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num)
struct flash_bank *p; struct flash_bank *p;
int i = 0; int i = 0;
for (p = flash_banks; p; p = p->next) for (p = flash_banks; p; p = p->next) {
{
if (i++ == num) if (i++ == num)
{
return p; return p;
} }
}
LOG_ERROR("flash bank %d does not exist", num); LOG_ERROR("flash bank %d does not exist", num);
return NULL; return NULL;
} }
@ -172,9 +162,7 @@ int flash_get_bank_count(void)
struct flash_bank *p; struct flash_bank *p;
int i = 0; int i = 0;
for (p = flash_banks; p; p = p->next) for (p = flash_banks; p; p = p->next)
{
i++; i++;
}
return i; return i;
} }
@ -184,8 +172,7 @@ struct flash_bank *get_flash_bank_by_name_noprobe(const char *name)
unsigned found = 0; unsigned found = 0;
struct flash_bank *bank; 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) if (strcmp(bank->name, name) == 0)
return bank; return bank;
if (!flash_driver_name_matches(bank->driver->name, name)) 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; int retval;
bank = get_flash_bank_by_name_noprobe(name); bank = get_flash_bank_by_name_noprobe(name);
if (bank != NULL) if (bank != NULL) {
{
retval = bank->driver->auto_probe(bank); retval = bank->driver->auto_probe(bank);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("auto_probe failed"); LOG_ERROR("auto_probe failed");
return retval; return retval;
} }
@ -224,14 +209,11 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank)
int retval; int retval;
if (p == NULL) if (p == NULL)
{
return ERROR_FAIL; return ERROR_FAIL;
}
retval = p->driver->auto_probe(p); retval = p->driver->auto_probe(p);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("auto_probe failed"); LOG_ERROR("auto_probe failed");
return retval; 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 /* lookup flash bank by address, bank not found is success, but
* result_bank is set to NULL. */ * 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; struct flash_bank *c;
/* cycle through bank list */ /* cycle through bank list */
for (c = flash_banks; c; c = c->next) for (c = flash_banks; c; c = c->next) {
{
int retval; int retval;
retval = c->driver->auto_probe(c); retval = c->driver->auto_probe(c);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("auto_probe failed"); LOG_ERROR("auto_probe failed");
return retval; return retval;
} }
/* check whether address belongs to this flash bank */ /* 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; *result_bank = c;
return ERROR_OK; return ERROR_OK;
} }
} }
*result_bank = NULL; *result_bank = NULL;
if (check) if (check) {
{
LOG_ERROR("No flash at address 0x%08" PRIx32, addr); LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -280,38 +261,33 @@ int default_flash_mem_blank_check(struct flash_bank *bank)
uint32_t nBytes; uint32_t nBytes;
int retval = ERROR_OK; int retval = ERROR_OK;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
uint8_t *buffer = malloc(buffer_size); 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; uint32_t j;
bank->sectors[i].is_erased = 1; 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; uint32_t chunk;
chunk = buffer_size; chunk = buffer_size;
if (chunk > (j - bank->sectors[i].size)) if (chunk > (j - bank->sectors[i].size))
{
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) if (retval != ERROR_OK)
{
goto done; goto done;
}
for (nBytes = 0; nBytes < chunk; nBytes++) for (nBytes = 0; nBytes < chunk; nBytes++) {
{ if (buffer[nBytes] != 0xFF) {
if (buffer[nBytes] != 0xFF)
{
bank->sectors[i].is_erased = 0; bank->sectors[i].is_erased = 0;
break; break;
} }
@ -333,20 +309,17 @@ int default_flash_blank_check(struct flash_bank *bank)
int fast_check = 0; int fast_check = 0;
uint32_t blank; uint32_t blank;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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 address = bank->base + bank->sectors[i].offset;
uint32_t size = bank->sectors[i].size; uint32_t size = bank->sectors[i].size;
retval = target_blank_check_memory(target, address, size, &blank); retval = target_blank_check_memory(target, address, size, &blank);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
fast_check = 0; fast_check = 0;
break; break;
} }
@ -357,8 +330,7 @@ int default_flash_blank_check(struct flash_bank *bank)
fast_check = 1; fast_check = 1;
} }
if (!fast_check) if (!fast_check) {
{
LOG_USER("Running slow fallback erase check - add working memory"); LOG_USER("Running slow fallback erase check - add working memory");
return default_flash_mem_blank_check(bank); return default_flash_mem_blank_check(bank);
} }
@ -394,17 +366,14 @@ static int flash_iterate_address_range_inner(struct target *target,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (c->size == 0 || c->num_sectors == 0) if (c->size == 0 || c->num_sectors == 0) {
{
LOG_ERROR("Bank is invalid"); LOG_ERROR("Bank is invalid");
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
} }
if (length == 0) if (length == 0) {
{
/* special case, erase whole bank when length is zero */ /* 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."); LOG_ERROR("Whole bank access must start at beginning of bank.");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; 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 */ /* 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."); LOG_ERROR("Flash access does not fit into bank.");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
@ -424,8 +392,7 @@ static int flash_iterate_address_range_inner(struct target *target,
addr -= c->base; addr -= c->base;
last_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; struct flash_sector *f = c->sectors + i;
uint32_t end = f->offset + f->size; uint32_t end = f->offset + f->size;
@ -510,16 +477,14 @@ static int flash_iterate_address_range(struct target *target,
int retval = ERROR_OK; int retval = ERROR_OK;
/* Danger! zero-length iterations means entire bank! */ /* Danger! zero-length iterations means entire bank! */
do do {
{
retval = get_flash_bank_by_addr(target, addr, true, &c); retval = get_flash_bank_by_addr(target, addr, true, &c);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
uint32_t cur_length = length; uint32_t cur_length = length;
/* check whether it all fits in this bank */ /* 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."); LOG_DEBUG("iterating over more than one flash bank.");
cur_length = c->base + c->size - addr; cur_length = c->base + c->size - addr;
} }
@ -565,17 +530,12 @@ static int compare_section (const void * a, const void * b)
b2 = *((struct imagesection **)b); b2 = *((struct imagesection **)b);
if (b1->base_address == b2->base_address) if (b1->base_address == b2->base_address)
{
return 0; return 0;
} else if (b1->base_address > b2->base_address) else if (b1->base_address > b2->base_address)
{
return 1; return 1;
} else else
{
return -1; return -1;
} }
}
int flash_write_unlock(struct target *target, struct image *image, int flash_write_unlock(struct target *target, struct image *image,
uint32_t *written, int erase, bool unlock) uint32_t *written, int erase, bool unlock)
@ -593,8 +553,7 @@ int flash_write_unlock(struct target *target, struct image *image,
if (written) if (written)
*written = 0; *written = 0;
if (erase) if (erase) {
{
/* assume all sectors need erasing - stops any problems /* assume all sectors need erasing - stops any problems
* when flash_write is called multiple times */ * when flash_write is called multiple times */
@ -610,16 +569,13 @@ int flash_write_unlock(struct target *target, struct image *image,
image->num_sections); image->num_sections);
int i; int i;
for (i = 0; i < image->num_sections; i++) for (i = 0; i < image->num_sections; i++)
{
sections[i] = &image->sections[i]; sections[i] = &image->sections[i];
}
qsort(sections, image->num_sections, sizeof(struct imagesection *), qsort(sections, image->num_sections, sizeof(struct imagesection *),
compare_section); compare_section);
/* loop until we reach end of the image */ /* loop until we reach end of the image */
while (section < image->num_sections) while (section < image->num_sections) {
{
uint32_t buffer_size; uint32_t buffer_size;
uint8_t *buffer; uint8_t *buffer;
int section_last; 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; uint32_t run_size = sections[section]->size - section_offset;
int pad_bytes = 0; int pad_bytes = 0;
if (sections[section]->size == 0) if (sections[section]->size == 0) {
{
LOG_WARNING("empty section %d", section); LOG_WARNING("empty section %d", section);
section++; section++;
section_offset = 0; section_offset = 0;
@ -638,11 +593,8 @@ int flash_write_unlock(struct target *target, struct image *image,
/* find the corresponding flash bank */ /* find the corresponding flash bank */
retval = get_flash_bank_by_addr(target, run_address, false, &c); retval = get_flash_bank_by_addr(target, run_address, false, &c);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
goto done; goto done;
} if (c == NULL) {
if (c == NULL)
{
section++; /* and skip it */ section++; /* and skip it */
section_offset = 0; section_offset = 0;
continue; continue;
@ -651,13 +603,11 @@ int flash_write_unlock(struct target *target, struct image *image,
/* collect consecutive sections which fall into the same bank */ /* collect consecutive sections which fall into the same bank */
section_last = section; section_last = section;
padding[section] = 0; padding[section] = 0;
while ((run_address + run_size - 1 < c->base + c->size - 1) while ((run_address + run_size - 1 < c->base + c->size - 1) &&
&& (section_last + 1 < image->num_sections)) (section_last + 1 < image->num_sections)) {
{
/* sections are sorted */ /* sections are sorted */
assert(sections[section_last + 1]->base_address >= c->base); assert(sections[section_last + 1]->base_address >= c->base);
if (sections[section_last + 1]->base_address >= (c->base + c->size)) if (sections[section_last + 1]->base_address >= (c->base + c->size)) {
{
/* Done with this bank */ /* Done with this bank */
break; break;
} }
@ -685,11 +635,12 @@ int flash_write_unlock(struct target *target, struct image *image,
run_size += pad_bytes; run_size += pad_bytes;
if (pad_bytes > 0) 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 /* If we have more than one flash chip back to back, then we limit
* the current write operation to the current chip. * the current write operation to the current chip.
*/ */
@ -722,8 +673,7 @@ int flash_write_unlock(struct target *target, struct image *image,
/* allocate buffer */ /* allocate buffer */
buffer = malloc(run_size); buffer = malloc(run_size);
if (buffer == NULL) if (buffer == NULL) {
{
LOG_ERROR("Out of memory for flash bank buffer"); LOG_ERROR("Out of memory for flash bank buffer");
retval = ERROR_FAIL; retval = ERROR_FAIL;
goto done; goto done;
@ -731,8 +681,7 @@ int flash_write_unlock(struct target *target, struct image *image,
buffer_size = 0; buffer_size = 0;
/* read sections to the buffer */ /* read sections to the buffer */
while (buffer_size < run_size) while (buffer_size < run_size) {
{
size_t size_read; size_t size_read;
size_read = run_size - buffer_size; size_read = run_size - buffer_size;
@ -747,12 +696,13 @@ int flash_write_unlock(struct target *target, struct image *image,
intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections; intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
int t_section_num = diff / sizeof(struct imagesection); 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", LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, "
(int)section, "section_offset = %d, buffer_size = %d, size_read = %d",
(int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read); (int)section, (int)t_section_num, (int)section_offset,
if ((retval = image_read_section(image, t_section_num, section_offset, (int)buffer_size, (int)size_read);
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0) 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); free(buffer);
goto done; goto done;
} }
@ -764,8 +714,7 @@ int flash_write_unlock(struct target *target, struct image *image,
buffer_size += size_read; buffer_size += size_read;
section_offset += size_read; section_offset += size_read;
if (section_offset >= sections[section]->size) if (section_offset >= sections[section]->size) {
{
section++; section++;
section_offset = 0; section_offset = 0;
} }
@ -774,29 +723,23 @@ int flash_write_unlock(struct target *target, struct image *image,
retval = ERROR_OK; retval = ERROR_OK;
if (unlock) if (unlock)
{
retval = flash_unlock_address_range(target, run_address, run_size); retval = flash_unlock_address_range(target, run_address, run_size);
} if (retval == ERROR_OK) {
if (retval == ERROR_OK) if (erase) {
{
if (erase)
{
/* calculate and erase sectors */ /* calculate and erase sectors */
retval = flash_erase_address_range(target, retval = flash_erase_address_range(target,
true, run_address, run_size); true, run_address, run_size);
} }
} }
if (retval == ERROR_OK) if (retval == ERROR_OK) {
{
/* write flash sectors */ /* write flash sectors */
retval = flash_driver_write(c, buffer, run_address - c->base, run_size); retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
} }
free(buffer); free(buffer);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
/* abort operation */ /* abort operation */
goto done; goto done;
} }
@ -805,7 +748,6 @@ int flash_write_unlock(struct target *target, struct image *image,
*written += run_size; /* add run size to total written counter */ *written += run_size; /* add run size to total written counter */
} }
done: done:
free(sections); free(sections);
free(padding); free(padding);

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NOR_CORE_H #ifndef FLASH_NOR_CORE_H
#define 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 * within a flash bank. A single bank typically consists of multiple
* sectors, each of which can be erased and protected independently. * sectors, each of which can be erased and protected independently.
*/ */
struct flash_sector struct flash_sector {
{ /** Bus offset from start of the flash chip (in bytes). */
/// Bus offset from start of the flash chip (in bytes).
uint32_t offset; uint32_t offset;
/// Number of bytes in this flash sector. /** Number of bytes in this flash sector. */
uint32_t size; uint32_t size;
/** /**
* Indication of erasure status: 0 = not erased, 1 = erased, * 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 * may use the @c driver_priv member to store additional data on a
* per-bank basis, if required. * per-bank basis, if required.
*/ */
struct flash_bank struct flash_bank {
{
const char *name; const char *name;
struct target *target; /**< Target to which this bank belongs. */ 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()". * some non-zero value during "probe()" or "auto_probe()".
*/ */
int num_sectors; 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_sector *sectors;
struct flash_bank *next; /**< The next flash bank on this chip */ 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); 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. * This routine must be called when the system may modify the status.
*/ */
void flash_set_dirty(void); 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); int flash_get_bank_count(void);
/** /**
* Provides default read implementation for flash memory. * 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 * @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. * @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 */

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NOR_DRIVER_H #ifndef FLASH_NOR_DRIVER_H
#define 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> * corresponding static <code>flash_driver_<i>callback</i>()</code>
* routine in flash.c. * routine in flash.c.
*/ */
struct flash_driver struct flash_driver {
{
/** /**
* Gives a human-readable name of this flash driver, * Gives a human-readable name of this flash driver,
* This field is used to select and initialize the 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); 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. * 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); struct flash_driver *flash_driver_find_by_name(const char *name);
#endif // FLASH_NOR_DRIVER_H #endif /* FLASH_NOR_DRIVER_H */

View File

@ -16,6 +16,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -84,8 +85,7 @@ static struct flash_driver *flash_drivers[] = {
struct flash_driver *flash_driver_find_by_name(const char *name) 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) if (strcmp(name, flash_drivers[i]->name) == 0)
return flash_drivers[i]; return flash_drivers[i];
} }

View File

@ -121,7 +121,8 @@ static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
/** /**
* Protection funcionality is not implemented. * Protection funcionality is not implemented.
* The current implementation applies/removes security on the chip. * 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. * The chip is effectively secured/unsecured after the first reset
* following the execution of this function.
* *
* @param bank * @param bank
* @param set Apply or remove security on the chip. * @param set Apply or remove security on the chip.
@ -154,7 +155,8 @@ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
} }
/** /**
* The dsp5680xx use word addressing. The "/2" that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing. * 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 bank
* @param buffer Data to write to flash. * @param buffer Data to write to flash.
@ -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. * This chip uses word addressing, Openocd only supports byte addressing.
* The workaround results in disabling writing to odd byte addresses * The workaround results in disabling writing to odd byte addresses
*/ */
LOG_ERROR LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
("%s: Writing to odd addresses not supported for this target",
__func__);
return ERROR_FAIL; return ERROR_FAIL;
} }
retval = retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count,
0);
uint32_t addr_word; uint32_t addr_word;
for (addr_word = bank->base + offset / 2; addr_word < count / 2; 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) if (retval == ERROR_OK)
bank->sectors[addr_word / bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0;
(HFM_SECTOR_SIZE / 2)].is_erased = 0;
else else
bank->sectors[addr_word / bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1;
(HFM_SECTOR_SIZE / 2)].is_erased = -1;
} }
return retval; return retval;
} }
@ -215,8 +211,11 @@ static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf,
} }
/** /**
* The flash module (FM) on the dsp5680xx supports both individual sector and mass erase of the flash memory. * The flash module (FM) on the dsp5680xx supports both individual sector
* 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). * 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 bank
* @param first * @param first
@ -228,10 +227,8 @@ static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
{ {
int retval; int retval;
retval = retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last); if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
if ((!(first | last))
|| ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
last = HFM_SECTOR_COUNT - 1; last = HFM_SECTOR_COUNT - 1;
if (retval == ERROR_OK) if (retval == ERROR_OK)
for (int i = first; i <= last; i++) for (int i = first; i <= last; i++)
@ -264,8 +261,7 @@ static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
for (i = 0; i < HFM_SECTOR_COUNT; i++) { for (i = 0; i < HFM_SECTOR_COUNT; i++) {
if (bank->sectors[i].is_erased == -1) { if (bank->sectors[i].is_erased == -1) {
retval = retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
dsp5680xx_f_erase_check(bank->target, &erased, i);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
} else { } else {

View File

@ -17,6 +17,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -26,16 +27,15 @@
#include <target/algorithm.h> #include <target/algorithm.h>
#include <target/image.h> #include <target/image.h>
#if 0 #if 0
static uint32_t ecosflash_get_flash_status(struct flash_bank *bank); 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 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 #endif
struct ecosflash_flash_bank struct ecosflash_flash_bank {
{
struct target *target; struct target *target;
struct working_area *write_algorithm; struct working_area *write_algorithm;
struct working_area *erase_check_algorithm; struct working_area *erase_check_algorithm;
@ -45,8 +45,7 @@ struct ecosflash_flash_bank
static const int sectorSize = 0x10000; static const int sectorSize = 0x10000;
char * char *flash_errmsg(int err);
flash_errmsg(int err);
#ifndef __ECOS #ifndef __ECOS
#define FLASH_ERR_OK 0x00 /* No error - operation complete */ #define FLASH_ERR_OK 0x00 /* No error - operation complete */
@ -65,8 +64,7 @@ flash_errmsg(int err);
#define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support 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 */ #define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */
char * char *flash_errmsg(int err)
flash_errmsg(int err)
{ {
switch (err) { switch (err) {
case FLASH_ERR_OK: case FLASH_ERR_OK:
@ -110,13 +108,10 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
struct ecosflash_flash_bank *info; struct ecosflash_flash_bank *info;
if (CMD_ARGC < 7) if (CMD_ARGC < 7)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
info = malloc(sizeof(struct ecosflash_flash_bank)); info = malloc(sizeof(struct ecosflash_flash_bank));
if (info == NULL) if (info == NULL) {
{
LOG_ERROR("no memory for flash bank info"); LOG_ERROR("no memory for flash bank info");
exit(-1); exit(-1);
} }
@ -131,8 +126,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
uint32_t offset = 0; uint32_t offset = 0;
bank->num_sectors = bank->size/sectorSize; bank->num_sectors = bank->size/sectorSize;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); 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].offset = offset;
bank->sectors[i].size = sectorSize; bank->sectors[i].size = sectorSize;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
@ -141,8 +135,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
} }
info->target = get_target(CMD_ARGV[5]); info->target = get_target(CMD_ARGV[5]);
if (info->target == NULL) if (info->target == NULL) {
{
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -160,20 +153,18 @@ static int loadDriver(struct ecosflash_flash_bank *info)
struct target *target = info->target; struct target *target = info->target;
int retval; 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; return retval;
}
info->start_address = image.start_address; info->start_address = image.start_address;
image_size = 0x0; image_size = 0x0;
int i; 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); 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); free(buffer);
image_close(&image); image_close(&image);
return retval; return retval;
@ -191,7 +182,7 @@ static int loadDriver(struct ecosflash_flash_bank *info)
return ERROR_OK; 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_ERASE_SIZE = 0x8;
static int const OFFSET_FLASH = 0xc; static int const OFFSET_FLASH = 0xc;
static int const OFFSET_FLASH_SIZE = 0x8; static int const OFFSET_FLASH_SIZE = 0x8;
@ -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[1].value, 0, 32, r1);
buf_set_u32(reg_params[2].value, 0, 32, r2); buf_set_u32(reg_params[2].value, 0, 32, r2);
int retval; int retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, codeStart, codeStop, timeout, &armv4_5_info);
codeStart, if (retval != ERROR_OK) {
codeStop, timeout,
&armv4_5_info)) != ERROR_OK)
{
LOG_ERROR("error executing eCos flash algorithm"); LOG_ERROR("error executing eCos flash algorithm");
return retval; return retval;
} }
@ -261,8 +249,7 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (flashErr != 0x0) if (flashErr != 0x0) {
{
LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr)); LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -270,7 +257,10 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address,
return ERROR_OK; 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; struct target *target = info->target;
const int chunk = 8192; const int chunk = 8192;
@ -295,13 +285,10 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32
uint32_t i; uint32_t i;
for (i = 0; i < len; i += chunk) for (i = 0; i < len; i += chunk) {
{
int t = len-i; int t = len-i;
if (t > chunk) if (t > chunk)
{
t = chunk; t = chunk;
}
retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i); retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -319,9 +306,9 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (flashErr != 0x0) if (flashErr != 0x0) {
{ LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr,
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr)); flash_errmsg(flashErr));
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
@ -339,29 +326,21 @@ static void command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
struct ecosflash_flash_bank *info = bank->driver_priv; struct ecosflash_flash_bank *info = bank->driver_priv;
int i; int i;
if (info->target->endianness == TARGET_LITTLE_ENDIAN) if (info->target->endianness == TARGET_LITTLE_ENDIAN) {
{
for (i = bank->bus_width; i > 0; i--) for (i = bank->bus_width; i > 0; i--)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd; *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
} } else {
}
else
{
for (i = 1; i <= bank->bus_width; i++) for (i = 1; i <= bank->bus_width; i++)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd; *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
} }
} }
}
#endif #endif
#if 0 #if 0
static uint32_t ecosflash_address(struct flash_bank *bank, uint32_t address) static uint32_t ecosflash_address(struct flash_bank *bank, uint32_t address)
{ {
uint32_t retval = 0; uint32_t retval = 0;
switch (bank->bus_width) switch (bank->bus_width) {
{
case 4: case 4:
retval = address & 0xfffffffc; retval = address & 0xfffffffc;
case 2: case 2:
@ -386,7 +365,8 @@ static int ecosflash_protect(struct flash_bank *bank, int set, int first, int la
return ERROR_OK; 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 ecosflash_flash_bank *info = bank->driver_priv;
struct flash_bank *c = bank; struct flash_bank *c = bank;
@ -421,7 +401,10 @@ static uint32_t ecosflash_wait_status_busy(struct flash_bank *bank, uint32_t wai
return ERROR_OK; 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; return ERROR_OK;
} }

View File

@ -23,6 +23,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -79,15 +80,13 @@
#define KEY1 0x45670123 #define KEY1 0x45670123
#define KEY2 0xCDEF89AB #define KEY2 0xCDEF89AB
struct em357_options struct em357_options {
{
uint16_t RDP; uint16_t RDP;
uint16_t user_options; uint16_t user_options;
uint16_t protection[3]; uint16_t protection[3];
}; };
struct em357_flash_bank struct em357_flash_bank {
{
struct em357_options option_bytes; struct em357_options option_bytes;
struct working_area *write_algorithm; struct working_area *write_algorithm;
int ppage_size; int ppage_size;
@ -103,9 +102,7 @@ FLASH_BANK_COMMAND_HANDLER(em357_flash_bank_command)
struct em357_flash_bank *em357_info; struct em357_flash_bank *em357_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
em357_info = malloc(sizeof(struct em357_flash_bank)); em357_info = malloc(sizeof(struct em357_flash_bank));
bank->driver_priv = em357_info; 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; int retval = ERROR_OK;
/* wait for busy to clear */ /* wait for busy to clear */
for (;;) for (;; ) {
{
retval = em357_get_flash_status(bank, &status); retval = em357_get_flash_status(bank, &status);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
LOG_DEBUG("status: 0x%" PRIx32 "", status); LOG_DEBUG("status: 0x%" PRIx32 "", status);
if ((status & FLASH_BSY) == 0) if ((status & FLASH_BSY) == 0)
break; break;
if (timeout-- <= 0) if (timeout-- <= 0) {
{
LOG_ERROR("timed out waiting for flash"); LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL; return ERROR_FAIL;
} }
alive_sleep(1); alive_sleep(1);
} }
if (status & FLASH_WRPRTERR) if (status & FLASH_WRPRTERR) {
{
LOG_ERROR("em357 device protected"); LOG_ERROR("em357 device protected");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
if (status & FLASH_PGERR) if (status & FLASH_PGERR) {
{
LOG_ERROR("em357 device programming failed"); LOG_ERROR("em357 device programming failed");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
/* Clear but report errors */ /* 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 /* If this operation fails, we ignore it and report the original
* retval * retval
*/ */
@ -330,8 +322,7 @@ static int em357_protect_check(struct flash_bank *bank)
int num_bits; int num_bits;
int set; int set;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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 */ /* each protection bit is for 4 * 2K pages */
num_bits = (bank->num_sectors / em357_info->ppage_size); 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; set = 1;
if (protection & (1 << i)) if (protection & (1 << i))
set = 0; set = 0;
@ -362,16 +352,13 @@ static int em357_erase(struct flash_bank *bank, int first, int last)
struct target *target = bank->target; struct target *target = bank->target;
int i; int i;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if ((first == 0) && (last == (bank->num_sectors - 1))) if ((first == 0) && (last == (bank->num_sectors - 1)))
{
return em357_mass_erase(bank); return em357_mass_erase(bank);
}
/* unlock flash registers */ /* unlock flash registers */
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); 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) if (retval != ERROR_OK)
return retval; return retval;
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER); retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -419,20 +405,17 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)
em357_info = bank->driver_priv; em357_info = bank->driver_priv;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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", 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); 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", LOG_WARNING("aligned end protect sector to a %d sector boundary",
em357_info->ppage_size); em357_info->ppage_size);
last++; 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[1] = (uint16_t)(protection >> 8);
prot_reg[2] = (uint16_t)(protection >> 16); 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; reg = (i / em357_info->ppage_size) / 8;
bit = (i / em357_info->ppage_size) - (reg * 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); prot_reg[reg] |= (1 << bit);
} }
if ((status = em357_erase_options(bank)) != ERROR_OK) status = em357_erase_options(bank);
if (retval != ERROR_OK)
return status; return status;
em357_info->option_bytes.protection[0] = prot_reg[0]; em357_info->option_bytes.protection[0] = prot_reg[0];
@ -487,18 +470,20 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
* a modified *_FLASH_BASE */ * a modified *_FLASH_BASE */
static const uint8_t em357_flash_write_code[] = { static const uint8_t em357_flash_write_code[] = {
/* #define EM357_FLASH_CR_OFFSET 0x10 */ /* #define EM357_FLASH_CR_OFFSET 0x10
/* #define EM357_FLASH_SR_OFFSET 0x0C */ * #define EM357_FLASH_SR_OFFSET 0x0C
/* write: */ * write: */
0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */ 0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */
0x1c, 0x44, /* add r4, r3 */ 0x1c, 0x44, /* add r4, r3 */
/* write_half_word: */ /* write_half_word: */
0x01, 0x23, /* movs r3, #0x01 */ 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 */ 0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */ 0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
/* busy: */ /* busy: */
0xe3, 0x68, /* ldr r3, [r4, #EM357_FLASH_SR_OFFSET] */ 0xe3, 0x68, /* ldr r3, [r4,
*#EM357_FLASH_SR_OFFSET] */
0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */ 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
0xfb, 0xd0, /* beq busy */ 0xfb, 0xd0, /* beq busy */
0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */ 0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
@ -512,32 +497,32 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
/* flash write code */ /* flash write code */
if (target_alloc_working_area(target, sizeof(em357_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"); LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}; }
;
if ((retval = target_write_buffer(target, em357_info->write_algorithm->address, retval = target_write_buffer(target, em357_info->write_algorithm->address,
sizeof(em357_flash_write_code), sizeof(em357_flash_write_code), (uint8_t *)em357_flash_write_code);
(uint8_t*)em357_flash_write_code)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
/* memory buffer */ /* 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 /= 2;
if (buffer_size <= 256) if (buffer_size <= 256) {
{
/* if we already allocated the writing code, but failed to get a /* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
if (em357_info->write_algorithm) if (em357_info->write_algorithm)
target_free_working_area(target, 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; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
}; }
;
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARMV7M_MODE_ANY; 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[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_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)) ? uint32_t thisrun_count = (count > (buffer_size / 2)) ?
(buffer_size / 2) : count; (buffer_size / 2) : count;
if ((retval = target_write_buffer(target, source->address, retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
thisrun_count * 2, buffer)) != ERROR_OK) if (retval != ERROR_OK)
break; break;
buf_set_u32(reg_params[0].value, 0, 32, source->address); 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[2].value, 0, 32, thisrun_count);
buf_set_u32(reg_params[3].value, 0, 32, 0); buf_set_u32(reg_params[3].value, 0, 32, 0);
if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
em357_info->write_algorithm->address, em357_info->write_algorithm->address, 0, 10000, &armv7m_info);
0, if (retval != ERROR_OK) {
10000, &armv7m_info)) != ERROR_OK)
{
LOG_ERROR("error executing em357 flash write algorithm"); LOG_ERROR("error executing em357 flash write algorithm");
break; 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"); LOG_ERROR("flash memory not erased before writing");
/* Clear but report errors */ /* Clear but report errors */
target_write_u32(target, EM357_FLASH_SR, FLASH_PGERR); 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; 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"); LOG_ERROR("flash memory write protected");
/* Clear but report errors */ /* Clear but report errors */
target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR); target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR);
@ -614,14 +594,12 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t bytes_written = 0; uint32_t bytes_written = 0;
int retval; int retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
@ -635,20 +613,17 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
return retval; return retval;
/* multiple half words (2-byte) to be programmed? */ /* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0) if (words_remaining > 0) {
{
/* try using a block write */ /* try using a block write */
if ((retval = em357_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) retval = em357_write_block(bank, buffer, offset, words_remaining);
{ if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
{
/* if block write failed (no sufficient working area), /* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */ * 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; buffer += words_remaining * 2;
address += words_remaining * 2; address += words_remaining * 2;
words_remaining = 0; 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)) if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
return retval; return retval;
while (words_remaining > 0) while (words_remaining > 0) {
{
uint16_t value; uint16_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); 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; address += 2;
} }
if (bytes_remaining) if (bytes_remaining) {
{
uint16_t value = 0xffff; uint16_t value = 0xffff;
memcpy(&value, buffer + bytes_written, bytes_remaining); 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); LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024);
if (bank->sectors) if (bank->sectors) {
{
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL; bank->sectors = NULL;
} }
@ -732,8 +704,7 @@ static int em357_probe(struct flash_bank *bank)
bank->num_sectors = num_pages; bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * 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].offset = i * page_size;
bank->sectors[i].size = page_size; bank->sectors[i].size = page_size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
@ -766,9 +737,7 @@ COMMAND_HANDLER(em357_handle_lock_command)
struct em357_flash_bank *em357_info = NULL; struct em357_flash_bank *em357_info = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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"); command_print(CMD_CTX, "em357 failed to erase options");
return ERROR_OK; return ERROR_OK;
} }
@ -794,8 +761,7 @@ COMMAND_HANDLER(em357_handle_lock_command)
/* set readout protection */ /* set readout protection */
em357_info->option_bytes.RDP = 0; 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"); command_print(CMD_CTX, "em357 failed to lock device");
return ERROR_OK; return ERROR_OK;
} }
@ -810,9 +776,7 @@ COMMAND_HANDLER(em357_handle_unlock_command)
struct target *target = NULL; struct target *target = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@ -821,20 +785,17 @@ COMMAND_HANDLER(em357_handle_unlock_command)
target = bank->target; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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"); command_print(CMD_CTX, "em357 failed to unlock device");
return ERROR_OK; 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"); command_print(CMD_CTX, "em357 failed to lock device");
return ERROR_OK; return ERROR_OK;
} }
@ -850,8 +811,7 @@ static int em357_mass_erase(struct flash_bank *bank)
{ {
struct target *target = bank->target; struct target *target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -888,9 +848,7 @@ COMMAND_HANDLER(em357_handle_mass_erase_command)
int i; int i;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; return retval;
retval = em357_mass_erase(bank); retval = em357_mass_erase(bank);
if (retval == ERROR_OK) if (retval == ERROR_OK) {
{
/* set all sectors as erased */ /* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++) for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1; bank->sectors[i].is_erased = 1;
}
command_print(CMD_CTX, "em357 mass erase complete"); command_print(CMD_CTX, "em357 mass erase complete");
} } else
else
{
command_print(CMD_CTX, "em357 mass erase failed"); command_print(CMD_CTX, "em357 mass erase failed");
}
return retval; return retval;
} }

View File

@ -17,6 +17,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -25,9 +26,7 @@
#include <target/image.h> #include <target/image.h>
#include "hello.h" #include "hello.h"
struct faux_flash_bank {
struct faux_flash_bank
{
struct target *target; struct target *target;
uint8_t *memory; uint8_t *memory;
uint32_t start_address; uint32_t start_address;
@ -43,19 +42,15 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
struct faux_flash_bank *info; struct faux_flash_bank *info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
info = malloc(sizeof(struct faux_flash_bank)); info = malloc(sizeof(struct faux_flash_bank));
if (info == NULL) if (info == NULL) {
{
LOG_ERROR("no memory for flash bank info"); LOG_ERROR("no memory for flash bank info");
return ERROR_FAIL; return ERROR_FAIL;
} }
info->memory = malloc(bank->size); info->memory = malloc(bank->size);
if (info == NULL) if (info == NULL) {
{
free(info); free(info);
LOG_ERROR("no memory for flash bank info"); LOG_ERROR("no memory for flash bank info");
return ERROR_FAIL; return ERROR_FAIL;
@ -67,8 +62,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
uint32_t offset = 0; uint32_t offset = 0;
bank->num_sectors = bank->size/sectorSize; bank->num_sectors = bank->size/sectorSize;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); 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].offset = offset;
bank->sectors[i].size = sectorSize; bank->sectors[i].size = sectorSize;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
@ -77,8 +71,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
} }
info->target = get_target(CMD_ARGV[5]); info->target = get_target(CMD_ARGV[5]);
if (info->target == NULL) if (info->target == NULL) {
{
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
free(info->memory); free(info->memory);
free(info); free(info);

View File

@ -31,8 +31,7 @@
#define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */ #define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */
#define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */ #define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */
enum fm3_variant enum fm3_variant {
{
mb9bfxx1, /* Flash Type '1' */ mb9bfxx1, /* Flash Type '1' */
mb9bfxx2, mb9bfxx2,
mb9bfxx3, mb9bfxx3,
@ -47,15 +46,13 @@ enum fm3_variant
mb9afxx6 mb9afxx6
}; };
enum fm3_flash_type enum fm3_flash_type {
{
fm3_no_flash_type = 0, fm3_no_flash_type = 0,
fm3_flash_type1 = 1, fm3_flash_type1 = 1,
fm3_flash_type2 = 2 fm3_flash_type2 = 2
}; };
struct fm3_flash_bank struct fm3_flash_bank {
{
struct working_area *write_algorithm; struct working_area *write_algorithm;
enum fm3_variant variant; enum fm3_variant variant;
enum fm3_flash_type flashtype; enum fm3_flash_type flashtype;

View File

@ -16,13 +16,14 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NOR_IMP_H #ifndef FLASH_NOR_IMP_H
#define FLASH_NOR_IMP_H #define FLASH_NOR_IMP_H
// this is an internal header /* this is an internal header */
#include "core.h" #include "core.h"
#include "driver.h" #include "driver.h"
// almost all drivers will need this file /* almost all drivers will need this file */
#include <target/target.h> #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, int flash_write_unlock(struct target *target, struct image *image,
uint32_t *written, int erase, bool unlock); uint32_t *written, int erase, bool unlock);
#endif // FLASH_NOR_IMP_H #endif /* FLASH_NOR_IMP_H */

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -51,9 +52,8 @@ static int kinetis_update_bank_info(struct flash_bank *bank)
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
/* update the info we do not have */ /* update the info we do not have */
bank->size = master_bank->size; bank->size = master_bank->size;
@ -69,9 +69,8 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
{ {
struct kinetis_flash_bank *bank_info; struct kinetis_flash_bank *bank_info;
if (CMD_ARGC < 6) { if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
LOG_INFO("add flash_bank kinetis %s", bank->name); LOG_INFO("add flash_bank kinetis %s", bank->name);
@ -92,9 +91,8 @@ static int kinetis_protect(struct flash_bank *bank, int set, int first,
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
LOG_WARNING("kinetis_protect not supported yet"); 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); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
/* read protection register FTFL_FPROT */ /* read protection register FTFL_FPROT */
result = target_read_memory(bank->target, 0x40020010, 1, 4, buffer); result = target_read_memory(bank->target, 0x40020010, 1, 4, buffer);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
fprot = target_buffer_get_u32(bank->target, buffer); fprot = target_buffer_get_u32(bank->target, buffer);
@ -167,9 +163,8 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
result = 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; return result;
}
if (buffer[0] & 0x80) if (buffer[0] & 0x80)
break; break;
@ -182,10 +177,9 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
buffer[0] = 0x30; buffer[0] = 0x30;
result = result =
target_write_memory(bank->target, 0x40020000, 1, 1, buffer); target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
} }
}
target_buffer_set_u32(bank->target, buffer, w0); target_buffer_set_u32(bank->target, buffer, w0);
target_buffer_set_u32(bank->target, buffer + 4, w1); target_buffer_set_u32(bank->target, buffer + 4, w1);
@ -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); result = target_write_memory(bank->target, 0x40020004, 4, 3, buffer);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
/* start command */ /* start command */
buffer[0] = 0x80; buffer[0] = 0x80;
result = target_write_memory(bank->target, 0x40020000, 1, 1, buffer); result = target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
/* wait for done */ /* wait for done */
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
result = 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; return result;
}
if (buffer[0] & 0x80) if (buffer[0] & 0x80)
break; break;
@ -243,13 +234,11 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; 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; return ERROR_FLASH_OPERATION_FAILED;
}
for (i = first; i <= last; i++) { for (i = first; i <= last; i++) {
/* set command and sector address */ /* set command and sector address */
@ -290,9 +279,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
if (offset >= kbank->nvm_start) if (offset >= kbank->nvm_start)
nvm = 1; nvm = 1;
@ -366,11 +354,10 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
result = kinetis_ftfl_command(bank, w0, w1, w2); result = kinetis_ftfl_command(bank, w0, w1, w2);
if (result != ERROR_OK) { if (result != ERROR_OK)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
} }
}
/* program longword command */ /* program longword command */
else { else {
for (i = 0; i < count; i += 4) { for (i = 0; i < count; i += 4) {
@ -381,11 +368,10 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
result = kinetis_ftfl_command(bank, w0, w1, w2); result = kinetis_ftfl_command(bank, w0, w1, w2);
if (result != ERROR_OK) { if (result != ERROR_OK)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
} }
}
return ERROR_OK; return ERROR_OK;
} }
@ -405,24 +391,20 @@ static int kinetis_probe(struct flash_bank *bank)
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
result = target_read_memory(bank->target, 0x40048024, 1, 4, buf); result = target_read_memory(bank->target, 0x40048024, 1, 4, buf);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
sim_sdid = target_buffer_get_u32(bank->target, buf); sim_sdid = target_buffer_get_u32(bank->target, buf);
result = target_read_memory(bank->target, 0x4004804c, 1, 4, buf); result = target_read_memory(bank->target, 0x4004804c, 1, 4, buf);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
sim_fcfg1 = target_buffer_get_u32(bank->target, buf); sim_fcfg1 = target_buffer_get_u32(bank->target, buf);
result = target_read_memory(bank->target, 0x40048050, 1, 4, buf); result = target_read_memory(bank->target, 0x40048050, 1, 4, buf);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
sim_fcfg2 = target_buffer_get_u32(bank->target, buf); sim_fcfg2 = target_buffer_get_u32(bank->target, buf);
LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", sim_sdid, sim_fcfg1, LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", sim_sdid, sim_fcfg1,
@ -526,9 +508,8 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size)
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
snprintf(buf, buf_size, snprintf(buf, buf_size,
"%s driver for flash bank %s at 0x%8.8" PRIx32 "", "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
@ -551,9 +532,8 @@ static int kinetis_blank_check(struct flash_bank *bank)
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
return ERROR_OK; return ERROR_OK;
} }
@ -573,9 +553,8 @@ static int kinetis_flash_read(struct flash_bank *bank,
result = kinetis_get_master_bank(bank, &master_bank); result = kinetis_get_master_bank(bank, &master_bank);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
return ERROR_OK; return ERROR_OK;
} }

View File

@ -61,15 +61,13 @@
* - 176x (tested with LPC1768) * - 176x (tested with LPC1768)
*/ */
typedef enum typedef enum {
{
lpc2000_v1, lpc2000_v1,
lpc2000_v2, lpc2000_v2,
lpc1700 lpc1700
} lpc2000_variant; } lpc2000_variant;
struct lpc2000_flash_bank struct lpc2000_flash_bank {
{
lpc2000_variant variant; lpc2000_variant variant;
struct working_area *iap_working_area; struct working_area *iap_working_area;
uint32_t cclk; uint32_t cclk;
@ -81,8 +79,7 @@ struct lpc2000_flash_bank
int checksum_vector; int checksum_vector;
}; };
enum lpc2000_status_codes enum lpc2000_status_codes {
{
LPC2000_CMD_SUCCESS = 0, LPC2000_CMD_SUCCESS = 0,
LPC2000_INVALID_COMMAND = 1, LPC2000_INVALID_COMMAND = 1,
LPC2000_SRC_ADDR_ERROR = 2, 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 */ /* default to a 4096 write buffer */
lpc2000_info->cmd51_max_buffer = 4096; 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 */ /* 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->num_sectors = 16;
bank->sectors = malloc(sizeof(struct flash_sector) * 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].offset = offset;
bank->sectors[i].size = 8 * 1024; bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
} }
} } else if (bank->size == 256 * 1024) {
else if (bank->size == 256 * 1024)
{
bank->num_sectors = 18; bank->num_sectors = 18;
bank->sectors = malloc(sizeof(struct flash_sector) * 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].offset = offset;
bank->sectors[i].size = 8 * 1024; bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 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].offset = offset;
bank->sectors[i].size = 64 * 1024; bank->sectors[i].size = 64 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 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].offset = offset;
bank->sectors[i].size = 8 * 1024; bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
} }
} } else {
else
{
LOG_ERROR("BUG: unknown bank->size encountered"); LOG_ERROR("BUG: unknown bank->size encountered");
exit(-1); 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 */ /* variant 2 has a uniform layout, only number of sectors differs */
switch (bank->size) switch (bank->size) {
{
case 4 * 1024: case 4 * 1024:
lpc2000_info->cmd51_max_buffer = 1024; lpc2000_info->cmd51_max_buffer = 1024;
bank->num_sectors = 1; 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); 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++) {
{ if (i < 8) {
if (i < 8)
{
bank->sectors[i].offset = offset; bank->sectors[i].offset = offset;
bank->sectors[i].size = 4 * 1024; bank->sectors[i].size = 4 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
} } else if (i < 22) {
else if (i < 22)
{
bank->sectors[i].offset = offset; bank->sectors[i].offset = offset;
bank->sectors[i].size = 32 * 1024; bank->sectors[i].size = 32 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
} } else if (i < 28) {
else if (i < 28)
{
bank->sectors[i].offset = offset; bank->sectors[i].offset = offset;
bank->sectors[i].size = 4 * 1024; bank->sectors[i].size = 4 * 1024;
offset += bank->sectors[i].size; 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; bank->sectors[i].is_protected = 1;
} }
} }
} } else if (lpc2000_info->variant == lpc1700) {
else if (lpc2000_info->variant == lpc1700) switch (bank->size) {
{
switch(bank->size)
{
case 32 * 1024: case 32 * 1024:
bank->num_sectors = 8; bank->num_sectors = 8;
break; 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); 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].offset = offset;
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */ /* 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; bank->sectors[i].size = (i < 16) ? 4 * 1024 : 32 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
} }
} } else {
else
{
LOG_ERROR("BUG: unknown lpc2000_info->variant encountered"); LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
exit(-1); exit(-1);
} }
@ -289,7 +262,10 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
* 0x20 to 0x33: command result table (1+4 words) * 0x20 to 0x33: command result table (1+4 words)
* 0x34 to 0xb3: stack (only 128b needed) * 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; int retval;
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
@ -302,25 +278,21 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
uint32_t iap_entry_point = 0; /* to make compiler happier */ uint32_t iap_entry_point = 0; /* to make compiler happier */
/* regrab previously allocated working_area, or allocate a new one */ /* 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]; uint8_t jump_gate[8];
/* make sure we have a working area */ /* 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"); LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
/* write IAP code to working area */ /* write IAP code to working area */
switch(lpc2000_info->variant) switch (lpc2000_info->variant) {
{
case lpc1700: case lpc1700:
target_buffer_set_u32(target, jump_gate, target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
ARMV4_5_T_BX(12)); target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
target_buffer_set_u32(target, jump_gate + 4,
ARMV5_T_BKPT(0));
break; break;
case lpc2000_v1: case lpc2000_v1:
case lpc2000_v2: case lpc2000_v2:
@ -332,15 +304,17 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
exit(-1); exit(-1);
} }
if ((retval = target_write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK) retval = target_write_memory(target,
{ lpc2000_info->iap_working_area->address, 4, 2, jump_gate);
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", lpc2000_info->iap_working_area->address); 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; return retval;
} }
} }
switch(lpc2000_info->variant) switch (lpc2000_info->variant) {
{
case lpc1700: case lpc1700:
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARMV7M_MODE_ANY; 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 */ /* 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, code);
target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]); 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]); 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); buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);
/* command result table */ /* 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); 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); buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
@ -380,30 +358,38 @@ 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); init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point); buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
switch(lpc2000_info->variant) switch (lpc2000_info->variant) {
{
case lpc1700: case lpc1700:
/* IAP stack */ /* IAP stack */
init_reg_param(&reg_params[3], "sp", 32, PARAM_OUT); 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 */ /* return address */
init_reg_param(&reg_params[4], "lr", 32, PARAM_OUT); 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; break;
case lpc2000_v1: case lpc2000_v1:
case lpc2000_v2: case lpc2000_v2:
/* IAP stack */ /* IAP stack */
init_reg_param(&reg_params[3], "sp_svc", 32, PARAM_OUT); 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 */ /* return address */
init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT); 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; break;
default: default:
LOG_ERROR("BUG: unknown lpc2000->variant encountered"); LOG_ERROR("BUG: unknown lpc2000->variant encountered");
@ -416,8 +402,11 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c); 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); 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, LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32
code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code); ", 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[0]);
destroy_mem_param(&mem_params[1]); 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)) if ((first < 0) || (last >= bank->num_sectors))
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
/* check single sector */ /* check single sector */
param_table[0] = param_table[1] = i; param_table[0] = param_table[1] = i;
status_code = lpc2000_iap_call(bank, 53, param_table, result_table); status_code = lpc2000_iap_call(bank, 53, param_table, result_table);
switch (status_code) switch (status_code) {
{
case ERROR_FLASH_OPERATION_FAILED: case ERROR_FLASH_OPERATION_FAILED:
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
case LPC2000_CMD_SUCCESS: case LPC2000_CMD_SUCCESS:
@ -480,39 +467,30 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
struct lpc2000_flash_bank *lpc2000_info; struct lpc2000_flash_bank *lpc2000_info;
if (CMD_ARGC < 8) if (CMD_ARGC < 8)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
lpc2000_info = malloc(sizeof(struct lpc2000_flash_bank)); lpc2000_info = malloc(sizeof(struct lpc2000_flash_bank));
bank->driver_priv = lpc2000_info; 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->variant = lpc2000_v1;
lpc2000_info->cmd51_dst_boundary = 512; lpc2000_info->cmd51_dst_boundary = 512;
lpc2000_info->cmd51_can_256b = 0; lpc2000_info->cmd51_can_256b = 0;
lpc2000_info->cmd51_can_8192b = 1; lpc2000_info->cmd51_can_8192b = 1;
lpc2000_info->checksum_vector = 5; 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->variant = lpc2000_v2;
lpc2000_info->cmd51_dst_boundary = 256; lpc2000_info->cmd51_dst_boundary = 256;
lpc2000_info->cmd51_can_256b = 1; lpc2000_info->cmd51_can_256b = 1;
lpc2000_info->cmd51_can_8192b = 0; lpc2000_info->cmd51_can_8192b = 0;
lpc2000_info->checksum_vector = 5; 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->variant = lpc1700;
lpc2000_info->cmd51_dst_boundary = 256; lpc2000_info->cmd51_dst_boundary = 256;
lpc2000_info->cmd51_can_256b = 1; lpc2000_info->cmd51_can_256b = 1;
lpc2000_info->cmd51_can_8192b = 0; lpc2000_info->cmd51_can_8192b = 0;
lpc2000_info->checksum_vector = 7; lpc2000_info->checksum_vector = 7;
} } else {
else
{
LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]); LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]);
free(lpc2000_info); free(lpc2000_info);
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
@ -523,8 +501,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
lpc2000_info->calc_checksum = 0; lpc2000_info->calc_checksum = 0;
lpc2000_build_sector_list(bank); lpc2000_build_sector_list(bank);
if (CMD_ARGC >= 9) if (CMD_ARGC >= 9) {
{
if (strcmp(CMD_ARGV[8], "calc_checksum") == 0) if (strcmp(CMD_ARGV[8], "calc_checksum") == 0)
lpc2000_info->calc_checksum = 1; 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]; uint32_t result_table[4];
int status_code; int status_code;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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 */ /* Prepare sectors */
status_code = lpc2000_iap_call(bank, 50, param_table, result_table); status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
switch (status_code) switch (status_code) {
{
case ERROR_FLASH_OPERATION_FAILED: case ERROR_FLASH_OPERATION_FAILED:
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
case LPC2000_CMD_SUCCESS: case LPC2000_CMD_SUCCESS:
@ -567,8 +542,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)
/* Erase sectors */ /* Erase sectors */
status_code = lpc2000_iap_call(bank, 52, param_table, result_table); status_code = lpc2000_iap_call(bank, 52, param_table, result_table);
switch (status_code) switch (status_code) {
{
case ERROR_FLASH_OPERATION_FAILED: case ERROR_FLASH_OPERATION_FAILED:
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
case LPC2000_CMD_SUCCESS: 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; struct working_area *download_area;
int retval = ERROR_OK; int retval = ERROR_OK;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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; dst_min_alignment = lpc2000_info->cmd51_dst_boundary;
if (offset % dst_min_alignment) if (offset % dst_min_alignment) {
{ LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32,
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, offset, dst_min_alignment); offset,
dst_min_alignment);
return ERROR_FLASH_DST_BREAKS_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) if (offset >= bank->sectors[i].offset)
first_sector = i; 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; last_sector = i;
} }
LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector); LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
/* check if exception vectors should be flashed */ /* 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; uint32_t checksum = 0;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
{ LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4,
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32)); buf_get_u32(buffer + (i * 4), 0, 32));
if (i != lpc2000_info->checksum_vector) if (i != lpc2000_info->checksum_vector)
checksum += buf_get_u32(buffer + (i * 4), 0, 32); checksum += buf_get_u32(buffer + (i * 4), 0, 32);
} }
checksum = 0 - checksum; checksum = 0 - checksum;
LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum); LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);
uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32); uint32_t original_value = buf_get_u32(buffer +
if (original_value != checksum) (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 ").", LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") "
original_value, checksum); "to be written to flash is different from calculated vector "
LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum."); "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); buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
} }
/* allocate a working area */ /* 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"); LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
while (bytes_remaining > 0) while (bytes_remaining > 0) {
{
uint32_t thisrun_bytes; uint32_t thisrun_bytes;
if (bytes_remaining >= lpc2000_info->cmd51_max_buffer) if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
thisrun_bytes = 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[0] = first_sector;
param_table[1] = last_sector; param_table[1] = last_sector;
status_code = lpc2000_iap_call(bank, 50, param_table, result_table); status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
switch (status_code) switch (status_code) {
{
case ERROR_FLASH_OPERATION_FAILED: case ERROR_FLASH_OPERATION_FAILED:
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; break;
@ -700,24 +673,28 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
if (retval != ERROR_OK) if (retval != ERROR_OK)
break; break;
if (bytes_remaining >= thisrun_bytes) if (bytes_remaining >= thisrun_bytes) {
{ retval = target_write_buffer(bank->target, download_area->address,
if ((retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written)) != ERROR_OK) thisrun_bytes, buffer + bytes_written);
{ if (retval != ERROR_OK) {
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; break;
} }
} } else {
else
{
uint8_t *last_buffer = malloc(thisrun_bytes); uint8_t *last_buffer = malloc(thisrun_bytes);
memcpy(last_buffer, buffer + bytes_written, bytes_remaining); memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining); memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes -
target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer); bytes_remaining);
target_write_buffer(bank->target,
download_area->address,
thisrun_bytes,
last_buffer);
free(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 */ /* Write data */
param_table[0] = bank->base + offset + bytes_written; 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[2] = thisrun_bytes;
param_table[3] = lpc2000_info->cclk; param_table[3] = lpc2000_info->cclk;
status_code = lpc2000_iap_call(bank, 51, param_table, result_table); status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
switch (status_code) switch (status_code) {
{
case ERROR_FLASH_OPERATION_FAILED: case ERROR_FLASH_OPERATION_FAILED:
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; break;
@ -767,8 +743,7 @@ static int lpc2000_probe(struct flash_bank *bank)
static int lpc2000_erase_check(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"); LOG_ERROR("Target not halted");
return 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; 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; return ERROR_OK;
} }
@ -798,34 +777,28 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command)
int status_code; int status_code;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0) status_code = lpc2000_iap_call(bank, 54, param_table, result_table);
{ if (status_code != 0x0) {
if (status_code == ERROR_FLASH_OPERATION_FAILED) if (status_code == ERROR_FLASH_OPERATION_FAILED) {
{ command_print(CMD_CTX,
command_print(CMD_CTX, "no sufficient working area specified, can't access LPC2000 IAP interface"); "no sufficient working area specified, can't access LPC2000 IAP interface");
return ERROR_OK; return ERROR_OK;
} }
command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code); command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code);
} } else
else
{
command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, result_table[0]); command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, result_table[0]);
}
return ERROR_OK; return ERROR_OK;
} }

View File

@ -34,7 +34,6 @@
#include "imp.h" #include "imp.h"
#include <helper/binarybuffer.h> #include <helper/binarybuffer.h>
#define LOAD_TIMER_ERASE 0 #define LOAD_TIMER_ERASE 0
#define LOAD_TIMER_WRITE 1 #define LOAD_TIMER_WRITE 1
@ -47,15 +46,18 @@
#define F_STAT 0x80102004 /* Flash status register RO 0x45 */ #define F_STAT 0x80102004 /* Flash status register RO 0x45 */
#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */ #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_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_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_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
#define F_INTEN_SET 0x80102FDC /* Set 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_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
#define F_INTEN 0x80102FE4 /* Interrupt enable 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_CLR 0x80102FE8 /* Clear interrupt status bits WO */
#define F_INT_SET 0x80102FEC /* Set 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_PD 0x80005030 /* Allows turning off the Flash memory for power
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from Power Down mode. R/W -*/ *savings. R/W 1*/
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from
*Power Down mode. R/W -*/
/* F_CTRL bits */ /* F_CTRL bits */
#define FC_CS 0x0001 #define FC_CS 0x0001
@ -84,8 +86,7 @@
/* F_CLK_TIME */ /* F_CLK_TIME */
#define FCT_CLK_DIV_MASK 0x0FFF #define FCT_CLK_DIV_MASK 0x0FFF
struct lpc288x_flash_bank struct lpc288x_flash_bank {
{
uint32_t working_area; uint32_t working_area;
uint32_t working_area_size; uint32_t working_area_size;
@ -106,15 +107,13 @@ static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout)
{ {
uint32_t status; uint32_t status;
struct target *target = bank->target; struct target *target = bank->target;
do do {
{
alive_sleep(1); alive_sleep(1);
timeout--; timeout--;
target_read_u32(target, F_STAT, &status); target_read_u32(target, F_STAT, &status);
} while (((status & FS_DONE) == 0) && timeout); } while (((status & FS_DONE) == 0) && timeout);
if (timeout == 0) if (timeout == 0) {
{
LOG_DEBUG("Timedout!"); LOG_DEBUG("Timedout!");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -132,13 +131,13 @@ static int lpc288x_read_part_info(struct flash_bank *bank)
uint32_t offset; uint32_t offset;
if (lpc288x_info->cidr == 0x0102100A) 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 */ /* Read and parse chip identification register */
target_read_u32(target, DBGU_CIDR, &cidr); target_read_u32(target, DBGU_CIDR, &cidr);
if (cidr != 0x0102100A) if (cidr != 0x0102100A) {
{
LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr); LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -152,16 +151,14 @@ static int lpc288x_read_part_info(struct flash_bank *bank)
bank->num_sectors = 23; bank->num_sectors = 23;
bank->sectors = malloc(sizeof(struct flash_sector) * 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].offset = offset;
bank->sectors[i].size = 64 * 1024; bank->sectors[i].size = 64 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 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].offset = offset;
bank->sectors[i].size = 8 * 1024; bank->sectors[i].size = 8 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
@ -183,9 +180,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command)
struct lpc288x_flash_bank *lpc288x_info; struct lpc288x_flash_bank *lpc288x_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank)); lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank));
bank->driver_priv = lpc288x_info; 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) static void lpc288x_load_timer(int erase, struct target *target)
{ {
if (erase == LOAD_TIMER_ERASE) if (erase == LOAD_TIMER_ERASE)
{
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500); target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
}
else else
{
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75); target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
} }
}
static uint32_t lpc288x_system_ready(struct flash_bank *bank) static uint32_t lpc288x_system_ready(struct flash_bank *bank)
{ {
struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv; struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
if (lpc288x_info->cidr == 0) if (lpc288x_info->cidr == 0)
{
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
}
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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) static int lpc288x_erase_check(struct flash_bank *bank)
{ {
uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */ uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
if (status != ERROR_OK) if (status != ERROR_OK) {
{
LOG_INFO("Processor not halted/not probed"); LOG_INFO("Processor not halted/not probed");
return status; return status;
} }
@ -265,12 +252,9 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last)
status = lpc288x_system_ready(bank); /* probed? halted? */ status = lpc288x_system_ready(bank); /* probed? halted? */
if (status != ERROR_OK) if (status != ERROR_OK)
{
return status; 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"); LOG_INFO("Bad sector range");
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
} }
@ -278,12 +262,9 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last)
/* Configure the flash controller timing */ /* Configure the flash controller timing */
lpc288x_set_flash_clk(bank); 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) if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
lpc288x_load_timer(LOAD_TIMER_ERASE, target); lpc288x_load_timer(LOAD_TIMER_ERASE, target);
@ -292,9 +273,7 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last)
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS); target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
} }
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK; return ERROR_OK;
} }
@ -310,39 +289,34 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
/* probed? halted? */ /* probed? halted? */
status = lpc288x_system_ready(bank); status = lpc288x_system_ready(bank);
if (status != ERROR_OK) if (status != ERROR_OK)
{
return status; return status;
}
/* Initialise search indices */ /* Initialise search indices */
first_sector = last_sector = 0xffffffff; first_sector = last_sector = 0xffffffff;
/* validate the write range... */ /* 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) && if ((offset >= bank->sectors[i].offset) &&
(offset < (bank->sectors[i].offset + bank->sectors[i].size)) && (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
(first_sector == 0xffffffff)) (first_sector == 0xffffffff)) {
{
first_sector = i; first_sector = i;
/* all writes must start on a sector boundary... */ /* all writes must start on a sector boundary... */
if (offset % bank->sectors[i].size) if (offset % bank->sectors[i].size) {
{ LOG_INFO(
LOG_INFO("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, bank->sectors[i].size); "offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
offset,
bank->sectors[i].size);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
} }
if (((offset + count) > bank->sectors[i].offset) && if (((offset + count) > bank->sectors[i].offset) &&
((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) && ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
(last_sector == 0xffffffff)) (last_sector == 0xffffffff))
{
last_sector = i; last_sector = i;
} }
}
/* Range check... */ /* 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); LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
return ERROR_FLASH_DST_OUT_OF_BANK; 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; source_offset = 0;
dest_offset = 0; dest_offset = 0;
for (sector = first_sector; sector <= last_sector; sector++) for (sector = first_sector; sector <= last_sector; sector++) {
{ for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) {
for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) if (bytes_remaining == 0) {
{
if (bytes_remaining == 0)
{
count = 0; count = 0;
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE); memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
} } else if (bytes_remaining < FLASH_PAGE_SIZE) {
else if (bytes_remaining < FLASH_PAGE_SIZE)
{
count = bytes_remaining; count = bytes_remaining;
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE); memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
memcpy(page_buffer, &buffer[source_offset], count); memcpy(page_buffer, &buffer[source_offset], count);
} } else {
else
{
count = FLASH_PAGE_SIZE; count = FLASH_PAGE_SIZE;
memcpy(page_buffer, &buffer[source_offset], count); memcpy(page_buffer, &buffer[source_offset], count);
} }
/* Wait for flash to become ready */ /* Wait for flash to become ready */
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* fill flash data latches with 1's */ /* fill flash data latches with 1's */
target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC); 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.... * it seems not to be a LOT slower....
* bulk_write_memory() is no quicker :(*/ * bulk_write_memory() is no quicker :(*/
#if 1 #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); LOG_ERROR("Write failed s %" PRIx32 " p %" PRIx32 "", sector, page);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
#else #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"); LOG_INFO("Write to flash buffer failed");
return ERROR_FLASH_OPERATION_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); 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; int retval;
if (lpc288x_info->cidr != 0) 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"); LOG_ERROR("Target not halted");
return 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? */ /* probed? halted? */
status = lpc288x_system_ready(bank); status = lpc288x_system_ready(bank);
if (status != ERROR_OK) if (status != ERROR_OK)
{
return status; return status;
}
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) if ((first < 0) || (last < first) || (last >= bank->num_sectors))
{
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
}
/* Configure the flash controller timing */ /* Configure the flash controller timing */
lpc288x_set_flash_clk(bank); lpc288x_set_flash_clk(bank);
for (lockregion = first; lockregion <= last; lockregion++) for (lockregion = first; lockregion <= last; lockregion++) {
{ if (set) {
if (set)
{
/* write an odd value to base addy to protect... */ /* write an odd value to base addy to protect... */
value = 0x01; value = 0x01;
} } else {
else
{
/* write an even value to base addy to unprotect... */ /* write an even value to base addy to unprotect... */
value = 0x00; value = 0x00;
} }
target_write_u32(target, bank->sectors[lockregion].offset, value); 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; return ERROR_OK;

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -27,7 +28,6 @@
#include "cfi.h" #include "cfi.h"
#include "non_cfi.h" #include "non_cfi.h"
#define KB 1024 #define KB 1024
#define MB (1024*1024) #define MB (1024*1024)
#define ERASE_REGION(num, size) (((size/256) << 16) | (num-1)) #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, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(16, 4*KB) ERASE_REGION(16, 4*KB)
} }
}, },
@ -57,8 +56,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(32, 4*KB) ERASE_REGION(32, 4*KB)
} }
}, },
@ -71,8 +69,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(64, 4*KB) ERASE_REGION(64, 4*KB)
} }
}, },
@ -85,8 +82,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(128, 4*KB) ERASE_REGION(128, 4*KB)
} }
}, },
@ -99,8 +95,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(8, 64*KB) ERASE_REGION(8, 64*KB)
} }
}, },
@ -113,8 +108,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(128, 4*KB) ERASE_REGION(128, 4*KB)
} }
}, },
@ -127,8 +121,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -144,8 +137,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(7, 64*KB), ERASE_REGION(7, 64*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
@ -168,8 +160,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(512, 4*KB) ERASE_REGION(512, 4*KB)
} }
}, },
@ -182,8 +173,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1024, 4*KB) ERASE_REGION(1024, 4*KB)
} }
}, },
@ -196,8 +186,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(512, 4*KB) ERASE_REGION(512, 4*KB)
} }
}, },
@ -210,8 +199,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(512, 4*KB) ERASE_REGION(512, 4*KB)
} }
}, },
@ -224,8 +212,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(512, 4*KB) ERASE_REGION(512, 4*KB)
} }
}, },
@ -238,8 +225,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1024, 4*KB) ERASE_REGION(1024, 4*KB)
} }
}, },
@ -252,8 +238,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1024, 4*KB) ERASE_REGION(1024, 4*KB)
} }
}, },
@ -266,8 +251,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
.num_erase_regions = 1, .num_erase_regions = 1,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(2048, 4*KB) ERASE_REGION(2048, 4*KB)
} }
}, },
@ -280,8 +264,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -297,8 +280,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(7, 64*KB), ERASE_REGION(7, 64*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
@ -314,8 +296,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -331,8 +312,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(15, 64*KB), ERASE_REGION(15, 64*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
@ -348,8 +328,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x00, .max_buf_write_size = 0x00,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -365,8 +344,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -382,8 +360,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -400,8 +377,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -417,8 +393,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(31, 64*KB), ERASE_REGION(31, 64*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
@ -434,8 +409,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -451,8 +425,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 3, .num_erase_regions = 3,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(8, 8*KB), ERASE_REGION(8, 8*KB),
ERASE_REGION(2, 32*KB), ERASE_REGION(2, 32*KB),
ERASE_REGION(30, 64*KB) ERASE_REGION(30, 64*KB)
@ -467,8 +440,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 3, .num_erase_regions = 3,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(30, 64*KB), ERASE_REGION(30, 64*KB),
ERASE_REGION(2, 32*KB), ERASE_REGION(2, 32*KB),
ERASE_REGION(8, 8*KB) ERASE_REGION(8, 8*KB)
@ -483,8 +455,7 @@ static struct non_cfi non_cfi_flashes[] = {
.max_buf_write_size = 0x0, .max_buf_write_size = 0x0,
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
.num_erase_regions = 4, .num_erase_regions = 4,
.erase_region_info = .erase_region_info = {
{
ERASE_REGION(1, 16*KB), ERASE_REGION(1, 16*KB),
ERASE_REGION(2, 8*KB), ERASE_REGION(2, 8*KB),
ERASE_REGION(1, 32*KB), ERASE_REGION(1, 32*KB),
@ -508,14 +479,11 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
else else
mask = 0xFFFF; 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) if ((cfi_info->manufacturer == non_cfi->mfr)
&& (cfi_info->device_id == (non_cfi->id & mask))) && (cfi_info->device_id == (non_cfi->id & mask)))
{
break; break;
} }
}
/* only fixup jedec flashs found in table */ /* only fixup jedec flashs found in table */
if (!non_cfi->mfr) if (!non_cfi->mfr)
@ -560,8 +528,7 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
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; 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)); struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
pri_ext->pri[0] = 'P'; pri_ext->pri[0] = 'P';
@ -589,8 +556,7 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
pri_ext->_reversed_geometry = 0; pri_ext->_reversed_geometry = 0;
cfi_info->pri_ext = pri_ext; 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"); LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
exit(-1); exit(-1);
} }

View File

@ -17,11 +17,11 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef NON_CFI_H #ifndef NON_CFI_H
#define NON_CFI_H #define NON_CFI_H
struct non_cfi struct non_cfi {
{
uint16_t mfr; uint16_t mfr;
uint16_t id; uint16_t id;
uint16_t pri_id; uint16_t pri_id;

View File

@ -17,6 +17,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -25,9 +26,7 @@
#include "ocl.h" #include "ocl.h"
#include <target/embeddedice.h> #include <target/embeddedice.h>
struct ocl_priv {
struct ocl_priv
{
struct arm_jtag *jtag_info; struct arm_jtag *jtag_info;
unsigned int buflen; unsigned int buflen;
unsigned int bufalign; unsigned int bufalign;
@ -50,9 +49,7 @@ FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
struct ocl_priv *ocl; struct ocl_priv *ocl;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
arm7_9 = target_to_arm7_9(bank->target); arm7_9 = target_to_arm7_9(bank->target);
if (!is_arm7_9(arm7_9)) 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) if (bank->num_sectors == 0)
return ERROR_FLASH_BANK_NOT_PROBED; 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"); LOG_ERROR("target has to be running to communicate with the loader");
return ERROR_TARGET_NOT_RUNNING; 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; 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; return retval;
} } else {
else
{
dcc_buffer[0] = OCL_ERASE_BLOCK; dcc_buffer[0] = OCL_ERASE_BLOCK;
dcc_buffer[1] = first; dcc_buffer[1] = first;
dcc_buffer[2] = last; 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; return retval;
} }
/* wait for response, fixed timeout of 1 s */ /* 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; return retval;
}
/* receive response */ /* 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; return retval;
if (dcc_buffer[1] != OCL_CMD_DONE) if (dcc_buffer[1] != OCL_CMD_DONE) {
{
if (dcc_buffer[0] == OCL_ERASE_ALL) if (dcc_buffer[0] == OCL_ERASE_ALL)
LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]); LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
else 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) if (ocl->buflen == 0 || ocl->bufalign == 0)
return ERROR_FLASH_BANK_NOT_PROBED; 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"); LOG_ERROR("target has to be running to communicate with the loader");
return ERROR_TARGET_NOT_RUNNING; 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 */ /* allocate buffer for max. ocl buffer + overhead */
dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3)); dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
while (count) while (count) {
{
if (count + (offset % ocl->bufalign) > ocl->buflen) if (count + (offset % ocl->bufalign) > ocl->buflen)
runlen = ocl->buflen - (offset % ocl->bufalign); runlen = ocl->buflen - (offset % ocl->bufalign);
else else
@ -165,10 +157,8 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
chksum = OCL_CHKS_INIT; chksum = OCL_CHKS_INIT;
/* copy data to DCC buffer in proper byte order and properly aligned */ /* copy data to DCC buffer in proper byte order and properly aligned */
for (i = 0; i < runlen; i++) for (i = 0; i < runlen; i++) {
{ switch (byteofs++) {
switch (byteofs++)
{
case 0: case 0:
*dcc_bufptr &= *(buffer++) | 0xffffff00; *dcc_bufptr &= *(buffer++) | 0xffffff00;
break; break;
@ -194,28 +184,27 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
*(dcc_bufptr++) = chksum; *(dcc_bufptr++) = chksum;
/* send the data */ /* 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); free(dcc_buffer);
return retval; return retval;
} }
/* wait for response, fixed timeout of 1 s */ /* 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); free(dcc_buffer);
return retval; return retval;
} }
/* receive response */ /* 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); free(dcc_buffer);
return retval; 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]); LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
free(dcc_buffer); free(dcc_buffer);
return ERROR_FLASH_OPERATION_FAILED; 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); embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
dcc_buffer[0] = OCL_PROBE; 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; return retval;
/* wait for response, fixed timeout of 1 s */ /* 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; return retval;
}
/* receive response */ /* 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; 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]); LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
/* receive and fill in parameters, detection of loader is important, receive it one by one */ /* 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_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval; return retval;
bank->base = dcc_buffer[0]; bank->base = dcc_buffer[0];
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK) retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval; return retval;
bank->size = dcc_buffer[0]; bank->size = dcc_buffer[0];
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK) retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval; return retval;
bank->num_sectors = dcc_buffer[0]; bank->num_sectors = dcc_buffer[0];
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK) retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) if (retval != ERROR_OK)
return retval;
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
if (retval != ERROR_OK)
return retval; return retval;
ocl->buflen = dcc_buffer[0] & 0xffff; ocl->buflen = dcc_buffer[0] & 0xffff;
ocl->bufalign = dcc_buffer[0] >> 16; ocl->bufalign = dcc_buffer[0] >> 16;
bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors); 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"); LOG_ERROR("number of sectors shall be non zero value");
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
} }
@ -293,8 +293,7 @@ static int ocl_probe(struct flash_bank *bank)
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
} }
sectsize = bank->size / bank->num_sectors; 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].offset = i * sectsize;
bank->sectors[i].size = sectsize; bank->sectors[i].size = sectsize;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
@ -304,20 +303,17 @@ static int ocl_probe(struct flash_bank *bank)
if (ocl->bufalign == 0) if (ocl->bufalign == 0)
ocl->bufalign = 1; ocl->bufalign = 1;
if (ocl->buflen == 0) if (ocl->buflen == 0) {
{
LOG_ERROR("buflen shall be non zero value"); LOG_ERROR("buflen shall be non zero value");
return ERROR_FLASH_BANK_INVALID; 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"); LOG_ERROR("buflen is not multiple of bufalign");
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
} }
if (ocl->buflen % 4) if (ocl->buflen % 4) {
{
LOG_ERROR("buflen shall be divisible by 4"); LOG_ERROR("buflen shall be divisible by 4");
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
} }

View File

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

View File

@ -23,6 +23,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -90,8 +91,7 @@
#define NVMKEY1 0xAA996655 #define NVMKEY1 0xAA996655
#define NVMKEY2 0x556699AA #define NVMKEY2 0x556699AA
struct pic32mx_flash_bank struct pic32mx_flash_bank {
{
struct working_area *write_algorithm; struct working_area *write_algorithm;
int probed; int probed;
}; };
@ -171,9 +171,7 @@ FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
struct pic32mx_flash_bank *pic32mx_info; struct pic32mx_flash_bank *pic32mx_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank)); pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
bank->driver_priv = pic32mx_info; 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; uint32_t status;
/* wait for busy to clear */ /* 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); LOG_DEBUG("status: 0x%" PRIx32, status);
alive_sleep(1); alive_sleep(1);
} }
@ -240,8 +237,7 @@ static int pic32mx_protect_check(struct flash_bank *bank)
int s; int s;
int num_pages; int num_pages;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -250,14 +246,12 @@ static int pic32mx_protect_check(struct flash_bank *bank)
if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */ if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
num_pages = 0xffff; /* All pages protected */ num_pages = 0xffff; /* All pages protected */
else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
{
if (devcfg0 & (1 << 24)) if (devcfg0 & (1 << 24))
num_pages = 0; /* All pages unprotected */ num_pages = 0; /* All pages unprotected */
else else
num_pages = 0xffff; /* All pages protected */ num_pages = 0xffff; /* All pages protected */
} } else /* pgm flash */
else /* pgm flash */
num_pages = (~devcfg0 >> 12) & 0xff; num_pages = (~devcfg0 >> 12) & 0xff;
for (s = 0; s < bank->num_sectors && s < num_pages; s++) 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; int i;
uint32_t status; uint32_t status;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if ((first == 0) && (last == (bank->num_sectors - 1)) 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) /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
* we need to use the MTAP to perform a full erase */ * we need to use the MTAP to perform a full erase */
LOG_DEBUG("Erasing entire program flash"); 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; 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)); target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset));
status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10); 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; struct target *target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -407,24 +397,20 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,
/* flash write code */ /* flash write code */
if (target_alloc_working_area(target, sizeof(pic32mx_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"); LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}; };
if ((retval = target_write_buffer(target, retval = target_write_buffer(target, pic32mx_info->write_algorithm->address,
pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), (uint8_t *)pic32mx_flash_write_code);
sizeof(pic32mx_flash_write_code), if (retval != ERROR_OK)
(uint8_t*)pic32mx_flash_write_code)) != ERROR_OK)
return retval; return retval;
/* memory buffer */ /* 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 /= 2;
if (buffer_size <= 256) if (buffer_size <= 256) {
{
/* if we already allocated the writing code, but failed to get a /* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
if (pic32mx_info->write_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[1], "a1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "a2", 32, PARAM_OUT); init_reg_param(&reg_params[2], "a2", 32, PARAM_OUT);
while (count > 0) while (count > 0) {
{
uint32_t status; uint32_t status;
uint32_t thisrun_count = (count > (buffer_size / 4)) ? uint32_t thisrun_count = (count > (buffer_size / 4)) ?
(buffer_size / 4) : count; (buffer_size / 4) : count;
if ((retval = target_write_buffer(target, source->address, retval = target_write_buffer(target, source->address,
thisrun_count * 4, buffer)) != ERROR_OK) thisrun_count * 4, buffer);
if (retval != ERROR_OK)
break; break;
buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address)); 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[1].value, 0, 32, Virt2Phys(address));
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); 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, pic32mx_info->write_algorithm->address,
0, 0, 10000, &mips32_info);
10000, &mips32_info)) != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("error executing pic32mx flash write algorithm"); LOG_ERROR("error executing pic32mx flash write algorithm");
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; 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); 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); LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; break;
} }
if (status & NVMCON_LVDERR) if (status & NVMCON_LVDERR) {
{
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; break;
@ -516,8 +499,7 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
uint32_t status; uint32_t status;
int retval; int retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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 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); " 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); LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
/* multiple words (4-byte) to be programmed? */ /* multiple words (4-byte) to be programmed? */
if (words_remaining > 0) if (words_remaining > 0) {
{
/* try using a block write */ /* try using a block write */
if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) retval = pic32mx_write_block(bank, buffer, offset, words_remaining);
{ if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
{
/* if block write failed (no sufficient working area), /* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */ * 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 if (retval == ERROR_FLASH_OPERATION_FAILED) {
else if (retval == ERROR_FLASH_OPERATION_FAILED)
{
LOG_ERROR("flash writing failed"); LOG_ERROR("flash writing failed");
return retval; return retval;
} }
} } else {
else
{
buffer += words_remaining * 4; buffer += words_remaining * 4;
address += words_remaining * 4; address += words_remaining * 4;
words_remaining = 0; words_remaining = 0;
} }
} }
while (words_remaining > 0) while (words_remaining > 0) {
{
uint32_t value; uint32_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint32_t)); memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
status = pic32mx_write_word(bank, address, value); 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); LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
if (status & NVMCON_LVDERR) if (status & NVMCON_LVDERR) {
{
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED; 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; address += 4;
} }
if (bytes_remaining) if (bytes_remaining) {
{
uint32_t value = 0xffffffff; uint32_t value = 0xffffffff;
memcpy(&value, buffer + bytes_written, bytes_remaining); memcpy(&value, buffer + bytes_written, bytes_remaining);
status = pic32mx_write_word(bank, address, value); 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); LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
if (status & NVMCON_LVDERR) if (status & NVMCON_LVDERR) {
{
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -631,8 +600,7 @@ static int pic32mx_probe(struct flash_bank *bank)
page_size = 4096; page_size = 4096;
if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
{
/* 0x1FC00000: Boot flash size */ /* 0x1FC00000: Boot flash size */
#if 0 #if 0
/* for some reason this register returns 8k for the boot bank size /* 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 */ /* fixed 12k boot bank - see comments above */
num_pages = (12 * 1024); num_pages = (12 * 1024);
#endif #endif
} } else {
else
{
/* read the flash size from the device */ /* read the flash size from the device */
if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) { if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash"); 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); LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024);
if (bank->sectors) if (bank->sectors) {
{
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL; bank->sectors = NULL;
} }
@ -670,8 +635,7 @@ static int pic32mx_probe(struct flash_bank *bank)
bank->num_sectors = num_pages; bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * 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].offset = i * page_size;
bank->sectors[i].size = page_size; bank->sectors[i].size = page_size;
bank->sectors[i].is_erased = -1; 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; 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)) { if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name); printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
break; break;
} }
} }
if (pic32mx_devs[i].name == NULL) { if (pic32mx_devs[i].name == NULL)
printed = snprintf(buf, buf_size, "Unknown"); printed = snprintf(buf, buf_size, "Unknown");
}
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
@ -735,9 +697,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
int status, res; int status, res;
if (CMD_ARGC != 3) if (CMD_ARGC != 3)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
@ -747,8 +707,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
if (ERROR_OK != retval) if (ERROR_OK != retval)
return 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]); command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
return ERROR_OK; return ERROR_OK;
} }
@ -776,8 +735,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
struct mips_ejtag *ejtag_info; struct mips_ejtag *ejtag_info;
int timeout = 10; int timeout = 10;
if (CMD_ARGC < 1) if (CMD_ARGC < 1) {
{
command_print(CMD_CTX, "pic32mx unlock <bank>"); command_print(CMD_CTX, "pic32mx unlock <bank>");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
@ -798,8 +756,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
/* first check status of device */ /* first check status of device */
mchip_cmd = MCHP_STATUS; mchip_cmd = MCHP_STATUS;
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
if (mchip_cmd & (1 << 7)) if (mchip_cmd & (1 << 7)) {
{
/* device is not locked */ /* device is not locked */
command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway"); command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway");
} }
@ -812,8 +769,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
do { do {
mchip_cmd = MCHP_STATUS; mchip_cmd = MCHP_STATUS;
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
if (timeout-- == 0) if (timeout-- == 0) {
{
LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd); LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd);
break; break;
} }

View File

@ -91,8 +91,7 @@
static void stellaris_read_clock_info(struct flash_bank *bank); static void stellaris_read_clock_info(struct flash_bank *bank);
static int stellaris_mass_erase(struct flash_bank *bank); static int stellaris_mass_erase(struct flash_bank *bank);
struct stellaris_flash_bank struct stellaris_flash_bank {
{
/* chip id register */ /* chip id register */
uint32_t did0; uint32_t did0;
uint32_t did1; uint32_t did1;
@ -123,8 +122,8 @@ struct stellaris_flash_bank
const char *mck_desc; const char *mck_desc;
}; };
// Autogenerated by contrib/gen-stellaris-part-header.pl /* Autogenerated by contrib/gen-stellaris-part-header.pl */
// From Stellaris Firmware Development Package revision 8049 /* From Stellaris Firmware Development Package revision 8049 */
static struct { static struct {
uint8_t class; uint8_t class;
uint8_t partno; uint8_t partno;
@ -415,8 +414,7 @@ static struct {
{0xFF, 0x00, "Unknown Part"} {0xFF, 0x00, "Unknown Part"}
}; };
static char * StellarisClassname[7] = static char *StellarisClassname[7] = {
{
"Sandstorm", "Sandstorm",
"Fury", "Fury",
"Unknown", "Unknown",
@ -437,9 +435,7 @@ FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
struct stellaris_flash_bank *stellaris_info; struct stellaris_flash_bank *stellaris_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1); stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
bank->base = 0x0; bank->base = 0x0;
@ -503,8 +499,7 @@ static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
if (stellaris_info->num_lockbits > 0) if (stellaris_info->num_lockbits > 0) {
{
snprintf(buf, snprintf(buf,
buf_size, buf_size,
"pagesize: %" PRIi32 ", pages: %d, " "pagesize: %" PRIi32 ", pages: %d, "
@ -613,8 +608,7 @@ static void stellaris_read_clock_info(struct flash_bank *bank)
stellaris_info->mck_desc = ""; stellaris_info->mck_desc = "";
switch (oscsrc) switch (oscsrc) {
{
case 0: /* MOSC */ case 0: /* MOSC */
mainfreq = rcc_xtal[xtal]; mainfreq = rcc_xtal[xtal];
break; break;
@ -670,22 +664,19 @@ static int stellaris_read_part_info(struct flash_bank *bank)
did0, did1, stellaris_info->dc0, stellaris_info->dc1); did0, did1, stellaris_info->dc0, stellaris_info->dc1);
ver = did0 >> 28; ver = did0 >> 28;
if ((ver != 0) && (ver != 1)) if ((ver != 0) && (ver != 1)) {
{
LOG_WARNING("Unknown did0 version, cannot identify target"); LOG_WARNING("Unknown did0 version, cannot identify target");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
if (did1 == 0) if (did1 == 0) {
{
LOG_WARNING("Cannot identify target as a Stellaris"); LOG_WARNING("Cannot identify target as a Stellaris");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
ver = did1 >> 28; ver = did1 >> 28;
fam = (did1 >> 24) & 0xF; fam = (did1 >> 24) & 0xF;
if (((ver != 0) && (ver != 1)) || (fam != 0)) if (((ver != 0) && (ver != 1)) || (fam != 0)) {
{
LOG_WARNING("Unknown did1 version/family."); LOG_WARNING("Unknown did1 version/family.");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -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 stellaris_flash_bank *stellaris_info = bank->driver_priv;
struct target *target = bank->target; struct target *target = bank->target;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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; return ERROR_FLASH_BANK_NOT_PROBED;
if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages)) if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
{
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
}
if ((first == 0) && (last == ((int)stellaris_info->num_pages-1))) if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
{
return stellaris_mass_erase(bank); return stellaris_mass_erase(bank);
}
/* Refresh flash controller timing */ /* Refresh flash controller timing */
stellaris_read_clock_info(bank); 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. * 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 */ /* Address is first word in page */
target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize); target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
/* Write erase command */ /* Write erase command */
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
/* Wait until erase complete */ /* Wait until erase complete */
do do {
{
target_read_u32(target, FLASH_FMC, &flash_fmc); target_read_u32(target, FLASH_FMC, &flash_fmc);
} } while (flash_fmc & FMC_ERASE);
while (flash_fmc & FMC_ERASE);
/* Check acess violations */ /* Check acess violations */
target_read_u32(target, FLASH_CRIS, &flash_cris); target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK)) if (flash_cris & (AMASK)) {
{ LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "",
LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris); banknr, flash_cris);
target_write_u32(target, FLASH_CRIS, 0); target_write_u32(target, FLASH_CRIS, 0);
return ERROR_FLASH_OPERATION_FAILED; 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 stellaris_flash_bank *stellaris_info = bank->driver_priv;
struct target *target = bank->target; struct target *target = bank->target;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (!set) if (!set) {
{
LOG_ERROR("Hardware doesn't support page-level unprotect. " LOG_ERROR("Hardware doesn't support page-level unprotect. "
"Try the 'recover' command."); "Try the 'recover' command.");
return ERROR_COMMAND_SYNTAX_ERROR; 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] */ /* lockregions are 2 pages ... must protect [even..odd] */
if ((first < 0) || (first & 1) if ((first < 0) || (first & 1)
|| (last < first) || !(last & 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."); LOG_ERROR("Can't protect unaligned or out-of-range pages.");
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
} }
@ -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); */ /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
/* Wait until erase complete */ /* Wait until erase complete */
do do {
{
target_read_u32(target, FLASH_FMC, &flash_fmc); target_read_u32(target, FLASH_FMC, &flash_fmc);
} } while (flash_fmc & FMC_COMT);
while (flash_fmc & FMC_COMT);
/* Check acess violations */ /* Check acess violations */
target_read_u32(target, FLASH_CRIS, &flash_cris); 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); LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
target_write_u32(target, FLASH_CRIS, 0); target_write_u32(target, FLASH_CRIS, 0);
return ERROR_FLASH_OPERATION_FAILED; 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 */ /* see contib/loaders/flash/stellaris.s for src */
static const uint8_t stellaris_write_code[] = static const uint8_t stellaris_write_code[] = {
{
/* /*
Call with : Call with :
r0 = buffer address r0 = buffer address
@ -1042,8 +1018,8 @@ static int stellaris_write_block(struct flash_bank *bank,
bank, buffer, offset, wcount); bank, buffer, offset, wcount);
/* flash write code */ /* 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"); LOG_DEBUG("no working area for block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}; };
@ -1053,11 +1029,9 @@ static int stellaris_write_block(struct flash_bank *bank,
buffer_size = wcount * 4; buffer_size = wcount * 4;
/* memory buffer */ /* 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 /= 2;
if (buffer_size <= buf_min) if (buffer_size <= buf_min) {
{
target_free_working_area(target, write_algorithm); target_free_working_area(target, write_algorithm);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; 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[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 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; uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
target_write_buffer(target, source->address, thisrun_count * 4, buffer); 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, write_algorithm->address,
0, 0,
10000, &armv7m_info); 10000, &armv7m_info);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("error %d executing stellaris " LOG_ERROR("error %d executing stellaris "
"flash write algorithm", "flash write algorithm",
retval); retval);
@ -1121,7 +1093,8 @@ static int stellaris_write_block(struct flash_bank *bank,
return retval; 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 stellaris_flash_bank *stellaris_info = bank->driver_priv;
struct target *target = bank->target; 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; uint32_t bytes_written = 0;
int retval; int retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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) if (stellaris_info->did1 == 0)
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
if (offset & 0x3) if (offset & 0x3) {
{
LOG_WARNING("offset size must be word aligned"); LOG_WARNING("offset size must be word aligned");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; 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? */ /* multiple words to be programmed? */
if (words_remaining > 0) if (words_remaining > 0) {
{
/* try using a block write */ /* try using a block write */
retval = stellaris_write_block(bank, buffer, offset, retval = stellaris_write_block(bank, buffer, offset,
words_remaining); words_remaining);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{ if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
LOG_DEBUG("writing flash word-at-a-time"); 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 */ /* if an error occured, we examine the reason, and quit */
target_read_u32(target, FLASH_CRIS, &flash_cris); target_read_u32(target, FLASH_CRIS, &flash_cris);
LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris); LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
} } else {
else
{
buffer += words_remaining * 4; buffer += words_remaining * 4;
address += words_remaining * 4; address += words_remaining * 4;
words_remaining = 0; words_remaining = 0;
} }
} }
while (words_remaining > 0) while (words_remaining > 0) {
{
if (!(address & 0xff)) if (!(address & 0xff))
LOG_DEBUG("0x%" PRIx32 "", address); 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); 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); */ /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
/* Wait until write complete */ /* Wait until write complete */
do do {
{
target_read_u32(target, FLASH_FMC, &flash_fmc); target_read_u32(target, FLASH_FMC, &flash_fmc);
} while (flash_fmc & FMC_WRITE); } 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--; words_remaining--;
} }
if (bytes_remaining) if (bytes_remaining) {
{
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff}; uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
/* copy the last remaining bytes into the write buffer */ /* 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); 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); */ /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
/* Wait until write complete */ /* Wait until write complete */
do do {
{
target_read_u32(target, FLASH_FMC, &flash_fmc); target_read_u32(target, FLASH_FMC, &flash_fmc);
} while (flash_fmc & FMC_WRITE); } while (flash_fmc & FMC_WRITE);
} }
/* Check access violations */ /* Check access violations */
target_read_u32(target, FLASH_CRIS, &flash_cris); target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK)) if (flash_cris & (AMASK)) {
{
LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris); LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -1266,8 +1225,7 @@ static int stellaris_probe(struct flash_bank *bank)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (bank->sectors) if (bank->sectors) {
{
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL; bank->sectors = NULL;
} }
@ -1276,8 +1234,7 @@ static int stellaris_probe(struct flash_bank *bank)
bank->size = 1024 * stellaris_info->num_pages; bank->size = 1024 * stellaris_info->num_pages;
bank->num_sectors = stellaris_info->num_pages; bank->num_sectors = stellaris_info->num_pages;
bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector)); 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].offset = i * stellaris_info->pagesize;
bank->sectors[i].size = stellaris_info->pagesize; bank->sectors[i].size = stellaris_info->pagesize;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
@ -1296,8 +1253,7 @@ static int stellaris_mass_erase(struct flash_bank *bank)
stellaris_info = bank->driver_priv; stellaris_info = bank->driver_priv;
target = bank->target; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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_FMA, 0);
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
/* Wait until erase complete */ /* Wait until erase complete */
do do {
{
target_read_u32(target, FLASH_FMC, &flash_fmc); 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 /* if device has > 128k, then second erase cycle is needed
* this is only valid for older devices, but will not hurt */ * 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_FMA, 0x20000);
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
/* Wait until erase complete */ /* Wait until erase complete */
do do {
{
target_read_u32(target, FLASH_FMC, &flash_fmc); target_read_u32(target, FLASH_FMC, &flash_fmc);
} } while (flash_fmc & FMC_MERASE);
while (flash_fmc & FMC_MERASE);
} }
return ERROR_OK; return ERROR_OK;
@ -1348,29 +1299,21 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command)
int i; int i;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (stellaris_mass_erase(bank) == ERROR_OK) if (stellaris_mass_erase(bank) == ERROR_OK) {
{
/* set all sectors as erased */ /* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++) for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1; bank->sectors[i].is_erased = 1;
}
command_print(CMD_CTX, "stellaris mass erase complete"); command_print(CMD_CTX, "stellaris mass erase complete");
} } else
else
{
command_print(CMD_CTX, "stellaris mass erase failed"); command_print(CMD_CTX, "stellaris mass erase failed");
}
return ERROR_OK; return ERROR_OK;
} }

View File

@ -23,6 +23,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -101,15 +102,13 @@
#define KEY1 0x45670123 #define KEY1 0x45670123
#define KEY2 0xCDEF89AB #define KEY2 0xCDEF89AB
struct stm32x_options struct stm32x_options {
{
uint16_t RDP; uint16_t RDP;
uint16_t user_options; uint16_t user_options;
uint16_t protection[4]; uint16_t protection[4];
}; };
struct stm32x_flash_bank struct stm32x_flash_bank {
{
struct stm32x_options option_bytes; struct stm32x_options option_bytes;
struct working_area *write_algorithm; struct working_area *write_algorithm;
int ppage_size; int ppage_size;
@ -129,9 +128,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
struct stm32x_flash_bank *stm32x_info; struct stm32x_flash_bank *stm32x_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
bank->driver_priv = stm32x_info; 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; int retval = ERROR_OK;
/* wait for busy to clear */ /* wait for busy to clear */
for (;;) for (;;) {
{
retval = stm32x_get_flash_status(bank, &status); retval = stm32x_get_flash_status(bank, &status);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
LOG_DEBUG("status: 0x%" PRIx32 "", status); LOG_DEBUG("status: 0x%" PRIx32 "", status);
if ((status & FLASH_BSY) == 0) if ((status & FLASH_BSY) == 0)
break; break;
if (timeout-- <= 0) if (timeout-- <= 0) {
{
LOG_ERROR("timed out waiting for flash"); LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL; return ERROR_FAIL;
} }
alive_sleep(1); alive_sleep(1);
} }
if (status & FLASH_WRPRTERR) if (status & FLASH_WRPRTERR) {
{
LOG_ERROR("stm32x device protected"); LOG_ERROR("stm32x device protected");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
if (status & FLASH_PGERR) if (status & FLASH_PGERR) {
{
LOG_ERROR("stm32x device programming failed"); LOG_ERROR("stm32x device programming failed");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
/* Clear but report errors */ /* 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 /* If this operation fails, we ignore it and report the original
* retval * retval
*/ */
@ -209,8 +201,7 @@ int stm32x_check_operation_supported(struct flash_bank *bank)
/* if we have a dual flash bank device then /* if we have a dual flash bank device then
* we need to perform option byte stuff on bank0 only */ * 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"); LOG_ERROR("Option Byte Operation's must use bank0");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -395,8 +386,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
int num_bits; int num_bits;
int set; int set;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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 */ * high density - each protection bit is for 2 * 2K pages */
num_bits = (bank->num_sectors / stm32x_info->ppage_size); 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 */ /* high density flash/connectivity line protection */
set = 1; 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 - 255 protection for high density
* bit 31 controls sector 62 - 127 protection for connectivity line */ * bit 31 controls sector 62 - 127 protection for connectivity line */
for (s = 62; s < bank->num_sectors; s++) for (s = 62; s < bank->num_sectors; s++)
{
bank->sectors[s].is_protected = set; bank->sectors[s].is_protected = set;
}
if (bank->num_sectors > 61) if (bank->num_sectors > 61)
num_bits = 31; num_bits = 31;
for (i = 0; i < num_bits; i++) for (i = 0; i < num_bits; i++) {
{
set = 1; set = 1;
if (protection & (1 << i)) 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++) for (s = 0; s < stm32x_info->ppage_size; s++)
bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set; bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
} }
} } else {
else
{
/* low/medium density flash protection */ /* low/medium density flash protection */
for (i = 0; i < num_bits; i++) for (i = 0; i < num_bits; i++) {
{
set = 1; set = 1;
if (protection & (1 << i)) 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; struct target *target = bank->target;
int i; int i;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if ((first == 0) && (last == (bank->num_sectors - 1))) if ((first == 0) && (last == (bank->num_sectors - 1)))
{
return stm32x_mass_erase(bank); return stm32x_mass_erase(bank);
}
/* unlock flash registers */ /* unlock flash registers */
int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1); 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) if (retval != ERROR_OK)
return retval; 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); retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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; stm32x_info = bank->driver_priv;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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) if (ERROR_OK != retval)
return 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", LOG_WARNING("aligned start protect sector to a %d sector boundary",
stm32x_info->ppage_size); stm32x_info->ppage_size);
first = first - (first % 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", LOG_WARNING("aligned end protect sector to a %d sector boundary",
stm32x_info->ppage_size); stm32x_info->ppage_size);
last++; 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[2] = (uint16_t)(protection >> 16);
prot_reg[3] = (uint16_t)(protection >> 24); prot_reg[3] = (uint16_t)(protection >> 24);
if (stm32x_info->ppage_size == 2) if (stm32x_info->ppage_size == 2) {
{
/* high density flash */ /* high density flash */
/* bit 7 controls sector 62 - 255 protection */ /* bit 7 controls sector 62 - 255 protection */
if (last > 61) if (last > 61) {
{
if (set) if (set)
prot_reg[3] &= ~(1 << 7); prot_reg[3] &= ~(1 << 7);
else else
@ -580,8 +554,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
if (last > 61) if (last > 61)
last = 61; last = 61;
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
reg = (i / stm32x_info->ppage_size) / 8; reg = (i / stm32x_info->ppage_size) / 8;
bit = (i / stm32x_info->ppage_size) - (reg * 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 else
prot_reg[reg] |= (1 << bit); prot_reg[reg] |= (1 << bit);
} }
} } else {
else
{
/* medium density flash */ /* medium density flash */
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
reg = (i / stm32x_info->ppage_size) / 8; reg = (i / stm32x_info->ppage_size) / 8;
bit = (i / stm32x_info->ppage_size) - (reg * 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; return status;
stm32x_info->option_bytes.protection[0] = prot_reg[0]; 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 */ /* flash write code */
if (target_alloc_working_area(target, sizeof(stm32x_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"); LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; 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), sizeof(stm32x_flash_write_code), (uint8_t *)stm32x_flash_write_code);
(uint8_t*)stm32x_flash_write_code)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
/* memory buffer */ /* 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 /= 2;
buffer_size &= ~3UL; // Make sure it's 4 byte aligned buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
if (buffer_size <= 256) if (buffer_size <= 256) {
{
/* if we already allocated the writing code, but failed to get a /* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
if (stm32x_info->write_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; armv7m_info.core_mode = ARMV7M_MODE_ANY;
/* Start up algorithm on target and let it idle while writing the first chunk */ /* 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, stm32x_info->write_algorithm->address,
0, 0,
&armv7m_info)) != ERROR_OK) &armv7m_info);
{ if (retval != ERROR_OK) {
LOG_ERROR("error starting stm32x flash write algorithm"); LOG_ERROR("error starting stm32x flash write algorithm");
goto cleanup; goto cleanup;
} }
while (count > 0) while (count > 0) {
{
retval = target_read_u32(target, rp_addr, &rp); retval = target_read_u32(target, rp_addr, &rp);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("failed to get read pointer"); LOG_ERROR("failed to get read pointer");
break; break;
} }
LOG_DEBUG("count 0x%"PRIx32" wp 0x%"PRIx32" rp 0x%"PRIx32, count, wp, rp); 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"); LOG_ERROR("flash write algorithm aborted by target");
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; 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); LOG_ERROR("corrupted fifo read pointer 0x%"PRIx32, rp);
break; break;
} }
@ -780,8 +744,7 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
else else
thisrun_bytes = fifo_end_addr - wp - 2; 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 /* Throttle polling a bit if transfer is (much) faster than flash
* programming. The exact delay shouldn't matter as long as it's * programming. The exact delay shouldn't matter as long as it's
* less than buffer size / flash speed. This is very unlikely to * 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; break;
} }
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
/* abort flash write algorithm on target */ /* abort flash write algorithm on target */
target_write_u32(target, wp_addr, 0); target_write_u32(target, wp_addr, 0);
} }
int retval2; int retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params,
if ((retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params, 0, 10000, &armv7m_info);
0, if (retval2 != ERROR_OK) {
10000,
&armv7m_info)) != ERROR_OK)
{
LOG_ERROR("error waiting for stm32x flash write algorithm"); LOG_ERROR("error waiting for stm32x flash write algorithm");
retval = retval2; retval = retval2;
} }
if (retval == ERROR_FLASH_OPERATION_FAILED) if (retval == ERROR_FLASH_OPERATION_FAILED) {
{
LOG_ERROR("flash write failed at address 0x%"PRIx32, LOG_ERROR("flash write failed at address 0x%"PRIx32,
buf_get_u32(reg_params[4].value, 0, 32)); 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"); LOG_ERROR("flash memory not erased before writing");
/* Clear but report errors */ /* Clear but report errors */
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_PGERR); 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"); LOG_ERROR("flash memory write protected");
/* Clear but report errors */ /* Clear but report errors */
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_WRPRTERR); 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; uint32_t bytes_written = 0;
int retval; int retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
@ -892,20 +846,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
return retval; return retval;
/* multiple half words (2-byte) to be programmed? */ /* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0) if (words_remaining > 0) {
{
/* try using a block write */ /* try using a block write */
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) retval = stm32x_write_block(bank, buffer, offset, words_remaining);
{ if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
{
/* if block write failed (no sufficient working area), /* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */ * 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; buffer += words_remaining * 2;
address += words_remaining * 2; address += words_remaining * 2;
words_remaining = 0; 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)) if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
return retval; return retval;
while (words_remaining > 0) while (words_remaining > 0) {
{
uint16_t value; uint16_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); 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; address += 2;
} }
if (bytes_remaining) if (bytes_remaining) {
{
uint16_t value = 0xffff; uint16_t value = 0xffff;
memcpy(&value, buffer + bytes_written, bytes_remaining); memcpy(&value, buffer + bytes_written, bytes_remaining);
@ -977,8 +925,7 @@ static int stm32x_probe(struct flash_bank *bank)
/* get flash size from target. */ /* get flash size from target. */
retval = target_read_u16(target, 0x1FFFF7E0, &flash_size_in_kb); 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"); LOG_WARNING("failed reading flash size, default to max target family");
/* failed reading flash size, default to max target family */ /* failed reading flash size, default to max target family */
flash_size_in_kb = 0xffff; flash_size_in_kb = 0xffff;
@ -991,8 +938,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4; stm32x_info->ppage_size = 4;
/* check for early silicon */ /* check for early silicon */
if (flash_size_in_kb == 0xffff) if (flash_size_in_kb == 0xffff) {
{
/* number of sectors incorrect on revA */ /* number of sectors incorrect on revA */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash"); LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
flash_size_in_kb = 128; flash_size_in_kb = 128;
@ -1004,8 +950,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4; stm32x_info->ppage_size = 4;
/* check for early silicon */ /* check for early silicon */
if (flash_size_in_kb == 0xffff) if (flash_size_in_kb == 0xffff) {
{
/* number of sectors incorrect on revA */ /* number of sectors incorrect on revA */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash"); LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash");
flash_size_in_kb = 32; flash_size_in_kb = 32;
@ -1017,8 +962,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 2; stm32x_info->ppage_size = 2;
/* check for early silicon */ /* check for early silicon */
if (flash_size_in_kb == 0xffff) if (flash_size_in_kb == 0xffff) {
{
/* number of sectors incorrect on revZ */ /* number of sectors incorrect on revZ */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash"); LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash");
flash_size_in_kb = 512; flash_size_in_kb = 512;
@ -1030,8 +974,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 2; stm32x_info->ppage_size = 2;
/* check for early silicon */ /* check for early silicon */
if (flash_size_in_kb == 0xffff) if (flash_size_in_kb == 0xffff) {
{
/* number of sectors incorrect on revZ */ /* number of sectors incorrect on revZ */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash"); LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash");
flash_size_in_kb = 256; flash_size_in_kb = 256;
@ -1043,8 +986,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4; stm32x_info->ppage_size = 4;
/* check for early silicon */ /* 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 */ /* number of sectors may be incorrrect on early silicon */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash"); LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
flash_size_in_kb = 128; flash_size_in_kb = 128;
@ -1056,8 +998,7 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->ppage_size = 4; stm32x_info->ppage_size = 4;
/* check for early silicon */ /* 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 */ /* number of sectors may be incorrrect on early silicon */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash"); LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
flash_size_in_kb = 128; flash_size_in_kb = 128;
@ -1070,29 +1011,23 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->has_dual_banks = true; stm32x_info->has_dual_banks = true;
/* check for early silicon */ /* 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 */ /* number of sectors may be incorrrect on early silicon */
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 1024k flash"); LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 1024k flash");
flash_size_in_kb = 1024; flash_size_in_kb = 1024;
} }
/* split reported size into matching bank */ /* split reported size into matching bank */
if (bank->base != 0x08080000) if (bank->base != 0x08080000) {
{
/* bank 0 will be fixed 512k */ /* bank 0 will be fixed 512k */
flash_size_in_kb = 512; flash_size_in_kb = 512;
} } else {
else
{
flash_size_in_kb -= 512; flash_size_in_kb -= 512;
/* bank1 also uses a register offset */ /* bank1 also uses a register offset */
stm32x_info->register_base = FLASH_REG_BASE_B1; stm32x_info->register_base = FLASH_REG_BASE_B1;
base_address = 0x08080000; base_address = 0x08080000;
} }
} } else {
else
{
LOG_WARNING("Cannot identify target as a STM32 family."); LOG_WARNING("Cannot identify target as a STM32 family.");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1108,8 +1043,7 @@ static int stm32x_probe(struct flash_bank *bank)
/* check that calculation result makes sense */ /* check that calculation result makes sense */
assert(num_pages > 0); assert(num_pages > 0);
if (bank->sectors) if (bank->sectors) {
{
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL; bank->sectors = NULL;
} }
@ -1119,8 +1053,7 @@ static int stm32x_probe(struct flash_bank *bank)
bank->num_sectors = num_pages; bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * 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].offset = i * page_size;
bank->sectors[i].size = page_size; bank->sectors[i].size = page_size;
bank->sectors[i].is_erased = -1; 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 += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x0000: case 0x0000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -1190,8 +1122,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x1000: case 0x1000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -1205,8 +1136,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x1000: case 0x1000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -1224,8 +1154,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x1000: case 0x1000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -1243,8 +1172,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x1000: case 0x1000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -1262,8 +1190,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x1000: case 0x1000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -1281,8 +1208,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x1000: case 0x1000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -1291,9 +1217,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
snprintf(buf, buf_size, "unknown"); snprintf(buf, buf_size, "unknown");
break; break;
} }
} } else {
else
{
snprintf(buf, buf_size, "Cannot identify target as a stm32x\n"); snprintf(buf, buf_size, "Cannot identify target as a stm32x\n");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1307,9 +1231,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
struct stm32x_flash_bank *stm32x_info = NULL; struct stm32x_flash_bank *stm32x_info = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -1330,8 +1251,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
if (ERROR_OK != retval) if (ERROR_OK != retval)
return 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"); command_print(CMD_CTX, "stm32x failed to erase options");
return ERROR_OK; return ERROR_OK;
} }
@ -1339,8 +1259,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
/* set readout protection */ /* set readout protection */
stm32x_info->option_bytes.RDP = 0; 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"); command_print(CMD_CTX, "stm32x failed to lock device");
return ERROR_OK; return ERROR_OK;
} }
@ -1355,9 +1274,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
struct target *target = NULL; struct target *target = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -1376,14 +1292,12 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
if (ERROR_OK != retval) if (ERROR_OK != retval)
return 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"); command_print(CMD_CTX, "stm32x failed to unlock device");
return ERROR_OK; 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"); command_print(CMD_CTX, "stm32x failed to lock device");
return ERROR_OK; return ERROR_OK;
} }
@ -1402,9 +1316,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
struct stm32x_flash_bank *stm32x_info = NULL; struct stm32x_flash_bank *stm32x_info = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -1453,8 +1364,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
else else
command_print(CMD_CTX, "Standby: Reset generated"); command_print(CMD_CTX, "Standby: Reset generated");
if (stm32x_info->has_dual_banks) if (stm32x_info->has_dual_banks) {
{
if (buf_get_u32((uint8_t *)&optionbyte, OPT_BFB2, 1)) if (buf_get_u32((uint8_t *)&optionbyte, OPT_BFB2, 1))
command_print(CMD_CTX, "Boot: Bank 0"); command_print(CMD_CTX, "Boot: Bank 0");
else else
@ -1471,9 +1381,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
uint16_t optionbyte = 0xF8; uint16_t optionbyte = 0xF8;
if (CMD_ARGC < 4) if (CMD_ARGC < 4)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -1500,57 +1407,38 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
/* OPT_RDWDGSW */ /* OPT_RDWDGSW */
if (strcmp(CMD_ARGV[1], "SWWDG") == 0) if (strcmp(CMD_ARGV[1], "SWWDG") == 0)
{
optionbyte |= (1 << 0); optionbyte |= (1 << 0);
}
else /* REVISIT must be "HWWDG" then ... */ else /* REVISIT must be "HWWDG" then ... */
{
optionbyte &= ~(1 << 0); optionbyte &= ~(1 << 0);
}
/* OPT_RDRSTSTOP */ /* OPT_RDRSTSTOP */
if (strcmp(CMD_ARGV[2], "NORSTSTOP") == 0) if (strcmp(CMD_ARGV[2], "NORSTSTOP") == 0)
{
optionbyte |= (1 << 1); optionbyte |= (1 << 1);
}
else /* REVISIT must be "RSTSTNDBY" then ... */ else /* REVISIT must be "RSTSTNDBY" then ... */
{
optionbyte &= ~(1 << 1); optionbyte &= ~(1 << 1);
}
/* OPT_RDRSTSTDBY */ /* OPT_RDRSTSTDBY */
if (strcmp(CMD_ARGV[3], "NORSTSTNDBY") == 0) if (strcmp(CMD_ARGV[3], "NORSTSTNDBY") == 0)
{
optionbyte |= (1 << 2); optionbyte |= (1 << 2);
}
else /* REVISIT must be "RSTSTOP" then ... */ else /* REVISIT must be "RSTSTOP" then ... */
{
optionbyte &= ~(1 << 2); optionbyte &= ~(1 << 2);
}
if (CMD_ARGC > 4 && stm32x_info->has_dual_banks) if (CMD_ARGC > 4 && stm32x_info->has_dual_banks) {
{
/* OPT_BFB2 */ /* OPT_BFB2 */
if (strcmp(CMD_ARGV[4], "BOOT0") == 0) if (strcmp(CMD_ARGV[4], "BOOT0") == 0)
{
optionbyte |= (1 << 3); optionbyte |= (1 << 3);
}
else else
{
optionbyte &= ~(1 << 3); 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"); command_print(CMD_CTX, "stm32x failed to erase options");
return ERROR_OK; return ERROR_OK;
} }
stm32x_info->option_bytes.user_options = optionbyte; 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"); command_print(CMD_CTX, "stm32x failed to write options");
return ERROR_OK; return ERROR_OK;
} }
@ -1566,8 +1454,7 @@ static int stm32x_mass_erase(struct flash_bank *bank)
{ {
struct target *target = bank->target; struct target *target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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) if (retval != ERROR_OK)
return retval; return retval;
@ -1604,9 +1492,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
int i; int i;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; return retval;
retval = stm32x_mass_erase(bank); retval = stm32x_mass_erase(bank);
if (retval == ERROR_OK) if (retval == ERROR_OK) {
{
/* set all sectors as erased */ /* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++) for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].is_erased = 1; bank->sectors[i].is_erased = 1;
}
command_print(CMD_CTX, "stm32x mass erase complete"); command_print(CMD_CTX, "stm32x mass erase complete");
} } else
else
{
command_print(CMD_CTX, "stm32x mass erase failed"); command_print(CMD_CTX, "stm32x mass erase failed");
}
return retval; return retval;
} }

View File

@ -23,6 +23,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -70,7 +71,8 @@
* http://www.st.com/internet/mcu/product/250192.jsp * http://www.st.com/internet/mcu/product/250192.jsp
* *
* PM0059 * 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 * STM32F1x series - notice that this code was copy, pasted and knocked
* into a stm32f2x driver, so in case something has been converted or * 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_ERASE_TIMEOUT 10000
#define FLASH_WRITE_TIMEOUT 5 #define FLASH_WRITE_TIMEOUT 5
#define STM32_FLASH_BASE 0x40023c00 #define STM32_FLASH_BASE 0x40023c00
#define STM32_FLASH_ACR 0x40023c00 #define STM32_FLASH_ACR 0x40023c00
#define STM32_FLASH_KEYR 0x40023c04 #define STM32_FLASH_KEYR 0x40023c04
@ -99,8 +100,6 @@
#define STM32_FLASH_OPTCR 0x40023c14 #define STM32_FLASH_OPTCR 0x40023c14
#define STM32_FLASH_OBR 0x40023c1C #define STM32_FLASH_OBR 0x40023c1C
/* option byte location */ /* option byte location */
#define STM32_OB_RDP 0x1FFFF800 #define STM32_OB_RDP 0x1FFFF800
@ -128,11 +127,11 @@
/* FLASH_SR register bits */ /* FLASH_SR register bits */
#define FLASH_BSY (1 << 16) #define FLASH_BSY (1 << 16)
#define FLASH_PGSERR (1 << 7) // Programming sequence error #define FLASH_PGSERR (1 << 7) /* Programming sequence error */
#define FLASH_PGPERR (1 << 6) // Programming parallelism error #define FLASH_PGPERR (1 << 6) /* Programming parallelism error */
#define FLASH_PGAERR (1 << 5) // Programming alignment error #define FLASH_PGAERR (1 << 5) /* Programming alignment error */
#define FLASH_WRPERR (1 << 4) // Write protection error #define FLASH_WRPERR (1 << 4) /* Write protection error */
#define FLASH_OPERR (1 << 1) // Operation 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)
@ -150,8 +149,7 @@
#define KEY1 0x45670123 #define KEY1 0x45670123
#define KEY2 0xCDEF89AB #define KEY2 0xCDEF89AB
struct stm32x_flash_bank struct stm32x_flash_bank {
{
struct working_area *write_algorithm; struct working_area *write_algorithm;
int probed; int probed;
}; };
@ -164,9 +162,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
struct stm32x_flash_bank *stm32x_info; struct stm32x_flash_bank *stm32x_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
bank->driver_priv = stm32x_info; 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; int retval = ERROR_OK;
/* wait for busy to clear */ /* wait for busy to clear */
for (;;) for (;;) {
{
retval = stm32x_get_flash_status(bank, &status); retval = stm32x_get_flash_status(bank, &status);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
LOG_DEBUG("status: 0x%" PRIx32 "", status); LOG_DEBUG("status: 0x%" PRIx32 "", status);
if ((status & FLASH_BSY) == 0) if ((status & FLASH_BSY) == 0)
break; break;
if (timeout-- <= 0) if (timeout-- <= 0) {
{
LOG_ERROR("timed out waiting for flash"); LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL; 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"); LOG_ERROR("stm32x device protected");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
/* Clear but report errors */ /* Clear but report errors */
if (status & FLASH_ERROR) if (status & FLASH_ERROR) {
{
/* If this operation fails, we ignore it and report the original /* If this operation fails, we ignore it and report the original
* retval * retval
*/ */
@ -275,8 +267,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
struct target *target = bank->target; struct target *target = bank->target;
int i; int i;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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 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, retval = target_write_u32(target,
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT); stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -361,30 +351,27 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
/* Flip endian */ /* Flip endian */
uint8_t stm32x_flash_write_code[sizeof(stm32x_flash_write_code_16)*2]; 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 + 0] = stm32x_flash_write_code_16[i] & 0xff;
stm32x_flash_write_code[i*2 + 1] = (stm32x_flash_write_code_16[i] >> 8) & 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), 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"); LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; 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), 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; return retval;
/* memory buffer */ /* 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 /= 2;
if (buffer_size <= 256) if (buffer_size <= 256) {
{
/* if we already allocated the writing code, but failed to get a /* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
if (stm32x_info->write_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[3], "r3", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[4], "r4", 32, PARAM_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)) ? uint32_t thisrun_count = (count > (buffer_size / 2)) ?
(buffer_size / 2) : count; (buffer_size / 2) : count;
if ((retval = target_write_buffer(target, source->address, retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
thisrun_count * 2, buffer)) != ERROR_OK) if (retval != ERROR_OK)
break; break;
buf_set_u32(reg_params[0].value, 0, 32, source->address); 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[1].value, 0, 32, address);
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); 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); 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), sizeof(reg_params) / sizeof(*reg_params),
reg_params, reg_params,
stm32x_info->write_algorithm->address, stm32x_info->write_algorithm->address,
0, 0,
10000, &armv7m_info)) != ERROR_OK) 10000, &armv7m_info);
{ if (retval != ERROR_OK) {
LOG_ERROR("error executing stm32x flash write algorithm"); LOG_ERROR("error executing stm32x flash write algorithm");
break; 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; uint32_t error = buf_get_u32(reg_params[3].value, 0, 32) & FLASH_ERROR;
if (error & FLASH_WRPERR) if (error & FLASH_WRPERR)
{
LOG_ERROR("flash memory write protected"); LOG_ERROR("flash memory write protected");
}
if (error != 0) if (error != 0) {
{
LOG_ERROR("flash write failed = %08x", error); LOG_ERROR("flash write failed = %08x", error);
/* Clear but report errors */ /* Clear but report errors */
target_write_u32(target, STM32_FLASH_SR, error); 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; uint32_t bytes_written = 0;
int retval; int retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
@ -490,20 +471,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
return retval; return retval;
/* multiple half words (2-byte) to be programmed? */ /* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0) if (words_remaining > 0) {
{
/* try using a block write */ /* try using a block write */
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) retval = stm32x_write_block(bank, buffer, offset, words_remaining);
{ if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
{
/* if block write failed (no sufficient working area), /* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */ * 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; buffer += words_remaining * 2;
address += words_remaining * 2; address += words_remaining * 2;
words_remaining = 0; 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 Double word access in case of x64 parallelism
Wait for the BSY bit to be cleared Wait for the BSY bit to be cleared
*/ */
while (words_remaining > 0) while (words_remaining > 0) {
{
uint16_t value; uint16_t value;
memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); 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; address += 2;
} }
if (bytes_remaining) if (bytes_remaining) {
{
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
FLASH_PG | FLASH_PSIZE_8); FLASH_PG | FLASH_PSIZE_8);
if (retval != ERROR_OK) 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) 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].offset = bank->size;
bank->sectors[i].size = size; bank->sectors[i].size = size;
bank->size += bank->sectors[i].size; bank->size += bank->sectors[i].size;

View File

@ -23,6 +23,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #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_erase_sector(struct flash_bank *bank, int sector);
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank); static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank);
struct stm32lx_flash_bank struct stm32lx_flash_bank {
{
struct working_area *write_algorithm; struct working_area *write_algorithm;
int probed; int probed;
}; };
@ -129,16 +129,13 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
{ {
struct stm32lx_flash_bank *stm32lx_info; struct stm32lx_flash_bank *stm32lx_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
// Create the bank structure /* Create the bank structure */
stm32lx_info = malloc(sizeof(struct stm32lx_flash_bank)); stm32lx_info = malloc(sizeof(struct stm32lx_flash_bank));
// Check allocation /* Check allocation */
if (stm32lx_info == NULL) if (stm32lx_info == NULL) {
{
LOG_ERROR("failed to allocate bank structure"); LOG_ERROR("failed to allocate bank structure");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -158,8 +155,7 @@ static int stm32lx_protect_check(struct flash_bank *bank)
uint32_t wrpr; uint32_t wrpr;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -172,17 +168,12 @@ static int stm32lx_protect_check(struct flash_bank *bank)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
for (int i = 0; i < 32; i++) for (int i = 0; i < 32; i++) {
{
if (wrpr & (1 << i)) if (wrpr & (1 << i))
{
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
}
else else
{
bank->sectors[i].is_protected = 0; bank->sectors[i].is_protected = 0;
} }
}
return ERROR_OK; 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. * erased, but it is not implemented yet.
*/ */
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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 * 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); retval = stm32lx_erase_sector(bank, i);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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 */ /* see contib/loaders/flash/stm32lx.s for src */
static const uint16_t stm32lx_flash_write_code_16[] = static const uint16_t stm32lx_flash_write_code_16[] = {
{ /* 00000000 <write_word-0x4>: */
// 00000000 <write_word-0x4>: 0x2300, /* 0: 2300 movs r3, #0 */
0x2300, // 0: 2300 movs r3, #0 0xe004, /* 2: e004 b.n e <test_done> */
0xe004, // 2: e004 b.n e <test_done>
// 00000004 <write_word>: /* 00000004 <write_word>: */
0xf851, 0xcb04, // 4: f851 cb04 ldr.w ip, [r1], #4 0xf851, 0xcb04, /* 4: f851 cb04 ldr.w ip, [r1], #4 */
0xf840, 0xcb04, // 8: f840 cb04 str.w ip, [r0], #4 0xf840, 0xcb04, /* 8: f840 cb04 str.w ip, [r0], #4 */
0x3301, // c: 3301 adds r3, #1 0x3301, /* c: 3301 adds r3, #1 */
// 0000000e <test_done>: /* 0000000e <test_done>: */
0x4293, // e: 4293 cmp r3, r2 0x4293, /* e: 4293 cmp r3, r2 */
0xd3f8, // 10: d3f8 bcc.n 4 <write_word> 0xd3f8, /* 10: d3f8 bcc.n 4 <write_word> */
0xbe00, // 12: be00 bkpt 0x0000 0xbe00, /* 12: be00 bkpt 0x0000 */
}; };
// Flip endian /* Flip endian */
uint8_t stm32lx_flash_write_code[sizeof(stm32lx_flash_write_code_16)]; 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] stm32lx_flash_write_code[i * 2 + 0] = stm32lx_flash_write_code_16[i]
& 0xff; & 0xff;
stm32lx_flash_write_code[i * 2 + 1] = (stm32lx_flash_write_code_16[i] stm32lx_flash_write_code[i * 2 + 1] = (stm32lx_flash_write_code_16[i]
>> 8) & 0xff; >> 8) & 0xff;
} }
// Check if there is an even number of half pages (128bytes) /* Check if there is an even number of half pages (128bytes) */
if (count % 128) if (count % 128) {
{
LOG_ERROR("there should be an even number " LOG_ERROR("there should be an even number "
"of half pages = 128 bytes (count = %" PRIi32 " bytes)", count); "of half pages = 128 bytes (count = %" PRIi32 " bytes)", count);
return ERROR_FAIL; return ERROR_FAIL;
} }
// Allocate working area /* Allocate working area */
reg32 = sizeof(stm32lx_flash_write_code); reg32 = sizeof(stm32lx_flash_write_code);
// Add bytes to make 4byte aligned /* Add bytes to make 4byte aligned */
reg32 += (4 - (reg32 % 4)) % 4; reg32 += (4 - (reg32 % 4)) % 4;
retval = target_alloc_working_area(target, reg32, retval = target_alloc_working_area(target, reg32,
&stm32lx_info->write_algorithm); &stm32lx_info->write_algorithm);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
// Write the flashing code /* Write the flashing code */
retval = target_write_buffer(target, retval = target_write_buffer(target,
stm32lx_info->write_algorithm->address, stm32lx_info->write_algorithm->address,
sizeof(stm32lx_flash_write_code), sizeof(stm32lx_flash_write_code),
(uint8_t *)stm32lx_flash_write_code); (uint8_t *)stm32lx_flash_write_code);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
target_free_working_area(target, stm32lx_info->write_algorithm); target_free_working_area(target, stm32lx_info->write_algorithm);
return retval; return retval;
} }
// Allocate half pages memory /* Allocate half pages memory */
while (target_alloc_working_area_try(target, buffer_size, &source) while (target_alloc_working_area_try(target, buffer_size, &source)
!= ERROR_OK) != ERROR_OK) {
{
if (buffer_size > 1024) if (buffer_size > 1024)
buffer_size -= 1024; buffer_size -= 1024;
else else
buffer_size /= 2; buffer_size /= 2;
if (buffer_size <= 256) if (buffer_size <= 256) {
{
/* if we already allocated the writing code, but failed to get a /* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
if (stm32lx_info->write_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[3], "r3", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[4], "r4", 32, PARAM_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); 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, source);
target_free_working_area(target, stm32lx_info->write_algorithm); 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[1]);
destroy_reg_param(&reg_params[2]); destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]); destroy_reg_param(&reg_params[3]);
return retval; return retval;
} }
// Loop while there are bytes to write /* Loop while there are bytes to write */
while (count > 0) while (count > 0) {
{
uint32_t this_count; uint32_t this_count;
this_count = (count > buffer_size) ? buffer_size : 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, retval = target_write_buffer(target, source->address, this_count,
buffer); buffer);
if (retval != ERROR_OK) if (retval != ERROR_OK)
break; break;
// 4: Store useful information in the registers /* 4: Store useful information in the registers */
// the destination address of the copy (R0) /* the destination address of the copy (R0) */
buf_set_u32(reg_params[0].value, 0, 32, address); 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); 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); 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) retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params)
/ sizeof(*reg_params), reg_params, / sizeof(*reg_params), reg_params,
stm32lx_info->write_algorithm->address, 0, 20000, &armv7m_info); stm32lx_info->write_algorithm->address, 0, 20000, &armv7m_info);
if (retval != ERROR_OK) if (retval != ERROR_OK)
break; break;
// 6: Wait while busy /* 6: Wait while busy */
retval = stm32lx_wait_until_bsy_clear(bank); retval = stm32lx_wait_until_bsy_clear(bank);
if (retval != ERROR_OK) if (retval != ERROR_OK)
break; break;
@ -401,34 +380,28 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t bytes_written = 0; uint32_t bytes_written = 0;
int retval; int retval;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
// Check if there are some full half pages /* Check if there are some full half pages */
if (((offset % 128) == 0) && (count >= 128)) if (((offset % 128) == 0) && (count >= 128)) {
{
halfpages_number = count / 128; halfpages_number = count / 128;
words_remaining = (count - 128 * halfpages_number) / 4; words_remaining = (count - 128 * halfpages_number) / 4;
bytes_remaining = (count & 0x3); bytes_remaining = (count & 0x3);
} } else {
else
{
halfpages_number = 0; halfpages_number = 0;
words_remaining = (count / 4); words_remaining = (count / 4);
bytes_remaining = (count & 0x3); bytes_remaining = (count & 0x3);
} }
if (halfpages_number) if (halfpages_number) {
{
retval = stm32lx_write_half_pages(bank, buffer, offset, 128 retval = stm32lx_write_half_pages(bank, buffer, offset, 128
* halfpages_number); * halfpages_number);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -441,12 +414,11 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
while (words_remaining > 0) while (words_remaining > 0) {
{
uint32_t value; 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); value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
retval = target_write_u32(target, address, value); retval = target_write_u32(target, address, value);
@ -462,8 +434,7 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
return retval; return retval;
} }
if (bytes_remaining) if (bytes_remaining) {
{
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff}; uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
/* copy the last remaining bytes into the write buffer */ /* copy the last remaining bytes into the write buffer */
@ -508,14 +479,13 @@ static int stm32lx_probe(struct flash_bank *bank)
return ERROR_FAIL; 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; uint8_t rdp;
retval = target_read_u32(target, FLASH_OBR, &reg32); retval = target_read_u32(target, FLASH_OBR, &reg32);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
rdp = reg32 & 0xFF; rdp = reg32 & 0xFF;
if (rdp != 0xAA) if (rdp != 0xAA) {
{
/* /*
* Unlocking the option byte is done by unlocking the PECR, then * Unlocking the option byte is done by unlocking the PECR, then
* by writing the 2 option byte keys to OPTKEYR * 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) if (retval != ERROR_OK)
return retval; return retval;
if (reg32 & FLASH_PECR__OPTLOCK) if (reg32 & FLASH_PECR__OPTLOCK) {
{
LOG_ERROR("OPTLOCK is not cleared"); LOG_ERROR("OPTLOCK is not cleared");
return ERROR_FLASH_OPERATION_FAILED; 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); reg32 = ((~0xAA) << 16) | (0xAA);
retval = target_write_u32(target, OB_RDP, reg32); retval = target_write_u32(target, OB_RDP, reg32);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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; reg32 = FLASH_PECR__OBL_LAUNCH;
retval = target_write_u32(target, FLASH_PECR, reg32); retval = target_write_u32(target, FLASH_PECR, reg32);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -574,8 +543,7 @@ static int stm32lx_probe(struct flash_bank *bank)
return retval; return retval;
/* check for valid flash size */ /* check for valid flash size */
if (flash_size == 0xffff) if (flash_size == 0xffff) {
{
/* number of sectors incorrect on revA */ /* number of sectors incorrect on revA */
LOG_ERROR("STM32 flash size failed, probe inaccurate"); LOG_ERROR("STM32 flash size failed, probe inaccurate");
return ERROR_FAIL; return ERROR_FAIL;
@ -588,8 +556,7 @@ static int stm32lx_probe(struct flash_bank *bank)
int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE; int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE;
LOG_INFO("flash size = %dkbytes", flash_size); LOG_INFO("flash size = %dkbytes", flash_size);
if (bank->sectors) if (bank->sectors) {
{
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL; bank->sectors = NULL;
} }
@ -598,14 +565,12 @@ static int stm32lx_probe(struct flash_bank *bank)
bank->size = flash_size * 1024; bank->size = flash_size * 1024;
bank->num_sectors = num_sectors; bank->num_sectors = num_sectors;
bank->sectors = malloc(sizeof(struct flash_sector) * 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"); LOG_ERROR("failed to allocate bank sectors");
return ERROR_FAIL; 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].offset = i * FLASH_SECTOR_SIZE;
bank->sectors[i].size = FLASH_SECTOR_SIZE; bank->sectors[i].size = FLASH_SECTOR_SIZE;
bank->sectors[i].is_erased = -1; 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; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
if (stm32lx_info->probed) if (stm32lx_info->probed)
{
return ERROR_OK; return ERROR_OK;
}
return stm32lx_probe(bank); return stm32lx_probe(bank);
} }
@ -637,60 +600,51 @@ static int stm32lx_erase_check(struct flash_bank *bank)
uint32_t nBytes; uint32_t nBytes;
int retval = ERROR_OK; int retval = ERROR_OK;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
uint8_t *buffer = malloc(buffer_size); uint8_t *buffer = malloc(buffer_size);
if (buffer == NULL) if (buffer == NULL) {
{
LOG_ERROR("failed to allocate read buffer"); LOG_ERROR("failed to allocate read buffer");
return ERROR_FAIL; return ERROR_FAIL;
} }
for (i = 0; i < bank->num_sectors; i++) for (i = 0; i < bank->num_sectors; i++) {
{
uint32_t j; uint32_t j;
bank->sectors[i].is_erased = 1; bank->sectors[i].is_erased = 1;
// Loop chunk by chunk over the sector /* Loop chunk by chunk over the sector */
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; uint32_t chunk;
chunk = buffer_size; chunk = buffer_size;
if (chunk > (j - bank->sectors[i].size)) if (chunk > (j - bank->sectors[i].size))
{
chunk = (j - bank->sectors[i].size); chunk = (j - bank->sectors[i].size);
}
retval = target_read_memory(target, bank->base retval = target_read_memory(target, bank->base
+ bank->sectors[i].offset + j, 4, chunk / 4, buffer); + bank->sectors[i].offset + j, 4, chunk / 4, buffer);
if (retval != ERROR_OK) if (retval != ERROR_OK)
break; break;
for (nBytes = 0; nBytes < chunk; nBytes++) for (nBytes = 0; nBytes < chunk; nBytes++) {
{ if (buffer[nBytes] != 0x00) {
if (buffer[nBytes] != 0x00)
{
bank->sectors[i].is_erased = 0; bank->sectors[i].is_erased = 0;
break; break;
} }
} }
} }
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
break; break;
} }
}
free(buffer); free(buffer);
return retval; return retval;
} }
static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) 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; struct target *target = bank->target;
uint32_t device_id; 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 += printed;
buf_size -= printed; buf_size -= printed;
switch (device_id >> 16) switch (device_id >> 16) {
{
case 0x1000: case 0x1000:
snprintf(buf, buf_size, "A"); snprintf(buf, buf_size, "A");
break; break;
@ -719,9 +672,7 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
snprintf(buf, buf_size, "unknown"); snprintf(buf, buf_size, "unknown");
break; break;
} }
} } else {
else
{
snprintf(buf, buf_size, "Cannot identify target as a stm32lx"); snprintf(buf, buf_size, "Cannot identify target as a stm32lx");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -729,13 +680,11 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
return ERROR_OK; return ERROR_OK;
} }
static const struct command_registration stm32lx_exec_command_handlers[] = static const struct command_registration stm32lx_exec_command_handlers[] = {
{
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
static const struct command_registration stm32lx_command_handlers[] = static const struct command_registration stm32lx_command_handlers[] = {
{
{ {
.name = "stm32lx", .name = "stm32lx",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
@ -746,8 +695,7 @@ static const struct command_registration stm32lx_command_handlers[] =
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
struct flash_driver stm32lx_flash = struct flash_driver stm32lx_flash = {
{
.name = "stm32lx", .name = "stm32lx",
.commands = stm32lx_command_handlers, .commands = stm32lx_command_handlers,
.flash_bank_command = stm32lx_flash_bank_command, .flash_bank_command = stm32lx_flash_bank_command,
@ -762,8 +710,7 @@ struct flash_driver stm32lx_flash =
.info = stm32lx_get_info, .info = stm32lx_get_info,
}; };
// Static methods implementation /* Static methods implementation */
static int stm32lx_unlock_program_memory(struct flash_bank *bank) static int stm32lx_unlock_program_memory(struct flash_bank *bank)
{ {
struct target *target = bank->target; struct target *target = bank->target;
@ -789,8 +736,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (reg32 & FLASH_PECR__PELOCK) if (reg32 & FLASH_PECR__PELOCK) {
{
LOG_ERROR("PELOCK is not cleared :("); LOG_ERROR("PELOCK is not cleared :(");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -807,8 +753,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (reg32 & FLASH_PECR__PRGLOCK) if (reg32 & FLASH_PECR__PRGLOCK) {
{
LOG_ERROR("PRGLOCK is not cleared :("); LOG_ERROR("PRGLOCK is not cleared :(");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -892,8 +837,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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; reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
retval = target_write_u32(target, FLASH_PECR, reg32); retval = target_write_u32(target, FLASH_PECR, reg32);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -929,32 +873,26 @@ static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank)
int timeout = 100; int timeout = 100;
/* wait for busy to clear */ /* wait for busy to clear */
for (;;) for (;;) {
{
retval = target_read_u32(target, FLASH_SR, &status); retval = target_read_u32(target, FLASH_SR, &status);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if ((status & FLASH_SR__BSY) == 0) if ((status & FLASH_SR__BSY) == 0)
{
break; break;
} if (timeout-- <= 0) {
if (timeout-- <= 0)
{
LOG_ERROR("timed out waiting for flash"); LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL; return ERROR_FAIL;
} }
alive_sleep(1); alive_sleep(1);
} }
if (status & FLASH_SR__WRPERR) if (status & FLASH_SR__WRPERR) {
{
LOG_ERROR("access denied / write protected"); LOG_ERROR("access denied / write protected");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
if (status & FLASH_SR__PGAERR) if (status & FLASH_SR__PGAERR) {
{
LOG_ERROR("invalid program address"); LOG_ERROR("invalid program address");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }

View File

@ -117,8 +117,7 @@
#define SMI_PROBE_TIMEOUT (100) #define SMI_PROBE_TIMEOUT (100)
#define SMI_MAX_TIMEOUT (3000) #define SMI_MAX_TIMEOUT (3000)
struct stmsmi_flash_bank struct stmsmi_flash_bank {
{
int probed; int probed;
uint32_t io_base; uint32_t io_base;
uint32_t bank_num; uint32_t bank_num;
@ -202,16 +201,13 @@ FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command)
{ {
struct stmsmi_flash_bank *stmsmi_info; struct stmsmi_flash_bank *stmsmi_info;
LOG_DEBUG("%s", __FUNCTION__); LOG_DEBUG("%s", __func__);
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank)); stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank));
if (stmsmi_info == NULL) if (stmsmi_info == NULL) {
{
LOG_ERROR("not enough memory"); LOG_ERROR("not enough memory");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -324,8 +320,7 @@ static int smi_write_enable(struct flash_bank *bank)
return retval; return retval;
/* Check write enabled */ /* 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); LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -391,37 +386,31 @@ static int stmsmi_erase(struct flash_bank *bank, int first, int last)
int retval = ERROR_OK; int retval = ERROR_OK;
int sector; 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"); LOG_ERROR("Target not halted");
return 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"); LOG_ERROR("Flash sector invalid");
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
} }
if (!(stmsmi_info->probed)) if (!(stmsmi_info->probed)) {
{
LOG_ERROR("Flash bank not probed"); LOG_ERROR("Flash bank not probed");
return ERROR_FLASH_BANK_NOT_PROBED; return ERROR_FLASH_BANK_NOT_PROBED;
} }
for (sector = first; sector <= last; sector++) for (sector = first; sector <= last; sector++) {
{ if (bank->sectors[sector].is_protected) {
if (bank->sectors[sector].is_protected)
{
LOG_ERROR("Flash sector %d protected", sector); LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
for (sector = first; sector <= last; sector++) for (sector = first; sector <= last; sector++) {
{
retval = smi_erase_sector(bank, sector); retval = smi_erase_sector(bank, sector);
if (retval != ERROR_OK) if (retval != ERROR_OK)
break; break;
@ -452,7 +441,7 @@ static int smi_write_buffer(struct flash_bank *bank, uint8_t *buffer,
int retval; int retval;
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32, LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
__FUNCTION__, address, len); __func__, address, len);
retval = smi_write_enable(bank); retval = smi_write_enable(bank);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -479,30 +468,26 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,
int retval = ERROR_OK; int retval = ERROR_OK;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, 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"); LOG_ERROR("Target not halted");
return 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."); LOG_WARNING("Write pasts end of flash. Extra data discarded.");
count = stmsmi_info->dev->size_in_bytes - offset; count = stmsmi_info->dev->size_in_bytes - offset;
} }
/* Check sector protection */ /* 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? */ /* Start offset in or before this sector? */
/* End offset in or behind this sector? */ /* End offset in or behind this sector? */
if ((offset < if ((offset <
(bank->sectors[sector].offset + bank->sectors[sector].size)) (bank->sectors[sector].offset + bank->sectors[sector].size))
&& ((offset + count - 1) >= bank->sectors[sector].offset) && ((offset + count - 1) >= bank->sectors[sector].offset)
&& bank->sectors[sector].is_protected ) && bank->sectors[sector].is_protected) {
{
LOG_ERROR("Flash sector %d protected", sector); LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -511,8 +496,7 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,
page_size = stmsmi_info->dev->pagesize; page_size = stmsmi_info->dev->pagesize;
/* unaligned buffer head */ /* unaligned buffer head */
if (count > 0 && (offset & 3) != 0) if (count > 0 && (offset & 3) != 0) {
{
cur_count = 4 - (offset & 3); cur_count = 4 - (offset & 3);
if (cur_count > count) if (cur_count > count)
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; page_offset = offset % page_size;
/* central part, aligned words */ /* central part, aligned words */
while (count >= 4) while (count >= 4) {
{
/* clip block at page boundary */ /* clip block at page boundary */
if (page_offset + count > page_size) if (page_offset + count > page_size)
cur_count = page_size - page_offset; 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; uint32_t io_base = stmsmi_info->io_base;
int retval; int retval;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
@ -617,15 +599,13 @@ static int stmsmi_probe(struct flash_bank *bank)
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) if (target_device->tap_idcode == target->tap->idcode)
break; break;
if (!target_device->name) if (!target_device->name) {
{
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable", LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable",
target->tap->idcode); target->tap->idcode);
return ERROR_FAIL; return ERROR_FAIL;
} }
switch (bank->base - target_device->smi_base) switch (bank->base - target_device->smi_base) {
{
case 0: case 0:
stmsmi_info->bank_num = SMI_SEL_BANK0; stmsmi_info->bank_num = SMI_SEL_BANK0;
break; break;
@ -661,8 +641,7 @@ static int stmsmi_probe(struct flash_bank *bank)
break; break;
} }
if (!stmsmi_info->dev) if (!stmsmi_info->dev) {
{
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -677,14 +656,12 @@ static int stmsmi_probe(struct flash_bank *bank)
bank->num_sectors = bank->num_sectors =
stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize; stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
if (sectors == NULL) if (sectors == NULL) {
{
LOG_ERROR("not enough memory"); LOG_ERROR("not enough memory");
return ERROR_FAIL; 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].offset = sector * stmsmi_info->dev->sectorsize;
sectors[sector].size = stmsmi_info->dev->sectorsize; sectors[sector].size = stmsmi_info->dev->sectorsize;
sectors[sector].is_erased = -1; 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; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
if (!(stmsmi_info->probed)) if (!(stmsmi_info->probed)) {
{
snprintf(buf, buf_size, snprintf(buf, buf_size,
"\nSMI flash bank not probed yet\n"); "\nSMI flash bank not probed yet\n");
return ERROR_OK; return ERROR_OK;

View File

@ -23,6 +23,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -32,7 +33,6 @@
#include <helper/binarybuffer.h> #include <helper/binarybuffer.h>
#include <target/algorithm.h> #include <target/algorithm.h>
/* Flash registers */ /* Flash registers */
#define FLASH_CR0 0x00000000 #define FLASH_CR0 0x00000000
@ -85,8 +85,7 @@
#define FLASH_ERR 0x00000001 #define FLASH_ERR 0x00000001
struct str7x_flash_bank struct str7x_flash_bank {
{
uint32_t *sector_bits; uint32_t *sector_bits;
uint32_t disable_bit; uint32_t disable_bit;
uint32_t busy_bits; uint32_t busy_bits;
@ -100,8 +99,7 @@ struct str7x_mem_layout {
uint32_t sector_bit; uint32_t sector_bit;
}; };
enum str7x_status_codes enum str7x_status_codes {
{
STR7X_CMD_SUCCESS = 0, STR7X_CMD_SUCCESS = 0,
STR7X_INVALID_COMMAND = 1, STR7X_INVALID_COMMAND = 1,
STR7X_SRC_ADDR_ERROR = 2, 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) static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
{ {
struct str7x_flash_bank *str7x_info = bank->driver_priv; 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) 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 num_sectors;
int b0_sectors = 0, b1_sectors = 0; int b0_sectors = 0, b1_sectors = 0;
switch (bank->size) switch (bank->size) {
{
case 16 * 1024: case 16 * 1024:
b1_sectors = 2; b1_sectors = 2;
break; break;
@ -173,8 +170,7 @@ static int str7x_build_block_list(struct flash_bank *bank)
num_sectors = 0; 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].offset = mem_layout_str7bank0[i].sector_start;
bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size; bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
bank->sectors[num_sectors].is_erased = -1; 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; 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].offset = mem_layout_str7bank1[i].sector_start;
bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size; bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
bank->sectors[num_sectors].is_erased = -1; 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; struct str7x_flash_bank *str7x_info;
if (CMD_ARGC < 7) if (CMD_ARGC < 7)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
str7x_info = malloc(sizeof(struct str7x_flash_bank)); str7x_info = malloc(sizeof(struct str7x_flash_bank));
bank->driver_priv = str7x_info; bank->driver_priv = str7x_info;
@ -219,21 +212,14 @@ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
str7x_info->disable_bit = (1 << 1); str7x_info->disable_bit = (1 << 1);
if (strcmp(CMD_ARGV[6], "STR71x") == 0) if (strcmp(CMD_ARGV[6], "STR71x") == 0)
{
str7x_info->register_base = 0x40100000; 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->register_base = 0x80100000;
str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0); 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->register_base = 0x20100000;
str7x_info->disable_bit = (1 << 0); str7x_info->disable_bit = (1 << 0);
} } else {
else
{
LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]); LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]);
free(str7x_info); free(str7x_info);
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
@ -263,8 +249,7 @@ static int str7x_waitbusy(struct flash_bank *bank)
struct target *target = bank->target; struct target *target = bank->target;
struct str7x_flash_bank *str7x_info = bank->driver_priv; struct str7x_flash_bank *str7x_info = bank->driver_priv;
for (i = 0 ; i < 10000; i++) for (i = 0 ; i < 10000; i++) {
{
uint32_t retval; uint32_t retval;
err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval); err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
if (err != ERROR_OK) if (err != ERROR_OK)
@ -290,35 +275,28 @@ static int str7x_result(struct flash_bank *bank)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (flash_flags & FLASH_WPF) if (flash_flags & FLASH_WPF) {
{
LOG_ERROR("str7x hw write protection set"); LOG_ERROR("str7x hw write protection set");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
if (flash_flags & FLASH_RESER) if (flash_flags & FLASH_RESER) {
{
LOG_ERROR("str7x suspended program erase not resumed"); LOG_ERROR("str7x suspended program erase not resumed");
retval = ERROR_FAIL; 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"); LOG_ERROR("str7x trying to set bit to 1 when it is already 0");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
if (flash_flags & FLASH_PGER) if (flash_flags & FLASH_PGER) {
{
LOG_ERROR("str7x program error"); LOG_ERROR("str7x program error");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
if (flash_flags & FLASH_ERER) if (flash_flags & FLASH_ERER) {
{
LOG_ERROR("str7x erase error"); LOG_ERROR("str7x erase error");
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
if (retval == ERROR_OK) if (retval == ERROR_OK) {
{ if (flash_flags & FLASH_ERR) {
if (flash_flags & FLASH_ERR)
{
/* this should always be set if one of the others are set... */ /* this should always be set if one of the others are set... */
LOG_ERROR("str7x write operation failed / bad setup"); LOG_ERROR("str7x write operation failed / bad setup");
retval = ERROR_FAIL; retval = ERROR_FAIL;
@ -336,8 +314,7 @@ static int str7x_protect_check(struct flash_bank *bank)
int i; int i;
uint32_t flash_flags; uint32_t flash_flags;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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) if (retval != ERROR_OK)
return retval; 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]) if (flash_flags & str7x_info->sector_bits[i])
bank->sectors[i].is_protected = 0; bank->sectors[i].is_protected = 0;
else else
@ -368,16 +344,13 @@ static int str7x_erase(struct flash_bank *bank, int first, int last)
uint32_t sectors = 0; uint32_t sectors = 0;
int err; int err;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
for (i = first; i <= last; i++) for (i = first; i <= last; i++)
{
sectors |= str7x_info->sector_bits[i]; sectors |= str7x_info->sector_bits[i];
}
LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors); 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 cmd;
uint32_t protect_blocks; uint32_t protect_blocks;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
protect_blocks = 0xFFFFFFFF; protect_blocks = 0xFFFFFFFF;
if (set) if (set) {
{
for (i = first; i <= last; i++) for (i = first; i <= last; i++)
protect_blocks &= ~(str7x_info->sector_bits[i]); protect_blocks &= ~(str7x_info->sector_bits[i]);
} }
@ -516,8 +487,7 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
/* flash write code */ /* flash write code */
if (target_alloc_working_area_try(target, sizeof(str7x_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; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}; };
@ -526,11 +496,9 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
(uint8_t *)str7x_flash_write_code); (uint8_t *)str7x_flash_write_code);
/* memory buffer */ /* 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 /= 2;
if (buffer_size <= 256) if (buffer_size <= 256) {
{
/* if we already allocated the writing code, but failed to get a /* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
if (str7x_info->write_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[4], "r4", 32, PARAM_IN);
init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT); 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; uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;
target_write_buffer(target, source->address, thisrun_count * 8, buffer); 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[3].value, 0, 32, thisrun_count);
buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits); 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,
str7x_info->write_algorithm->address + (sizeof(str7x_flash_write_code) - 4), 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; 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); retval = str7x_result(bank);
break; break;
} }
@ -609,26 +574,22 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
uint32_t check_address = offset; uint32_t check_address = offset;
int i; int i;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; 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_start = bank->sectors[i].offset;
uint32_t sec_end = sec_start + bank->sectors[i].size; uint32_t sec_end = sec_start + bank->sectors[i].size;
/* check if destination falls within the current sector */ /* 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 */ /* check if destination ends in the current sector */
if (offset + count < sec_end) if (offset + count < sec_end)
check_address = offset + count; 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); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
/* multiple dwords (8-byte) to be programmed? */ /* multiple dwords (8-byte) to be programmed? */
if (dwords_remaining > 0) if (dwords_remaining > 0) {
{
/* try using a block write */ /* try using a block write */
if ((retval = str7x_write_block(bank, buffer, offset, retval = str7x_write_block(bank, buffer, offset, dwords_remaining);
dwords_remaining)) != ERROR_OK) if (retval != ERROR_OK) {
{ if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
/* if block write failed (no sufficient working area), /* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */ * 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 {
{
return retval; return retval;
} }
} } else {
else
{
buffer += dwords_remaining * 8; buffer += dwords_remaining * 8;
address += dwords_remaining * 8; address += dwords_remaining * 8;
dwords_remaining = 0; dwords_remaining = 0;
} }
} }
while (dwords_remaining > 0) while (dwords_remaining > 0) {
{
/* command */ /* command */
cmd = FLASH_DWPG; cmd = FLASH_DWPG;
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); 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; address += 8;
} }
if (bytes_remaining) if (bytes_remaining) {
{
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/* copy the last remaining bytes into the write buffer */ /* copy the last remaining bytes into the write buffer */
@ -777,9 +730,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
uint16_t ProtectionRegs; uint16_t ProtectionRegs;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; target = bank->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), &reg);
if (!(reg & str7x_info->disable_bit)) if (!(reg & str7x_info->disable_bit))
{
ProtectionLevel = 1; ProtectionLevel = 1;
}
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &reg); target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &reg);
ProtectionRegs = ~(reg >> 16); ProtectionRegs = ~(reg >> 16);
while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) {
{
ProtectionRegs >>= 1; ProtectionRegs >>= 1;
ProtectionLevel++; ProtectionLevel++;
} }
if (ProtectionLevel == 0) if (ProtectionLevel == 0) {
{
flash_cmd = FLASH_SPR; 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_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_AR), 0x4010DFB8);
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
flash_cmd = FLASH_SPR | FLASH_WMS; flash_cmd = FLASH_SPR | FLASH_WMS;
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
} } else {
else
{
flash_cmd = FLASH_SPR; 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_CR0), flash_cmd);
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC); target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);

View File

@ -23,6 +23,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -31,7 +32,6 @@
#include <target/arm966e.h> #include <target/arm966e.h>
#include <target/algorithm.h> #include <target/algorithm.h>
/* Flash registers */ /* Flash registers */
#define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */ #define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */
@ -42,17 +42,14 @@
#define FLASH_SR 0x5400001C /* Status Register */ #define FLASH_SR 0x5400001C /* Status Register */
#define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */ #define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */
struct str9x_flash_bank {
struct str9x_flash_bank
{
uint32_t *sector_bits; uint32_t *sector_bits;
int variant; int variant;
int bank1; int bank1;
struct working_area *write_algorithm; struct working_area *write_algorithm;
}; };
enum str9x_status_codes enum str9x_status_codes {
{
STR9X_CMD_SUCCESS = 0, STR9X_CMD_SUCCESS = 0,
STR9X_INVALID_COMMAND = 1, STR9X_INVALID_COMMAND = 1,
STR9X_SRC_ADDR_ERROR = 2, 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->variant = 0;
str9x_info->bank1 = 0; str9x_info->bank1 = 0;
switch (bank->size) switch (bank->size) {
{
case (256 * 1024): case (256 * 1024):
b0_sectors = 4; b0_sectors = 4;
break; break;
@ -124,8 +120,7 @@ static int str9x_build_block_list(struct flash_bank *bank)
num_sectors = 0; 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].offset = offset;
bank->sectors[num_sectors].size = 0x10000; bank->sectors[num_sectors].size = 0x10000;
offset += bank->sectors[i].size; 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); 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].offset = offset;
bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000; bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
@ -157,9 +151,7 @@ FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command)
struct str9x_flash_bank *str9x_info; struct str9x_flash_bank *str9x_info;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
str9x_info = malloc(sizeof(struct str9x_flash_bank)); str9x_info = malloc(sizeof(struct str9x_flash_bank));
bank->driver_priv = str9x_info; bank->driver_priv = str9x_info;
@ -182,64 +174,49 @@ static int str9x_protect_check(struct flash_bank *bank)
uint32_t status = 0; uint32_t status = 0;
uint16_t hstatus = 0; uint16_t hstatus = 0;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
/* read level one protection */ /* read level one protection */
if (str9x_info->variant) if (str9x_info->variant) {
{ if (str9x_info->bank1) {
if (str9x_info->bank1)
{
adr = bank1start + 0x18; 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; return retval;
} retval = target_read_u16(target, adr, &hstatus);
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
status = hstatus; status = hstatus;
} } else {
else
{
adr = bank1start + 0x14; 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;
retval = target_read_u32(target, adr, &status);
if (retval != ERROR_OK)
return retval; return retval;
} }
if ((retval = target_read_u32(target, adr, &status)) != ERROR_OK) } else {
{
return retval;
}
}
}
else
{
adr = bank1start + 0x10; 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; return retval;
} retval = target_read_u16(target, adr, &hstatus);
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
status = hstatus; status = hstatus;
} }
/* read array command */ /* 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; 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]) if (status & str9x_info->sector_bits[i])
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
else else
@ -258,22 +235,18 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
uint8_t erase_cmd; uint8_t erase_cmd;
int total_timeout; int total_timeout;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
/* Check if we can erase whole bank */ /* 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 */ /* Optimize to run erase bank command instead of sector */
erase_cmd = 0x80; 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; total_timeout = 1000 * bank->num_sectors;
} } else {
else
{
/* Erase sector command */ /* Erase sector command */
erase_cmd = 0x20; erase_cmd = 0x20;
total_timeout = 1000; 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* */ /* this is so the compiler can *know* */
assert(total_timeout > 0); assert(total_timeout > 0);
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
int retval; int retval;
adr = bank->base + bank->sectors[i].offset; adr = bank->base + bank->sectors[i].offset;
/* erase sectors or block */ /* 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; return retval;
} retval = target_write_u16(target, adr, 0xD0);
if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
/* get status */ /* 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; return retval;
}
int timeout; int timeout;
for (timeout = 0; timeout < total_timeout; timeout++) for (timeout = 0; timeout < total_timeout; timeout++) {
{ retval = target_read_u8(target, adr, &status);
if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
if (status & 0x80) if (status & 0x80)
break; break;
alive_sleep(1); alive_sleep(1);
} }
if (timeout == total_timeout) if (timeout == total_timeout) {
{
LOG_ERROR("erase timed out"); LOG_ERROR("erase timed out");
return ERROR_FAIL; return ERROR_FAIL;
} }
/* clear status, also clear read array */ /* 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; return retval;
}
/* read array command */ /* 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; return retval;
}
if (status & 0x22) if (status & 0x22) {
{
LOG_ERROR("error erasing flash bank, status: 0x%x", status); LOG_ERROR("error erasing flash bank, status: 0x%x", status);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -357,14 +320,12 @@ static int str9x_protect(struct flash_bank *bank,
uint32_t adr; uint32_t adr;
uint8_t status; uint8_t status;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
/* Level One Protection */ /* Level One Protection */
adr = bank->base + bank->sectors[i].offset; adr = bank->base + bank->sectors[i].offset;
@ -429,8 +390,7 @@ static int str9x_write_block(struct flash_bank *bank,
/* flash write code */ /* flash write code */
if (target_alloc_working_area(target, sizeof(str9x_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"); LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}; };
@ -440,11 +400,9 @@ static int str9x_write_block(struct flash_bank *bank,
(uint8_t *)str9x_flash_write_code); (uint8_t *)str9x_flash_write_code);
/* memory buffer */ /* 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 /= 2;
if (buffer_size <= 256) if (buffer_size <= 256) {
{
/* if we already allocated the writing code, but failed to get a /* if we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
if (str9x_info->write_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[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_IN); 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; uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
target_write_buffer(target, source->address, thisrun_count * 2, buffer); 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[1].value, 0, 32, address);
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); 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, 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"); LOG_ERROR("error executing str9x flash write algorithm");
retval = ERROR_FLASH_OPERATION_FAILED; retval = ERROR_FLASH_OPERATION_FAILED;
break; 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; retval = ERROR_FLASH_OPERATION_FAILED;
break; break;
} }
@ -519,26 +475,22 @@ static int str9x_write(struct flash_bank *bank,
uint32_t bank_adr; uint32_t bank_adr;
int i; int i;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return 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); LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; 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_start = bank->sectors[i].offset;
uint32_t sec_end = sec_start + bank->sectors[i].size; uint32_t sec_end = sec_start + bank->sectors[i].size;
/* check if destination falls within the current sector */ /* 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 */ /* check if destination ends in the current sector */
if (offset + count < sec_end) if (offset + count < sec_end)
check_address = offset + count; check_address = offset + count;
@ -551,33 +503,26 @@ static int str9x_write(struct flash_bank *bank,
return ERROR_FLASH_DST_OUT_OF_BANK; return ERROR_FLASH_DST_OUT_OF_BANK;
/* multiple half words (2-byte) to be programmed? */ /* multiple half words (2-byte) to be programmed? */
if (words_remaining > 0) if (words_remaining > 0) {
{
/* try using a block write */ /* try using a block write */
if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) retval = str9x_write_block(bank, buffer, offset, words_remaining);
{ if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
{
/* if block write failed (no sufficient working area), /* if block write failed (no sufficient working area),
* we use normal (slow) single dword accesses */ * 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 if (retval == ERROR_FLASH_OPERATION_FAILED) {
else if (retval == ERROR_FLASH_OPERATION_FAILED)
{
LOG_ERROR("flash writing failed"); LOG_ERROR("flash writing failed");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
} } else {
else
{
buffer += words_remaining * 2; buffer += words_remaining * 2;
address += words_remaining * 2; address += words_remaining * 2;
words_remaining = 0; words_remaining = 0;
} }
} }
while (words_remaining > 0) while (words_remaining > 0) {
{
bank_adr = address & ~0x03; bank_adr = address & ~0x03;
/* write data command */ /* write data command */
@ -588,15 +533,13 @@ static int str9x_write(struct flash_bank *bank,
target_write_u16(target, bank_adr, 0x70); target_write_u16(target, bank_adr, 0x70);
int timeout; int timeout;
for (timeout = 0; timeout < 1000; timeout++) for (timeout = 0; timeout < 1000; timeout++) {
{
target_read_u8(target, bank_adr, &status); target_read_u8(target, bank_adr, &status);
if (status & 0x80) if (status & 0x80)
break; break;
alive_sleep(1); alive_sleep(1);
} }
if (timeout == 1000) if (timeout == 1000) {
{
LOG_ERROR("write timed out"); LOG_ERROR("write timed out");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -615,8 +558,7 @@ static int str9x_write(struct flash_bank *bank,
address += 2; address += 2;
} }
if (bytes_remaining) if (bytes_remaining) {
{
uint8_t last_halfword[2] = {0xff, 0xff}; uint8_t last_halfword[2] = {0xff, 0xff};
/* copy the last remaining bytes into the write buffer */ /* 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); target_write_u16(target, bank_adr, 0x70);
int timeout; int timeout;
for (timeout = 0; timeout < 1000; timeout++) for (timeout = 0; timeout < 1000; timeout++) {
{
target_read_u8(target, bank_adr, &status); target_read_u8(target, bank_adr, &status);
if (status & 0x80) if (status & 0x80)
break; break;
alive_sleep(1); alive_sleep(1);
} }
if (timeout == 1000) if (timeout == 1000) {
{
LOG_ERROR("write timed out"); LOG_ERROR("write timed out");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -681,9 +621,7 @@ COMMAND_HANDLER(str9x_handle_flash_config_command)
struct target *target = NULL; struct target *target = NULL;
if (CMD_ARGC < 5) if (CMD_ARGC < 5)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; target = bank->target;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -27,7 +28,6 @@
#include "imp.h" #include "imp.h"
#include <target/arm7_9_common.h> #include <target/arm7_9_common.h>
/* ISC commands */ /* ISC commands */
#define ISC_IDCODE 0xFE #define ISC_IDCODE 0xFE
@ -61,16 +61,14 @@
#define STR9XPEC_OPT_LVDWARNBIT 51 #define STR9XPEC_OPT_LVDWARNBIT 51
#define STR9XPEC_OPT_OTPBIT 63 #define STR9XPEC_OPT_OTPBIT 63
enum str9xpec_status_codes enum str9xpec_status_codes {
{
STR9XPEC_INVALID_COMMAND = 1, STR9XPEC_INVALID_COMMAND = 1,
STR9XPEC_ISC_SUCCESS = 2, STR9XPEC_ISC_SUCCESS = 2,
STR9XPEC_ISC_DISABLED = 3, STR9XPEC_ISC_DISABLED = 3,
STR9XPEC_ISC_INTFAIL = 32, STR9XPEC_ISC_INTFAIL = 32,
}; };
struct str9xpec_flash_controller struct str9xpec_flash_controller {
{
struct jtag_tap *tap; struct jtag_tap *tap;
uint32_t *sector_bits; uint32_t *sector_bits;
int chain_pos; int chain_pos;
@ -84,12 +82,10 @@ 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) 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; 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; struct scan_field field;
field.num_bits = tap->ir_length; field.num_bits = tap->ir_length;
@ -147,8 +143,7 @@ static int str9xpec_isc_enable(struct flash_bank *bank)
/* check ISC status */ /* check ISC status */
status = str9xpec_isc_status(tap); status = str9xpec_isc_status(tap);
if (status & ISC_STATUS_MODE) if (status & ISC_STATUS_MODE) {
{
/* we have entered isc mode */ /* we have entered isc mode */
str9xpec_info->isc_enable = 1; str9xpec_info->isc_enable = 1;
LOG_DEBUG("ISC_MODE Enabled"); LOG_DEBUG("ISC_MODE Enabled");
@ -176,8 +171,7 @@ static int str9xpec_isc_disable(struct flash_bank *bank)
/* check ISC status */ /* check ISC status */
status = str9xpec_isc_status(tap); status = str9xpec_isc_status(tap);
if (!(status & ISC_STATUS_MODE)) if (!(status & ISC_STATUS_MODE)) {
{
/* we have left isc mode */ /* we have left isc mode */
str9xpec_info->isc_enable = 0; str9xpec_info->isc_enable = 0;
LOG_DEBUG("ISC_MODE Disabled"); LOG_DEBUG("ISC_MODE Disabled");
@ -224,8 +218,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
uint32_t offset = 0; uint32_t offset = 0;
int b1_size = 0x2000; int b1_size = 0x2000;
switch (bank->size) switch (bank->size) {
{
case (256 * 1024): case (256 * 1024):
b0_sectors = 4; b0_sectors = 4;
break; break;
@ -258,8 +251,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
num_sectors = 0; 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].offset = offset;
bank->sectors[num_sectors].size = 0x10000; bank->sectors[num_sectors].size = 0x10000;
offset += bank->sectors[i].size; 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; 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].offset = offset;
bank->sectors[num_sectors].size = b1_size; bank->sectors[num_sectors].size = b1_size;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
@ -291,9 +282,7 @@ FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command)
struct arm_jtag *jtag_info = NULL; struct arm_jtag *jtag_info = NULL;
if (CMD_ARGC < 6) if (CMD_ARGC < 6)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller)); str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller));
bank->driver_priv = str9xpec_info; 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; tap = str9xpec_info->tap;
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank); str9xpec_isc_enable(bank);
}
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
buffer = calloc(DIV_ROUND_UP(64, 8), 1); buffer = calloc(DIV_ROUND_UP(64, 8), 1);
LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last); 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); buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
}
/* execute ISC_BLANK_CHECK command */ /* execute ISC_BLANK_CHECK command */
str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE); 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); 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)) if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
bank->sectors[i].is_erased = 0; bank->sectors[i].is_erased = 0;
else else
@ -391,8 +376,7 @@ static int str9xpec_protect_check(struct flash_bank *bank)
status = str9xpec_read_config(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)) if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
else else
@ -416,13 +400,11 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
tap = str9xpec_info->tap; tap = str9xpec_info->tap;
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank); str9xpec_isc_enable(bank);
}
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
return ISC_STATUS_ERROR; return ISC_STATUS_ERROR;
}
buffer = calloc(DIV_ROUND_UP(64, 8), 1); buffer = calloc(DIV_ROUND_UP(64, 8), 1);
@ -430,22 +412,15 @@ 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: 0xFF signals a full erase (unlock complete device) */
/* last bank: 0xFE signals a option byte erase */ /* last bank: 0xFE signals a option byte erase */
if (last == 0xFF) if (last == 0xFF) {
{ for (i = 0; i < 64; i++)
for (i = 0; i < 64; i++) {
buf_set_u32(buffer, i, 1, 1); buf_set_u32(buffer, i, 1, 1);
} } else if (last == 0xFE)
}
else if (last == 0xFE)
{
buf_set_u32(buffer, 49, 1, 1); buf_set_u32(buffer, 49, 1, 1);
} else {
else for (i = first; i <= last; i++)
{
for (i = first; i <= last; i++) {
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1); buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
} }
}
LOG_DEBUG("ISC_ERASE"); 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); jtag_add_sleep(10);
/* wait for erase completion */ /* 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); alive_sleep(1);
}
free(buffer); free(buffer);
@ -495,13 +469,11 @@ static int str9xpec_lock_device(struct flash_bank *bank)
str9xpec_info = bank->driver_priv; str9xpec_info = bank->driver_priv;
tap = str9xpec_info->tap; tap = str9xpec_info->tap;
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank); str9xpec_isc_enable(bank);
}
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
return ISC_STATUS_ERROR; return ISC_STATUS_ERROR;
}
/* set security address */ /* set security address */
str9xpec_set_address(bank, 0x80); 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); LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
/* last bank: 0xFF signals a full device protect */ /* last bank: 0xFF signals a full device protect */
if (last == 0xFF) if (last == 0xFF) {
{
if (set) if (set)
{
status = str9xpec_lock_device(bank); status = str9xpec_lock_device(bank);
} else {
else
{
/* perform full erase to unlock device */ /* perform full erase to unlock device */
status = str9xpec_unlock_device(bank); status = str9xpec_unlock_device(bank);
} }
} } else {
else for (i = first; i <= last; i++) {
{
for (i = first; i <= last; i++)
{
if (set) if (set)
buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1); buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
else else
@ -619,28 +584,23 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
tap = str9xpec_info->tap; tap = str9xpec_info->tap;
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank); str9xpec_isc_enable(bank);
}
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
if (offset & 0x7) if (offset & 0x7) {
{
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset); LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; 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_start = bank->sectors[i].offset;
uint32_t sec_end = sec_start + bank->sectors[i].size; uint32_t sec_end = sec_start + bank->sectors[i].size;
/* check if destination falls within the current sector */ /* 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 */ /* check if destination ends in the current sector */
if (offset + count < sec_end) if (offset + count < sec_end)
check_address = offset + count; check_address = offset + count;
@ -648,14 +608,12 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
check_address = sec_end; check_address = sec_end;
} }
if ((offset >= sec_start) && (offset < sec_end)) { if ((offset >= sec_start) && (offset < sec_end))
first_sector = i; first_sector = i;
}
if ((offset + count >= sec_start) && (offset + count < sec_end)) { if ((offset + count >= sec_start) && (offset + count < sec_end))
last_sector = i; last_sector = i;
} }
}
if (check_address != offset + count) if (check_address != offset + count)
return ERROR_FLASH_DST_OUT_OF_BANK; return ERROR_FLASH_DST_OUT_OF_BANK;
@ -666,15 +624,13 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
LOG_DEBUG("ISC_PROGRAM"); 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]); str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) dwords_remaining = dwords_remaining < (bank->sectors[i].size/8)
? 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); str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
field.num_bits = 64; 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}; uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/* copy the last remaining bytes into the write buffer */ /* 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; struct str9xpec_flash_controller *str9xpec_info = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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) if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
return status; return status;
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
str9xpec_isc_enable(bank); str9xpec_isc_enable(bank);
}
if (!str9xpec_info->isc_enable) { if (!str9xpec_info->isc_enable)
return ISC_STATUS_ERROR; return ISC_STATUS_ERROR;
}
/* according to data 64th bit has to be set */ /* according to data 64th bit has to be set */
buf_set_u32(str9xpec_info->options, 63, 1, 1); buf_set_u32(str9xpec_info->options, 63, 1, 1);
@ -931,9 +882,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
uint8_t status; uint8_t status;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; struct str9xpec_flash_controller *str9xpec_info = NULL;
if (CMD_ARGC < 2) if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; str9xpec_info = bank->driver_priv;
if (strcmp(CMD_ARGV[1], "bank1") == 0) if (strcmp(CMD_ARGV[1], "bank1") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
}
else else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
}
return ERROR_OK; return ERROR_OK;
} }
@ -985,9 +928,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
struct str9xpec_flash_controller *str9xpec_info = NULL; struct str9xpec_flash_controller *str9xpec_info = NULL;
if (CMD_ARGC < 2) if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; str9xpec_info = bank->driver_priv;
if (strcmp(CMD_ARGV[1], "2.7v") == 0) if (strcmp(CMD_ARGV[1], "2.7v") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
}
else else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
}
return ERROR_OK; return ERROR_OK;
} }
@ -1013,9 +950,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
struct str9xpec_flash_controller *str9xpec_info = NULL; struct str9xpec_flash_controller *str9xpec_info = NULL;
if (CMD_ARGC < 2) if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; str9xpec_info = bank->driver_priv;
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0) if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
}
else else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
}
return ERROR_OK; return ERROR_OK;
} }
@ -1041,9 +972,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
struct str9xpec_flash_controller *str9xpec_info = NULL; struct str9xpec_flash_controller *str9xpec_info = NULL;
if (CMD_ARGC < 2) if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; str9xpec_info = bank->driver_priv;
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0) if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
}
else else
{
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0); buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
}
return ERROR_OK; return ERROR_OK;
} }
@ -1069,9 +994,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_lock_command)
uint8_t status; uint8_t status;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; uint8_t status;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; struct str9xpec_flash_controller *str9xpec_info = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@ -1135,15 +1054,13 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
/* remove arm core from chain - enter turbo mode */ /* remove arm core from chain - enter turbo mode */
tap1 = tap0->next_tap; tap1 = tap0->next_tap;
if (tap1 == NULL) if (tap1 == NULL) {
{
/* things are *WRONG* */ /* things are *WRONG* */
command_print(CMD_CTX, "**STR9FLASH** (tap1) invalid chain?"); command_print(CMD_CTX, "**STR9FLASH** (tap1) invalid chain?");
return ERROR_OK; return ERROR_OK;
} }
tap2 = tap1->next_tap; tap2 = tap1->next_tap;
if (tap2 == NULL) if (tap2 == NULL) {
{
/* things are *WRONG* */ /* things are *WRONG* */
command_print(CMD_CTX, "**STR9FLASH** (tap2) invalid chain?"); command_print(CMD_CTX, "**STR9FLASH** (tap2) invalid chain?");
return ERROR_OK; return ERROR_OK;
@ -1151,7 +1068,8 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
/* enable turbo mode - TURBO-PROG-ENABLE */ /* enable turbo mode - TURBO-PROG-ENABLE */
str9xpec_set_instr(tap2, 0xD, TAP_IDLE); str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
if ((retval = jtag_execute_queue()) != ERROR_OK) retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval; return retval;
/* modify scan chain - str9 core has been removed */ /* 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; struct str9xpec_flash_controller *str9xpec_info = NULL;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *bank; struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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(); jtag_execute_queue();
/* restore previous scan chain */ /* restore previous scan chain */
if (tap->next_tap) { if (tap->next_tap)
tap->next_tap->enabled = 1; tap->next_tap->enabled = 1;
}
return ERROR_OK; return ERROR_OK;
} }

View File

@ -47,7 +47,6 @@ COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
return get_flash_bank_by_num(bank_num, bank); return get_flash_bank_by_num(bank_num, bank);
} }
COMMAND_HANDLER(handle_flash_info_command) COMMAND_HANDLER(handle_flash_info_command)
{ {
struct flash_bank *p; struct flash_bank *p;
@ -61,12 +60,12 @@ COMMAND_HANDLER(handle_flash_info_command)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (p != NULL) if (p != NULL) {
{
char buf[1024]; char buf[1024];
/* attempt auto probe */ /* attempt auto probe */
if ((retval = p->driver->auto_probe(p)) != ERROR_OK) retval = p->driver->auto_probe(p);
if (retval != ERROR_OK)
return retval; return retval;
/* We must query the hardware to avoid printing stale information! */ /* We must query the hardware to avoid printing stale information! */
@ -75,15 +74,15 @@ COMMAND_HANDLER(handle_flash_info_command)
return retval; return retval;
command_print(CMD_CTX, command_print(CMD_CTX,
"#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", buswidth %i, chipwidth %i", "#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32
", buswidth %i, chipwidth %i",
p->bank_number, p->bank_number,
p->driver->name, p->driver->name,
p->base, p->base,
p->size, p->size,
p->bus_width, p->bus_width,
p->chip_width); p->chip_width);
for (j = 0; j < p->num_sectors; j++) for (j = 0; j < p->num_sectors; j++) {
{
char *protect_state; char *protect_state;
if (p->sectors[j].is_protected == 0) if (p->sectors[j].is_protected == 0)
@ -102,7 +101,8 @@ COMMAND_HANDLER(handle_flash_info_command)
protect_state); 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)); retval = p->driver->info(p, buf, sizeof(buf));
command_print(CMD_CTX, "%s", buf); command_print(CMD_CTX, "%s", buf);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -118,23 +118,20 @@ COMMAND_HANDLER(handle_flash_probe_command)
int retval; int retval;
if (CMD_ARGC != 1) if (CMD_ARGC != 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (p) if (p) {
{ retval = p->driver->probe(p);
if ((retval = p->driver->probe(p)) == ERROR_OK) if (retval == ERROR_OK)
{ command_print(CMD_CTX,
command_print(CMD_CTX, "flash '%s' found at 0x%8.8" PRIx32, p->driver->name, p->base); "flash '%s' found at 0x%8.8" PRIx32,
} p->driver->name,
} p->base);
else } else {
{
command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]); command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
retval = ERROR_FAIL; retval = ERROR_FAIL;
} }
@ -145,9 +142,7 @@ COMMAND_HANDLER(handle_flash_probe_command)
COMMAND_HANDLER(handle_flash_erase_check_command) COMMAND_HANDLER(handle_flash_erase_check_command)
{ {
if (CMD_ARGC != 1) if (CMD_ARGC != 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct flash_bank *p; struct flash_bank *p;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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; return retval;
int j; 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"); command_print(CMD_CTX, "successfully checked erase state");
} else {
else command_print(CMD_CTX,
{ "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
command_print(CMD_CTX, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32, CMD_ARGV[0],
CMD_ARGV[0], p->base); p->base);
} }
for (j = 0; j < p->num_sectors; j++) for (j = 0; j < p->num_sectors; j++) {
{
char *erase_state; char *erase_state;
if (p->sectors[j].is_erased == 0) if (p->sectors[j].is_erased == 0)
@ -198,35 +192,27 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
bool do_unlock = false; bool do_unlock = false;
struct target *target = get_current_target(CMD_CTX); 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 /* Optionally pad out the address range to block/sector
* boundaries. We can't know if there's data in that part * boundaries. We can't know if there's data in that part
* of the flash; only do padding if we're told to. * of the flash; only do padding if we're told to.
*/ */
if (strcmp("pad", CMD_ARGV[0]) == 0) if (strcmp("pad", CMD_ARGV[0]) == 0)
{
do_pad = true; do_pad = true;
} else if (strcmp("unlock", CMD_ARGV[0]) == 0) else if (strcmp("unlock", CMD_ARGV[0]) == 0)
{
do_unlock = true; do_unlock = true;
} else else
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
CMD_ARGC--; CMD_ARGC--;
CMD_ARGV++; CMD_ARGV++;
} }
if (CMD_ARGC != 2) if (CMD_ARGC != 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
if (length <= 0) if (length <= 0) {
{
command_print(CMD_CTX, "Length must be >0"); command_print(CMD_CTX, "Length must be >0");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
@ -235,24 +221,20 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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(); flash_set_dirty();
struct duration bench; struct duration bench;
duration_start(&bench); duration_start(&bench);
if (do_unlock) if (do_unlock)
{
retval = flash_unlock_address_range(target, address, length); retval = flash_unlock_address_range(target, address, length);
}
if (retval == ERROR_OK) if (retval == ERROR_OK)
{
retval = flash_erase_address_range(target, do_pad, address, length); 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)" command_print(CMD_CTX, "erased address 0x%8.8x (length %i)"
" in %fs (%0.3f KiB/s)", address, length, " in %fs (%0.3f KiB/s)", address, length,
duration_elapsed(&bench), duration_kbps(&bench, length)); duration_elapsed(&bench), duration_kbps(&bench, length));
@ -300,8 +282,8 @@ COMMAND_HANDLER(handle_flash_erase_command)
else else
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
if ((retval = flash_check_sector_parameters(CMD_CTX, retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
first, last, p->num_sectors)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
struct duration bench; struct duration bench;
@ -309,8 +291,7 @@ COMMAND_HANDLER(handle_flash_erase_command)
retval = flash_driver_erase(p, first, last); 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 " " command_print(CMD_CTX, "erased sectors %" PRIu32 " "
"through %" PRIu32 " on flash bank %" PRIu32 " " "through %" PRIu32 " on flash bank %" PRIu32 " "
"in %fs", first, last, p->bank_number, duration_elapsed(&bench)); "in %fs", first, last, p->bank_number, duration_elapsed(&bench));
@ -343,8 +324,8 @@ COMMAND_HANDLER(handle_flash_protect_command)
bool set; bool set;
COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set); COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
if ((retval = flash_check_sector_parameters(CMD_CTX, retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
first, last, p->num_sectors)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
retval = flash_driver_protect(p, set, first, last); retval = flash_driver_protect(p, set, first, last);
@ -368,41 +349,31 @@ COMMAND_HANDLER(handle_flash_write_image_command)
int retval; int retval;
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
/* flash auto-erase is disabled by default*/ /* flash auto-erase is disabled by default*/
int auto_erase = 0; int auto_erase = 0;
bool auto_unlock = false; bool auto_unlock = false;
for (;;) for (;; ) {
{ if (strcmp(CMD_ARGV[0], "erase") == 0) {
if (strcmp(CMD_ARGV[0], "erase") == 0)
{
auto_erase = 1; auto_erase = 1;
CMD_ARGV++; CMD_ARGV++;
CMD_ARGC--; CMD_ARGC--;
command_print(CMD_CTX, "auto erase enabled"); 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; auto_unlock = true;
CMD_ARGV++; CMD_ARGV++;
CMD_ARGC--; CMD_ARGC--;
command_print(CMD_CTX, "auto unlock enabled"); command_print(CMD_CTX, "auto unlock enabled");
} else } else
{
break; break;
} }
}
if (CMD_ARGC < 1) if (CMD_ARGC < 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
if (!target) if (!target) {
{
LOG_ERROR("no target selected"); LOG_ERROR("no target selected");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -410,13 +381,10 @@ COMMAND_HANDLER(handle_flash_write_image_command)
struct duration bench; struct duration bench;
duration_start(&bench); duration_start(&bench);
if (CMD_ARGC >= 2) if (CMD_ARGC >= 2) {
{
image.base_address_set = 1; image.base_address_set = 1;
COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address); COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
} } else {
else
{
image.base_address_set = 0; image.base_address_set = 0;
image.base_address = 0x0; image.base_address = 0x0;
} }
@ -425,19 +393,15 @@ COMMAND_HANDLER(handle_flash_write_image_command)
retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock); retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
image_close(&image); image_close(&image);
return retval; 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 " command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
"in %fs (%0.3f KiB/s)", written, CMD_ARGV[0], "in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
duration_elapsed(&bench), duration_kbps(&bench, written)); duration_elapsed(&bench), duration_kbps(&bench, written));
@ -468,20 +432,17 @@ COMMAND_HANDLER(handle_flash_fill_command)
return ERROR_FAIL; return ERROR_FAIL;
uint8_t *readback = malloc(chunksize); uint8_t *readback = malloc(chunksize);
if (readback == NULL) if (readback == NULL) {
{
free(chunk); free(chunk);
return ERROR_FAIL; return ERROR_FAIL;
} }
if (CMD_ARGC != 3) if (CMD_ARGC != 3) {
{
retval = ERROR_COMMAND_SYNTAX_ERROR; retval = ERROR_COMMAND_SYNTAX_ERROR;
goto done; goto done;
} }
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
@ -489,8 +450,7 @@ COMMAND_HANDLER(handle_flash_fill_command)
if (count == 0) if (count == 0)
goto done; goto done;
switch (CMD_NAME[4]) switch (CMD_NAME[4]) {
{
case 'w': case 'w':
wordsize = 4; wordsize = 4;
break; break;
@ -506,19 +466,14 @@ COMMAND_HANDLER(handle_flash_fill_command)
} }
chunk_count = MIN(count, (chunksize / wordsize)); chunk_count = MIN(count, (chunksize / wordsize));
switch (wordsize) switch (wordsize) {
{
case 4: case 4:
for (i = 0; i < chunk_count; i++) for (i = 0; i < chunk_count; i++)
{
target_buffer_set_u32(target, chunk + i * wordsize, pattern); target_buffer_set_u32(target, chunk + i * wordsize, pattern);
}
break; break;
case 2: case 2:
for (i = 0; i < chunk_count; i++) for (i = 0; i < chunk_count; i++)
{
target_buffer_set_u16(target, chunk + i * wordsize, pattern); target_buffer_set_u16(target, chunk + i * wordsize, pattern);
}
break; break;
case 1: case 1:
memset(chunk, pattern, chunk_count); memset(chunk, pattern, chunk_count);
@ -531,8 +486,7 @@ COMMAND_HANDLER(handle_flash_fill_command)
struct duration bench; struct duration bench;
duration_start(&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; struct flash_bank *bank;
retval = get_flash_bank_by_addr(target, address, true, &bank); retval = get_flash_bank_by_addr(target, address, true, &bank);
@ -541,33 +495,31 @@ COMMAND_HANDLER(handle_flash_fill_command)
cur_size = MIN((count * wordsize - wrote), chunksize); cur_size = MIN((count * wordsize - wrote), chunksize);
err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size); err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size);
if (err != ERROR_OK) if (err != ERROR_OK) {
{
retval = err; retval = err;
goto done; goto done;
} }
err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size); err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size);
if (err != ERROR_OK) if (err != ERROR_OK) {
{
retval = err; retval = err;
goto done; goto done;
} }
for (i = 0; i < cur_size; i++) for (i = 0; i < cur_size; i++) {
{ if (readback[i] != chunk[i]) {
if (readback[i]!=chunk[i]) LOG_ERROR(
{ "Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
LOG_ERROR("Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x", address + wrote + i,
address + wrote + i, readback[i], chunk[i]); readback[i],
chunk[i]);
retval = ERROR_FAIL; retval = ERROR_FAIL;
goto done; 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 command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)", wrote, address, " in %fs (%0.3f KiB/s)", wrote, address,
duration_elapsed(&bench), duration_kbps(&bench, wrote)); duration_elapsed(&bench), duration_kbps(&bench, wrote));
@ -600,28 +552,23 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
{
return ERROR_OK; return ERROR_OK;
}
int filesize; int filesize;
retval = fileio_size(&fileio, &filesize); retval = fileio_size(&fileio, &filesize);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
fileio_close(&fileio); fileio_close(&fileio);
return retval; return retval;
} }
buffer = malloc(filesize); buffer = malloc(filesize);
if (buffer == NULL) if (buffer == NULL) {
{
fileio_close(&fileio); fileio_close(&fileio);
LOG_ERROR("Out of memory"); LOG_ERROR("Out of memory");
return ERROR_FAIL; return ERROR_FAIL;
} }
size_t buf_cnt; 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); free(buffer);
fileio_close(&fileio); fileio_close(&fileio);
return ERROR_OK; return ERROR_OK;
@ -632,8 +579,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
free(buffer); free(buffer);
buffer = NULL; 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" 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)", " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
(long)filesize, CMD_ARGV[1], p->bank_number, offset, (long)filesize, CMD_ARGV[1], p->bank_number, offset,
@ -651,14 +597,11 @@ void flash_set_dirty(void)
int i; int i;
/* set all flash to require erasing */ /* 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++) for (i = 0; i < c->num_sectors; i++)
{
c->sectors[i].is_erased = 0; c->sectors[i].is_erased = 0;
} }
} }
}
static const struct command_registration flash_exec_command_handlers[] = { static const struct command_registration flash_exec_command_handlers[] = {
{ {
@ -770,47 +713,41 @@ static int flash_init_drivers(struct command_context *cmd_ctx)
COMMAND_HANDLER(handle_flash_bank_command) COMMAND_HANDLER(handle_flash_bank_command)
{ {
if (CMD_ARGC < 7) if (CMD_ARGC < 7) {
{
LOG_ERROR("usage: flash bank <name> <driver> " 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; 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++; const char *bank_name = *CMD_ARGV++;
CMD_ARGC--; CMD_ARGC--;
struct target *target; struct target *target = get_target(CMD_ARGV[5]);
if ((target = get_target(CMD_ARGV[5])) == NULL) if (target == NULL) {
{
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
return ERROR_FAIL; return ERROR_FAIL;
} }
const char *driver_name = CMD_ARGV[0]; const char *driver_name = CMD_ARGV[0];
struct flash_driver *driver = flash_driver_find_by_name(driver_name); struct flash_driver *driver = flash_driver_find_by_name(driver_name);
if (NULL == driver) if (NULL == driver) {
{
/* no matching flash driver found */ /* no matching flash driver found */
LOG_ERROR("flash driver '%s' not found", driver_name); LOG_ERROR("flash driver '%s' not found", driver_name);
return ERROR_FAIL; return ERROR_FAIL;
} }
/* check the flash bank name is unique */ /* 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 */ /* flash bank name already exists */
LOG_ERROR("flash bank name '%s' already exists", bank_name); LOG_ERROR("flash bank name '%s' already exists", bank_name);
return ERROR_FAIL; return ERROR_FAIL;
} }
/* register flash specific commands */ /* register flash specific commands */
if (NULL != driver->commands) if (NULL != driver->commands) {
{
int retval = register_commands(CMD_CTX, NULL, int retval = register_commands(CMD_CTX, NULL,
driver->commands); driver->commands);
if (ERROR_OK != retval) if (ERROR_OK != retval) {
{
LOG_ERROR("couldn't register '%s' commands", LOG_ERROR("couldn't register '%s' commands",
driver_name); driver_name);
return ERROR_FAIL; return ERROR_FAIL;
@ -832,8 +769,7 @@ COMMAND_HANDLER(handle_flash_bank_command)
int retval; int retval;
retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c); 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", 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); free(c);
@ -854,8 +790,7 @@ COMMAND_HANDLER(handle_flash_banks_command)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
unsigned n = 0; 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 ", " LOG_USER("#%" PRIu32 " : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
"buswidth %u, chipwidth %u", p->bank_number, "buswidth %u, chipwidth %u", p->bank_number,
p->name, p->driver->name, p->base, p->size, p->name, p->driver->name, p->base, p->size,
@ -866,8 +801,7 @@ COMMAND_HANDLER(handle_flash_banks_command)
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, Jim_WrongNumArgs(interp, 1, argv,
"no arguments to 'flash list' command"); "no arguments to 'flash list' command");
return JIM_ERR; return JIM_ERR;
@ -875,8 +809,7 @@ static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_Obj *list = Jim_NewListObj(interp, NULL, 0); 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_Obj *elem = Jim_NewListObj(interp, NULL, 0);
Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1)); 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; return JIM_OK;
} }
COMMAND_HANDLER(handle_flash_init_command) COMMAND_HANDLER(handle_flash_init_command)
{ {
if (CMD_ARGC != 0) if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
static bool flash_initialized = false; static bool flash_initialized;
if (flash_initialized) if (flash_initialized) {
{
LOG_INFO("'flash init' has already been called"); LOG_INFO("'flash init' has already been called");
return ERROR_OK; return ERROR_OK;
} }

View File

@ -17,19 +17,18 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "imp.h" #include "imp.h"
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
Internal Support, Helpers * Internal Support, Helpers
---------------------------------------------------------------------- */ * ---------------------------------------------------------------------- */
struct tms470_flash_bank struct tms470_flash_bank {
{
unsigned ordinal; unsigned ordinal;
/* device identification register */ /* device identification register */
@ -141,8 +140,7 @@ static int tms470_read_part_info(struct flash_bank *bank)
LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", 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."); LOG_WARNING("Cannot identify target as a TMS470 family.");
return ERROR_FLASH_OPERATION_FAILED; 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; rom_flash = (device_ident_reg >> 10) & 1;
part_number = (device_ident_reg >> 3) & 0x7f; part_number = (device_ident_reg >> 3) & 0x7f;
if (bank->sectors) if (bank->sectors) {
{
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL; bank->sectors = NULL;
} }
@ -164,14 +161,14 @@ static int tms470_read_part_info(struct flash_bank *bank)
* ranges. Then fixup/complete the remaining fields of the flash * ranges. Then fixup/complete the remaining fields of the flash
* bank structure. * bank structure.
*/ */
switch (part_number) switch (part_number) {
{
case 0x0a: case 0x0a:
part_name = "TMS470R1A256"; part_name = "TMS470R1A256";
if (bank->base >= 0x00040000) if (bank->base >= 0x00040000) {
{ LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base); part_name,
bank->base);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
tms470_info->ordinal = 0; tms470_info->ordinal = 0;
@ -180,44 +177,36 @@ static int tms470_read_part_info(struct flash_bank *bank)
bank->num_sectors = TMS470R1A256_NUM_SECTORS; bank->num_sectors = TMS470R1A256_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS)); bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
if (!bank->sectors) if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS)); (void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
break; break;
case 0x2b: case 0x2b:
part_name = "TMS470R1A288"; part_name = "TMS470R1A288";
if (bank->base < 0x00008000) if (bank->base < 0x00008000) {
{
tms470_info->ordinal = 0; tms470_info->ordinal = 0;
bank->base = 0x00000000; bank->base = 0x00000000;
bank->size = 32 * 1024; bank->size = 32 * 1024;
bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS; bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS)); bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
if (!bank->sectors) if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} (void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS,
(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS, sizeof(TMS470R1A288_BANK0_SECTORS)); sizeof(TMS470R1A288_BANK0_SECTORS));
} } else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000))
{
tms470_info->ordinal = 1; tms470_info->ordinal = 1;
bank->base = 0x00040000; bank->base = 0x00040000;
bank->size = 256 * 1024; bank->size = 256 * 1024;
bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS; bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS)); bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
if (!bank->sectors) if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} (void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS,
(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, sizeof(TMS470R1A288_BANK1_SECTORS)); sizeof(TMS470R1A288_BANK1_SECTORS));
} } else {
else LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
{ part_name, bank->base);
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
break; break;
@ -225,54 +214,46 @@ static int tms470_read_part_info(struct flash_bank *bank)
case 0x2d: case 0x2d:
part_name = "TMS470R1A384"; part_name = "TMS470R1A384";
if (bank->base < 0x00020000) if (bank->base < 0x00020000) {
{
tms470_info->ordinal = 0; tms470_info->ordinal = 0;
bank->base = 0x00000000; bank->base = 0x00000000;
bank->size = 128 * 1024; bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS; bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS)); bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
if (!bank->sectors) if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} (void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS,
(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS, sizeof(TMS470R1A384_BANK0_SECTORS)); sizeof(TMS470R1A384_BANK0_SECTORS));
} } else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000))
{
tms470_info->ordinal = 1; tms470_info->ordinal = 1;
bank->base = 0x00020000; bank->base = 0x00020000;
bank->size = 128 * 1024; bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS; bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS)); bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
if (!bank->sectors) if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} (void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS,
(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS, sizeof(TMS470R1A384_BANK1_SECTORS)); sizeof(TMS470R1A384_BANK1_SECTORS));
} } else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000))
{
tms470_info->ordinal = 2; tms470_info->ordinal = 2;
bank->base = 0x00040000; bank->base = 0x00040000;
bank->size = 128 * 1024; bank->size = 128 * 1024;
bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS; bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS)); bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
if (!bank->sectors) if (!bank->sectors)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} (void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS,
(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, sizeof(TMS470R1A384_BANK2_SECTORS)); sizeof(TMS470R1A384_BANK2_SECTORS));
} } else {
else LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
{ part_name, bank->base);
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
break; break;
default: default:
LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", (unsigned)part_number); LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.",
(unsigned)part_number);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
@ -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]; static uint32_t flashKeys[4];
COMMAND_HANDLER(tms470_handle_flash_keyset_command) COMMAND_HANDLER(tms470_handle_flash_keyset_command)
{ {
if (CMD_ARGC > 4) if (CMD_ARGC > 4)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} else if (CMD_ARGC == 4) {
else if (CMD_ARGC == 4)
{
int i; 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; int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;
if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) {
{ command_print(CMD_CTX, "could not process flash key %s",
command_print(CMD_CTX, "could not process flash key %s", CMD_ARGV[i]); CMD_ARGV[i]);
LOG_ERROR("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; return ERROR_COMMAND_SYNTAX_ERROR;
} }
} }
keysSet = 1; keysSet = 1;
} } else if (CMD_ARGC != 0) {
else if (CMD_ARGC != 0)
{
command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>"); command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
if (keysSet) if (keysSet) {
{ command_print(CMD_CTX,
command_print(CMD_CTX, "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "", "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3]); flashKeys[0],
} flashKeys[1],
else flashKeys[2],
{ flashKeys[3]);
} else
command_print(CMD_CTX, "flash keys not set"); command_print(CMD_CTX, "flash keys not set");
}
return ERROR_OK; return ERROR_OK;
} }
static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF, static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,};
};
static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000, static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,};
};
static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff, static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
0xf0fff0ff, 0xf0fff0ff 0xf0fff0ff, 0xf0fff0ff};
};
static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff, 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) COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
{ {
if (CMD_ARGC > 1) if (CMD_ARGC > 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
else if (CMD_ARGC == 1) else if (CMD_ARGC == 1)
{
sscanf(CMD_ARGV[0], "%d", &oscMHz); sscanf(CMD_ARGV[0], "%d", &oscMHz);
}
if (oscMHz <= 0) if (oscMHz <= 0) {
{
LOG_ERROR("osc_megahertz must be positive and non-zero!"); LOG_ERROR("osc_megahertz must be positive and non-zero!");
command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!"); command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!");
oscMHz = 12; 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) COMMAND_HANDLER(tms470_handle_plldis_command)
{ {
if (CMD_ARGC > 1) if (CMD_ARGC > 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} else if (CMD_ARGC == 1) {
else if (CMD_ARGC == 1)
{
sscanf(CMD_ARGV[0], "%d", &plldis); sscanf(CMD_ARGV[0], "%d", &plldis);
plldis = plldis ? 1 : 0; plldis = plldis ? 1 : 0;
} }
@ -424,7 +387,9 @@ static int tms470_check_flash_unlocked(struct target * target)
uint32_t fmbbusy; uint32_t fmbbusy;
target_read_u32(target, 0xFFE89C08, &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; return fmbbusy & 0x8000 ? ERROR_OK : 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 */ /* only perform the key match when 3VSTAT is clear */
target_read_u32(target, 0xFFE8BC0C, &fmmstat); target_read_u32(target, 0xFFE8BC0C, &fmmstat);
if (!(fmmstat & 0x08)) if (!(fmmstat & 0x08)) {
{
unsigned i; unsigned i;
uint32_t fmbptr, fmbac2, orig_fmregopt; uint32_t fmbptr, fmbac2, orig_fmregopt;
target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07); target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);
/* wait for pump ready */ /* wait for pump ready */
do do {
{
target_read_u32(target, 0xFFE8A814, &fmbptr); target_read_u32(target, 0xFFE8A814, &fmbptr);
alive_sleep(1); alive_sleep(1);
} } while (!(fmbptr & 0x0200));
while (!(fmbptr & 0x0200));
/* force max wait states */ /* force max wait states */
target_read_u32(target, 0xFFE88004, &fmbac2); 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_read_u32(target, 0xFFE89C00, &orig_fmregopt);
target_write_u32(target, 0xFFE89C00, 0x00); target_write_u32(target, 0xFFE89C00, 0x00);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++) {
{
uint32_t tmp; uint32_t tmp;
/* There is no point displaying the value of tmp, it is /* 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]); 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 * There seems to be a side-effect of reading the FMPKEY
* register in that it re-enables the protection. So we * register in that it re-enables the protection. So we
* re-enable it. * re-enable it.
*/ */
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++) {
{
uint32_t tmp; uint32_t tmp;
target_read_u32(target, 0x00001FF0 + 4 * i, &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]; const uint32_t *p_key_sets[5];
unsigned i, key_set_count; unsigned i, key_set_count;
if (keysSet) if (keysSet) {
{
key_set_count = 5; key_set_count = 5;
p_key_sets[0] = flashKeys; p_key_sets[0] = flashKeys;
p_key_sets[1] = FLASH_KEYS_ALL_ONES; p_key_sets[1] = FLASH_KEYS_ALL_ONES;
p_key_sets[2] = FLASH_KEYS_ALL_ZEROS; p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
p_key_sets[3] = FLASH_KEYS_MIX1; p_key_sets[3] = FLASH_KEYS_MIX1;
p_key_sets[4] = FLASH_KEYS_MIX2; p_key_sets[4] = FLASH_KEYS_MIX2;
} } else {
else
{
key_set_count = 4; key_set_count = 4;
p_key_sets[0] = FLASH_KEYS_ALL_ONES; p_key_sets[0] = FLASH_KEYS_ALL_ONES;
p_key_sets[1] = FLASH_KEYS_ALL_ZEROS; 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; p_key_sets[3] = FLASH_KEYS_MIX2;
} }
for (i = 0; i < key_set_count; i++) for (i = 0; i < key_set_count; i++) {
{ if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) {
if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK)
{
LOG_INFO("tms470 flash is unlocked"); LOG_INFO("tms470 flash is unlocked");
return ERROR_OK; return ERROR_OK;
} }
@ -594,14 +548,11 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban
* configure VHV * configure VHV
*/ */
target_read_u32(target, 0xFFE8A080, &fmmaxep); target_read_u32(target, 0xFFE8A080, &fmmaxep);
if (fmmaxep == 0xf000) if (fmmaxep == 0xf000) {
{
fmmaxep = 0xf000 + 4095; fmmaxep = 0xf000 + 4095;
target_write_u32(target, 0xFFE8A80C, 0x9964); target_write_u32(target, 0xFFE8A80C, 0x9964);
LOG_DEBUG("set fmptr3 = 0x9964"); LOG_DEBUG("set fmptr3 = 0x9964");
} } else {
else
{
fmmaxep = 0xa000 + 4095; fmmaxep = 0xa000 + 4095;
target_write_u32(target, 0xFFE8A80C, 0x9b64); target_write_u32(target, 0xFFE8A80C, 0x9b64);
LOG_DEBUG("set fmptr3 = 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); target_read_u32(target, 0xFFE8BC0C, &fmmstat);
LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", 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."); LOG_WARNING("tms470 flash command: erase still active after busy clear.");
result = ERROR_FLASH_OPERATION_FAILED; result = ERROR_FLASH_OPERATION_FAILED;
} }
if (fmmstat & 0x0040) if (fmmstat & 0x0040) {
{
LOG_WARNING("tms470 flash command: program still active after busy clear."); LOG_WARNING("tms470 flash command: program still active after busy clear.");
result = ERROR_FLASH_OPERATION_FAILED; result = ERROR_FLASH_OPERATION_FAILED;
} }
if (fmmstat & 0x0020) if (fmmstat & 0x0020) {
{
LOG_WARNING("tms470 flash command: invalid data command."); LOG_WARNING("tms470 flash command: invalid data command.");
result = ERROR_FLASH_OPERATION_FAILED; result = ERROR_FLASH_OPERATION_FAILED;
} }
if (fmmstat & 0x0010) if (fmmstat & 0x0010) {
{
LOG_WARNING("tms470 flash command: program, erase or validate sector failed."); LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
result = ERROR_FLASH_OPERATION_FAILED; result = ERROR_FLASH_OPERATION_FAILED;
} }
if (fmmstat & 0x0008) if (fmmstat & 0x0008) {
{
LOG_WARNING("tms470 flash command: voltage instability detected."); LOG_WARNING("tms470 flash command: voltage instability detected.");
result = ERROR_FLASH_OPERATION_FAILED; result = ERROR_FLASH_OPERATION_FAILED;
} }
if (fmmstat & 0x0006) if (fmmstat & 0x0006) {
{
LOG_WARNING("tms470 flash command: command suspend detected."); LOG_WARNING("tms470 flash command: command suspend detected.");
result = ERROR_FLASH_OPERATION_FAILED; result = ERROR_FLASH_OPERATION_FAILED;
} }
if (fmmstat & 0x0001) if (fmmstat & 0x0001) {
{
LOG_WARNING("tms470 flash command: sector was locked."); LOG_WARNING("tms470 flash command: sector was locked.");
result = ERROR_FLASH_OPERATION_FAILED; 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 * Select one or more bits in FMBSEA or FMBSEB to disable Level 1
* protection for the particular sector to be erased/written. * protection for the particular sector to be erased/written.
*/ */
if (sector < 16) if (sector < 16) {
{
target_read_u32(target, 0xFFE88008, &fmbsea); target_read_u32(target, 0xFFE88008, &fmbsea);
target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector)); target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector)); LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
} } else {
else
{
target_read_u32(target, 0xFFE8800C, &fmbseb); target_read_u32(target, 0xFFE8800C, &fmbseb);
target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16))); target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", 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 * Monitor FMMSTAT, busy until clear, then check and other flags for
* ultimate result of the operation. * ultimate result of the operation.
*/ */
do do {
{
target_read_u32(target, 0xFFE8BC0C, &fmmstat); target_read_u32(target, 0xFFE8BC0C, &fmmstat);
if (fmmstat & 0x0100) if (fmmstat & 0x0100)
{
alive_sleep(1); alive_sleep(1);
} } while (fmmstat & 0x0100);
}
while (fmmstat & 0x0100);
result = tms470_flash_status(bank); result = tms470_flash_status(bank);
if (sector < 16) if (sector < 16) {
{
target_write_u32(target, 0xFFE88008, fmbsea); target_write_u32(target, 0xFFE88008, fmbsea);
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea); LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1; bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
} } else {
else
{
target_write_u32(target, 0xFFE8800C, fmbseb); target_write_u32(target, 0xFFE8800C, fmbseb);
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb); LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1; 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); LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
if (result == ERROR_OK) if (result == ERROR_OK)
{
bank->sectors[sector].is_erased = 1; bank->sectors[sector].is_erased = 1;
}
return result; return result;
} }
/*---------------------------------------------------------------------- /*----------------------------------------------------------------------
Implementation of Flash Driver Interfaces * Implementation of Flash Driver Interfaces
---------------------------------------------------------------------- */ *---------------------------------------------------------------------- */
static const struct command_registration tms470_any_command_handlers[] = { static const struct command_registration tms470_any_command_handlers[] = {
{ {
@ -876,42 +808,34 @@ static int tms470_erase(struct flash_bank *bank, int first, int last)
struct tms470_flash_bank *tms470_info = bank->driver_priv; struct tms470_flash_bank *tms470_info = bank->driver_priv;
int sector, result = ERROR_OK; int sector, result = ERROR_OK;
if (bank->target->state != TARGET_HALTED) if (bank->target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
tms470_read_part_info(bank); 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); LOG_ERROR("Sector range %d to %d invalid.", first, last);
return ERROR_FLASH_SECTOR_INVALID; return ERROR_FLASH_SECTOR_INVALID;
} }
result = tms470_unlock_flash(bank); result = tms470_unlock_flash(bank);
if (result != ERROR_OK) if (result != ERROR_OK)
{
return result; 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); LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector);
result = tms470_erase_sector(bank, sector); result = tms470_erase_sector(bank, sector);
if (result != ERROR_OK) if (result != ERROR_OK) {
{
LOG_ERROR("tms470 could not erase flash sector."); LOG_ERROR("tms470 could not erase flash sector.");
break; break;
} } else
else
{
LOG_INFO("sector erased successfully."); LOG_INFO("sector erased successfully.");
} }
}
return result; 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; uint32_t fmmac2, fmbsea, fmbseb;
int sector; int sector;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
tms470_read_part_info(bank); 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); LOG_ERROR("Sector range %d to %d invalid.", first, last);
return ERROR_FLASH_SECTOR_INVALID; 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, 0xFFE88008, &fmbsea);
target_read_u32(target, 0xFFE8800C, &fmbseb); target_read_u32(target, 0xFFE8800C, &fmbseb);
for (sector = 0; sector < bank->num_sectors; sector++) for (sector = 0; sector < bank->num_sectors; sector++) {
{ if (sector < 16) {
if (sector < 16)
{
fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector); fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
bank->sectors[sector].is_protected = set ? 1 : 0; bank->sectors[sector].is_protected = set ? 1 : 0;
} } else {
else fmbseb = set ? fmbseb &
{ ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
fmbseb = set ? fmbseb & ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
bank->sectors[sector].is_protected = set ? 1 : 0; bank->sectors[sector].is_protected = set ? 1 : 0;
} }
} }
@ -977,15 +897,15 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs
int result = ERROR_OK; int result = ERROR_OK;
uint32_t i; uint32_t i;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
tms470_read_part_info(bank); 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 */ /* set GLBCTRL.4 */
target_read_u32(target, 0xFFFFFFDC, &glbctrl); 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 */ /* read MAXPP */
target_read_u32(target, 0xFFE8A07C, &fmmaxpp); 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; uint32_t addr = bank->base + offset + i;
uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1]; 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); LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);
/* clear status register */ /* clear status register */
@ -1032,29 +950,24 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs
* Monitor FMMSTAT, busy until clear, then check and other flags * Monitor FMMSTAT, busy until clear, then check and other flags
* for ultimate result of the operation. * for ultimate result of the operation.
*/ */
do do {
{
target_read_u32(target, 0xFFE8BC0C, &fmmstat); target_read_u32(target, 0xFFE8BC0C, &fmmstat);
if (fmmstat & 0x0100) if (fmmstat & 0x0100)
{
alive_sleep(1); alive_sleep(1);
} } while (fmmstat & 0x0100);
}
while (fmmstat & 0x0100);
if (fmmstat & 0x3ff) if (fmmstat & 0x3ff) {
{
LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat); 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; result = ERROR_FLASH_OPERATION_FAILED;
break; break;
} }
} } else
else
{
LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr); LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
} }
}
/* restore */ /* restore */
target_write_u32(target, 0xFFE88008, fmbsea); target_write_u32(target, 0xFFE88008, fmbsea);
@ -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) 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."); LOG_WARNING("Cannot communicate... target not halted.");
return ERROR_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; uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt;
static uint8_t buffer[64 * 1024]; static uint8_t buffer[64 * 1024];
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (!tms470_info->device_ident_reg) if (!tms470_info->device_ident_reg)
{
tms470_read_part_info(bank); tms470_read_part_info(bank);
}
/* set GLBCTRL.4 */ /* set GLBCTRL.4 */
target_read_u32(target, 0xFFFFFFDC, &glbctrl); 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 * word at a time. Here we read an entire sector and inspect it in
* an attempt to reduce the JTAG overhead. * an attempt to reduce the JTAG overhead.
*/ */
for (sector = 0; sector < bank->num_sectors; sector++) for (sector = 0; sector < bank->num_sectors; sector++) {
{ if (bank->sectors[sector].is_erased != 1) {
if (bank->sectors[sector].is_erased != 1)
{
uint32_t i, addr = bank->base + bank->sectors[sector].offset; uint32_t i, addr = bank->base + bank->sectors[sector].offset;
LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector); LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector);
@ -1147,28 +1054,27 @@ static int tms470_erase_check(struct flash_bank *bank)
target_read_buffer(target, addr, bank->sectors[sector].size, buffer); target_read_buffer(target, addr, bank->sectors[sector].size, buffer);
bank->sectors[sector].is_erased = 1; bank->sectors[sector].is_erased = 1;
for (i = 0; i < bank->sectors[sector].size; i++) for (i = 0; i < bank->sectors[sector].size; i++) {
{ if (buffer[i] != 0xff) {
if (buffer[i] != 0xff) LOG_WARNING("tms470 bank %d, sector %d, not erased.",
{ tms470_info->ordinal,
LOG_WARNING("tms470 bank %d, sector %d, not erased.", tms470_info->ordinal, sector); sector);
LOG_WARNING("at location 0x%08" PRIx32 ": flash data is 0x%02x.", addr + i, buffer[i]); LOG_WARNING(
"at location 0x%08" PRIx32 ": flash data is 0x%02x.",
addr + i,
buffer[i]);
bank->sectors[sector].is_erased = 0; bank->sectors[sector].is_erased = 0;
break; break;
} }
} }
} }
if (bank->sectors[sector].is_erased != 1) if (bank->sectors[sector].is_erased != 1) {
{
result = ERROR_FLASH_SECTOR_NOT_ERASED; result = ERROR_FLASH_SECTOR_NOT_ERASED;
break; break;
} } else
else
{
LOG_INFO("sector erased"); LOG_INFO("sector erased");
} }
}
/* reset TEZ, wait states, read mode, GLBCTRL.4 */ /* reset TEZ, wait states, read mode, GLBCTRL.4 */
target_write_u32(target, 0xFFE88010, 0x0f); target_write_u32(target, 0xFFE88010, 0x0f);
@ -1188,16 +1094,13 @@ static int tms470_protect_check(struct flash_bank *bank)
int sector, result = ERROR_OK; int sector, result = ERROR_OK;
uint32_t fmmac2, fmbsea, fmbseb; uint32_t fmmac2, fmbsea, fmbseb;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{
LOG_ERROR("Target not halted"); LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (!tms470_info->device_ident_reg) if (!tms470_info->device_ident_reg)
{
tms470_read_part_info(bank); tms470_read_part_info(bank);
}
/* enable the appropriate bank */ /* enable the appropriate bank */
target_read_u32(target, 0xFFE8BC04, &fmmac2); 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, 0xFFE88008, &fmbsea);
target_read_u32(target, 0xFFE8800C, &fmbseb); target_read_u32(target, 0xFFE8800C, &fmbseb);
for (sector = 0; sector < bank->num_sectors; sector++) for (sector = 0; sector < bank->num_sectors; sector++) {
{
int protected; int protected;
if (sector < 16) if (sector < 16) {
{
protected = fmbsea & (1 << sector) ? 0 : 1; protected = fmbsea & (1 << sector) ? 0 : 1;
bank->sectors[sector].is_protected = protected; bank->sectors[sector].is_protected = protected;
} } else {
else
{
protected = fmbseb & (1 << (sector - 16)) ? 0 : 1; protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
bank->sectors[sector].is_protected = protected; 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; 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; struct tms470_flash_bank *tms470_info = bank->driver_priv;
if (!tms470_info->device_ident_reg) if (!tms470_info->device_ident_reg)
{
tms470_read_part_info(bank); 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"); (void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
return ERROR_FLASH_OPERATION_FAILED; 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 += used;
buf_size -= 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; return ERROR_OK;
} }
@ -1266,9 +1168,7 @@ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
bank->driver_priv = malloc(sizeof(struct tms470_flash_bank)); bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
if (!bank->driver_priv) if (!bank->driver_priv)
{
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
(void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank)); (void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));

View File

@ -17,6 +17,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -28,9 +29,8 @@ 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); master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv);
if (master_bank == NULL) { if (master_bank == NULL)
LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv); LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv);
}
return master_bank; 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
if (master_bank == NULL) { if (master_bank == NULL)
return; return;
}
/* update the info we do not have */ /* update the info we do not have */
bank->size = master_bank->size; 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) FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
{ {
if (CMD_ARGC < 7) if (CMD_ARGC < 7)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
/* get the master flash bank */ /* get the master flash bank */
const char *bank_name = CMD_ARGV[6]; const char *bank_name = CMD_ARGV[6];
struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name); 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); LOG_ERROR("master flash bank '%s' does not exist", bank_name);
return ERROR_FLASH_OPERATION_FAILED; 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* call master handler */
if ((retval = master_bank->driver->protect(master_bank, set, retval = master_bank->driver->protect(master_bank, set, first, last);
first, last)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
return ERROR_OK; 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* 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 retval;
return ERROR_OK; 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* call master handler */
if ((retval = master_bank->driver->erase(master_bank, retval = master_bank->driver->erase(master_bank, first, last);
first, last)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
return ERROR_OK; 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* call master handler */
if ((retval = master_bank->driver->write(master_bank, buffer, retval = master_bank->driver->write(master_bank, buffer, offset, count);
offset, count)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
return ERROR_OK; 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* 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; return retval;
/* update the info we do not have */ /* 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* 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; return retval;
/* update the info we do not have */ /* 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "", snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
bank->driver->name, master_bank->name, master_bank->base); 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* 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 retval;
return ERROR_OK; 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); struct flash_bank *master_bank = virtual_get_master_bank(bank);
int retval; int retval;
if (master_bank == NULL) { if (master_bank == NULL)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
}
/* call master handler */ /* call master handler */
if ((retval = master_bank->driver->read(master_bank, buffer, retval = master_bank->driver->read(master_bank, buffer, offset, count);
offset, count)) != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
return ERROR_OK; return ERROR_OK;