Change-Id: Ic299de969ce566282c055ba4dd8b94892c4c4311 Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/420 Tested-by: jenkinstags/v0.6.0-rc1
@@ -29,20 +29,19 @@ | |||
#include <target/algorithm.h> | |||
#include <target/arm.h> | |||
static int aduc702x_build_sector_list(struct flash_bank *bank); | |||
static int aduc702x_check_flash_completion(struct target* target, unsigned int timeout_ms); | |||
static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms); | |||
static int aduc702x_set_write_enable(struct target *target, int enable); | |||
#define ADUC702x_FLASH 0xfffff800 | |||
#define ADUC702x_FLASH_FEESTA (0*4) | |||
#define ADUC702x_FLASH_FEEMOD (1*4) | |||
#define ADUC702x_FLASH_FEECON (2*4) | |||
#define ADUC702x_FLASH_FEEDAT (3*4) | |||
#define ADUC702x_FLASH_FEEADR (4*4) | |||
#define ADUC702x_FLASH_FEESIGN (5*4) | |||
#define ADUC702x_FLASH_FEEPRO (6*4) | |||
#define ADUC702x_FLASH_FEEHIDE (7*4) | |||
#define ADUC702x_FLASH 0xfffff800 | |||
#define ADUC702x_FLASH_FEESTA (0*4) | |||
#define ADUC702x_FLASH_FEEMOD (1*4) | |||
#define ADUC702x_FLASH_FEECON (2*4) | |||
#define ADUC702x_FLASH_FEEDAT (3*4) | |||
#define ADUC702x_FLASH_FEEADR (4*4) | |||
#define ADUC702x_FLASH_FEESIGN (5*4) | |||
#define ADUC702x_FLASH_FEEPRO (6*4) | |||
#define ADUC702x_FLASH_FEEHIDE (7*4) | |||
struct aduc702x_flash_bank { | |||
struct working_area *write_algorithm; | |||
@@ -56,33 +55,32 @@ FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command) | |||
nbank = malloc(sizeof(struct aduc702x_flash_bank)); | |||
bank->base = 0x80000; | |||
bank->size = 0xF800; // top 4k not accessible | |||
bank->base = 0x80000; | |||
bank->size = 0xF800; /* top 4k not accessible */ | |||
bank->driver_priv = nbank; | |||
aduc702x_build_sector_list(bank); | |||
aduc702x_build_sector_list(bank); | |||
return ERROR_OK; | |||
return ERROR_OK; | |||
} | |||
static int aduc702x_build_sector_list(struct flash_bank *bank) | |||
{ | |||
//aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; | |||
int i = 0; | |||
uint32_t offset = 0; | |||
// sector size is 512 | |||
bank->num_sectors = bank->size / 512; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); | |||
for (i = 0; i < bank->num_sectors; ++i) | |||
{ | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 512; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 0; | |||
} | |||
/* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */ | |||
int i = 0; | |||
uint32_t offset = 0; | |||
/* sector size is 512 */ | |||
bank->num_sectors = bank->size / 512; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); | |||
for (i = 0; i < bank->num_sectors; ++i) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 512; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 0; | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -95,13 +93,13 @@ static int aduc702x_protect_check(struct flash_bank *bank) | |||
static int aduc702x_erase(struct flash_bank *bank, int first, int last) | |||
{ | |||
//int res; | |||
/* int res; */ | |||
int x; | |||
int count; | |||
//uint32_t v; | |||
/* uint32_t v; */ | |||
struct target *target = bank->target; | |||
aduc702x_set_write_enable(target, 1); | |||
aduc702x_set_write_enable(target, 1); | |||
/* mass erase */ | |||
if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) { | |||
@@ -110,38 +108,35 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last) | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3); | |||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06); | |||
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) | |||
{ | |||
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) { | |||
LOG_ERROR("mass erase failed"); | |||
aduc702x_set_write_enable(target, 0); | |||
aduc702x_set_write_enable(target, 0); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
LOG_DEBUG("mass erase successful."); | |||
return ERROR_OK; | |||
} else { | |||
unsigned long adr; | |||
unsigned long adr; | |||
count = last - first + 1; | |||
for (x = 0; x < count; ++x) | |||
{ | |||
adr = bank->base + ((first + x) * 512); | |||
count = last - first + 1; | |||
for (x = 0; x < count; ++x) { | |||
adr = bank->base + ((first + x) * 512); | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr); | |||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05); | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr); | |||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05); | |||
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) | |||
{ | |||
LOG_ERROR("failed to erase sector at address 0x%08lX", adr); | |||
aduc702x_set_write_enable(target, 0); | |||
return ERROR_FLASH_SECTOR_NOT_ERASED; | |||
} | |||
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) { | |||
LOG_ERROR("failed to erase sector at address 0x%08lX", adr); | |||
aduc702x_set_write_enable(target, 0); | |||
return ERROR_FLASH_SECTOR_NOT_ERASED; | |||
} | |||
LOG_DEBUG("erased sector at address 0x%08lX", adr); | |||
} | |||
} | |||
LOG_DEBUG("erased sector at address 0x%08lX", adr); | |||
} | |||
} | |||
aduc702x_set_write_enable(target, 0); | |||
aduc702x_set_write_enable(target, 0); | |||
return ERROR_OK; | |||
} | |||
@@ -157,7 +152,10 @@ static int aduc702x_protect(struct flash_bank *bank, int set, int first, int las | |||
* | |||
* Caller should not check for other return values specifically | |||
*/ | |||
static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) | |||
static int aduc702x_write_block(struct flash_bank *bank, | |||
uint8_t *buffer, | |||
uint32_t offset, | |||
uint32_t count) | |||
{ | |||
struct aduc702x_flash_bank *aduc702x_info = bank->driver_priv; | |||
struct target *target = bank->target; | |||
@@ -168,71 +166,66 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32 | |||
struct arm_algorithm armv4_5_info; | |||
int retval = ERROR_OK; | |||
if (((count%2)!=0)||((offset%2)!=0)) | |||
{ | |||
if (((count%2) != 0) || ((offset%2) != 0)) { | |||
LOG_ERROR("write block must be multiple of two bytes in offset & length"); | |||
return ERROR_FAIL; | |||
} | |||
/* parameters: | |||
r0 - address of source data (absolute) | |||
r1 - number of halfwords to be copied | |||
r2 - start address in flash (offset from beginning of flash memory) | |||
r3 - exit code | |||
r4 - base address of flash controller (0xFFFFF800) | |||
registers: | |||
r5 - scratch | |||
r6 - set to 2, used to write flash command | |||
*/ | |||
static const uint32_t aduc702x_flash_write_code[] = { | |||
//<_start>: | |||
0xe3a05008, // mov r5, #8 ; 0x8 | |||
0xe5845004, // str r5, [r4, #4] | |||
0xe3a06002, // mov r6, #2 ; 0x2 | |||
//<next>: | |||
0xe1c421b0, // strh r2, [r4, #16] | |||
0xe0d050b2, // ldrh r5, [r0], #2 | |||
0xe1c450bc, // strh r5, [r4, #12] | |||
0xe5c46008, // strb r6, [r4, #8] | |||
//<wait_complete>: | |||
0xe1d430b0, // ldrh r3, [r4] | |||
0xe3130004, // tst r3, #4 ; 0x4 | |||
0x1afffffc, // bne 1001c <wait_complete> | |||
0xe2822002, // add r2, r2, #2 ; 0x2 | |||
0xe2511001, // subs r1, r1, #1 ; 0x1 | |||
0x0a000001, // beq 1003c <done> | |||
0xe3130001, // tst r3, #1 ; 0x1 | |||
0x1afffff3, // bne 1000c <next> | |||
//<done>: | |||
0xeafffffe // b 1003c <done> | |||
/* parameters: | |||
r0 - address of source data (absolute) | |||
r1 - number of halfwords to be copied | |||
r2 - start address in flash (offset from beginning of flash memory) | |||
r3 - exit code | |||
r4 - base address of flash controller (0xFFFFF800) | |||
registers: | |||
r5 - scratch | |||
r6 - set to 2, used to write flash command | |||
*/ | |||
static const uint32_t aduc702x_flash_write_code[] = { | |||
/* <_start>: */ | |||
0xe3a05008, /* mov r5, #8 ; 0x8 */ | |||
0xe5845004, /* str r5, [r4, #4] */ | |||
0xe3a06002, /* mov r6, #2 ; 0x2 */ | |||
/* <next>: */ | |||
0xe1c421b0, /* strh r2, [r4, #16] */ | |||
0xe0d050b2, /* ldrh r5, [r0], #2 */ | |||
0xe1c450bc, /* strh r5, [r4, #12] */ | |||
0xe5c46008, /* strb r6, [r4, #8] */ | |||
/* <wait_complete>: */ | |||
0xe1d430b0, /* ldrh r3, [r4] */ | |||
0xe3130004, /* tst r3, #4 ; 0x4 */ | |||
0x1afffffc, /* bne 1001c <wait_complete> */ | |||
0xe2822002, /* add r2, r2, #2 ; 0x2 */ | |||
0xe2511001, /* subs r1, r1, #1 ; 0x1 */ | |||
0x0a000001, /* beq 1003c <done> */ | |||
0xe3130001, /* tst r3, #1 ; 0x1 */ | |||
0x1afffff3, /* bne 1000c <next> */ | |||
/* <done>: */ | |||
0xeafffffe /* b 1003c <done> */ | |||
}; | |||
/* flash write code */ | |||
if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code), | |||
&aduc702x_info->write_algorithm) != ERROR_OK) | |||
{ | |||
&aduc702x_info->write_algorithm) != ERROR_OK) { | |||
LOG_WARNING("no working area available, can't do block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
} | |||
retval=target_write_buffer(target, aduc702x_info->write_algorithm->address, | |||
sizeof(aduc702x_flash_write_code), (uint8_t*)aduc702x_flash_write_code); | |||
if (retval!=ERROR_OK) | |||
{ | |||
retval = target_write_buffer(target, aduc702x_info->write_algorithm->address, | |||
sizeof(aduc702x_flash_write_code), (uint8_t *)aduc702x_flash_write_code); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
if (buffer_size <= 256) | |||
{ | |||
/* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a buffer, | |||
*free the algorithm */ | |||
if (aduc702x_info->write_algorithm) | |||
target_free_working_area(target, aduc702x_info->write_algorithm); | |||
@@ -251,32 +244,29 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32 | |||
init_reg_param(®_params[3], "r3", 32, PARAM_IN); | |||
init_reg_param(®_params[4], "r4", 32, PARAM_OUT); | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count; | |||
retval=target_write_buffer(target, source->address, thisrun_count, buffer); | |||
if (retval!=ERROR_OK) | |||
{ | |||
retval = target_write_buffer(target, source->address, thisrun_count, buffer); | |||
if (retval != ERROR_OK) | |||
break; | |||
} | |||
buf_set_u32(reg_params[0].value, 0, 32, source->address); | |||
buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2); | |||
buf_set_u32(reg_params[2].value, 0, 32, address); | |||
buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800); | |||
if ((retval = target_run_algorithm(target, 0, NULL, 5, | |||
reg_params, aduc702x_info->write_algorithm->address, | |||
aduc702x_info->write_algorithm->address + sizeof(aduc702x_flash_write_code) - 4, | |||
10000, &armv4_5_info)) != ERROR_OK) | |||
{ | |||
retval = target_run_algorithm(target, 0, NULL, 5, | |||
reg_params, aduc702x_info->write_algorithm->address, | |||
aduc702x_info->write_algorithm->address + | |||
sizeof(aduc702x_flash_write_code) - 4, | |||
10000, &armv4_5_info); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error executing aduc702x flash write algorithm"); | |||
break; | |||
} | |||
if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) | |||
{ | |||
if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) { | |||
/* FIX!!!! what does this mean??? replace w/sensible error message */ | |||
LOG_ERROR("aduc702x detected error writing flash"); | |||
retval = ERROR_FAIL; | |||
@@ -302,43 +292,44 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32 | |||
/* All-JTAG, single-access method. Very slow. Used only if there is no | |||
* working area available. */ | |||
static int aduc702x_write_single(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) | |||
static int aduc702x_write_single(struct flash_bank *bank, | |||
uint8_t *buffer, | |||
uint32_t offset, | |||
uint32_t count) | |||
{ | |||
uint32_t x; | |||
uint8_t b; | |||
uint8_t b; | |||
struct target *target = bank->target; | |||
aduc702x_set_write_enable(target, 1); | |||
aduc702x_set_write_enable(target, 1); | |||
for (x = 0; x < count; x += 2) { | |||
// FEEADR = address | |||
/* FEEADR = address */ | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x); | |||
// set up data | |||
if ((x + 1) == count) | |||
{ | |||
// last byte | |||
target_read_u8(target, offset + x + 1, &b); | |||
} | |||
else | |||
b = buffer[x + 1]; | |||
/* set up data */ | |||
if ((x + 1) == count) { | |||
/* last byte */ | |||
target_read_u8(target, offset + x + 1, &b); | |||
} else | |||
b = buffer[x + 1]; | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8)); | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8)); | |||
// do single-write command | |||
/* do single-write command */ | |||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02); | |||
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) | |||
{ | |||
LOG_ERROR("single write failed for address 0x%08lX", (unsigned long)(offset + x)); | |||
aduc702x_set_write_enable(target, 0); | |||
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) { | |||
LOG_ERROR("single write failed for address 0x%08lX", | |||
(unsigned long)(offset + x)); | |||
aduc702x_set_write_enable(target, 0); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x)); | |||
LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x)); | |||
aduc702x_set_write_enable(target, 0); | |||
aduc702x_set_write_enable(target, 0); | |||
return ERROR_OK; | |||
} | |||
@@ -347,24 +338,23 @@ static int aduc702x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off | |||
{ | |||
int retval; | |||
/* try using a block write */ | |||
if ((retval = aduc702x_write_block(bank, buffer, offset, count)) != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
/* if block write failed (no sufficient working area), | |||
* use normal (slow) JTAG method */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
if ((retval = aduc702x_write_single(bank, buffer, offset, count)) != ERROR_OK) | |||
{ | |||
LOG_ERROR("slow write failed"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
} | |||
return retval; | |||
/* try using a block write */ | |||
retval = aduc702x_write_block(bank, buffer, offset, count); | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
/* if block write failed (no sufficient working area), | |||
* use normal (slow) JTAG method */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
retval = aduc702x_write_single(bank, buffer, offset, count); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("slow write failed"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
} | |||
return retval; | |||
} | |||
static int aduc702x_probe(struct flash_bank *bank) | |||
@@ -382,10 +372,10 @@ static int aduc702x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
* enable = 1 enables writes & erases, 0 disables them */ | |||
static int aduc702x_set_write_enable(struct target *target, int enable) | |||
{ | |||
// don't bother to preserve int enable bit here | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0); | |||
/* don't bother to preserve int enable bit here */ | |||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0); | |||
return ERROR_OK; | |||
return ERROR_OK; | |||
} | |||
/* wait up to timeout_ms for controller to not be busy, | |||
@@ -393,22 +383,27 @@ static int aduc702x_set_write_enable(struct target *target, int enable) | |||
* | |||
* this function sleeps 1ms between checks (after the first one), | |||
* so in some cases may slow things down without a usleep after the first read */ | |||
static int aduc702x_check_flash_completion(struct target* target, unsigned int timeout_ms) | |||
static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms) | |||
{ | |||
uint8_t v = 4; | |||
long long endtime = timeval_ms() + timeout_ms; | |||
while (1) { | |||
target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v); | |||
if ((v & 4) == 0) break; | |||
alive_sleep(1); | |||
if (timeval_ms() >= endtime) break; | |||
} | |||
if (v & 2) return ERROR_FAIL; | |||
// if a command is ignored, both the success and fail bits may be 0 | |||
else if ((v & 3) == 0) return ERROR_FAIL; | |||
else return ERROR_OK; | |||
uint8_t v = 4; | |||
long long endtime = timeval_ms() + timeout_ms; | |||
while (1) { | |||
target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v); | |||
if ((v & 4) == 0) | |||
break; | |||
alive_sleep(1); | |||
if (timeval_ms() >= endtime) | |||
break; | |||
} | |||
if (v & 2) | |||
return ERROR_FAIL; | |||
/* if a command is ignored, both the success and fail bits may be 0 */ | |||
else if ((v & 3) == 0) | |||
return ERROR_FAIL; | |||
else | |||
return ERROR_OK; | |||
} | |||
struct flash_driver aduc702x_flash = { | |||
@@ -52,55 +52,54 @@ | |||
#include "imp.h" | |||
#include <helper/binarybuffer.h> | |||
/* AT91SAM7 control registers */ | |||
#define DBGU_CIDR 0xFFFFF240 | |||
#define CKGR_MCFR 0xFFFFFC24 | |||
#define CKGR_MOR 0xFFFFFC20 | |||
#define CKGR_MCFR_MAINRDY 0x10000 | |||
#define CKGR_PLLR 0xFFFFFC2c | |||
#define CKGR_PLLR_DIV 0xff | |||
#define CKGR_PLLR_MUL 0x07ff0000 | |||
#define PMC_MCKR 0xFFFFFC30 | |||
#define PMC_MCKR_CSS 0x03 | |||
#define PMC_MCKR_PRES 0x1c | |||
#define DBGU_CIDR 0xFFFFF240 | |||
#define CKGR_MCFR 0xFFFFFC24 | |||
#define CKGR_MOR 0xFFFFFC20 | |||
#define CKGR_MCFR_MAINRDY 0x10000 | |||
#define CKGR_PLLR 0xFFFFFC2c | |||
#define CKGR_PLLR_DIV 0xff | |||
#define CKGR_PLLR_MUL 0x07ff0000 | |||
#define PMC_MCKR 0xFFFFFC30 | |||
#define PMC_MCKR_CSS 0x03 | |||
#define PMC_MCKR_PRES 0x1c | |||
/* Flash Controller Commands */ | |||
#define WP 0x01 | |||
#define SLB 0x02 | |||
#define WPL 0x03 | |||
#define CLB 0x04 | |||
#define EA 0x08 | |||
#define SGPB 0x0B | |||
#define CGPB 0x0D | |||
#define SSB 0x0F | |||
#define WP 0x01 | |||
#define SLB 0x02 | |||
#define WPL 0x03 | |||
#define CLB 0x04 | |||
#define EA 0x08 | |||
#define SGPB 0x0B | |||
#define CGPB 0x0D | |||
#define SSB 0x0F | |||
/* MC_FSR bit definitions */ | |||
#define MC_FSR_FRDY 1 | |||
#define MC_FSR_EOL 2 | |||
#define MC_FSR_FRDY 1 | |||
#define MC_FSR_EOL 2 | |||
/* AT91SAM7 constants */ | |||
#define RC_FREQ 32000 | |||
#define RC_FREQ 32000 | |||
/* Flash timing modes */ | |||
#define FMR_TIMING_NONE 0 | |||
#define FMR_TIMING_NVBITS 1 | |||
#define FMR_TIMING_FLASH 2 | |||
#define FMR_TIMING_NONE 0 | |||
#define FMR_TIMING_NVBITS 1 | |||
#define FMR_TIMING_FLASH 2 | |||
/* Flash size constants */ | |||
#define FLASH_SIZE_8KB 1 | |||
#define FLASH_SIZE_16KB 2 | |||
#define FLASH_SIZE_32KB 3 | |||
#define FLASH_SIZE_64KB 5 | |||
#define FLASH_SIZE_128KB 7 | |||
#define FLASH_SIZE_256KB 9 | |||
#define FLASH_SIZE_512KB 10 | |||
#define FLASH_SIZE_1024KB 12 | |||
#define FLASH_SIZE_2048KB 14 | |||
#define FLASH_SIZE_8KB 1 | |||
#define FLASH_SIZE_16KB 2 | |||
#define FLASH_SIZE_32KB 3 | |||
#define FLASH_SIZE_64KB 5 | |||
#define FLASH_SIZE_128KB 7 | |||
#define FLASH_SIZE_256KB 9 | |||
#define FLASH_SIZE_512KB 10 | |||
#define FLASH_SIZE_1024KB 12 | |||
#define FLASH_SIZE_2048KB 14 | |||
static int at91sam7_protect_check(struct flash_bank *bank); | |||
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count); | |||
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
uint32_t count); | |||
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number); | |||
static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode); | |||
@@ -111,10 +110,11 @@ static uint32_t MC_FMR[4] = { 0xFFFFFF60, 0xFFFFFF70, 0xFFFFFF80, 0xFFFFFF90 }; | |||
static uint32_t MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 }; | |||
static uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 }; | |||
static char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"}; | |||
static char *EPROC[8] = { | |||
"Unknown", "ARM946-E", "ARM7TDMI", "Unknown", "ARM920T", "ARM926EJ-S", "Unknown", "Unknown" | |||
}; | |||
struct at91sam7_flash_bank | |||
{ | |||
struct at91sam7_flash_bank { | |||
/* chip id register */ | |||
uint32_t cidr; | |||
uint16_t cidr_ext; | |||
@@ -128,7 +128,7 @@ struct at91sam7_flash_bank | |||
const char *target_name; | |||
/* flash auto-detection */ | |||
uint8_t flash_autodetection; | |||
uint8_t flash_autodetection; | |||
/* flash geometry */ | |||
uint16_t pages_per_sector; | |||
@@ -141,15 +141,15 @@ struct at91sam7_flash_bank | |||
uint16_t num_nvmbits; | |||
uint16_t num_nvmbits_on; | |||
uint16_t nvmbits; | |||
uint8_t securitybit; | |||
uint8_t securitybit; | |||
/* 0: not init | |||
* 1: fmcn for nvbits (1uS) | |||
* 2: fmcn for flash (1.5uS) */ | |||
uint8_t flashmode; | |||
uint8_t flashmode; | |||
/* main clock status */ | |||
uint8_t mck_valid; | |||
uint8_t mck_valid; | |||
uint32_t mck_freq; | |||
/* external clock frequency */ | |||
@@ -178,7 +178,6 @@ static long SRAMSIZ[16] = { | |||
}; | |||
#endif | |||
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number) | |||
{ | |||
uint32_t fsr; | |||
@@ -206,8 +205,7 @@ static void at91sam7_read_clock_info(struct flash_bank *bank) | |||
at91sam7_info->mck_valid = 0; | |||
at91sam7_info->mck_freq = 0; | |||
switch (mckr & PMC_MCKR_CSS) | |||
{ | |||
switch (mckr & PMC_MCKR_CSS) { | |||
case 0: /* Slow Clock */ | |||
at91sam7_info->mck_valid = 1; | |||
tmp = RC_FREQ; | |||
@@ -215,13 +213,10 @@ static void at91sam7_read_clock_info(struct flash_bank *bank) | |||
case 1: /* Main Clock */ | |||
if ((mcfr & CKGR_MCFR_MAINRDY) && | |||
(at91sam7_info->ext_freq == 0)) | |||
{ | |||
(at91sam7_info->ext_freq == 0)) { | |||
at91sam7_info->mck_valid = 1; | |||
tmp = RC_FREQ / 16ul * (mcfr & 0xffff); | |||
} | |||
else if (at91sam7_info->ext_freq != 0) | |||
{ | |||
} else if (at91sam7_info->ext_freq != 0) { | |||
at91sam7_info->mck_valid = 1; | |||
tmp = at91sam7_info->ext_freq; | |||
} | |||
@@ -232,35 +227,30 @@ static void at91sam7_read_clock_info(struct flash_bank *bank) | |||
case 3: /* PLL Clock */ | |||
if ((mcfr & CKGR_MCFR_MAINRDY) && | |||
(at91sam7_info->ext_freq == 0)) | |||
{ | |||
(at91sam7_info->ext_freq == 0)) { | |||
target_read_u32(target, CKGR_PLLR, &pllr); | |||
if (!(pllr & CKGR_PLLR_DIV)) | |||
break; /* 0 Hz */ | |||
break; /* 0 Hz */ | |||
at91sam7_info->mck_valid = 1; | |||
mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff); | |||
/* Integer arithmetic should have sufficient precision | |||
* as long as PLL is properly configured. */ | |||
tmp = mainfreq / (pllr & CKGR_PLLR_DIV)* | |||
(((pllr & CKGR_PLLR_MUL) >> 16) + 1); | |||
} | |||
else if ((at91sam7_info->ext_freq != 0) && | |||
((pllr&CKGR_PLLR_DIV) != 0)) | |||
{ | |||
(((pllr & CKGR_PLLR_MUL) >> 16) + 1); | |||
} else if ((at91sam7_info->ext_freq != 0) && | |||
((pllr&CKGR_PLLR_DIV) != 0)) { | |||
at91sam7_info->mck_valid = 1; | |||
tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)* | |||
(((pllr & CKGR_PLLR_MUL) >> 16) + 1); | |||
(((pllr & CKGR_PLLR_MUL) >> 16) + 1); | |||
} | |||
break; | |||
} | |||
/* Prescaler adjust */ | |||
if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0)) | |||
{ | |||
if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0)) { | |||
at91sam7_info->mck_valid = 0; | |||
at91sam7_info->mck_freq = 0; | |||
} | |||
else if (((mckr & PMC_MCKR_PRES) >> 2) != 0) | |||
} else if (((mckr & PMC_MCKR_PRES) >> 2) != 0) | |||
at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2); | |||
else | |||
at91sam7_info->mck_freq = tmp; | |||
@@ -273,24 +263,17 @@ static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode) | |||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; | |||
struct target *target = bank->target; | |||
if (mode && (mode != at91sam7_info->flashmode)) | |||
{ | |||
if (mode && (mode != at91sam7_info->flashmode)) { | |||
/* Always round up (ceil) */ | |||
if (mode == FMR_TIMING_NVBITS) | |||
{ | |||
if (at91sam7_info->cidr_arch == 0x60) | |||
{ | |||
if (mode == FMR_TIMING_NVBITS) { | |||
if (at91sam7_info->cidr_arch == 0x60) { | |||
/* AT91SAM7A3 uses master clocks in 100 ns */ | |||
fmcn = (at91sam7_info->mck_freq/10000000ul) + 1; | |||
} | |||
else | |||
{ | |||
} else { | |||
/* master clocks in 1uS for ARCH 0x7 types */ | |||
fmcn = (at91sam7_info->mck_freq/1000000ul) + 1; | |||
} | |||
} | |||
else if (mode == FMR_TIMING_FLASH) | |||
{ | |||
} else if (mode == FMR_TIMING_FLASH) { | |||
/* main clocks in 1.5uS */ | |||
fmcn = (at91sam7_info->mck_freq/1000000ul)+ | |||
(at91sam7_info->mck_freq/2000000ul) + 1; | |||
@@ -319,16 +302,15 @@ static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t wait | |||
{ | |||
uint32_t status; | |||
while ((!((status = at91sam7_get_flash_status(bank->target, bank->bank_number)) & waitbits)) && (timeout-- > 0)) | |||
{ | |||
while ((!((status = at91sam7_get_flash_status(bank->target, | |||
bank->bank_number)) & waitbits)) && (timeout-- > 0)) { | |||
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status); | |||
alive_sleep(1); | |||
} | |||
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status); | |||
if (status & 0x0C) | |||
{ | |||
if (status & 0x0C) { | |||
LOG_ERROR("status register: 0x%" PRIx32 "", status); | |||
if (status & 0x4) | |||
LOG_ERROR("Lock Error Bit Detected, Operation Abort"); | |||
@@ -350,22 +332,20 @@ static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t | |||
fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd; | |||
target_write_u32(target, MC_FCR[bank->bank_number], fcr); | |||
LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u", fcr, bank->bank_number + 1, pagen); | |||
LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u", | |||
fcr, | |||
bank->bank_number + 1, | |||
pagen); | |||
if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB))) | |||
{ | |||
if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB))) { | |||
/* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */ | |||
if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
return ERROR_OK; | |||
} | |||
if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -392,14 +372,12 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
at91sam7_info = t_bank->driver_priv; | |||
if (at91sam7_info->cidr != 0) | |||
{ | |||
if (at91sam7_info->cidr != 0) { | |||
/* flash already configured, update clock and check for protected sectors */ | |||
struct flash_bank *fb = bank; | |||
t_bank = fb; | |||
while (t_bank) | |||
{ | |||
while (t_bank) { | |||
/* re-calculate master clock frequency */ | |||
at91sam7_read_clock_info(t_bank); | |||
@@ -418,19 +396,16 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
/* Read and parse chip identification register */ | |||
target_read_u32(target, DBGU_CIDR, &cidr); | |||
if (cidr == 0) | |||
{ | |||
if (cidr == 0) { | |||
LOG_WARNING("Cannot identify target as an AT91SAM"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (at91sam7_info->flash_autodetection == 0) | |||
{ | |||
if (at91sam7_info->flash_autodetection == 0) { | |||
/* banks and sectors are already created, based on data from input file */ | |||
struct flash_bank *fb = bank; | |||
t_bank = fb; | |||
while (t_bank) | |||
{ | |||
while (t_bank) { | |||
at91sam7_info = t_bank->driver_priv; | |||
at91sam7_info->cidr = cidr; | |||
@@ -462,8 +437,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
arch = (cidr >> 20)&0x00FF; | |||
/* check flash size */ | |||
switch ((cidr >> 8)&0x000F) | |||
{ | |||
switch ((cidr >> 8)&0x000F) { | |||
case FLASH_SIZE_8KB: | |||
break; | |||
@@ -473,8 +447,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
pages_per_sector = 32; | |||
page_size = 64; | |||
base_address = 0x00100000; | |||
if (arch == 0x70) | |||
{ | |||
if (arch == 0x70) { | |||
num_nvmbits = 2; | |||
target_name_t = "AT91SAM7S161/16"; | |||
} | |||
@@ -486,13 +459,11 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
pages_per_sector = 32; | |||
page_size = 128; | |||
base_address = 0x00100000; | |||
if (arch == 0x70) | |||
{ | |||
if (arch == 0x70) { | |||
num_nvmbits = 2; | |||
target_name_t = "AT91SAM7S321/32"; | |||
} | |||
if (arch == 0x72) | |||
{ | |||
if (arch == 0x72) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7SE32"; | |||
} | |||
@@ -504,8 +475,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
pages_per_sector = 32; | |||
page_size = 128; | |||
base_address = 0x00100000; | |||
if (arch == 0x70) | |||
{ | |||
if (arch == 0x70) { | |||
num_nvmbits = 2; | |||
target_name_t = "AT91SAM7S64"; | |||
} | |||
@@ -517,23 +487,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
pages_per_sector = 64; | |||
page_size = 256; | |||
base_address = 0x00100000; | |||
if (arch == 0x70) | |||
{ | |||
if (arch == 0x70) { | |||
num_nvmbits = 2; | |||
target_name_t = "AT91SAM7S128"; | |||
} | |||
if (arch == 0x71) | |||
{ | |||
if (arch == 0x71) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7XC128"; | |||
} | |||
if (arch == 0x72) | |||
{ | |||
if (arch == 0x72) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7SE128"; | |||
} | |||
if (arch == 0x75) | |||
{ | |||
if (arch == 0x75) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7X128"; | |||
} | |||
@@ -545,28 +511,23 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
pages_per_sector = 64; | |||
page_size = 256; | |||
base_address = 0x00100000; | |||
if (arch == 0x60) | |||
{ | |||
if (arch == 0x60) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7A3"; | |||
} | |||
if (arch == 0x70) | |||
{ | |||
if (arch == 0x70) { | |||
num_nvmbits = 2; | |||
target_name_t = "AT91SAM7S256"; | |||
} | |||
if (arch == 0x71) | |||
{ | |||
if (arch == 0x71) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7XC256"; | |||
} | |||
if (arch == 0x72) | |||
{ | |||
if (arch == 0x72) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7SE256"; | |||
} | |||
if (arch == 0x75) | |||
{ | |||
if (arch == 0x75) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7X256"; | |||
} | |||
@@ -578,23 +539,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
pages_per_sector = 64; | |||
page_size = 256; | |||
base_address = 0x00100000; | |||
if (arch == 0x70) | |||
{ | |||
if (arch == 0x70) { | |||
num_nvmbits = 2; | |||
target_name_t = "AT91SAM7S512"; | |||
} | |||
if (arch == 0x71) | |||
{ | |||
if (arch == 0x71) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7XC512"; | |||
} | |||
if (arch == 0x72) | |||
{ | |||
if (arch == 0x72) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7SE512"; | |||
} | |||
if (arch == 0x75) | |||
{ | |||
if (arch == 0x75) { | |||
num_nvmbits = 3; | |||
target_name_t = "AT91SAM7X512"; | |||
} | |||
@@ -607,9 +564,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
break; | |||
} | |||
if (strcmp(target_name_t, "Unknown") == 0) | |||
{ | |||
LOG_ERROR("Target autodetection failed! Please specify target parameters in configuration file"); | |||
if (strcmp(target_name_t, "Unknown") == 0) { | |||
LOG_ERROR( | |||
"Target autodetection failed! Please specify target parameters in configuration file"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -618,10 +575,8 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
/* calculate bank size */ | |||
bank_size = sectors_num * pages_per_sector * page_size; | |||
for (bnk = 0; bnk < banks_num; bnk++) | |||
{ | |||
if (bnk > 0) | |||
{ | |||
for (bnk = 0; bnk < banks_num; bnk++) { | |||
if (bnk > 0) { | |||
if (!t_bank->next) { | |||
/* create a new flash bank element */ | |||
struct flash_bank *fb = malloc(sizeof(struct flash_bank)); | |||
@@ -646,8 +601,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
/* allocate sectors */ | |||
t_bank->sectors = malloc(sectors_num * sizeof(struct flash_sector)); | |||
for (sec = 0; sec < sectors_num; sec++) | |||
{ | |||
for (sec = 0; sec < sectors_num; sec++) { | |||
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size; | |||
t_bank->sectors[sec].size = pages_per_sector * page_size; | |||
t_bank->sectors[sec].is_erased = -1; | |||
@@ -684,7 +638,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank) | |||
at91sam7_protect_check(t_bank); | |||
} | |||
LOG_DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch); | |||
LOG_DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", | |||
at91sam7_info->cidr_nvptyp, | |||
at91sam7_info->cidr_arch); | |||
return ERROR_OK; | |||
} | |||
@@ -699,8 +655,7 @@ static int at91sam7_erase_check(struct flash_bank *bank) | |||
uint16_t nSector; | |||
uint16_t nByte; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -710,12 +665,12 @@ static int at91sam7_erase_check(struct flash_bank *bank) | |||
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); | |||
fast_check = 1; | |||
for (nSector = 0; nSector < bank->num_sectors; nSector++) | |||
{ | |||
retval = target_blank_check_memory(target, bank->base + bank->sectors[nSector].offset, | |||
bank->sectors[nSector].size, &blank); | |||
if (retval != ERROR_OK) | |||
{ | |||
for (nSector = 0; nSector < bank->num_sectors; nSector++) { | |||
retval = target_blank_check_memory(target, | |||
bank->base + bank->sectors[nSector].offset, | |||
bank->sectors[nSector].size, | |||
&blank); | |||
if (retval != ERROR_OK) { | |||
fast_check = 0; | |||
break; | |||
} | |||
@@ -726,25 +681,20 @@ static int at91sam7_erase_check(struct flash_bank *bank) | |||
} | |||
if (fast_check) | |||
{ | |||
return ERROR_OK; | |||
} | |||
LOG_USER("Running slow fallback erase check - add working memory"); | |||
buffer = malloc(bank->sectors[0].size); | |||
for (nSector = 0; nSector < bank->num_sectors; nSector++) | |||
{ | |||
for (nSector = 0; nSector < bank->num_sectors; nSector++) { | |||
bank->sectors[nSector].is_erased = 1; | |||
retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4, | |||
bank->sectors[nSector].size/4, buffer); | |||
bank->sectors[nSector].size/4, buffer); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) | |||
{ | |||
if (buffer[nByte] != 0xFF) | |||
{ | |||
for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) { | |||
if (buffer[nByte] != 0xFF) { | |||
bank->sectors[nSector].is_erased = 0; | |||
break; | |||
} | |||
@@ -763,11 +713,8 @@ static int at91sam7_protect_check(struct flash_bank *bank) | |||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; | |||
if (at91sam7_info->cidr == 0) | |||
{ | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
} | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -776,14 +723,11 @@ static int at91sam7_protect_check(struct flash_bank *bank) | |||
at91sam7_info->lockbits = (status >> 16); | |||
at91sam7_info->num_lockbits_on = 0; | |||
for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) | |||
{ | |||
if (((status >> (16 + lock_pos))&(0x0001)) == 1) | |||
{ | |||
for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) { | |||
if (((status >> (16 + lock_pos))&(0x0001)) == 1) { | |||
at91sam7_info->num_lockbits_on++; | |||
bank->sectors[lock_pos].is_protected = 1; | |||
} | |||
else | |||
} else | |||
bank->sectors[lock_pos].is_protected = 0; | |||
} | |||
@@ -794,12 +738,9 @@ static int at91sam7_protect_check(struct flash_bank *bank) | |||
at91sam7_info->nvmbits = (status >> 8)&0xFF; | |||
at91sam7_info->num_nvmbits_on = 0; | |||
for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++) | |||
{ | |||
for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++) { | |||
if (((status >> (8 + gpnvm_pos))&(0x01)) == 1) | |||
{ | |||
at91sam7_info->num_nvmbits_on++; | |||
} | |||
} | |||
return ERROR_OK; | |||
@@ -837,8 +778,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) | |||
at91sam7_info->ext_freq = 0; | |||
at91sam7_info->flash_autodetection = 0; | |||
if (CMD_ARGC < 13) | |||
{ | |||
if (CMD_ARGC < 13) { | |||
at91sam7_info->flash_autodetection = 1; | |||
return ERROR_OK; | |||
} | |||
@@ -862,8 +802,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) | |||
} | |||
if ((bus_width == 0) || (banks_num == 0) || (num_sectors == 0) || | |||
(pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0)) | |||
{ | |||
(pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0)) { | |||
at91sam7_info->flash_autodetection = 1; | |||
return ERROR_OK; | |||
} | |||
@@ -874,10 +813,8 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) | |||
/* calculate bank size */ | |||
bank_size = num_sectors * pages_per_sector * page_size; | |||
for (bnk = 0; bnk < banks_num; bnk++) | |||
{ | |||
if (bnk > 0) | |||
{ | |||
for (bnk = 0; bnk < banks_num; bnk++) { | |||
if (bnk > 0) { | |||
if (!t_bank->next) { | |||
/* create a new bank element */ | |||
struct flash_bank *fb = malloc(sizeof(struct flash_bank)); | |||
@@ -902,8 +839,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) | |||
/* allocate sectors */ | |||
t_bank->sectors = malloc(num_sectors * sizeof(struct flash_sector)); | |||
for (sec = 0; sec < num_sectors; sec++) | |||
{ | |||
for (sec = 0; sec < num_sectors; sec++) { | |||
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size; | |||
t_bank->sectors[sec].size = pages_per_sector * page_size; | |||
t_bank->sectors[sec].is_erased = -1; | |||
@@ -933,61 +869,43 @@ static int at91sam7_erase(struct flash_bank *bank, int first, int last) | |||
uint8_t erase_all; | |||
if (at91sam7_info->cidr == 0) | |||
{ | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
} | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) | |||
{ | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
erase_all = 0; | |||
if ((first == 0) && (last == (bank->num_sectors-1))) | |||
{ | |||
erase_all = 1; | |||
} | |||
/* Configure the flash controller timing */ | |||
at91sam7_read_clock_info(bank); | |||
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); | |||
if (erase_all) | |||
{ | |||
if (erase_all) { | |||
if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
/* allocate and clean buffer */ | |||
nbytes = (last - first + 1) * bank->sectors[first].size; | |||
buffer = malloc(nbytes * sizeof(uint8_t)); | |||
for (pos = 0; pos < nbytes; pos++) | |||
{ | |||
buffer[pos] = 0xFF; | |||
} | |||
if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
free(buffer); | |||
} | |||
/* mark erased sectors */ | |||
for (sec = first; sec <= last; sec++) | |||
{ | |||
bank->sectors[sec].is_erased = 1; | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -1001,27 +919,21 @@ static int at91sam7_protect(struct flash_bank *bank, int set, int first, int las | |||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; | |||
if (at91sam7_info->cidr == 0) | |||
{ | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
} | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) | |||
{ | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
/* Configure the flash controller timing */ | |||
at91sam7_read_clock_info(bank); | |||
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS); | |||
for (sector = first; sector <= last; sector++) | |||
{ | |||
for (sector = first; sector <= last; sector++) { | |||
if (set) | |||
cmd = SLB; | |||
else | |||
@@ -1032,9 +944,7 @@ static int at91sam7_protect(struct flash_bank *bank, int set, int first, int las | |||
pagen = sector * at91sam7_info->pages_per_sector; | |||
if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
at91sam7_protect_check(bank); | |||
@@ -1051,12 +961,9 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off | |||
uint32_t first_page, last_page, pagen, buffer_pos; | |||
if (at91sam7_info->cidr == 0) | |||
{ | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
} | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1066,9 +973,10 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off | |||
dst_min_alignment = at91sam7_info->pagesize; | |||
if (offset % dst_min_alignment) | |||
{ | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, dst_min_alignment); | |||
if (offset % dst_min_alignment) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", | |||
offset, | |||
dst_min_alignment); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -1078,14 +986,16 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off | |||
first_page = offset/dst_min_alignment; | |||
last_page = DIV_ROUND_UP(offset + count, dst_min_alignment); | |||
LOG_DEBUG("first_page: %i, last_page: %i, count %i", (int)first_page, (int)last_page, (int)count); | |||
LOG_DEBUG("first_page: %i, last_page: %i, count %i", | |||
(int)first_page, | |||
(int)last_page, | |||
(int)count); | |||
/* Configure the flash controller timing */ | |||
at91sam7_read_clock_info(bank); | |||
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH); | |||
for (pagen = first_page; pagen < last_page; pagen++) | |||
{ | |||
for (pagen = first_page; pagen < last_page; pagen++) { | |||
if (bytes_remaining < dst_min_alignment) | |||
count = bytes_remaining; | |||
else | |||
@@ -1094,17 +1004,15 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off | |||
/* Write one block to the PageWriteBuffer */ | |||
buffer_pos = (pagen-first_page)*dst_min_alignment; | |||
wcount = DIV_ROUND_UP(count,4); | |||
if ((retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4, wcount, buffer + buffer_pos)) != ERROR_OK) | |||
{ | |||
wcount = DIV_ROUND_UP(count, 4); | |||
retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4, | |||
wcount, buffer + buffer_pos); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
/* Send Write Page command to Flash Controller */ | |||
if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
LOG_DEBUG("Write flash bank:%i page number:%" PRIi32 "", bank->bank_number, pagen); | |||
} | |||
@@ -1117,8 +1025,7 @@ static int at91sam7_probe(struct flash_bank *bank) | |||
* if this is an at91sam7, it has the configured flash */ | |||
int retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1136,40 +1043,44 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size) | |||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv; | |||
if (at91sam7_info->cidr == 0) | |||
{ | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
} | |||
printed = snprintf(buf, buf_size, | |||
"\n at91sam7 driver information: Chip is %s\n", | |||
at91sam7_info->target_name); | |||
"\n at91sam7 driver information: Chip is %s\n", | |||
at91sam7_info->target_name); | |||
buf += printed; | |||
buf_size -= printed; | |||
printed = snprintf(buf, | |||
buf_size, | |||
" Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | Flashsize: 0x%8.8" PRIx32 "\n", | |||
at91sam7_info->cidr, | |||
at91sam7_info->cidr_arch, | |||
EPROC[at91sam7_info->cidr_eproc], | |||
at91sam7_info->cidr_version, | |||
bank->size); | |||
buf_size, | |||
" Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | " | |||
"Flashsize: 0x%8.8" PRIx32 "\n", | |||
at91sam7_info->cidr, | |||
at91sam7_info->cidr_arch, | |||
EPROC[at91sam7_info->cidr_eproc], | |||
at91sam7_info->cidr_version, | |||
bank->size); | |||
buf += printed; | |||
buf_size -= printed; | |||
printed = snprintf(buf, buf_size, | |||
" Master clock (estimated): %u KHz | External clock: %u KHz\n", | |||
(unsigned)(at91sam7_info->mck_freq / 1000), (unsigned)(at91sam7_info->ext_freq / 1000)); | |||
" Master clock (estimated): %u KHz | External clock: %u KHz\n", | |||
(unsigned)(at91sam7_info->mck_freq / 1000), | |||
(unsigned)(at91sam7_info->ext_freq / 1000)); | |||
buf += printed; | |||
buf_size -= printed; | |||
printed = snprintf(buf, buf_size, | |||
" Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i \n", | |||
at91sam7_info->pagesize, bank->num_sectors, at91sam7_info->num_lockbits_on, | |||
at91sam7_info->lockbits, at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on); | |||
printed = snprintf(buf, | |||
buf_size, | |||
" Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i\n", | |||
at91sam7_info->pagesize, | |||
bank->num_sectors, | |||
at91sam7_info->num_lockbits_on, | |||
at91sam7_info->lockbits, | |||
at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on); | |||
buf += printed; | |||
buf_size -= printed; | |||
@@ -1196,59 +1107,46 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command) | |||
{ | |||
struct flash_bank *bank; | |||
int bit; | |||
uint8_t flashcmd; | |||
uint8_t flashcmd; | |||
uint32_t status; | |||
struct at91sam7_flash_bank *at91sam7_info; | |||
int retval; | |||
if (CMD_ARGC != 2) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
bank = get_flash_bank_by_num_noprobe(0); | |||
if (bank == NULL) | |||
{ | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
if (strcmp(bank->driver->name, "at91sam7")) | |||
{ | |||
if (strcmp(bank->driver->name, "at91sam7")) { | |||
command_print(CMD_CTX, "not an at91sam7 flash bank '%s'", CMD_ARGV[0]); | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("target has to be halted to perform flash operation"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (strcmp(CMD_ARGV[1], "set") == 0) | |||
{ | |||
flashcmd = SGPB; | |||
} | |||
else if (strcmp(CMD_ARGV[1], "clear") == 0) | |||
{ | |||
flashcmd = CGPB; | |||
} | |||
else | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
at91sam7_info = bank->driver_priv; | |||
if (at91sam7_info->cidr == 0) | |||
{ | |||
if (at91sam7_info->cidr == 0) { | |||
retval = at91sam7_read_part_info(bank); | |||
if (retval != ERROR_OK) | |||
{ | |||
return retval; | |||
} | |||
} | |||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit); | |||
if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) | |||
{ | |||
command_print(CMD_CTX, "gpnvm bit '#%s' is out of bounds for target %s", CMD_ARGV[0], at91sam7_info->target_name); | |||
if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) { | |||
command_print(CMD_CTX, | |||
"gpnvm bit '#%s' is out of bounds for target %s", | |||
CMD_ARGV[0], | |||
at91sam7_info->target_name); | |||
return ERROR_OK; | |||
} | |||
@@ -1257,13 +1155,14 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command) | |||
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS); | |||
if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */ | |||
status = at91sam7_get_flash_status(bank->target, 0); | |||
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32, flashcmd, bit, status); | |||
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32, | |||
flashcmd, | |||
bit, | |||
status); | |||
/* check protect state */ | |||
at91sam7_protect_check(bank); | |||
@@ -17,6 +17,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -24,33 +25,31 @@ | |||
#include "imp.h" | |||
#include <target/avrt.h> | |||
/* AVR_JTAG_Instructions */ | |||
#define AVR_JTAG_INS_LEN 4 | |||
// Public Instructions: | |||
#define AVR_JTAG_INS_EXTEST 0x00 | |||
#define AVR_JTAG_INS_IDCODE 0x01 | |||
#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02 | |||
#define AVR_JTAG_INS_BYPASS 0x0F | |||
// AVR Specified Public Instructions: | |||
#define AVR_JTAG_INS_AVR_RESET 0x0C | |||
#define AVR_JTAG_INS_PROG_ENABLE 0x04 | |||
#define AVR_JTAG_INS_PROG_COMMANDS 0x05 | |||
#define AVR_JTAG_INS_PROG_PAGELOAD 0x06 | |||
#define AVR_JTAG_INS_PROG_PAGEREAD 0x07 | |||
// Data Registers: | |||
#define AVR_JTAG_REG_Bypass_Len 1 | |||
#define AVR_JTAG_REG_DeviceID_Len 32 | |||
#define AVR_JTAG_REG_Reset_Len 1 | |||
#define AVR_JTAG_REG_JTAGID_Len 32 | |||
#define AVR_JTAG_REG_ProgrammingEnable_Len 16 | |||
#define AVR_JTAG_REG_ProgrammingCommand_Len 15 | |||
#define AVR_JTAG_REG_FlashDataByte_Len 16 | |||
struct avrf_type | |||
{ | |||
#define AVR_JTAG_INS_LEN 4 | |||
/* Public Instructions: */ | |||
#define AVR_JTAG_INS_EXTEST 0x00 | |||
#define AVR_JTAG_INS_IDCODE 0x01 | |||
#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02 | |||
#define AVR_JTAG_INS_BYPASS 0x0F | |||
/* AVR Specified Public Instructions: */ | |||
#define AVR_JTAG_INS_AVR_RESET 0x0C | |||
#define AVR_JTAG_INS_PROG_ENABLE 0x04 | |||
#define AVR_JTAG_INS_PROG_COMMANDS 0x05 | |||
#define AVR_JTAG_INS_PROG_PAGELOAD 0x06 | |||
#define AVR_JTAG_INS_PROG_PAGEREAD 0x07 | |||
/* Data Registers: */ | |||
#define AVR_JTAG_REG_Bypass_Len 1 | |||
#define AVR_JTAG_REG_DeviceID_Len 32 | |||
#define AVR_JTAG_REG_Reset_Len 1 | |||
#define AVR_JTAG_REG_JTAGID_Len 32 | |||
#define AVR_JTAG_REG_ProgrammingEnable_Len 16 | |||
#define AVR_JTAG_REG_ProgrammingCommand_Len 15 | |||
#define AVR_JTAG_REG_FlashDataByte_Len 16 | |||
struct avrf_type { | |||
char name[15]; | |||
uint16_t chip_id; | |||
int flash_page_size; | |||
@@ -59,26 +58,24 @@ struct avrf_type | |||
int eeprom_page_num; | |||
}; | |||
struct avrf_flash_bank | |||
{ | |||
struct avrf_flash_bank { | |||
int ppage_size; | |||
int probed; | |||
}; | |||
static struct avrf_type avft_chips_info[] = | |||
{ | |||
static struct avrf_type avft_chips_info[] = { | |||
/* name, chip_id, flash_page_size, flash_page_num, | |||
* eeprom_page_size, eeprom_page_num | |||
*/ | |||
{"atmega128", 0x9702, 256, 512, 8, 512}, | |||
{"at90can128", 0x9781, 256, 512, 8, 512}, | |||
{"atmega128", 0x9702, 256, 512, 8, 512}, | |||
{"at90can128", 0x9781, 256, 512, 8, 512}, | |||
}; | |||
/* avr program functions */ | |||
static int avr_jtag_reset(struct avr_common *avr, uint32_t reset) | |||
{ | |||
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_AVR_RESET); | |||
avr_jtag_senddat(avr->jtag_info.tap, NULL, reset ,AVR_JTAG_REG_Reset_Len); | |||
avr_jtag_senddat(avr->jtag_info.tap, NULL, reset, AVR_JTAG_REG_Reset_Len); | |||
return ERROR_OK; | |||
} | |||
@@ -127,42 +124,48 @@ static int avr_jtagprg_chiperase(struct avr_common *avr) | |||
do { | |||
poll_value = 0; | |||
avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len); | |||
avr_jtag_senddat(avr->jtag_info.tap, | |||
&poll_value, | |||
0x3380, | |||
AVR_JTAG_REG_ProgrammingCommand_Len); | |||
if (ERROR_OK != mcu_execute_queue()) | |||
{ | |||
return ERROR_FAIL; | |||
} | |||
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value); | |||
} while (!(poll_value & 0x0200)); | |||
return ERROR_OK; | |||
} | |||
static int avr_jtagprg_writeflashpage(struct avr_common *avr, uint8_t *page_buf, uint32_t buf_size, uint32_t addr, uint32_t page_size) | |||
static int avr_jtagprg_writeflashpage(struct avr_common *avr, | |||
uint8_t *page_buf, | |||
uint32_t buf_size, | |||
uint32_t addr, | |||
uint32_t page_size) | |||
{ | |||
uint32_t i, poll_value; | |||
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); | |||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len); | |||
// load addr high byte | |||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0700 | ((addr >> 9) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len); | |||
/* load addr high byte */ | |||
avr_jtag_senddat(avr->jtag_info.tap, | |||
NULL, | |||
0x0700 | ((addr >> 9) & 0xFF), | |||
AVR_JTAG_REG_ProgrammingCommand_Len); | |||
// load addr low byte | |||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0300 | ((addr >> 1) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len); | |||
/* load addr low byte */ | |||
avr_jtag_senddat(avr->jtag_info.tap, | |||
NULL, | |||
0x0300 | ((addr >> 1) & 0xFF), | |||
AVR_JTAG_REG_ProgrammingCommand_Len); | |||
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGELOAD); | |||
for (i = 0; i < page_size; i++) | |||
{ | |||
for (i = 0; i < page_size; i++) { | |||
if (i < buf_size) | |||
{ | |||
avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8); | |||
} | |||
else | |||
{ | |||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8); | |||
} | |||
} | |||
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); | |||
@@ -174,11 +177,12 @@ static int avr_jtagprg_writeflashpage(struct avr_common *avr, uint8_t *page_buf, | |||
do { | |||
poll_value = 0; | |||
avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len); | |||
avr_jtag_senddat(avr->jtag_info.tap, | |||
&poll_value, | |||
0x3700, | |||
AVR_JTAG_REG_ProgrammingCommand_Len); | |||
if (ERROR_OK != mcu_execute_queue()) | |||
{ | |||
return ERROR_FAIL; | |||
} | |||
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value); | |||
} while (!(poll_value & 0x0200)); | |||
@@ -190,9 +194,7 @@ FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command) | |||
struct avrf_flash_bank *avrf_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
avrf_info = malloc(sizeof(struct avrf_flash_bank)); | |||
bank->driver_priv = avrf_info; | |||
@@ -208,10 +210,9 @@ static int avrf_erase(struct flash_bank *bank, int first, int last) | |||
struct avr_common *avr = target->arch_info; | |||
int status; | |||
LOG_DEBUG("%s", __FUNCTION__); | |||
LOG_DEBUG("%s", __func__); | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -229,7 +230,7 @@ static int avrf_erase(struct flash_bank *bank, int first, int last) | |||
static int avrf_protect(struct flash_bank *bank, int set, int first, int last) | |||
{ | |||
LOG_INFO("%s", __FUNCTION__); | |||
LOG_INFO("%s", __func__); | |||
return ERROR_OK; | |||
} | |||
@@ -239,16 +240,16 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
struct avr_common *avr = target->arch_info; | |||
uint32_t cur_size, cur_buffer_size, page_size; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
page_size = bank->sectors[0].size; | |||
if ((offset % page_size) != 0) | |||
{ | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment", offset, page_size); | |||
if ((offset % page_size) != 0) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment", | |||
offset, | |||
page_size); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -256,22 +257,19 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
LOG_DEBUG("count is %" PRId32 "", count); | |||
if (ERROR_OK != avr_jtagprg_enterprogmode(avr)) | |||
{ | |||
return ERROR_FAIL; | |||
} | |||
cur_size = 0; | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
if (count > page_size) | |||
{ | |||
cur_buffer_size = page_size; | |||
} | |||
else | |||
{ | |||
cur_buffer_size = count; | |||
} | |||
avr_jtagprg_writeflashpage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size); | |||
avr_jtagprg_writeflashpage(avr, | |||
buffer + cur_size, | |||
cur_buffer_size, | |||
offset + cur_size, | |||
page_size); | |||
count -= cur_buffer_size; | |||
cur_size += cur_buffer_size; | |||
@@ -284,6 +282,7 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1) | |||
#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12) | |||
#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28) | |||
static int avrf_probe(struct flash_bank *bank) | |||
{ | |||
struct target *target = bank->target; | |||
@@ -293,8 +292,7 @@ static int avrf_probe(struct flash_bank *bank) | |||
int i; | |||
uint32_t device_id; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -303,42 +301,35 @@ static int avrf_probe(struct flash_bank *bank) | |||
avr_jtag_read_jtagid(avr, &device_id); | |||
if (ERROR_OK != mcu_execute_queue()) | |||
{ | |||
return ERROR_FAIL; | |||
} | |||
LOG_INFO("device id = 0x%08" PRIx32 "", device_id); | |||
if (EXTRACT_MFG(device_id) != 0x1F) | |||
{ | |||
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); | |||
} | |||
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", | |||
EXTRACT_MFG(device_id), | |||
0x1F); | |||
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) | |||
{ | |||
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) | |||
{ | |||
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) { | |||
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) { | |||
avr_info = &avft_chips_info[i]; | |||
LOG_INFO("target device is %s", avr_info->name); | |||
break; | |||
} | |||
} | |||
if (avr_info != NULL) | |||
{ | |||
if (bank->sectors) | |||
{ | |||
if (avr_info != NULL) { | |||
if (bank->sectors) { | |||
free(bank->sectors); | |||
bank->sectors = NULL; | |||
} | |||
// chip found | |||
/* chip found */ | |||
bank->base = 0x00000000; | |||
bank->size = (avr_info->flash_page_size * avr_info->flash_page_num); | |||
bank->num_sectors = avr_info->flash_page_num; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num); | |||
for (i = 0; i < avr_info->flash_page_num; i++) | |||
{ | |||
for (i = 0; i < avr_info->flash_page_num; i++) { | |||
bank->sectors[i].offset = i * avr_info->flash_page_size; | |||
bank->sectors[i].size = avr_info->flash_page_size; | |||
bank->sectors[i].is_erased = -1; | |||
@@ -347,10 +338,8 @@ static int avrf_probe(struct flash_bank *bank) | |||
avrf_info->probed = 1; | |||
return ERROR_OK; | |||
} | |||
else | |||
{ | |||
// chip not supported | |||
} else { | |||
/* chip not supported */ | |||
LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id)); | |||
avrf_info->probed = 1; | |||
@@ -368,7 +357,7 @@ static int avrf_auto_probe(struct flash_bank *bank) | |||
static int avrf_protect_check(struct flash_bank *bank) | |||
{ | |||
LOG_INFO("%s", __FUNCTION__); | |||
LOG_INFO("%s", __func__); | |||
return ERROR_OK; | |||
} | |||
@@ -380,28 +369,23 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size) | |||
int i; | |||
uint32_t device_id; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
avr_jtag_read_jtagid(avr, &device_id); | |||
if (ERROR_OK != mcu_execute_queue()) | |||
{ | |||
return ERROR_FAIL; | |||
} | |||
LOG_INFO("device id = 0x%08" PRIx32 "", device_id); | |||
if (EXTRACT_MFG(device_id) != 0x1F) | |||
{ | |||
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); | |||
} | |||
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", | |||
EXTRACT_MFG(device_id), | |||
0x1F); | |||
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) | |||
{ | |||
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) | |||
{ | |||
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) { | |||
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) { | |||
avr_info = &avft_chips_info[i]; | |||
LOG_INFO("target device is %s", avr_info->name); | |||
@@ -409,15 +393,13 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size) | |||
} | |||
} | |||
if (avr_info != NULL) | |||
{ | |||
// chip found | |||
snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name, EXTRACT_VER(device_id)); | |||
if (avr_info != NULL) { | |||
/* chip found */ | |||
snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name, | |||
EXTRACT_VER(device_id)); | |||
return ERROR_OK; | |||
} | |||
else | |||
{ | |||
// chip not supported | |||
} else { | |||
/* chip not supported */ | |||
snprintf(buf, buf_size, "Cannot identify target as a avr\n"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -428,18 +410,15 @@ static int avrf_mass_erase(struct flash_bank *bank) | |||
struct target *target = bank->target; | |||
struct avr_common *avr = target->arch_info; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((ERROR_OK != avr_jtagprg_enterprogmode(avr)) | |||
|| (ERROR_OK != avr_jtagprg_chiperase(avr)) | |||
|| (ERROR_OK != avr_jtagprg_leaveprogmode(avr))) | |||
{ | |||
|| (ERROR_OK != avr_jtagprg_chiperase(avr)) | |||
|| (ERROR_OK != avr_jtagprg_leaveprogmode(avr))) | |||
return ERROR_FAIL; | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -449,31 +428,23 @@ COMMAND_HANDLER(avrf_handle_mass_erase_command) | |||
int i; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
if (ERROR_OK != retval) | |||
return retval; | |||
if (avrf_mass_erase(bank) == ERROR_OK) | |||
{ | |||
if (avrf_mass_erase(bank) == ERROR_OK) { | |||
/* set all sectors as erased */ | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
bank->sectors[i].is_erased = 1; | |||
} | |||
command_print(CMD_CTX, "avr mass erase complete"); | |||
} | |||
else | |||
{ | |||
} else | |||
command_print(CMD_CTX, "avr mass erase failed"); | |||
} | |||
LOG_DEBUG("%s", __FUNCTION__); | |||
LOG_DEBUG("%s", __func__); | |||
return ERROR_OK; | |||
} | |||
@@ -17,14 +17,14 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef CFI_H | |||
#define CFI_H | |||
#define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */ | |||
#define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */ | |||
struct cfi_flash_bank | |||
{ | |||
struct cfi_flash_bank { | |||
struct working_area *write_algorithm; | |||
int x16_as_x8; | |||
@@ -80,8 +80,7 @@ struct cfi_flash_bank | |||
* as defined for the Advanced+ Boot Block Flash Memory (C3) | |||
* and used by the linux kernel cfi driver (as of 2.6.14) | |||
*/ | |||
struct cfi_intel_pri_ext | |||
{ | |||
struct cfi_intel_pri_ext { | |||
uint8_t pri[3]; | |||
uint8_t major_version; | |||
uint8_t minor_version; | |||
@@ -100,8 +99,7 @@ struct cfi_intel_pri_ext | |||
/* Spansion primary extended query table as defined for and used by | |||
* the linux kernel cfi driver (as of 2.6.15) | |||
*/ | |||
struct cfi_spansion_pri_ext | |||
{ | |||
struct cfi_spansion_pri_ext { | |||
uint8_t pri[3]; | |||
uint8_t major_version; | |||
uint8_t minor_version; | |||
@@ -124,8 +122,7 @@ struct cfi_spansion_pri_ext | |||
/* Atmel primary extended query table as defined for and used by | |||
* the linux kernel cfi driver (as of 2.6.20+) | |||
*/ | |||
struct cfi_atmel_pri_ext | |||
{ | |||
struct cfi_atmel_pri_ext { | |||
uint8_t pri[3]; | |||
uint8_t major_version; | |||
uint8_t minor_version; | |||
@@ -140,14 +137,12 @@ enum { | |||
CFI_UNLOCK_5555_2AAA, | |||
}; | |||
struct cfi_unlock_addresses | |||
{ | |||
struct cfi_unlock_addresses { | |||
uint32_t unlock1; | |||
uint32_t unlock2; | |||
}; | |||
struct cfi_fixup | |||
{ | |||
struct cfi_fixup { | |||
uint16_t mfr; | |||
uint16_t id; | |||
void (*fixup)(struct flash_bank *bank, void *param); | |||
@@ -29,7 +29,6 @@ | |||
#include <flash/nor/imp.h> | |||
#include <target/image.h> | |||
/** | |||
* @file | |||
* Upper level of NOR flash framework. | |||
@@ -45,9 +44,7 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last) | |||
retval = bank->driver->erase(bank, first, last); | |||
if (retval != ERROR_OK) | |||
{ | |||
LOG_ERROR("failed erasing sectors %d to %d", first, last); | |||
} | |||
return retval; | |||
} | |||
@@ -57,8 +54,7 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) | |||
int retval; | |||
/* callers may not supply illegal parameters ... */ | |||
if (first < 0 || first > last || last >= bank->num_sectors) | |||
{ | |||
if (first < 0 || first > last || last >= bank->num_sectors) { | |||
LOG_ERROR("illegal sector range"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -79,47 +75,47 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) | |||
*/ | |||
retval = bank->driver->protect(bank, set, first, last); | |||
if (retval != ERROR_OK) | |||
{ | |||
LOG_ERROR("failed setting protection for areas %d to %d", first, last); | |||
} | |||
return retval; | |||
} | |||
int flash_driver_write(struct flash_bank *bank, | |||
uint8_t *buffer, uint32_t offset, uint32_t count) | |||
uint8_t *buffer, uint32_t offset, uint32_t count) | |||
{ | |||
int retval; | |||
retval = bank->driver->write(bank, buffer, offset, count); | |||
if (retval != ERROR_OK) | |||
{ | |||
LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, | |||
bank->base, offset); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR( | |||
"error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, | |||
bank->base, | |||
offset); | |||
} | |||
return retval; | |||
} | |||
int flash_driver_read(struct flash_bank *bank, | |||
uint8_t *buffer, uint32_t offset, uint32_t count) | |||
uint8_t *buffer, uint32_t offset, uint32_t count) | |||
{ | |||
int retval; | |||
LOG_DEBUG("call flash_driver_read()"); | |||
retval = bank->driver->read(bank, buffer, offset, count); | |||
if (retval != ERROR_OK) | |||
{ | |||
LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, | |||
bank->base, offset); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR( | |||
"error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, | |||
bank->base, | |||
offset); | |||
} | |||
return retval; | |||
} | |||
int default_flash_read(struct flash_bank *bank, | |||
uint8_t *buffer, uint32_t offset, uint32_t count) | |||
uint8_t *buffer, uint32_t offset, uint32_t count) | |||
{ | |||
return target_read_buffer(bank->target, offset + bank->base, count, buffer); | |||
} | |||
@@ -128,19 +124,16 @@ void flash_bank_add(struct flash_bank *bank) | |||
{ | |||
/* put flash bank in linked list */ | |||
unsigned bank_num = 0; | |||
if (flash_banks) | |||
{ | |||
if (flash_banks) { | |||
/* find last flash bank */ | |||
struct flash_bank *p = flash_banks; | |||
while (NULL != p->next) | |||
{ | |||
while (NULL != p->next) { | |||
bank_num += 1; | |||
p = p->next; | |||
} | |||
p->next = bank; | |||
bank_num += 1; | |||
} | |||
else | |||
} else | |||
flash_banks = bank; | |||
bank->bank_number = bank_num; | |||
@@ -156,12 +149,9 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num) | |||
struct flash_bank *p; | |||
int i = 0; | |||
for (p = flash_banks; p; p = p->next) | |||
{ | |||
for (p = flash_banks; p; p = p->next) { | |||
if (i++ == num) | |||
{ | |||
return p; | |||
} | |||
} | |||
LOG_ERROR("flash bank %d does not exist", num); | |||
return NULL; | |||
@@ -172,9 +162,7 @@ int flash_get_bank_count(void) | |||
struct flash_bank *p; | |||
int i = 0; | |||
for (p = flash_banks; p; p = p->next) | |||
{ | |||
i++; | |||
} | |||
return i; | |||
} | |||
@@ -184,8 +172,7 @@ struct flash_bank *get_flash_bank_by_name_noprobe(const char *name) | |||
unsigned found = 0; | |||
struct flash_bank *bank; | |||
for (bank = flash_banks; NULL != bank; bank = bank->next) | |||
{ | |||
for (bank = flash_banks; NULL != bank; bank = bank->next) { | |||
if (strcmp(bank->name, name) == 0) | |||
return bank; | |||
if (!flash_driver_name_matches(bank->driver->name, name)) | |||
@@ -203,12 +190,10 @@ int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result) | |||
int retval; | |||
bank = get_flash_bank_by_name_noprobe(name); | |||
if (bank != NULL) | |||
{ | |||
if (bank != NULL) { | |||
retval = bank->driver->auto_probe(bank); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("auto_probe failed"); | |||
return retval; | |||
} | |||
@@ -224,14 +209,11 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank) | |||
int retval; | |||
if (p == NULL) | |||
{ | |||
return ERROR_FAIL; | |||
} | |||
retval = p->driver->auto_probe(p); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("auto_probe failed"); | |||
return retval; | |||
} | |||
@@ -241,31 +223,30 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank) | |||
/* lookup flash bank by address, bank not found is success, but | |||
* result_bank is set to NULL. */ | |||
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank) | |||
int get_flash_bank_by_addr(struct target *target, | |||
uint32_t addr, | |||
bool check, | |||
struct flash_bank **result_bank) | |||
{ | |||
struct flash_bank *c; | |||
/* cycle through bank list */ | |||
for (c = flash_banks; c; c = c->next) | |||
{ | |||
for (c = flash_banks; c; c = c->next) { | |||
int retval; | |||
retval = c->driver->auto_probe(c); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("auto_probe failed"); | |||
return retval; | |||
} | |||
/* check whether address belongs to this flash bank */ | |||
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target) | |||
{ | |||
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target) { | |||
*result_bank = c; | |||
return ERROR_OK; | |||
} | |||
} | |||
*result_bank = NULL; | |||
if (check) | |||
{ | |||
if (check) { | |||
LOG_ERROR("No flash at address 0x%08" PRIx32, addr); | |||
return ERROR_FAIL; | |||
} | |||
@@ -280,38 +261,33 @@ int default_flash_mem_blank_check(struct flash_bank *bank) | |||
uint32_t nBytes; | |||
int retval = ERROR_OK; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
uint8_t *buffer = malloc(buffer_size); | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
uint32_t j; | |||
bank->sectors[i].is_erased = 1; | |||
for (j = 0; j < bank->sectors[i].size; j += buffer_size) | |||
{ | |||
for (j = 0; j < bank->sectors[i].size; j += buffer_size) { | |||
uint32_t chunk; | |||
chunk = buffer_size; | |||
if (chunk > (j - bank->sectors[i].size)) | |||
{ | |||
chunk = (j - bank->sectors[i].size); | |||
} | |||
retval = target_read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk/4, buffer); | |||
retval = target_read_memory(target, | |||
bank->base + bank->sectors[i].offset + j, | |||
4, | |||
chunk/4, | |||
buffer); | |||
if (retval != ERROR_OK) | |||
{ | |||
goto done; | |||
} | |||
for (nBytes = 0; nBytes < chunk; nBytes++) | |||
{ | |||
if (buffer[nBytes] != 0xFF) | |||
{ | |||
for (nBytes = 0; nBytes < chunk; nBytes++) { | |||
if (buffer[nBytes] != 0xFF) { | |||
bank->sectors[i].is_erased = 0; | |||
break; | |||
} | |||
@@ -319,7 +295,7 @@ int default_flash_mem_blank_check(struct flash_bank *bank) | |||
} | |||
} | |||
done: | |||
done: | |||
free(buffer); | |||
return retval; | |||
@@ -333,20 +309,17 @@ int default_flash_blank_check(struct flash_bank *bank) | |||
int fast_check = 0; | |||
uint32_t blank; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
uint32_t address = bank->base + bank->sectors[i].offset; | |||
uint32_t size = bank->sectors[i].size; | |||
retval = target_blank_check_memory(target, address, size, &blank); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
fast_check = 0; | |||
break; | |||
} | |||
@@ -357,8 +330,7 @@ int default_flash_blank_check(struct flash_bank *bank) | |||
fast_check = 1; | |||
} | |||
if (!fast_check) | |||
{ | |||
if (!fast_check) { | |||
LOG_USER("Running slow fallback erase check - add working memory"); | |||
return default_flash_mem_blank_check(bank); | |||
} | |||
@@ -381,8 +353,8 @@ int default_flash_blank_check(struct flash_bank *bank) | |||
* warning about those additions. | |||
*/ | |||
static int flash_iterate_address_range_inner(struct target *target, | |||
char *pad_reason, uint32_t addr, uint32_t length, | |||
int (*callback)(struct flash_bank *bank, int first, int last)) | |||
char *pad_reason, uint32_t addr, uint32_t length, | |||
int (*callback)(struct flash_bank *bank, int first, int last)) | |||
{ | |||
struct flash_bank *c; | |||
uint32_t last_addr = addr + length; /* first address AFTER end */ | |||
@@ -394,17 +366,14 @@ static int flash_iterate_address_range_inner(struct target *target, | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (c->size == 0 || c->num_sectors == 0) | |||
{ | |||
if (c->size == 0 || c->num_sectors == 0) { | |||
LOG_ERROR("Bank is invalid"); | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
if (length == 0) | |||
{ | |||
if (length == 0) { | |||
/* special case, erase whole bank when length is zero */ | |||
if (addr != c->base) | |||
{ | |||
if (addr != c->base) { | |||
LOG_ERROR("Whole bank access must start at beginning of bank."); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -413,8 +382,7 @@ static int flash_iterate_address_range_inner(struct target *target, | |||
} | |||
/* check whether it all fits in this bank */ | |||
if (addr + length - 1 > c->base + c->size - 1) | |||
{ | |||
if (addr + length - 1 > c->base + c->size - 1) { | |||
LOG_ERROR("Flash access does not fit into bank."); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -424,8 +392,7 @@ static int flash_iterate_address_range_inner(struct target *target, | |||
addr -= c->base; | |||
last_addr -= c->base; | |||
for (i = 0; i < c->num_sectors; i++) | |||
{ | |||
for (i = 0; i < c->num_sectors; i++) { | |||
struct flash_sector *f = c->sectors + i; | |||
uint32_t end = f->offset + f->size; | |||
@@ -449,7 +416,7 @@ static int flash_iterate_address_range_inner(struct target *target, | |||
else if (addr < end && pad_reason) { | |||
/* FIXME say how many bytes (e.g. 80 KB) */ | |||
LOG_WARNING("Adding extra %s range, " | |||
"%#8.8x to %#8.8x", | |||
"%#8.8x to %#8.8x", | |||
pad_reason, | |||
(unsigned) f->offset, | |||
(unsigned) addr - 1); | |||
@@ -470,7 +437,7 @@ static int flash_iterate_address_range_inner(struct target *target, | |||
if (last_addr < end && pad_reason) { | |||
/* FIXME say how many bytes (e.g. 80 KB) */ | |||
LOG_WARNING("Adding extra %s range, " | |||
"%#8.8x to %#8.8x", | |||
"%#8.8x to %#8.8x", | |||
pad_reason, | |||
(unsigned) last_addr, | |||
(unsigned) end - 1); | |||
@@ -486,9 +453,9 @@ static int flash_iterate_address_range_inner(struct target *target, | |||
/* invalid start or end address? */ | |||
if (first == -1 || last == -1) { | |||
LOG_ERROR("address range 0x%8.8x .. 0x%8.8x " | |||
"is not sector-aligned", | |||
(unsigned) (c->base + addr), | |||
(unsigned) (c->base + last_addr - 1)); | |||
"is not sector-aligned", | |||
(unsigned) (c->base + addr), | |||
(unsigned) (c->base + last_addr - 1)); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -503,23 +470,21 @@ static int flash_iterate_address_range_inner(struct target *target, | |||
* multiple chips. | |||
*/ | |||
static int flash_iterate_address_range(struct target *target, | |||
char *pad_reason, uint32_t addr, uint32_t length, | |||
int (*callback)(struct flash_bank *bank, int first, int last)) | |||
char *pad_reason, uint32_t addr, uint32_t length, | |||
int (*callback)(struct flash_bank *bank, int first, int last)) | |||
{ | |||
struct flash_bank *c; | |||
int retval = ERROR_OK; | |||
/* Danger! zero-length iterations means entire bank! */ | |||
do | |||
{ | |||
do { | |||
retval = get_flash_bank_by_addr(target, addr, true, &c); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
uint32_t cur_length = length; | |||
/* check whether it all fits in this bank */ | |||
if (addr + length - 1 > c->base + c->size - 1) | |||
{ | |||
if (addr + length - 1 > c->base + c->size - 1) { | |||
LOG_DEBUG("iterating over more than one flash bank."); | |||
cur_length = c->base + c->size - addr; | |||
} | |||
@@ -537,10 +502,10 @@ static int flash_iterate_address_range(struct target *target, | |||
} | |||
int flash_erase_address_range(struct target *target, | |||
bool pad, uint32_t addr, uint32_t length) | |||
bool pad, uint32_t addr, uint32_t length) | |||
{ | |||
return flash_iterate_address_range(target, pad ? "erase" : NULL, | |||
addr, length, &flash_driver_erase); | |||
addr, length, &flash_driver_erase); | |||
} | |||
static int flash_driver_unprotect(struct flash_bank *bank, int first, int last) | |||
@@ -555,30 +520,25 @@ int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t le | |||
* and doesn't restore it. | |||
*/ | |||
return flash_iterate_address_range(target, "unprotect", | |||
addr, length, &flash_driver_unprotect); | |||
addr, length, &flash_driver_unprotect); | |||
} | |||
static int compare_section (const void * a, const void * b) | |||
static int compare_section(const void *a, const void *b) | |||
{ | |||
struct imagesection *b1, *b2; | |||
b1=*((struct imagesection **)a); | |||
b2=*((struct imagesection **)b); | |||
b1 = *((struct imagesection **)a); | |||
b2 = *((struct imagesection **)b); | |||
if (b1->base_address == b2->base_address) | |||
{ | |||
return 0; | |||
} else if (b1->base_address > b2->base_address) | |||
{ | |||
else if (b1->base_address > b2->base_address) | |||
return 1; | |||
} else | |||
{ | |||
else | |||
return -1; | |||
} | |||
} | |||
int flash_write_unlock(struct target *target, struct image *image, | |||
uint32_t *written, int erase, bool unlock) | |||
uint32_t *written, int erase, bool unlock) | |||
{ | |||
int retval = ERROR_OK; | |||
@@ -593,8 +553,7 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
if (written) | |||
*written = 0; | |||
if (erase) | |||
{ | |||
if (erase) { | |||
/* assume all sectors need erasing - stops any problems | |||
* when flash_write is called multiple times */ | |||
@@ -610,16 +569,13 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
image->num_sections); | |||
int i; | |||
for (i = 0; i < image->num_sections; i++) | |||
{ | |||
sections[i] = &image->sections[i]; | |||
} | |||
qsort(sections, image->num_sections, sizeof(struct imagesection *), | |||
compare_section); | |||
compare_section); | |||
/* loop until we reach end of the image */ | |||
while (section < image->num_sections) | |||
{ | |||
while (section < image->num_sections) { | |||
uint32_t buffer_size; | |||
uint8_t *buffer; | |||
int section_last; | |||
@@ -627,8 +583,7 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
uint32_t run_size = sections[section]->size - section_offset; | |||
int pad_bytes = 0; | |||
if (sections[section]->size == 0) | |||
{ | |||
if (sections[section]->size == 0) { | |||
LOG_WARNING("empty section %d", section); | |||
section++; | |||
section_offset = 0; | |||
@@ -638,12 +593,9 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
/* find the corresponding flash bank */ | |||
retval = get_flash_bank_by_addr(target, run_address, false, &c); | |||
if (retval != ERROR_OK) | |||
{ | |||
goto done; | |||
} | |||
if (c == NULL) | |||
{ | |||
section++; /* and skip it */ | |||
if (c == NULL) { | |||
section++; /* and skip it */ | |||
section_offset = 0; | |||
continue; | |||
} | |||
@@ -651,15 +603,13 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
/* collect consecutive sections which fall into the same bank */ | |||
section_last = section; | |||
padding[section] = 0; | |||
while ((run_address + run_size - 1 < c->base + c->size - 1) | |||
&& (section_last + 1 < image->num_sections)) | |||
{ | |||
while ((run_address + run_size - 1 < c->base + c->size - 1) && | |||
(section_last + 1 < image->num_sections)) { | |||
/* sections are sorted */ | |||
assert(sections[section_last + 1]->base_address >= c->base); | |||
if (sections[section_last + 1]->base_address >= (c->base + c->size)) | |||
{ | |||
/* Done with this bank */ | |||
break; | |||
if (sections[section_last + 1]->base_address >= (c->base + c->size)) { | |||
/* Done with this bank */ | |||
break; | |||
} | |||
/* FIXME This needlessly touches sectors BETWEEN the | |||
@@ -685,11 +635,12 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
run_size += pad_bytes; | |||
if (pad_bytes > 0) | |||
LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes); | |||
LOG_INFO("Padding image section %d with %d bytes", | |||
section_last-1, | |||
pad_bytes); | |||
} | |||
if (run_address + run_size - 1 > c->base + c->size - 1) | |||
{ | |||
if (run_address + run_size - 1 > c->base + c->size - 1) { | |||
/* If we have more than one flash chip back to back, then we limit | |||
* the current write operation to the current chip. | |||
*/ | |||
@@ -710,7 +661,7 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
for (sector = 0; sector < c->num_sectors; sector++) { | |||
end = c->sectors[sector].offset | |||
+ c->sectors[sector].size; | |||
+ c->sectors[sector].size; | |||
if (offset_end <= end) | |||
break; | |||
} | |||
@@ -722,8 +673,7 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
/* allocate buffer */ | |||
buffer = malloc(run_size); | |||
if (buffer == NULL) | |||
{ | |||
if (buffer == NULL) { | |||
LOG_ERROR("Out of memory for flash bank buffer"); | |||
retval = ERROR_FAIL; | |||
goto done; | |||
@@ -731,13 +681,12 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
buffer_size = 0; | |||
/* read sections to the buffer */ | |||
while (buffer_size < run_size) | |||
{ | |||
while (buffer_size < run_size) { | |||
size_t size_read; | |||
size_read = run_size - buffer_size; | |||
if (size_read > sections[section]->size - section_offset) | |||
size_read = sections[section]->size - section_offset; | |||
size_read = sections[section]->size - section_offset; | |||
/* KLUDGE! | |||
* | |||
@@ -747,25 +696,25 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections; | |||
int t_section_num = diff / sizeof(struct imagesection); | |||
LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d", | |||
(int)section, | |||
(int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read); | |||
if ((retval = image_read_section(image, t_section_num, section_offset, | |||
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0) | |||
{ | |||
LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, " | |||
"section_offset = %d, buffer_size = %d, size_read = %d", | |||
(int)section, (int)t_section_num, (int)section_offset, | |||
(int)buffer_size, (int)size_read); | |||
retval = image_read_section(image, t_section_num, section_offset, | |||
size_read, buffer + buffer_size, &size_read); | |||
if (retval != ERROR_OK || size_read == 0) { | |||
free(buffer); | |||
goto done; | |||
} | |||
/* see if we need to pad the section */ | |||
while (padding[section]--) | |||
(buffer + buffer_size)[size_read++] = 0xff; | |||
(buffer + buffer_size)[size_read++] = 0xff; | |||
buffer_size += size_read; | |||
section_offset += size_read; | |||
if (section_offset >= sections[section]->size) | |||
{ | |||
if (section_offset >= sections[section]->size) { | |||
section++; | |||
section_offset = 0; | |||
} | |||
@@ -774,38 +723,31 @@ int flash_write_unlock(struct target *target, struct image *image, | |||
retval = ERROR_OK; | |||
if (unlock) | |||
{ | |||
retval = flash_unlock_address_range(target, run_address, run_size); | |||
} | |||
if (retval == ERROR_OK) | |||
{ | |||
if (erase) | |||
{ | |||
if (retval == ERROR_OK) { | |||
if (erase) { | |||
/* calculate and erase sectors */ | |||
retval = flash_erase_address_range(target, | |||
true, run_address, run_size); | |||
} | |||
} | |||
if (retval == ERROR_OK) | |||
{ | |||
if (retval == ERROR_OK) { | |||
/* write flash sectors */ | |||
retval = flash_driver_write(c, buffer, run_address - c->base, run_size); | |||
} | |||
free(buffer); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
/* abort operation */ | |||
goto done; | |||
} | |||
if (written != NULL) | |||
*written += run_size; /* add run size to total written counter */ | |||
*written += run_size; /* add run size to total written counter */ | |||
} | |||
done: | |||
free(sections); | |||
free(padding); | |||
@@ -814,7 +756,7 @@ done: | |||
} | |||
int flash_write(struct target *target, struct image *image, | |||
uint32_t *written, int erase) | |||
uint32_t *written, int erase) | |||
{ | |||
return flash_write_unlock(target, image, written, erase, false); | |||
} |
@@ -20,6 +20,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef FLASH_NOR_CORE_H | |||
#define FLASH_NOR_CORE_H | |||
@@ -39,11 +40,10 @@ struct image; | |||
* within a flash bank. A single bank typically consists of multiple | |||
* sectors, each of which can be erased and protected independently. | |||
*/ | |||
struct flash_sector | |||
{ | |||
/// Bus offset from start of the flash chip (in bytes). | |||
struct flash_sector { | |||
/** Bus offset from start of the flash chip (in bytes). */ | |||
uint32_t offset; | |||
/// Number of bytes in this flash sector. | |||
/** Number of bytes in this flash sector. */ | |||
uint32_t size; | |||
/** | |||
* Indication of erasure status: 0 = not erased, 1 = erased, | |||
@@ -72,8 +72,7 @@ struct flash_sector | |||
* may use the @c driver_priv member to store additional data on a | |||
* per-bank basis, if required. | |||
*/ | |||
struct flash_bank | |||
{ | |||
struct flash_bank { | |||
const char *name; | |||
struct target *target; /**< Target to which this bank belongs. */ | |||
@@ -94,13 +93,13 @@ struct flash_bank | |||
* some non-zero value during "probe()" or "auto_probe()". | |||
*/ | |||
int num_sectors; | |||
/// Array of sectors, allocated and initilized by the flash driver | |||
/** Array of sectors, allocated and initilized by the flash driver */ | |||
struct flash_sector *sectors; | |||
struct flash_bank *next; /**< The next flash bank on this chip */ | |||
}; | |||
/// Registers the 'flash' subsystem commands | |||
/** Registers the 'flash' subsystem commands */ | |||
int flash_register_commands(struct command_context *cmd_ctx); | |||
/** | |||
@@ -134,7 +133,7 @@ int flash_write(struct target *target, | |||
* This routine must be called when the system may modify the status. | |||
*/ | |||
void flash_set_dirty(void); | |||
/// @returns The number of flash banks currently defined. | |||
/** @returns The number of flash banks currently defined. */ | |||
int flash_get_bank_count(void); | |||
/** | |||
* Provides default read implementation for flash memory. | |||
@@ -209,6 +208,7 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num); | |||
* @param check return ERROR_OK and result_bank NULL if the bank does not exist | |||
* @returns The struct flash_bank located at @a addr, or NULL. | |||
*/ | |||
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank); | |||
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, | |||
struct flash_bank **result_bank); | |||
#endif // FLASH_NOR_CORE_H | |||
#endif /* FLASH_NOR_CORE_H */ |
@@ -20,6 +20,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef FLASH_NOR_DRIVER_H | |||
#define FLASH_NOR_DRIVER_H | |||
@@ -48,8 +49,7 @@ struct flash_bank; | |||
* corresponding static <code>flash_driver_<i>callback</i>()</code> | |||
* routine in flash.c. | |||
*/ | |||
struct flash_driver | |||
{ | |||
struct flash_driver { | |||
/** | |||
* Gives a human-readable name of this flash driver, | |||
* This field is used to select and initialize the driver. | |||
@@ -213,7 +213,8 @@ struct flash_driver | |||
int (*auto_probe)(struct flash_bank *bank); | |||
}; | |||
#define FLASH_BANK_COMMAND_HANDLER(name) static __FLASH_BANK_COMMAND(name) | |||
#define FLASH_BANK_COMMAND_HANDLER(name) \ | |||
static __FLASH_BANK_COMMAND(name) | |||
/** | |||
* Find a NOR flash driver by its name. | |||
@@ -222,4 +223,4 @@ struct flash_driver | |||
*/ | |||
struct flash_driver *flash_driver_find_by_name(const char *name); | |||
#endif // FLASH_NOR_DRIVER_H | |||
#endif /* FLASH_NOR_DRIVER_H */ |
@@ -16,6 +16,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -84,8 +85,7 @@ static struct flash_driver *flash_drivers[] = { | |||
struct flash_driver *flash_driver_find_by_name(const char *name) | |||
{ | |||
for (unsigned i = 0; flash_drivers[i]; i++) | |||
{ | |||
for (unsigned i = 0; flash_drivers[i]; i++) { | |||
if (strcmp(name, flash_drivers[i]->name) == 0) | |||
return flash_drivers[i]; | |||
} | |||
@@ -27,12 +27,12 @@ | |||
* @file dsp5680xx_flash.c | |||
* @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com> | |||
* @date Thu Jun 9 18:21:58 2011 | |||
* | |||
* | |||
* @brief This file implements the basic functions to run flashing commands | |||
* from the TCL interface. | |||
* It allows the user to flash the Freescale 5680xx DSP. | |||
* | |||
* | |||
* | |||
* | |||
*/ | |||
#ifdef HAVE_CONFIG_H | |||
@@ -84,14 +84,14 @@ FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command) | |||
return ERROR_OK; | |||
} | |||
/** | |||
/** | |||
* A memory mapped register (PROT) holds information regarding sector protection. | |||
* Protection refers to undesired core access. | |||
* The value in this register is loaded from flash upon reset. | |||
* | |||
* @param bank | |||
* | |||
* @return | |||
* | |||
* @param bank | |||
* | |||
* @return | |||
*/ | |||
static int dsp5680xx_flash_protect_check(struct flash_bank *bank) | |||
{ | |||
@@ -118,17 +118,18 @@ static int dsp5680xx_flash_protect_check(struct flash_bank *bank) | |||
return retval; | |||
} | |||
/** | |||
/** | |||
* Protection funcionality is not implemented. | |||
* The current implementation applies/removes security on the chip. | |||
* The chip is effectively secured/unsecured after the first reset following the execution of this function. | |||
* | |||
* @param bank | |||
* The chip is effectively secured/unsecured after the first reset | |||
* following the execution of this function. | |||
* | |||
* @param bank | |||
* @param set Apply or remove security on the chip. | |||
* @param first This parameter is ignored. | |||
* @param last This parameter is ignored. | |||
* | |||
* @return | |||
* | |||
* @return | |||
*/ | |||
static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, | |||
int last) | |||
@@ -153,15 +154,16 @@ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, | |||
return retval; | |||
} | |||
/** | |||
* The dsp5680xx use word addressing. The "/2" that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing. | |||
* | |||
* @param bank | |||
/** | |||
* The dsp5680xx use word addressing. The "/2" that appear in the following code | |||
* are a workaround for the fact that OpenOCD uses byte addressing. | |||
* | |||
* @param bank | |||
* @param buffer Data to write to flash. | |||
* @param offset | |||
* @param offset | |||
* @param count In bytes (2 bytes per address). | |||
* | |||
* @return | |||
* | |||
* @return | |||
*/ | |||
static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t * buffer, | |||
uint32_t offset, uint32_t count) | |||
@@ -178,24 +180,18 @@ static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t * buffer, | |||
* This chip uses word addressing, Openocd only supports byte addressing. | |||
* The workaround results in disabling writing to odd byte addresses | |||
*/ | |||
LOG_ERROR | |||
("%s: Writing to odd addresses not supported for this target", | |||
__func__); | |||
LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__); | |||
return ERROR_FAIL; | |||
} | |||
retval = | |||
dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, | |||
0); | |||
retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0); | |||
uint32_t addr_word; | |||
for (addr_word = bank->base + offset / 2; addr_word < count / 2; | |||
addr_word += (HFM_SECTOR_SIZE / 2)) { | |||
addr_word += (HFM_SECTOR_SIZE / 2)) { | |||
if (retval == ERROR_OK) | |||
bank->sectors[addr_word / | |||
(HFM_SECTOR_SIZE / 2)].is_erased = 0; | |||
bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0; | |||
else | |||
bank->sectors[addr_word / | |||
(HFM_SECTOR_SIZE / 2)].is_erased = -1; | |||
bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1; | |||
} | |||
return retval; | |||
} | |||
@@ -207,31 +203,32 @@ static int dsp5680xx_probe(struct flash_bank *bank) | |||
} | |||
static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf, | |||
int buf_size) | |||
int buf_size) | |||
{ | |||
snprintf(buf, buf_size, | |||
"\ndsp5680xx flash driver info:\n - See comments in code."); | |||
return ERROR_OK; | |||
} | |||
/** | |||
* The flash module (FM) on the dsp5680xx supports both individual sector and mass erase of the flash memory. | |||
* If this function is called with @first == @last == 0 or if @first is the first sector (#0) and @last is the last sector then the mass erase command is executed (much faster than erasing each sector individually). | |||
* | |||
* @param bank | |||
* @param first | |||
* @param last | |||
* | |||
* @return | |||
/** | |||
* The flash module (FM) on the dsp5680xx supports both individual sector | |||
* and mass erase of the flash memory. | |||
* If this function is called with @first == @last == 0 or if @first is the | |||
* first sector (#0) and @last is the last sector then the mass erase command | |||
* is executed (much faster than erasing each sector individually). | |||
* | |||
* @param bank | |||
* @param first | |||
* @param last | |||
* | |||
* @return | |||
*/ | |||
static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last) | |||
{ | |||
int retval; | |||
retval = | |||
dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last); | |||
if ((!(first | last)) | |||
|| ((first == 0) && (last == (HFM_SECTOR_COUNT - 1)))) | |||
retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last); | |||
if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1)))) | |||
last = HFM_SECTOR_COUNT - 1; | |||
if (retval == ERROR_OK) | |||
for (int i = first; i <= last; i++) | |||
@@ -246,13 +243,13 @@ static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last) | |||
return retval; | |||
} | |||
/** | |||
/** | |||
* The flash module (FM) on the dsp5680xx support a blank check function. | |||
* This function executes the FM's blank check functionality on each and every sector. | |||
* | |||
* @param bank | |||
* | |||
* @return | |||
* | |||
* @param bank | |||
* | |||
* @return | |||
*/ | |||
static int dsp5680xx_flash_erase_check(struct flash_bank *bank) | |||
{ | |||
@@ -264,8 +261,7 @@ static int dsp5680xx_flash_erase_check(struct flash_bank *bank) | |||
for (i = 0; i < HFM_SECTOR_COUNT; i++) { | |||
if (bank->sectors[i].is_erased == -1) { | |||
retval = | |||
dsp5680xx_f_erase_check(bank->target, &erased, i); | |||
retval = dsp5680xx_f_erase_check(bank->target, &erased, i); | |||
if (retval != ERROR_OK) { | |||
bank->sectors[i].is_erased = -1; | |||
} else { | |||
@@ -17,6 +17,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -26,16 +27,15 @@ | |||
#include <target/algorithm.h> | |||
#include <target/image.h> | |||
#if 0 | |||
static uint32_t ecosflash_get_flash_status(struct flash_bank *bank); | |||
static void ecosflash_set_flash_mode(struct flash_bank *bank,int mode); | |||
static void ecosflash_set_flash_mode(struct flash_bank *bank, int mode); | |||
static uint32_t ecosflash_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout); | |||
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc); | |||
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, | |||
char *cmd, char **args, int argc); | |||
#endif | |||
struct ecosflash_flash_bank | |||
{ | |||
struct ecosflash_flash_bank { | |||
struct target *target; | |||
struct working_area *write_algorithm; | |||
struct working_area *erase_check_algorithm; | |||
@@ -45,60 +45,58 @@ struct ecosflash_flash_bank | |||
static const int sectorSize = 0x10000; | |||
char * | |||
flash_errmsg(int err); | |||
char *flash_errmsg(int err); | |||
#ifndef __ECOS | |||
#define FLASH_ERR_OK 0x00 /* No error - operation complete */ | |||
#define FLASH_ERR_INVALID 0x01 /* Invalid FLASH address */ | |||
#define FLASH_ERR_ERASE 0x02 /* Error trying to erase */ | |||
#define FLASH_ERR_LOCK 0x03 /* Error trying to lock/unlock */ | |||
#define FLASH_ERR_PROGRAM 0x04 /* Error trying to program */ | |||
#define FLASH_ERR_PROTOCOL 0x05 /* Generic error */ | |||
#define FLASH_ERR_PROTECT 0x06 /* Device/region is write-protected */ | |||
#define FLASH_ERR_NOT_INIT 0x07 /* FLASH info not yet initialized */ | |||
#define FLASH_ERR_HWR 0x08 /* Hardware (configuration?) problem */ | |||
#define FLASH_ERR_ERASE_SUSPEND 0x09 /* Device is in erase suspend mode */ | |||
#define FLASH_ERR_PROGRAM_SUSPEND 0x0a /* Device is in in program suspend mode */ | |||
#define FLASH_ERR_DRV_VERIFY 0x0b /* Driver failed to verify data */ | |||
#define FLASH_ERR_DRV_TIMEOUT 0x0c /* Driver timed out waiting for device */ | |||
#define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support device */ | |||
#define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */ | |||
char * | |||
flash_errmsg(int err) | |||
#define FLASH_ERR_OK 0x00 /* No error - operation complete */ | |||
#define FLASH_ERR_INVALID 0x01 /* Invalid FLASH address */ | |||
#define FLASH_ERR_ERASE 0x02 /* Error trying to erase */ | |||
#define FLASH_ERR_LOCK 0x03 /* Error trying to lock/unlock */ | |||
#define FLASH_ERR_PROGRAM 0x04 /* Error trying to program */ | |||
#define FLASH_ERR_PROTOCOL 0x05 /* Generic error */ | |||
#define FLASH_ERR_PROTECT 0x06 /* Device/region is write-protected */ | |||
#define FLASH_ERR_NOT_INIT 0x07 /* FLASH info not yet initialized */ | |||
#define FLASH_ERR_HWR 0x08 /* Hardware (configuration?) problem */ | |||
#define FLASH_ERR_ERASE_SUSPEND 0x09 /* Device is in erase suspend mode */ | |||
#define FLASH_ERR_PROGRAM_SUSPEND 0x0a /* Device is in in program suspend mode */ | |||
#define FLASH_ERR_DRV_VERIFY 0x0b /* Driver failed to verify data */ | |||
#define FLASH_ERR_DRV_TIMEOUT 0x0c /* Driver timed out waiting for device */ | |||
#define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support device */ | |||
#define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */ | |||
char *flash_errmsg(int err) | |||
{ | |||
switch (err) { | |||
case FLASH_ERR_OK: | |||
return "No error - operation complete"; | |||
case FLASH_ERR_ERASE_SUSPEND: | |||
return "Device is in erase suspend state"; | |||
case FLASH_ERR_PROGRAM_SUSPEND: | |||
return "Device is in program suspend state"; | |||
case FLASH_ERR_INVALID: | |||
return "Invalid FLASH address"; | |||
case FLASH_ERR_ERASE: | |||
return "Error trying to erase"; | |||
case FLASH_ERR_LOCK: | |||
return "Error trying to lock/unlock"; | |||
case FLASH_ERR_PROGRAM: | |||
return "Error trying to program"; | |||
case FLASH_ERR_PROTOCOL: | |||
return "Generic error"; | |||
case FLASH_ERR_PROTECT: | |||
return "Device/region is write-protected"; | |||
case FLASH_ERR_NOT_INIT: | |||
return "FLASH sub-system not initialized"; | |||
case FLASH_ERR_DRV_VERIFY: | |||
return "Data verify failed after operation"; | |||
case FLASH_ERR_DRV_TIMEOUT: | |||
return "Driver timed out waiting for device"; | |||
case FLASH_ERR_DRV_WRONG_PART: | |||
return "Driver does not support device"; | |||
case FLASH_ERR_LOW_VOLTAGE: | |||
return "Device reports low voltage"; | |||
default: | |||
return "Unknown error"; | |||
case FLASH_ERR_OK: | |||
return "No error - operation complete"; | |||
case FLASH_ERR_ERASE_SUSPEND: | |||
return "Device is in erase suspend state"; | |||
case FLASH_ERR_PROGRAM_SUSPEND: | |||
return "Device is in program suspend state"; | |||
case FLASH_ERR_INVALID: | |||
return "Invalid FLASH address"; | |||
case FLASH_ERR_ERASE: | |||
return "Error trying to erase"; | |||
case FLASH_ERR_LOCK: | |||
return "Error trying to lock/unlock"; | |||
case FLASH_ERR_PROGRAM: | |||
return "Error trying to program"; | |||
case FLASH_ERR_PROTOCOL: | |||
return "Generic error"; | |||
case FLASH_ERR_PROTECT: | |||
return "Device/region is write-protected"; | |||
case FLASH_ERR_NOT_INIT: | |||
return "FLASH sub-system not initialized"; | |||
case FLASH_ERR_DRV_VERIFY: | |||
return "Data verify failed after operation"; | |||
case FLASH_ERR_DRV_TIMEOUT: | |||
return "Driver timed out waiting for device"; | |||
case FLASH_ERR_DRV_WRONG_PART: | |||
return "Driver does not support device"; | |||
case FLASH_ERR_LOW_VOLTAGE: | |||
return "Device reports low voltage"; | |||
default: | |||
return "Unknown error"; | |||
} | |||
} | |||
#endif | |||
@@ -110,13 +108,10 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command) | |||
struct ecosflash_flash_bank *info; | |||
if (CMD_ARGC < 7) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
info = malloc(sizeof(struct ecosflash_flash_bank)); | |||
if (info == NULL) | |||
{ | |||
if (info == NULL) { | |||
LOG_ERROR("no memory for flash bank info"); | |||
exit(-1); | |||
} | |||
@@ -131,8 +126,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command) | |||
uint32_t offset = 0; | |||
bank->num_sectors = bank->size/sectorSize; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = sectorSize; | |||
offset += bank->sectors[i].size; | |||
@@ -141,8 +135,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command) | |||
} | |||
info->target = get_target(CMD_ARGV[5]); | |||
if (info->target == NULL) | |||
{ | |||
if (info->target == NULL) { | |||
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); | |||
return ERROR_FAIL; | |||
} | |||
@@ -160,20 +153,18 @@ static int loadDriver(struct ecosflash_flash_bank *info) | |||
struct target *target = info->target; | |||
int retval; | |||
if ((retval = image_open(&image, info->driverPath, NULL)) != ERROR_OK) | |||
{ | |||
retval = image_open(&image, info->driverPath, NULL); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
info->start_address = image.start_address; | |||
image_size = 0x0; | |||
int i; | |||
for (i = 0; i < image.num_sections; i++) | |||
{ | |||
for (i = 0; i < image.num_sections; i++) { | |||
void *buffer = malloc(image.sections[i].size); | |||
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK) | |||
{ | |||
retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); | |||
if (retval != ERROR_OK) { | |||
free(buffer); | |||
image_close(&image); | |||
return retval; | |||
@@ -181,7 +172,7 @@ static int loadDriver(struct ecosflash_flash_bank *info) | |||
target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer); | |||
image_size += buf_cnt; | |||
LOG_DEBUG("%zu bytes written at address 0x%8.8" PRIx32 "", | |||
buf_cnt, image.sections[i].base_address); | |||
buf_cnt, image.sections[i].base_address); | |||
free(buffer); | |||
} | |||
@@ -191,7 +182,7 @@ static int loadDriver(struct ecosflash_flash_bank *info) | |||
return ERROR_OK; | |||
} | |||
static int const OFFSET_ERASE = 0x0; | |||
static int const OFFSET_ERASE; | |||
static int const OFFSET_ERASE_SIZE = 0x8; | |||
static int const OFFSET_FLASH = 0xc; | |||
static int const OFFSET_FLASH_SIZE = 0x8; | |||
@@ -199,10 +190,10 @@ static int const OFFSET_GET_WORKAREA = 0x18; | |||
static int const OFFSET_GET_WORKAREA_SIZE = 0x4; | |||
static int runCode(struct ecosflash_flash_bank *info, | |||
uint32_t codeStart, uint32_t codeStop, uint32_t r0, uint32_t r1, uint32_t r2, | |||
uint32_t *result, | |||
/* timeout in ms */ | |||
int timeout) | |||
uint32_t codeStart, uint32_t codeStop, uint32_t r0, uint32_t r1, uint32_t r2, | |||
uint32_t *result, | |||
/* timeout in ms */ | |||
int timeout) | |||
{ | |||
struct target *target = info->target; | |||
@@ -220,12 +211,9 @@ static int runCode(struct ecosflash_flash_bank *info, | |||
buf_set_u32(reg_params[1].value, 0, 32, r1); | |||
buf_set_u32(reg_params[2].value, 0, 32, r2); | |||
int retval; | |||
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, | |||
codeStart, | |||
codeStop, timeout, | |||
&armv4_5_info)) != ERROR_OK) | |||
{ | |||
int retval = target_run_algorithm(target, 0, NULL, 3, reg_params, | |||
codeStart, codeStop, timeout, &armv4_5_info); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error executing eCos flash algorithm"); | |||
return retval; | |||
} | |||
@@ -242,7 +230,7 @@ static int runCode(struct ecosflash_flash_bank *info, | |||
static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address, uint32_t len) | |||
{ | |||
int retval; | |||
int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/ | |||
int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/ | |||
retval = loadDriver(info); | |||
if (retval != ERROR_OK) | |||
@@ -257,12 +245,11 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address, | |||
0, | |||
&flashErr, | |||
timeout | |||
); | |||
); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (flashErr != 0x0) | |||
{ | |||
if (flashErr != 0x0) { | |||
LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr)); | |||
return ERROR_FAIL; | |||
} | |||
@@ -270,12 +257,15 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address, | |||
return ERROR_OK; | |||
} | |||
static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32_t address, uint32_t len) | |||
static int eCosBoard_flash(struct ecosflash_flash_bank *info, | |||
void *data, | |||
uint32_t address, | |||
uint32_t len) | |||
{ | |||
struct target *target = info->target; | |||
const int chunk = 8192; | |||
int retval = ERROR_OK; | |||
int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/ | |||
int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/ | |||
retval = loadDriver(info); | |||
if (retval != ERROR_OK) | |||
@@ -295,13 +285,10 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32 | |||
uint32_t i; | |||
for (i = 0; i < len; i += chunk) | |||
{ | |||
for (i = 0; i < len; i += chunk) { | |||
int t = len-i; | |||
if (t > chunk) | |||
{ | |||
t = chunk; | |||
} | |||
retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i); | |||
if (retval != ERROR_OK) | |||
@@ -319,9 +306,9 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32 | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (flashErr != 0x0) | |||
{ | |||
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr)); | |||
if (flashErr != 0x0) { | |||
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr, | |||
flash_errmsg(flashErr)); | |||
return ERROR_FAIL; | |||
} | |||
} | |||
@@ -339,19 +326,12 @@ static void command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) | |||
struct ecosflash_flash_bank *info = bank->driver_priv; | |||
int i; | |||
if (info->target->endianness == TARGET_LITTLE_ENDIAN) | |||
{ | |||
if (info->target->endianness == TARGET_LITTLE_ENDIAN) { | |||
for (i = bank->bus_width; i > 0; i--) | |||
{ | |||
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
for (i = 1; i <= bank->bus_width; i++) | |||
{ | |||
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd; | |||
} | |||
} | |||
} | |||
#endif | |||
@@ -360,8 +340,7 @@ static void command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) | |||
static uint32_t ecosflash_address(struct flash_bank *bank, uint32_t address) | |||
{ | |||
uint32_t retval = 0; | |||
switch (bank->bus_width) | |||
{ | |||
switch (bank->bus_width) { | |||
case 4: | |||
retval = address & 0xfffffffc; | |||
case 2: | |||
@@ -386,7 +365,8 @@ static int ecosflash_protect(struct flash_bank *bank, int set, int first, int la | |||
return ERROR_OK; | |||
} | |||
static int ecosflash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) | |||
static int ecosflash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
uint32_t count) | |||
{ | |||
struct ecosflash_flash_bank *info = bank->driver_priv; | |||
struct flash_bank *c = bank; | |||
@@ -411,7 +391,7 @@ static uint32_t ecosflash_get_flash_status(struct flash_bank *bank) | |||
return ERROR_OK; | |||
} | |||
static void ecosflash_set_flash_mode(struct flash_bank *bank,int mode) | |||
static void ecosflash_set_flash_mode(struct flash_bank *bank, int mode) | |||
{ | |||
} | |||
@@ -421,7 +401,10 @@ static uint32_t ecosflash_wait_status_busy(struct flash_bank *bank, uint32_t wai | |||
return ERROR_OK; | |||
} | |||
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc) | |||
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, | |||
char *cmd, | |||
char **args, | |||
int argc) | |||
{ | |||
return ERROR_OK; | |||
} | |||
@@ -7,7 +7,7 @@ | |||
* | |||
* Copyright (C) 2011 by Erik Botö | |||
* erik.boto@pelagicore.com | |||
* | |||
* | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
@@ -23,6 +23,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -34,60 +35,58 @@ | |||
/* em357 register locations */ | |||
#define EM357_FLASH_ACR 0x40008000 | |||
#define EM357_FLASH_KEYR 0x40008004 | |||
#define EM357_FLASH_OPTKEYR 0x40008008 | |||
#define EM357_FLASH_SR 0x4000800C | |||
#define EM357_FLASH_CR 0x40008010 | |||
#define EM357_FLASH_AR 0x40008014 | |||
#define EM357_FLASH_OBR 0x4000801C | |||
#define EM357_FLASH_WRPR 0x40008020 | |||
#define EM357_FLASH_ACR 0x40008000 | |||
#define EM357_FLASH_KEYR 0x40008004 | |||
#define EM357_FLASH_OPTKEYR 0x40008008 | |||
#define EM357_FLASH_SR 0x4000800C | |||
#define EM357_FLASH_CR 0x40008010 | |||
#define EM357_FLASH_AR 0x40008014 | |||
#define EM357_FLASH_OBR 0x4000801C | |||
#define EM357_FLASH_WRPR 0x40008020 | |||
#define EM357_FPEC_CLK 0x4000402c | |||
#define EM357_FPEC_CLK 0x4000402c | |||
/* option byte location */ | |||
#define EM357_OB_RDP 0x08040800 | |||
#define EM357_OB_WRP0 0x08040808 | |||
#define EM357_OB_WRP1 0x0804080A | |||
#define EM357_OB_WRP2 0x0804080C | |||
#define EM357_OB_RDP 0x08040800 | |||
#define EM357_OB_WRP0 0x08040808 | |||
#define EM357_OB_WRP1 0x0804080A | |||
#define EM357_OB_WRP2 0x0804080C | |||
/* FLASH_CR register bits */ | |||
#define FLASH_PG (1 << 0) | |||
#define FLASH_PER (1 << 1) | |||
#define FLASH_MER (1 << 2) | |||
#define FLASH_OPTPG (1 << 4) | |||
#define FLASH_OPTER (1 << 5) | |||
#define FLASH_STRT (1 << 6) | |||
#define FLASH_LOCK (1 << 7) | |||
#define FLASH_OPTWRE (1 << 9) | |||
#define FLASH_PG (1 << 0) | |||
#define FLASH_PER (1 << 1) | |||
#define FLASH_MER (1 << 2) | |||
#define FLASH_OPTPG (1 << 4) | |||
#define FLASH_OPTER (1 << 5) | |||
#define FLASH_STRT (1 << 6) | |||
#define FLASH_LOCK (1 << 7) | |||
#define FLASH_OPTWRE (1 << 9) | |||
/* FLASH_SR register bits */ | |||
#define FLASH_BSY (1 << 0) | |||
#define FLASH_PGERR (1 << 2) | |||
#define FLASH_WRPRTERR (1 << 4) | |||
#define FLASH_EOP (1 << 5) | |||
#define FLASH_BSY (1 << 0) | |||
#define FLASH_PGERR (1 << 2) | |||
#define FLASH_WRPRTERR (1 << 4) | |||
#define FLASH_EOP (1 << 5) | |||
/* EM357_FLASH_OBR bit definitions (reading) */ | |||
#define OPT_ERROR 0 | |||
#define OPT_READOUT 1 | |||
#define OPT_ERROR 0 | |||
#define OPT_READOUT 1 | |||
/* register unlock keys */ | |||
#define KEY1 0x45670123 | |||
#define KEY2 0xCDEF89AB | |||
#define KEY1 0x45670123 | |||
#define KEY2 0xCDEF89AB | |||
struct em357_options | |||
{ | |||
struct em357_options { | |||
uint16_t RDP; | |||
uint16_t user_options; | |||
uint16_t protection[3]; | |||
}; | |||
struct em357_flash_bank | |||
{ | |||
struct em357_flash_bank { | |||
struct em357_options option_bytes; | |||
struct working_area *write_algorithm; | |||
int ppage_size; | |||
@@ -103,9 +102,7 @@ FLASH_BANK_COMMAND_HANDLER(em357_flash_bank_command) | |||
struct em357_flash_bank *em357_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
em357_info = malloc(sizeof(struct em357_flash_bank)); | |||
bank->driver_priv = em357_info; | |||
@@ -129,37 +126,32 @@ static int em357_wait_status_busy(struct flash_bank *bank, int timeout) | |||
int retval = ERROR_OK; | |||
/* wait for busy to clear */ | |||
for (;;) | |||
{ | |||
for (;; ) { | |||
retval = em357_get_flash_status(bank, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
LOG_DEBUG("status: 0x%" PRIx32 "", status); | |||
if ((status & FLASH_BSY) == 0) | |||
break; | |||
if (timeout-- <= 0) | |||
{ | |||
if (timeout-- <= 0) { | |||
LOG_ERROR("timed out waiting for flash"); | |||
return ERROR_FAIL; | |||
} | |||
alive_sleep(1); | |||
} | |||
if (status & FLASH_WRPRTERR) | |||
{ | |||
if (status & FLASH_WRPRTERR) { | |||
LOG_ERROR("em357 device protected"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (status & FLASH_PGERR) | |||
{ | |||
if (status & FLASH_PGERR) { | |||
LOG_ERROR("em357 device programming failed"); | |||
retval = ERROR_FAIL; | |||
} | |||
/* Clear but report errors */ | |||
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) | |||
{ | |||
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) { | |||
/* If this operation fails, we ignore it and report the original | |||
* retval | |||
*/ | |||
@@ -330,8 +322,7 @@ static int em357_protect_check(struct flash_bank *bank) | |||
int num_bits; | |||
int set; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -344,8 +335,7 @@ static int em357_protect_check(struct flash_bank *bank) | |||
/* each protection bit is for 4 * 2K pages */ | |||
num_bits = (bank->num_sectors / em357_info->ppage_size); | |||
for (i = 0; i < num_bits; i++) | |||
{ | |||
for (i = 0; i < num_bits; i++) { | |||
set = 1; | |||
if (protection & (1 << i)) | |||
set = 0; | |||
@@ -362,16 +352,13 @@ static int em357_erase(struct flash_bank *bank, int first, int last) | |||
struct target *target = bank->target; | |||
int i; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((first == 0) && (last == (bank->num_sectors - 1))) | |||
{ | |||
return em357_mass_erase(bank); | |||
} | |||
/* unlock flash registers */ | |||
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); | |||
@@ -381,8 +368,7 @@ static int em357_erase(struct flash_bank *bank, int first, int last) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
@@ -419,22 +405,19 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last) | |||
em357_info = bank->driver_priv; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((first % em357_info->ppage_size) != 0) | |||
{ | |||
if ((first % em357_info->ppage_size) != 0) { | |||
LOG_WARNING("aligned start protect sector to a %d sector boundary", | |||
em357_info->ppage_size); | |||
em357_info->ppage_size); | |||
first = first - (first % em357_info->ppage_size); | |||
} | |||
if (((last + 1) % em357_info->ppage_size) != 0) | |||
{ | |||
if (((last + 1) % em357_info->ppage_size) != 0) { | |||
LOG_WARNING("aligned end protect sector to a %d sector boundary", | |||
em357_info->ppage_size); | |||
em357_info->ppage_size); | |||
last++; | |||
last = last - (last % em357_info->ppage_size); | |||
last--; | |||
@@ -449,8 +432,7 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last) | |||
prot_reg[1] = (uint16_t)(protection >> 8); | |||
prot_reg[2] = (uint16_t)(protection >> 16); | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
reg = (i / em357_info->ppage_size) / 8; | |||
bit = (i / em357_info->ppage_size) - (reg * 8); | |||
@@ -461,7 +443,8 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last) | |||
prot_reg[reg] |= (1 << bit); | |||
} | |||
if ((status = em357_erase_options(bank)) != ERROR_OK) | |||
status = em357_erase_options(bank); | |||
if (retval != ERROR_OK) | |||
return status; | |||
em357_info->option_bytes.protection[0] = prot_reg[0]; | |||
@@ -472,7 +455,7 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last) | |||
} | |||
static int em357_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t offset, uint32_t count) | |||
uint32_t offset, uint32_t count) | |||
{ | |||
struct em357_flash_bank *em357_info = bank->driver_priv; | |||
struct target *target = bank->target; | |||
@@ -483,61 +466,63 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
struct armv7m_algorithm armv7m_info; | |||
int retval = ERROR_OK; | |||
/* see contib/loaders/flash/stm32x.s for src, the same is used here except for | |||
/* see contib/loaders/flash/stm32x.s for src, the same is used here except for | |||
* a modified *_FLASH_BASE */ | |||
static const uint8_t em357_flash_write_code[] = { | |||
/* #define EM357_FLASH_CR_OFFSET 0x10 */ | |||
/* #define EM357_FLASH_SR_OFFSET 0x0C */ | |||
/* write: */ | |||
/* #define EM357_FLASH_CR_OFFSET 0x10 | |||
* #define EM357_FLASH_SR_OFFSET 0x0C | |||
* write: */ | |||
0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */ | |||
0x1c, 0x44, /* add r4, r3 */ | |||
/* write_half_word: */ | |||
/* write_half_word: */ | |||
0x01, 0x23, /* movs r3, #0x01 */ | |||
0x23, 0x61, /* str r3, [r4, #EM357_FLASH_CR_OFFSET] */ | |||
0x23, 0x61, /* str r3, [r4, | |||
*#EM357_FLASH_CR_OFFSET] */ | |||
0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */ | |||
0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */ | |||
/* busy: */ | |||
0xe3, 0x68, /* ldr r3, [r4, #EM357_FLASH_SR_OFFSET] */ | |||
/* busy: */ | |||
0xe3, 0x68, /* ldr r3, [r4, | |||
*#EM357_FLASH_SR_OFFSET] */ | |||
0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */ | |||
0xfb, 0xd0, /* beq busy */ | |||
0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */ | |||
0x01, 0xd1, /* bne exit */ | |||
0x01, 0x3a, /* subs r2, r2, #0x01 */ | |||
0xf0, 0xd1, /* bne write_half_word */ | |||
/* exit: */ | |||
/* exit: */ | |||
0x00, 0xbe, /* bkpt #0x00 */ | |||
0x00, 0x80, 0x00, 0x40, /* EM357_FLASH_BASE: .word 0x40008000 */ | |||
}; | |||
/* flash write code */ | |||
if (target_alloc_working_area(target, sizeof(em357_flash_write_code), | |||
&em357_info->write_algorithm) != ERROR_OK) | |||
{ | |||
&em357_info->write_algorithm) != ERROR_OK) { | |||
LOG_WARNING("no working area available, can't do block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
} | |||
; | |||
if ((retval = target_write_buffer(target, em357_info->write_algorithm->address, | |||
sizeof(em357_flash_write_code), | |||
(uint8_t*)em357_flash_write_code)) != ERROR_OK) | |||
retval = target_write_buffer(target, em357_info->write_algorithm->address, | |||
sizeof(em357_flash_write_code), (uint8_t *)em357_flash_write_code); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
if (buffer_size <= 256) | |||
{ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a | |||
* buffer, free the algorithm */ | |||
if (em357_info->write_algorithm) | |||
target_free_working_area(target, em357_info->write_algorithm); | |||
LOG_WARNING("no large enough working area available, can't do block memory writes"); | |||
LOG_WARNING( | |||
"no large enough working area available, can't do block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
} | |||
}; | |||
} | |||
; | |||
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; | |||
armv7m_info.core_mode = ARMV7M_MODE_ANY; | |||
@@ -547,13 +532,12 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
init_reg_param(®_params[2], "r2", 32, PARAM_OUT); | |||
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT); | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
uint32_t thisrun_count = (count > (buffer_size / 2)) ? | |||
(buffer_size / 2) : count; | |||
(buffer_size / 2) : count; | |||
if ((retval = target_write_buffer(target, source->address, | |||
thisrun_count * 2, buffer)) != ERROR_OK) | |||
retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer); | |||
if (retval != ERROR_OK) | |||
break; | |||
buf_set_u32(reg_params[0].value, 0, 32, source->address); | |||
@@ -561,17 +545,14 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); | |||
buf_set_u32(reg_params[3].value, 0, 32, 0); | |||
if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, | |||
em357_info->write_algorithm->address, | |||
0, | |||
10000, &armv7m_info)) != ERROR_OK) | |||
{ | |||
retval = target_run_algorithm(target, 0, NULL, 4, reg_params, | |||
em357_info->write_algorithm->address, 0, 10000, &armv7m_info); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error executing em357 flash write algorithm"); | |||
break; | |||
} | |||
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR) | |||
{ | |||
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR) { | |||
LOG_ERROR("flash memory not erased before writing"); | |||
/* Clear but report errors */ | |||
target_write_u32(target, EM357_FLASH_SR, FLASH_PGERR); | |||
@@ -579,8 +560,7 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
break; | |||
} | |||
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR) | |||
{ | |||
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR) { | |||
LOG_ERROR("flash memory write protected"); | |||
/* Clear but report errors */ | |||
target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR); | |||
@@ -605,7 +585,7 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
} | |||
static int em357_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t offset, uint32_t count) | |||
uint32_t offset, uint32_t count) | |||
{ | |||
struct target *target = bank->target; | |||
uint32_t words_remaining = (count / 2); | |||
@@ -614,14 +594,12 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t bytes_written = 0; | |||
int retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (offset & 0x1) | |||
{ | |||
if (offset & 0x1) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -635,20 +613,17 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer, | |||
return retval; | |||
/* multiple half words (2-byte) to be programmed? */ | |||
if (words_remaining > 0) | |||
{ | |||
if (words_remaining > 0) { | |||
/* try using a block write */ | |||
if ((retval = em357_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
retval = em357_write_block(bank, buffer, offset, words_remaining); | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
/* if block write failed (no sufficient working area), | |||
* we use normal (slow) single dword accesses */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
LOG_WARNING( | |||
"couldn't use block writes, falling back to single memory accesses"); | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
buffer += words_remaining * 2; | |||
address += words_remaining * 2; | |||
words_remaining = 0; | |||
@@ -658,8 +633,7 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer, | |||
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)) | |||
return retval; | |||
while (words_remaining > 0) | |||
{ | |||
while (words_remaining > 0) { | |||
uint16_t value; | |||
memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); | |||
@@ -679,8 +653,7 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer, | |||
address += 2; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint16_t value = 0xffff; | |||
memcpy(&value, buffer + bytes_written, bytes_remaining); | |||
@@ -721,8 +694,7 @@ static int em357_probe(struct flash_bank *bank) | |||
LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024); | |||
if (bank->sectors) | |||
{ | |||
if (bank->sectors) { | |||
free(bank->sectors); | |||
bank->sectors = NULL; | |||
} | |||
@@ -732,8 +704,7 @@ static int em357_probe(struct flash_bank *bank) | |||
bank->num_sectors = num_pages; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); | |||
for (i = 0; i < num_pages; i++) | |||
{ | |||
for (i = 0; i < num_pages; i++) { | |||
bank->sectors[i].offset = i * page_size; | |||
bank->sectors[i].size = page_size; | |||
bank->sectors[i].is_erased = -1; | |||
@@ -766,9 +737,7 @@ COMMAND_HANDLER(em357_handle_lock_command) | |||
struct em357_flash_bank *em357_info = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -779,14 +748,12 @@ COMMAND_HANDLER(em357_handle_lock_command) | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (em357_erase_options(bank) != ERROR_OK) | |||
{ | |||
if (em357_erase_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "em357 failed to erase options"); | |||
return ERROR_OK; | |||
} | |||
@@ -794,8 +761,7 @@ COMMAND_HANDLER(em357_handle_lock_command) | |||
/* set readout protection */ | |||
em357_info->option_bytes.RDP = 0; | |||
if (em357_write_options(bank) != ERROR_OK) | |||
{ | |||
if (em357_write_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "em357 failed to lock device"); | |||
return ERROR_OK; | |||
} | |||
@@ -810,9 +776,7 @@ COMMAND_HANDLER(em357_handle_unlock_command) | |||
struct target *target = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -821,27 +785,24 @@ COMMAND_HANDLER(em357_handle_unlock_command) | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (em357_erase_options(bank) != ERROR_OK) | |||
{ | |||
if (em357_erase_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "em357 failed to unlock device"); | |||
return ERROR_OK; | |||
} | |||
if (em357_write_options(bank) != ERROR_OK) | |||
{ | |||
if (em357_write_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "em357 failed to lock device"); | |||
return ERROR_OK; | |||
} | |||
command_print(CMD_CTX, "em357 unlocked.\n" | |||
"INFO: a reset or power cycle is required " | |||
"for the new settings to take effect."); | |||
"INFO: a reset or power cycle is required " | |||
"for the new settings to take effect."); | |||
return ERROR_OK; | |||
} | |||
@@ -850,8 +811,7 @@ static int em357_mass_erase(struct flash_bank *bank) | |||
{ | |||
struct target *target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -888,9 +848,7 @@ COMMAND_HANDLER(em357_handle_mass_erase_command) | |||
int i; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -898,20 +856,14 @@ COMMAND_HANDLER(em357_handle_mass_erase_command) | |||
return retval; | |||
retval = em357_mass_erase(bank); | |||
if (retval == ERROR_OK) | |||
{ | |||
if (retval == ERROR_OK) { | |||
/* set all sectors as erased */ | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
bank->sectors[i].is_erased = 1; | |||
} | |||
command_print(CMD_CTX, "em357 mass erase complete"); | |||
} | |||
else | |||
{ | |||
} else | |||
command_print(CMD_CTX, "em357 mass erase failed"); | |||
} | |||
return retval; | |||
} | |||
@@ -17,6 +17,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -25,9 +26,7 @@ | |||
#include <target/image.h> | |||
#include "hello.h" | |||
struct faux_flash_bank | |||
{ | |||
struct faux_flash_bank { | |||
struct target *target; | |||
uint8_t *memory; | |||
uint32_t start_address; | |||
@@ -43,19 +42,15 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command) | |||
struct faux_flash_bank *info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
info = malloc(sizeof(struct faux_flash_bank)); | |||
if (info == NULL) | |||
{ | |||
if (info == NULL) { | |||
LOG_ERROR("no memory for flash bank info"); | |||
return ERROR_FAIL; | |||
} | |||
info->memory = malloc(bank->size); | |||
if (info == NULL) | |||
{ | |||
if (info == NULL) { | |||
free(info); | |||
LOG_ERROR("no memory for flash bank info"); | |||
return ERROR_FAIL; | |||
@@ -67,8 +62,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command) | |||
uint32_t offset = 0; | |||
bank->num_sectors = bank->size/sectorSize; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = sectorSize; | |||
offset += bank->sectors[i].size; | |||
@@ -77,8 +71,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command) | |||
} | |||
info->target = get_target(CMD_ARGV[5]); | |||
if (info->target == NULL) | |||
{ | |||
if (info->target == NULL) { | |||
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); | |||
free(info->memory); | |||
free(info); | |||
@@ -96,7 +89,7 @@ static int faux_erase(struct flash_bank *bank, int first, int last) | |||
static int faux_protect(struct flash_bank *bank, int set, int first, int last) | |||
{ | |||
LOG_USER("set protection sector %d to %d to %s", first, last, set?"on":"off"); | |||
LOG_USER("set protection sector %d to %d to %s", first, last, set ? "on" : "off"); | |||
return ERROR_OK; | |||
} | |||
@@ -31,8 +31,7 @@ | |||
#define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */ | |||
#define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */ | |||
enum fm3_variant | |||
{ | |||
enum fm3_variant { | |||
mb9bfxx1, /* Flash Type '1' */ | |||
mb9bfxx2, | |||
mb9bfxx3, | |||
@@ -47,15 +46,13 @@ enum fm3_variant | |||
mb9afxx6 | |||
}; | |||
enum fm3_flash_type | |||
{ | |||
enum fm3_flash_type { | |||
fm3_no_flash_type = 0, | |||
fm3_flash_type1 = 1, | |||
fm3_flash_type2 = 2 | |||
}; | |||
struct fm3_flash_bank | |||
{ | |||
struct fm3_flash_bank { | |||
struct working_area *write_algorithm; | |||
enum fm3_variant variant; | |||
enum fm3_flash_type flashtype; | |||
@@ -16,13 +16,14 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef FLASH_NOR_IMP_H | |||
#define FLASH_NOR_IMP_H | |||
// this is an internal header | |||
/* this is an internal header */ | |||
#include "core.h" | |||
#include "driver.h" | |||
// almost all drivers will need this file | |||
/* almost all drivers will need this file */ | |||
#include <target/target.h> | |||
/** | |||
@@ -47,4 +48,4 @@ int flash_driver_read(struct flash_bank *bank, | |||
int flash_write_unlock(struct target *target, struct image *image, | |||
uint32_t *written, int erase, bool unlock); | |||
#endif // FLASH_NOR_IMP_H | |||
#endif /* FLASH_NOR_IMP_H */ |
@@ -20,6 +20,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -32,12 +33,12 @@ struct kinetis_flash_bank { | |||
}; | |||
static int kinetis_get_master_bank(struct flash_bank *bank, | |||
struct flash_bank **master_bank) | |||
struct flash_bank **master_bank) | |||
{ | |||
*master_bank = get_flash_bank_by_name_noprobe(bank->name); | |||
if (*master_bank == NULL) { | |||
LOG_ERROR("master flash bank '%s' does not exist", | |||
(char *)bank->driver_priv); | |||
(char *)bank->driver_priv); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -51,9 +52,8 @@ static int kinetis_update_bank_info(struct flash_bank *bank) | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
/* update the info we do not have */ | |||
bank->size = master_bank->size; | |||
@@ -69,9 +69,8 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) | |||
{ | |||
struct kinetis_flash_bank *bank_info; | |||
if (CMD_ARGC < 6) { | |||
if (CMD_ARGC < 6) | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
LOG_INFO("add flash_bank kinetis %s", bank->name); | |||
@@ -85,16 +84,15 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) | |||
} | |||
static int kinetis_protect(struct flash_bank *bank, int set, int first, | |||
int last) | |||
int last) | |||
{ | |||
int result; | |||
struct flash_bank *master_bank; | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
LOG_WARNING("kinetis_protect not supported yet"); | |||
@@ -121,16 +119,14 @@ static int kinetis_protect_check(struct flash_bank *bank) | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
/* read protection register FTFL_FPROT */ | |||
result = target_read_memory(bank->target, 0x40020010, 1, 4, buffer); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
fprot = target_buffer_get_u32(bank->target, buffer); | |||
@@ -157,7 +153,7 @@ static int kinetis_protect_check(struct flash_bank *bank) | |||
} | |||
static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0, | |||
uint32_t w1, uint32_t w2) | |||
uint32_t w1, uint32_t w2) | |||
{ | |||
uint8_t buffer[12]; | |||
int result, i; | |||
@@ -165,11 +161,10 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0, | |||
/* wait for done */ | |||
for (i = 0; i < 50; i++) { | |||
result = | |||
target_read_memory(bank->target, 0x40020000, 1, 1, buffer); | |||
target_read_memory(bank->target, 0x40020000, 1, 1, buffer); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
if (buffer[0] & 0x80) | |||
break; | |||
@@ -181,10 +176,9 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0, | |||
/* reset error flags */ | |||
buffer[0] = 0x30; | |||
result = | |||
target_write_memory(bank->target, 0x40020000, 1, 1, buffer); | |||
if (result != ERROR_OK) { | |||
target_write_memory(bank->target, 0x40020000, 1, 1, buffer); | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
} | |||
target_buffer_set_u32(bank->target, buffer, w0); | |||
@@ -193,25 +187,22 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0, | |||
result = target_write_memory(bank->target, 0x40020004, 4, 3, buffer); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
/* start command */ | |||
buffer[0] = 0x80; | |||
result = target_write_memory(bank->target, 0x40020000, 1, 1, buffer); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
/* wait for done */ | |||
for (i = 0; i < 50; i++) { | |||
result = | |||
target_read_memory(bank->target, 0x40020000, 1, 1, buffer); | |||
target_read_memory(bank->target, 0x40020000, 1, 1, buffer); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
if (buffer[0] & 0x80) | |||
break; | |||
@@ -221,8 +212,8 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0, | |||
if (buffer[0] != 0x80) { | |||
LOG_ERROR | |||
("ftfl command failed FSTAT: %02X W0: %08X W1: %08X W2: %08X", | |||
buffer[0], w0, w1, w2); | |||
("ftfl command failed FSTAT: %02X W0: %08X W1: %08X W2: %08X", | |||
buffer[0], w0, w1, w2); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -243,13 +234,11 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
if ((first > bank->num_sectors) || (last > bank->num_sectors)) { | |||
if ((first > bank->num_sectors) || (last > bank->num_sectors)) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
for (i = first; i <= last; i++) { | |||
/* set command and sector address */ | |||
@@ -267,20 +256,20 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) | |||
if (first == 0) { | |||
LOG_WARNING | |||
("flash configuration field erased, please reset the device"); | |||
("flash configuration field erased, please reset the device"); | |||
} | |||
return ERROR_OK; | |||
} | |||
static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, | |||
uint32_t offset, uint32_t count) | |||
static int kinetis_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t offset, uint32_t count) | |||
{ | |||
struct flash_bank *master_bank; | |||
unsigned int i, result, fallback = 0, nvm = 0; | |||
uint8_t buf[8]; | |||
uint32_t wc, w0 = 0, w1 = 0, w2 = 0; | |||
struct kinetis_flash_bank * kbank = (struct kinetis_flash_bank *) | |||
struct kinetis_flash_bank *kbank = (struct kinetis_flash_bank *) | |||
bank->driver_priv; | |||
if (bank->target->state != TARGET_HALTED) { | |||
@@ -290,9 +279,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
if (offset >= kbank->nvm_start) | |||
nvm = 1; | |||
@@ -327,8 +315,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, | |||
/* fallback to longword write */ | |||
fallback = 1; | |||
LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", | |||
buf[0]); | |||
LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", | |||
buf[0]); | |||
} | |||
} else { | |||
LOG_DEBUG("flash write into PFLASH @08%X", offset); | |||
@@ -347,12 +335,12 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, | |||
} | |||
LOG_DEBUG("write section @ %08X with length %d", | |||
offset + i, wc * 4); | |||
offset + i, wc * 4); | |||
/* write data to flexram */ | |||
result = | |||
target_write_memory(bank->target, 0x14000000, 4, wc, | |||
buffer + i); | |||
target_write_memory(bank->target, 0x14000000, 4, wc, | |||
buffer + i); | |||
if (result != ERROR_OK) { | |||
LOG_ERROR("target_write_memory failed"); | |||
@@ -366,9 +354,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, | |||
result = kinetis_ftfl_command(bank, w0, w1, w2); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
} | |||
/* program longword command */ | |||
@@ -381,9 +368,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, | |||
result = kinetis_ftfl_command(bank, w0, w1, w2); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
} | |||
@@ -405,97 +391,93 @@ static int kinetis_probe(struct flash_bank *bank) | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
result = target_read_memory(bank->target, 0x40048024, 1, 4, buf); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
sim_sdid = target_buffer_get_u32(bank->target, buf); | |||
result = target_read_memory(bank->target, 0x4004804c, 1, 4, buf); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
sim_fcfg1 = target_buffer_get_u32(bank->target, buf); | |||
result = target_read_memory(bank->target, 0x40048050, 1, 4, buf); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
sim_fcfg2 = target_buffer_get_u32(bank->target, buf); | |||
LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", sim_sdid, sim_fcfg1, | |||
sim_fcfg2); | |||
sim_fcfg2); | |||
switch ((sim_fcfg1 >> 28) & 0x0f) { | |||
case 0x07: | |||
nvm_size = 128 * 1024; | |||
break; | |||
case 0x09: | |||
case 0x0f: | |||
nvm_size = 256 * 1024; | |||
break; | |||
default: | |||
nvm_size = 0; | |||
break; | |||
case 0x07: | |||
nvm_size = 128 * 1024; | |||
break; | |||
case 0x09: | |||
case 0x0f: | |||
nvm_size = 256 * 1024; | |||
break; | |||
default: | |||
nvm_size = 0; | |||
break; | |||
} | |||
switch ((sim_fcfg1 >> 24) & 0x0f) { | |||
case 0x07: | |||
pf_size = 128 * 1024; | |||
break; | |||
case 0x09: | |||
pf_size = 256 * 1024; | |||
break; | |||
case 0x0b: | |||
case 0x0f: | |||
pf_size = 512 * 1024; | |||
break; | |||
default: | |||
pf_size = 0; | |||
break; | |||
case 0x07: | |||
pf_size = 128 * 1024; | |||
break; | |||
case 0x09: | |||
pf_size = 256 * 1024; | |||
break; | |||
case 0x0b: | |||
case 0x0f: | |||
pf_size = 512 * 1024; | |||
break; | |||
default: | |||
pf_size = 0; | |||
break; | |||
} | |||
switch ((sim_fcfg1 >> 16) & 0x0f) { | |||
case 0x02: | |||
ee_size = 4 * 1024; | |||
break; | |||
case 0x03: | |||
ee_size = 2 * 1024; | |||
break; | |||
case 0x04: | |||
ee_size = 1 * 1024; | |||
break; | |||
case 0x05: | |||
ee_size = 512; | |||
break; | |||
case 0x06: | |||
ee_size = 256; | |||
break; | |||
case 0x07: | |||
ee_size = 128; | |||
break; | |||
case 0x08: | |||
ee_size = 64; | |||
break; | |||
case 0x09: | |||
ee_size = 32; | |||
break; | |||
default: | |||
ee_size = 0; | |||
break; | |||
case 0x02: | |||
ee_size = 4 * 1024; | |||
break; | |||
case 0x03: | |||
ee_size = 2 * 1024; | |||
break; | |||
case 0x04: | |||
ee_size = 1 * 1024; | |||
break; | |||
case 0x05: | |||
ee_size = 512; | |||
break; | |||
case 0x06: | |||
ee_size = 256; | |||
break; | |||
case 0x07: | |||
ee_size = 128; | |||
break; | |||
case 0x08: | |||
ee_size = 64; | |||
break; | |||
case 0x09: | |||
ee_size = 32; | |||
break; | |||
default: | |||
ee_size = 0; | |||
break; | |||
} | |||
((struct kinetis_flash_bank *) bank->driver_priv)->nvm_start = | |||
pf_size - nvm_size; | |||
LOG_DEBUG("NVM: %d PF: %d EE: %d BL1: %d", nvm_size, pf_size, ee_size, | |||
(sim_fcfg2 >> 23) & 1); | |||
(sim_fcfg2 >> 23) & 1); | |||
if (pf_size != bank->size) { | |||
LOG_WARNING("flash size is different %d != %d", pf_size, | |||
bank->size); | |||
bank->size); | |||
} | |||
bank->num_sectors = bank->size / (2 * 1024); | |||
@@ -526,13 +508,12 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size) | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
snprintf(buf, buf_size, | |||
"%s driver for flash bank %s at 0x%8.8" PRIx32 "", | |||
bank->driver->name, master_bank->name, master_bank->base); | |||
"%s driver for flash bank %s at 0x%8.8" PRIx32 "", | |||
bank->driver->name, master_bank->name, master_bank->base); | |||
return ERROR_OK; | |||
} | |||
@@ -551,15 +532,14 @@ static int kinetis_blank_check(struct flash_bank *bank) | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
return ERROR_OK; | |||
} | |||
static int kinetis_flash_read(struct flash_bank *bank, | |||
uint8_t * buffer, uint32_t offset, uint32_t count) | |||
uint8_t *buffer, uint32_t offset, uint32_t count) | |||
{ | |||
int result; | |||
struct flash_bank *master_bank; | |||
@@ -573,9 +553,8 @@ static int kinetis_flash_read(struct flash_bank *bank, | |||
result = kinetis_get_master_bank(bank, &master_bank); | |||
if (result != ERROR_OK) { | |||
if (result != ERROR_OK) | |||
return result; | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -61,15 +61,13 @@ | |||
* - 176x (tested with LPC1768) | |||
*/ | |||
typedef enum | |||
{ | |||
typedef enum { | |||
lpc2000_v1, | |||
lpc2000_v2, | |||
lpc1700 | |||
} lpc2000_variant; | |||
struct lpc2000_flash_bank | |||
{ | |||
struct lpc2000_flash_bank { | |||
lpc2000_variant variant; | |||
struct working_area *iap_working_area; | |||
uint32_t cclk; | |||
@@ -81,8 +79,7 @@ struct lpc2000_flash_bank | |||
int checksum_vector; | |||
}; | |||
enum lpc2000_status_codes | |||
{ | |||
enum lpc2000_status_codes { | |||
LPC2000_CMD_SUCCESS = 0, | |||
LPC2000_INVALID_COMMAND = 1, | |||
LPC2000_SRC_ADDR_ERROR = 2, | |||
@@ -114,63 +111,50 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) | |||
/* default to a 4096 write buffer */ | |||
lpc2000_info->cmd51_max_buffer = 4096; | |||
if (lpc2000_info->variant == lpc2000_v1) | |||
{ | |||
if (lpc2000_info->variant == lpc2000_v1) { | |||
/* variant 1 has different layout for 128kb and 256kb flashes */ | |||
if (bank->size == 128 * 1024) | |||
{ | |||
if (bank->size == 128 * 1024) { | |||
bank->num_sectors = 16; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * 16); | |||
for (i = 0; i < 16; i++) | |||
{ | |||
for (i = 0; i < 16; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 8 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
} | |||
else if (bank->size == 256 * 1024) | |||
{ | |||
} else if (bank->size == 256 * 1024) { | |||
bank->num_sectors = 18; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * 18); | |||
for (i = 0; i < 8; i++) | |||
{ | |||
for (i = 0; i < 8; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 8 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
for (i = 8; i < 10; i++) | |||
{ | |||
for (i = 8; i < 10; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 64 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
for (i = 10; i < 18; i++) | |||
{ | |||
for (i = 10; i < 18; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 8 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
LOG_ERROR("BUG: unknown bank->size encountered"); | |||
exit(-1); | |||
} | |||
} | |||
else if (lpc2000_info->variant == lpc2000_v2) | |||
{ | |||
} else if (lpc2000_info->variant == lpc2000_v2) { | |||
/* variant 2 has a uniform layout, only number of sectors differs */ | |||
switch (bank->size) | |||
{ | |||
switch (bank->size) { | |||
case 4 * 1024: | |||
lpc2000_info->cmd51_max_buffer = 1024; | |||
bank->num_sectors = 1; | |||
@@ -209,26 +193,20 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) | |||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
if (i < 8) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
if (i < 8) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 4 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
else if (i < 22) | |||
{ | |||
} else if (i < 22) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 32 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
else if (i < 28) | |||
{ | |||
} else if (i < 28) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 4 * 1024; | |||
offset += bank->sectors[i].size; | |||
@@ -236,11 +214,8 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
} | |||
} | |||
else if (lpc2000_info->variant == lpc1700) | |||
{ | |||
switch(bank->size) | |||
{ | |||
} else if (lpc2000_info->variant == lpc1700) { | |||
switch (bank->size) { | |||
case 32 * 1024: | |||
bank->num_sectors = 8; | |||
break; | |||
@@ -249,7 +224,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) | |||
break; | |||
case 128 * 1024: | |||
bank->num_sectors = 18; | |||
break; | |||
break; | |||
case 256 * 1024: | |||
bank->num_sectors = 22; | |||
break; | |||
@@ -263,18 +238,16 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) | |||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); | |||
for(i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
bank->sectors[i].offset = offset; | |||
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */ | |||
bank->sectors[i].size = (i < 16)? 4 * 1024 : 32 * 1024; | |||
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx | |||
*devices */ | |||
bank->sectors[i].size = (i < 16) ? 4 * 1024 : 32 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
LOG_ERROR("BUG: unknown lpc2000_info->variant encountered"); | |||
exit(-1); | |||
} | |||
@@ -289,38 +262,37 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) | |||
* 0x20 to 0x33: command result table (1+4 words) | |||
* 0x34 to 0xb3: stack (only 128b needed) | |||
*/ | |||
static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_table[5], uint32_t result_table[4]) | |||
static int lpc2000_iap_call(struct flash_bank *bank, | |||
int code, | |||
uint32_t param_table[5], | |||
uint32_t result_table[4]) | |||
{ | |||
int retval; | |||
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; | |||
struct target *target = bank->target; | |||
struct mem_param mem_params[2]; | |||
struct reg_param reg_params[5]; | |||
struct arm_algorithm armv4_5_info; /* for LPC2000 */ | |||
struct armv7m_algorithm armv7m_info; /* for LPC1700 */ | |||
uint32_t status_code; | |||
uint32_t iap_entry_point = 0; /* to make compiler happier */ | |||
struct arm_algorithm armv4_5_info; /* for LPC2000 */ | |||
struct armv7m_algorithm armv7m_info; /* for LPC1700 */ | |||
uint32_t status_code; | |||
uint32_t iap_entry_point = 0; /* to make compiler happier */ | |||
/* regrab previously allocated working_area, or allocate a new one */ | |||
if (!lpc2000_info->iap_working_area) | |||
{ | |||
if (!lpc2000_info->iap_working_area) { | |||
uint8_t jump_gate[8]; | |||
/* make sure we have a working area */ | |||
if (target_alloc_working_area(target, 180, &lpc2000_info->iap_working_area) != ERROR_OK) | |||
{ | |||
if (target_alloc_working_area(target, 180, | |||
&lpc2000_info->iap_working_area) != ERROR_OK) { | |||
LOG_ERROR("no working area specified, can't write LPC2000 internal flash"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* write IAP code to working area */ | |||
switch(lpc2000_info->variant) | |||
{ | |||
switch (lpc2000_info->variant) { | |||
case lpc1700: | |||
target_buffer_set_u32(target, jump_gate, | |||
ARMV4_5_T_BX(12)); | |||
target_buffer_set_u32(target, jump_gate + 4, | |||
ARMV5_T_BKPT(0)); | |||
target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12)); | |||
target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0)); | |||
break; | |||
case lpc2000_v1: | |||
case lpc2000_v2: | |||
@@ -332,15 +304,17 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta | |||
exit(-1); | |||
} | |||
if ((retval = target_write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK) | |||
{ | |||
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", lpc2000_info->iap_working_area->address); | |||
retval = target_write_memory(target, | |||
lpc2000_info->iap_working_area->address, 4, 2, jump_gate); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR( | |||
"Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", | |||
lpc2000_info->iap_working_area->address); | |||
return retval; | |||
} | |||
} | |||
switch(lpc2000_info->variant) | |||
{ | |||
switch (lpc2000_info->variant) { | |||
case lpc1700: | |||
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; | |||
armv7m_info.core_mode = ARMV7M_MODE_ANY; | |||
@@ -359,7 +333,8 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta | |||
} | |||
/* command parameter table */ | |||
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4, PARAM_OUT); | |||
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4, | |||
PARAM_OUT); | |||
target_buffer_set_u32(target, mem_params[0].value, code); | |||
target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]); | |||
target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]); | |||
@@ -371,7 +346,10 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta | |||
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08); | |||
/* command result table */ | |||
init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 5 * 4, PARAM_IN); | |||
init_mem_param(&mem_params[1], | |||
lpc2000_info->iap_working_area->address + 0x20, | |||
5 * 4, | |||
PARAM_IN); | |||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); | |||
buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20); | |||
@@ -380,44 +358,55 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta | |||
init_reg_param(®_params[2], "r12", 32, PARAM_OUT); | |||
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point); | |||
switch(lpc2000_info->variant) | |||
{ | |||
switch (lpc2000_info->variant) { | |||
case lpc1700: | |||
/* IAP stack */ | |||
init_reg_param(®_params[3], "sp", 32, PARAM_OUT); | |||
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4); | |||
buf_set_u32(reg_params[3].value, 0, 32, | |||
lpc2000_info->iap_working_area->address + 0xb4); | |||
/* return address */ | |||
init_reg_param(®_params[4], "lr", 32, PARAM_OUT); | |||
buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */ | |||
buf_set_u32(reg_params[4].value, 0, 32, | |||
(lpc2000_info->iap_working_area->address + 0x04) | 1); | |||
/* bit0 of LR = 1 to return in Thumb mode */ | |||
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info); | |||
target_run_algorithm(target, 2, mem_params, 5, reg_params, | |||
lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info); | |||
break; | |||
case lpc2000_v1: | |||
case lpc2000_v2: | |||
/* IAP stack */ | |||
init_reg_param(®_params[3], "sp_svc", 32, PARAM_OUT); | |||
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4); | |||
buf_set_u32(reg_params[3].value, 0, 32, | |||
lpc2000_info->iap_working_area->address + 0xb4); | |||
/* return address */ | |||
init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT); | |||
buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x04); | |||
buf_set_u32(reg_params[4].value, 0, 32, | |||
lpc2000_info->iap_working_area->address + 0x04); | |||
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv4_5_info); | |||
target_run_algorithm(target, 2, mem_params, 5, reg_params, | |||
lpc2000_info->iap_working_area->address, | |||
lpc2000_info->iap_working_area->address + 0x4, | |||
10000, &armv4_5_info); | |||
break; | |||
default: | |||
LOG_ERROR("BUG: unknown lpc2000->variant encountered"); | |||
exit(-1); | |||
} | |||
status_code = target_buffer_get_u32(target, mem_params[1].value); | |||
status_code = target_buffer_get_u32(target, mem_params[1].value); | |||
result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04); | |||
result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08); | |||
result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c); | |||
result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10); | |||
LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32") completed with result = %8.8" PRIx32, | |||
code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code); | |||
LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32 | |||
", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8" | |||
PRIx32 ") completed with result = %8.8" PRIx32, | |||
code, param_table[0], param_table[1], param_table[2], | |||
param_table[3], param_table[4], status_code); | |||
destroy_mem_param(&mem_params[0]); | |||
destroy_mem_param(&mem_params[1]); | |||
@@ -441,14 +430,12 @@ static int lpc2000_iap_blank_check(struct flash_bank *bank, int first, int last) | |||
if ((first < 0) || (last >= bank->num_sectors)) | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
/* check single sector */ | |||
param_table[0] = param_table[1] = i; | |||
status_code = lpc2000_iap_call(bank, 53, param_table, result_table); | |||
switch (status_code) | |||
{ | |||
switch (status_code) { | |||
case ERROR_FLASH_OPERATION_FAILED: | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
case LPC2000_CMD_SUCCESS: | |||
@@ -480,39 +467,30 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command) | |||
struct lpc2000_flash_bank *lpc2000_info; | |||
if (CMD_ARGC < 8) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
lpc2000_info = malloc(sizeof(struct lpc2000_flash_bank)); | |||
bank->driver_priv = lpc2000_info; | |||
if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0) | |||
{ | |||
if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0) { | |||
lpc2000_info->variant = lpc2000_v1; | |||
lpc2000_info->cmd51_dst_boundary = 512; | |||
lpc2000_info->cmd51_can_256b = 0; | |||
lpc2000_info->cmd51_can_8192b = 1; | |||
lpc2000_info->checksum_vector = 5; | |||
} | |||
else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0) | |||
{ | |||
} else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0) { | |||
lpc2000_info->variant = lpc2000_v2; | |||
lpc2000_info->cmd51_dst_boundary = 256; | |||
lpc2000_info->cmd51_can_256b = 1; | |||
lpc2000_info->cmd51_can_8192b = 0; | |||
lpc2000_info->checksum_vector = 5; | |||
} | |||
else if (strcmp(CMD_ARGV[6], "lpc1700") == 0) | |||
{ | |||
} else if (strcmp(CMD_ARGV[6], "lpc1700") == 0) { | |||
lpc2000_info->variant = lpc1700; | |||
lpc2000_info->cmd51_dst_boundary = 256; | |||
lpc2000_info->cmd51_can_256b = 1; | |||
lpc2000_info->cmd51_can_8192b = 0; | |||
lpc2000_info->checksum_vector = 7; | |||
} | |||
else | |||
{ | |||
} else { | |||
LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]); | |||
free(lpc2000_info); | |||
return ERROR_FLASH_BANK_INVALID; | |||
@@ -523,8 +501,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command) | |||
lpc2000_info->calc_checksum = 0; | |||
lpc2000_build_sector_list(bank); | |||
if (CMD_ARGC >= 9) | |||
{ | |||
if (CMD_ARGC >= 9) { | |||
if (strcmp(CMD_ARGV[8], "calc_checksum") == 0) | |||
lpc2000_info->calc_checksum = 1; | |||
} | |||
@@ -539,8 +516,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last) | |||
uint32_t result_table[4]; | |||
int status_code; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -551,8 +527,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last) | |||
/* Prepare sectors */ | |||
status_code = lpc2000_iap_call(bank, 50, param_table, result_table); | |||
switch (status_code) | |||
{ | |||
switch (status_code) { | |||
case ERROR_FLASH_OPERATION_FAILED: | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
case LPC2000_CMD_SUCCESS: | |||
@@ -567,8 +542,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last) | |||
/* Erase sectors */ | |||
status_code = lpc2000_iap_call(bank, 52, param_table, result_table); | |||
switch (status_code) | |||
{ | |||
switch (status_code) { | |||
case ERROR_FLASH_OPERATION_FAILED: | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
case LPC2000_CMD_SUCCESS: | |||
@@ -606,8 +580,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
struct working_area *download_area; | |||
int retval = ERROR_OK; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -617,55 +590,56 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
dst_min_alignment = lpc2000_info->cmd51_dst_boundary; | |||
if (offset % dst_min_alignment) | |||
{ | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, offset, dst_min_alignment); | |||
if (offset % dst_min_alignment) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, | |||
offset, | |||
dst_min_alignment); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
if (offset >= bank->sectors[i].offset) | |||
first_sector = i; | |||
if (offset + DIV_ROUND_UP(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset) | |||
if (offset + DIV_ROUND_UP(count, dst_min_alignment) | |||
* dst_min_alignment > bank->sectors[i].offset) | |||
last_sector = i; | |||
} | |||
LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector); | |||
/* check if exception vectors should be flashed */ | |||
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) | |||
{ | |||
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) { | |||
uint32_t checksum = 0; | |||
for (i = 0; i < 8; i++) | |||
{ | |||
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32)); | |||
for (i = 0; i < 8; i++) { | |||
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, | |||
buf_get_u32(buffer + (i * 4), 0, 32)); | |||
if (i != lpc2000_info->checksum_vector) | |||
checksum += buf_get_u32(buffer + (i * 4), 0, 32); | |||
} | |||
checksum = 0 - checksum; | |||
LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum); | |||
uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32); | |||
if (original_value != checksum) | |||
{ | |||
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is different from calculated vector checksum (0x%8.8" PRIx32 ").", | |||
original_value, checksum); | |||
LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum."); | |||
uint32_t original_value = buf_get_u32(buffer + | |||
(lpc2000_info->checksum_vector * 4), 0, 32); | |||
if (original_value != checksum) { | |||
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") " | |||
"to be written to flash is different from calculated vector " | |||
"checksum (0x%8.8" PRIx32 ").", original_value, checksum); | |||
LOG_WARNING("To remove this warning modify build tools on developer PC " | |||
"to inject correct LPC vector checksum."); | |||
} | |||
buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum); | |||
} | |||
/* allocate a working area */ | |||
if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, &download_area) != ERROR_OK) | |||
{ | |||
if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, | |||
&download_area) != ERROR_OK) { | |||
LOG_ERROR("no working area specified, can't write LPC2000 internal flash"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
while (bytes_remaining > 0) | |||
{ | |||
while (bytes_remaining > 0) { | |||
uint32_t thisrun_bytes; | |||
if (bytes_remaining >= lpc2000_info->cmd51_max_buffer) | |||
thisrun_bytes = lpc2000_info->cmd51_max_buffer; | |||
@@ -680,8 +654,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
param_table[0] = first_sector; | |||
param_table[1] = last_sector; | |||
status_code = lpc2000_iap_call(bank, 50, param_table, result_table); | |||
switch (status_code) | |||
{ | |||
switch (status_code) { | |||
case ERROR_FLASH_OPERATION_FAILED: | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
@@ -700,24 +673,28 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
if (retval != ERROR_OK) | |||
break; | |||
if (bytes_remaining >= thisrun_bytes) | |||
{ | |||
if ((retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written)) != ERROR_OK) | |||
{ | |||
if (bytes_remaining >= thisrun_bytes) { | |||
retval = target_write_buffer(bank->target, download_area->address, | |||
thisrun_bytes, buffer + bytes_written); | |||
if (retval != ERROR_OK) { | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
uint8_t *last_buffer = malloc(thisrun_bytes); | |||
memcpy(last_buffer, buffer + bytes_written, bytes_remaining); | |||
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining); | |||
target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer); | |||
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - | |||
bytes_remaining); | |||
target_write_buffer(bank->target, | |||
download_area->address, | |||
thisrun_bytes, | |||
last_buffer); | |||
free(last_buffer); | |||
} | |||
LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32 , thisrun_bytes, bank->base + offset + bytes_written); | |||
LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32, | |||
thisrun_bytes, | |||
bank->base + offset + bytes_written); | |||
/* Write data */ | |||
param_table[0] = bank->base + offset + bytes_written; | |||
@@ -725,8 +702,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
param_table[2] = thisrun_bytes; | |||
param_table[3] = lpc2000_info->cclk; | |||
status_code = lpc2000_iap_call(bank, 51, param_table, result_table); | |||
switch (status_code) | |||
{ | |||
switch (status_code) { | |||
case ERROR_FLASH_OPERATION_FAILED: | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
@@ -767,8 +743,7 @@ static int lpc2000_probe(struct flash_bank *bank) | |||
static int lpc2000_erase_check(struct flash_bank *bank) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -786,7 +761,11 @@ static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size) | |||
{ | |||
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; | |||
snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz" , lpc2000_info->variant, lpc2000_info->cclk); | |||
snprintf(buf, | |||
buf_size, | |||
"lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz", | |||
lpc2000_info->variant, | |||
lpc2000_info->cclk); | |||
return ERROR_OK; | |||
} | |||
@@ -798,34 +777,28 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command) | |||
int status_code; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
if (ERROR_OK != retval) | |||
return retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0) | |||
{ | |||
if (status_code == ERROR_FLASH_OPERATION_FAILED) | |||
{ | |||
command_print(CMD_CTX, "no sufficient working area specified, can't access LPC2000 IAP interface"); | |||
status_code = lpc2000_iap_call(bank, 54, param_table, result_table); | |||
if (status_code != 0x0) { | |||
if (status_code == ERROR_FLASH_OPERATION_FAILED) { | |||
command_print(CMD_CTX, | |||
"no sufficient working area specified, can't access LPC2000 IAP interface"); | |||
return ERROR_OK; | |||
} | |||
command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code); | |||
} | |||
else | |||
{ | |||
command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32 , result_table[0]); | |||
} | |||
} else | |||
command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, result_table[0]); | |||
return ERROR_OK; | |||
} | |||
@@ -34,64 +34,65 @@ | |||
#include "imp.h" | |||
#include <helper/binarybuffer.h> | |||
#define LOAD_TIMER_ERASE 0 | |||
#define LOAD_TIMER_WRITE 1 | |||
#define LOAD_TIMER_ERASE 0 | |||
#define LOAD_TIMER_WRITE 1 | |||
#define FLASH_PAGE_SIZE 512 | |||
#define FLASH_PAGE_SIZE 512 | |||
/* LPC288X control registers */ | |||
#define DBGU_CIDR 0x8000507C | |||
#define DBGU_CIDR 0x8000507C | |||
/* LPC288X flash registers */ | |||
#define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */ | |||
#define F_STAT 0x80102004 /* Flash status register RO 0x45 */ | |||
#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */ | |||
#define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */ | |||
#define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 */ | |||
#define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */ | |||
#define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */ | |||
#define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */ | |||
#define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */ | |||
#define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */ | |||
#define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */ | |||
#define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power savings. R/W 1*/ | |||
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from Power Down mode. R/W -*/ | |||
#define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */ | |||
#define F_STAT 0x80102004 /* Flash status register RO 0x45 */ | |||
#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */ | |||
#define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */ | |||
#define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 | |||
**/ | |||
#define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */ | |||
#define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */ | |||
#define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */ | |||
#define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */ | |||
#define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */ | |||
#define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */ | |||
#define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power | |||
*savings. R/W 1*/ | |||
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from | |||
*Power Down mode. R/W -*/ | |||
/* F_CTRL bits */ | |||
#define FC_CS 0x0001 | |||
#define FC_FUNC 0x0002 | |||
#define FC_WEN 0x0004 | |||
#define FC_RD_LATCH 0x0020 | |||
#define FC_PROTECT 0x0080 | |||
#define FC_SET_DATA 0x0400 | |||
#define FC_RSSL 0x0800 | |||
#define FC_PROG_REQ 0x1000 | |||
#define FC_CLR_BUF 0x4000 | |||
#define FC_LOAD_REQ 0x8000 | |||
#define FC_CS 0x0001 | |||
#define FC_FUNC 0x0002 | |||
#define FC_WEN 0x0004 | |||
#define FC_RD_LATCH 0x0020 | |||
#define FC_PROTECT 0x0080 | |||
#define FC_SET_DATA 0x0400 | |||
#define FC_RSSL 0x0800 | |||
#define FC_PROG_REQ 0x1000 | |||
#define FC_CLR_BUF 0x4000 | |||
#define FC_LOAD_REQ 0x8000 | |||
/* F_STAT bits */ | |||
#define FS_DONE 0x0001 | |||
#define FS_PROGGNT 0x0002 | |||
#define FS_RDY 0x0004 | |||
#define FS_ERR 0x0020 | |||
#define FS_DONE 0x0001 | |||
#define FS_PROGGNT 0x0002 | |||
#define FS_RDY 0x0004 | |||
#define FS_ERR 0x0020 | |||
/* F_PROG_TIME */ | |||
#define FPT_TIME_MASK 0x7FFF | |||
#define FPT_TIME_MASK 0x7FFF | |||
#define FPT_ENABLE 0x8000 | |||
#define FPT_ENABLE 0x8000 | |||
/* F_WAIT */ | |||
#define FW_WAIT_STATES_MASK 0x00FF | |||
#define FW_SET_MASK 0xC000 | |||
#define FW_WAIT_STATES_MASK 0x00FF | |||
#define FW_SET_MASK 0xC000 | |||
/* F_CLK_TIME */ | |||
#define FCT_CLK_DIV_MASK 0x0FFF | |||
struct lpc288x_flash_bank | |||
{ | |||
struct lpc288x_flash_bank { | |||
uint32_t working_area; | |||
uint32_t working_area_size; | |||
/* chip id register */ | |||
uint32_t cidr; | |||
const char * target_name; | |||
const char *target_name; | |||
uint32_t cclk; | |||
uint32_t sector_size_break; | |||
@@ -106,15 +107,13 @@ static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout) | |||
{ | |||
uint32_t status; | |||
struct target *target = bank->target; | |||
do | |||
{ | |||
do { | |||
alive_sleep(1); | |||
timeout--; | |||
target_read_u32(target, F_STAT, &status); | |||
} while (((status & FS_DONE) == 0) && timeout); | |||
if (timeout == 0) | |||
{ | |||
if (timeout == 0) { | |||
LOG_DEBUG("Timedout!"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -132,14 +131,14 @@ static int lpc288x_read_part_info(struct flash_bank *bank) | |||
uint32_t offset; | |||
if (lpc288x_info->cidr == 0x0102100A) | |||
return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */ | |||
return ERROR_OK;/* already probed, multiple probes may cause memory leak, not | |||
*allowed */ | |||
/* Read and parse chip identification register */ | |||
target_read_u32(target, DBGU_CIDR, &cidr); | |||
if (cidr != 0x0102100A) | |||
{ | |||
LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")",cidr); | |||
if (cidr != 0x0102100A) { | |||
LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -152,16 +151,14 @@ static int lpc288x_read_part_info(struct flash_bank *bank) | |||
bank->num_sectors = 23; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * 23); | |||
for (i = 0; i < 15; i++) | |||
{ | |||
for (i = 0; i < 15; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 64 * 1024; | |||
offset += bank->sectors[i].size; | |||
bank->sectors[i].is_erased = -1; | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
for (i = 15; i < 23; i++) | |||
{ | |||
for (i = 15; i < 23; i++) { | |||
bank->sectors[i].offset = offset; | |||
bank->sectors[i].size = 8 * 1024; | |||
offset += bank->sectors[i].size; | |||
@@ -183,9 +180,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command) | |||
struct lpc288x_flash_bank *lpc288x_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank)); | |||
bank->driver_priv = lpc288x_info; | |||
@@ -220,25 +215,18 @@ static void lpc288x_set_flash_clk(struct flash_bank *bank) | |||
static void lpc288x_load_timer(int erase, struct target *target) | |||
{ | |||
if (erase == LOAD_TIMER_ERASE) | |||
{ | |||
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500); | |||
} | |||
else | |||
{ | |||
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75); | |||
} | |||
} | |||
static uint32_t lpc288x_system_ready(struct flash_bank *bank) | |||
{ | |||
struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv; | |||
if (lpc288x_info->cidr == 0) | |||
{ | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
} | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -248,8 +236,7 @@ static uint32_t lpc288x_system_ready(struct flash_bank *bank) | |||
static int lpc288x_erase_check(struct flash_bank *bank) | |||
{ | |||
uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */ | |||
if (status != ERROR_OK) | |||
{ | |||
if (status != ERROR_OK) { | |||
LOG_INFO("Processor not halted/not probed"); | |||
return status; | |||
} | |||
@@ -263,14 +250,11 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last) | |||
int sector; | |||
struct target *target = bank->target; | |||
status = lpc288x_system_ready(bank); /* probed? halted? */ | |||
status = lpc288x_system_ready(bank); /* probed? halted? */ | |||
if (status != ERROR_OK) | |||
{ | |||
return status; | |||
} | |||
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) | |||
{ | |||
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { | |||
LOG_INFO("Bad sector range"); | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
@@ -278,30 +262,25 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last) | |||
/* Configure the flash controller timing */ | |||
lpc288x_set_flash_clk(bank); | |||
for (sector = first; sector <= last; sector++) | |||
{ | |||
for (sector = first; sector <= last; sector++) { | |||
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
lpc288x_load_timer(LOAD_TIMER_ERASE,target); | |||
lpc288x_load_timer(LOAD_TIMER_ERASE, target); | |||
target_write_u32(target, bank->sectors[sector].offset, 0x00); | |||
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS); | |||
} | |||
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
return ERROR_OK; | |||
} | |||
static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) | |||
{ | |||
uint8_t page_buffer[FLASH_PAGE_SIZE]; | |||
uint32_t status, source_offset,dest_offset; | |||
uint32_t status, source_offset, dest_offset; | |||
struct target *target = bank->target; | |||
uint32_t bytes_remaining = count; | |||
uint32_t first_sector, last_sector, sector, page; | |||
@@ -310,39 +289,34 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
/* probed? halted? */ | |||
status = lpc288x_system_ready(bank); | |||
if (status != ERROR_OK) | |||
{ | |||
return status; | |||
} | |||
/* Initialise search indices */ | |||
first_sector = last_sector = 0xffffffff; | |||
/* validate the write range... */ | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
if ((offset >= bank->sectors[i].offset) && | |||
(offset < (bank->sectors[i].offset + bank->sectors[i].size)) && | |||
(first_sector == 0xffffffff)) | |||
{ | |||
(offset < (bank->sectors[i].offset + bank->sectors[i].size)) && | |||
(first_sector == 0xffffffff)) { | |||
first_sector = i; | |||
/* all writes must start on a sector boundary... */ | |||
if (offset % bank->sectors[i].size) | |||
{ | |||
LOG_INFO("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, bank->sectors[i].size); | |||
if (offset % bank->sectors[i].size) { | |||
LOG_INFO( | |||
"offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", | |||
offset, | |||
bank->sectors[i].size); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
} | |||
if (((offset + count) > bank->sectors[i].offset) && | |||
((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) && | |||
(last_sector == 0xffffffff)) | |||
{ | |||
((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) && | |||
(last_sector == 0xffffffff)) | |||
last_sector = i; | |||
} | |||
} | |||
/* Range check... */ | |||
if (first_sector == 0xffffffff || last_sector == 0xffffffff) | |||
{ | |||
if (first_sector == 0xffffffff || last_sector == 0xffffffff) { | |||
LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count); | |||
return ERROR_FLASH_DST_OUT_OF_BANK; | |||
} | |||
@@ -354,32 +328,23 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
source_offset = 0; | |||
dest_offset = 0; | |||
for (sector = first_sector; sector <= last_sector; sector++) | |||
{ | |||
for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) | |||
{ | |||
if (bytes_remaining == 0) | |||
{ | |||
for (sector = first_sector; sector <= last_sector; sector++) { | |||
for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) { | |||
if (bytes_remaining == 0) { | |||
count = 0; | |||
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE); | |||
} | |||
else if (bytes_remaining < FLASH_PAGE_SIZE) | |||
{ | |||
} else if (bytes_remaining < FLASH_PAGE_SIZE) { | |||
count = bytes_remaining; | |||
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE); | |||
memcpy(page_buffer, &buffer[source_offset], count); | |||
} | |||
else | |||
{ | |||
} else { | |||
count = FLASH_PAGE_SIZE; | |||
memcpy(page_buffer, &buffer[source_offset], count); | |||
} | |||
/* Wait for flash to become ready */ | |||
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* fill flash data latches with 1's */ | |||
target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC); | |||
@@ -389,14 +354,14 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
* it seems not to be a LOT slower.... | |||
* bulk_write_memory() is no quicker :(*/ | |||
#if 1 | |||
if (target_write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK) | |||
{ | |||
if (target_write_memory(target, offset + dest_offset, 4, 128, | |||
page_buffer) != ERROR_OK) { | |||
LOG_ERROR("Write failed s %" PRIx32 " p %" PRIx32 "", sector, page); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
#else | |||
if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK) | |||
{ | |||
if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, | |||
page_buffer) != ERROR_OK) { | |||
LOG_INFO("Write to flash buffer failed"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -407,7 +372,8 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
lpc288x_load_timer(LOAD_TIMER_WRITE, target); | |||
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | FC_CS); | |||
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | | |||
FC_CS); | |||
} | |||
} | |||
@@ -421,12 +387,9 @@ static int lpc288x_probe(struct flash_bank *bank) | |||
int retval; | |||
if (lpc288x_info->cidr != 0) | |||
{ | |||
return ERROR_OK; /* already probed */ | |||
} | |||
return ERROR_OK;/* already probed */ | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -452,32 +415,25 @@ static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last | |||
/* probed? halted? */ | |||
status = lpc288x_system_ready(bank); | |||
if (status != ERROR_OK) | |||
{ | |||
return status; | |||
} | |||
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) | |||
{ | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
/* Configure the flash controller timing */ | |||
lpc288x_set_flash_clk(bank); | |||
for (lockregion = first; lockregion <= last; lockregion++) | |||
{ | |||
if (set) | |||
{ | |||
for (lockregion = first; lockregion <= last; lockregion++) { | |||
if (set) { | |||
/* write an odd value to base addy to protect... */ | |||
value = 0x01; | |||
} | |||
else | |||
{ | |||
} else { | |||
/* write an even value to base addy to unprotect... */ | |||
value = 0x00; | |||
} | |||
target_write_u32(target, bank->sectors[lockregion].offset, value); | |||
target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | FC_CS); | |||
target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | | |||
FC_CS); | |||
} | |||
return ERROR_OK; | |||
@@ -19,6 +19,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -27,7 +28,6 @@ | |||
#include "cfi.h" | |||
#include "non_cfi.h" | |||
#define KB 1024 | |||
#define MB (1024*1024) | |||
#define ERASE_REGION(num, size) (((size/256) << 16) | (num-1)) | |||
@@ -43,8 +43,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(16, 4*KB) | |||
} | |||
}, | |||
@@ -57,8 +56,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(32, 4*KB) | |||
} | |||
}, | |||
@@ -71,8 +69,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(64, 4*KB) | |||
} | |||
}, | |||
@@ -85,8 +82,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(128, 4*KB) | |||
} | |||
}, | |||
@@ -99,8 +95,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(8, 64*KB) | |||
} | |||
}, | |||
@@ -113,8 +108,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(128, 4*KB) | |||
} | |||
}, | |||
@@ -127,8 +121,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -144,8 +137,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(7, 64*KB), | |||
ERASE_REGION(1, 32*KB), | |||
ERASE_REGION(2, 8*KB), | |||
@@ -156,9 +148,9 @@ static struct non_cfi non_cfi_flashes[] = { | |||
/* SST 39VF* do not support DQ5 status polling - this currently is | |||
only supported by the host algorithm, not by the target code using | |||
the work area. | |||
Only true for 8-bit and 32-bit wide memories. 16-bit wide memories | |||
without DQ5 status polling are supported by the target code. | |||
*/ | |||
Only true for 8-bit and 32-bit wide memories. 16-bit wide memories | |||
without DQ5 status polling are supported by the target code. | |||
*/ | |||
{ | |||
.mfr = CFI_MFR_SST, | |||
.id = 0x2782, /* SST39xF160 */ | |||
@@ -168,8 +160,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(512, 4*KB) | |||
} | |||
}, | |||
@@ -182,8 +173,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1024, 4*KB) | |||
} | |||
}, | |||
@@ -196,8 +186,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(512, 4*KB) | |||
} | |||
}, | |||
@@ -210,8 +199,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(512, 4*KB) | |||
} | |||
}, | |||
@@ -224,8 +212,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(512, 4*KB) | |||
} | |||
}, | |||
@@ -238,8 +225,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1024, 4*KB) | |||
} | |||
}, | |||
@@ -252,26 +238,24 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1024, 4*KB) | |||
} | |||
}, | |||
{ | |||
.mfr = CFI_MFR_SST, | |||
.id = 0x236d, /* SST39VF6401B */ | |||
.pri_id = 0x02, | |||
.dev_size = 8*MB, | |||
.interface_desc = 0x2, /* x8 or x16 device with nBYTE */ | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = | |||
{ | |||
ERASE_REGION(2048, 4*KB) | |||
} | |||
}, | |||
{ | |||
.mfr = CFI_MFR_SST, | |||
.id = 0x236d, /* SST39VF6401B */ | |||
.pri_id = 0x02, | |||
.dev_size = 8*MB, | |||
.interface_desc = 0x2, /* x8 or x16 device with nBYTE */ | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, | |||
.num_erase_regions = 1, | |||
.erase_region_info = { | |||
ERASE_REGION(2048, 4*KB) | |||
} | |||
}, | |||
{ | |||
.mfr = CFI_MFR_AMD, | |||
.id = 0x22ab, /* AM29F400BB */ | |||
.pri_id = 0x02, | |||
@@ -280,8 +264,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -297,8 +280,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(7, 64*KB), | |||
ERASE_REGION(1, 32*KB), | |||
ERASE_REGION(2, 8*KB), | |||
@@ -314,15 +296,14 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
ERASE_REGION(15, 64*KB) | |||
} | |||
}, | |||
{ | |||
{ | |||
.mfr = CFI_MFR_FUJITSU, | |||
.id = 0x22ea, /* MBM29SL800TE */ | |||
.pri_id = 0x02, | |||
@@ -331,8 +312,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(15, 64*KB), | |||
ERASE_REGION(1, 32*KB), | |||
ERASE_REGION(2, 8*KB), | |||
@@ -348,8 +328,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x00, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -365,8 +344,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -382,8 +360,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -400,8 +377,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -417,8 +393,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(31, 64*KB), | |||
ERASE_REGION(1, 32*KB), | |||
ERASE_REGION(2, 8*KB), | |||
@@ -434,8 +409,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -451,8 +425,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 3, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(8, 8*KB), | |||
ERASE_REGION(2, 32*KB), | |||
ERASE_REGION(30, 64*KB) | |||
@@ -467,8 +440,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 3, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(30, 64*KB), | |||
ERASE_REGION(2, 32*KB), | |||
ERASE_REGION(8, 8*KB) | |||
@@ -483,8 +455,7 @@ static struct non_cfi non_cfi_flashes[] = { | |||
.max_buf_write_size = 0x0, | |||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, | |||
.num_erase_regions = 4, | |||
.erase_region_info = | |||
{ | |||
.erase_region_info = { | |||
ERASE_REGION(1, 16*KB), | |||
ERASE_REGION(2, 8*KB), | |||
ERASE_REGION(1, 32*KB), | |||
@@ -503,18 +474,15 @@ void cfi_fixup_non_cfi(struct flash_bank *bank) | |||
struct cfi_flash_bank *cfi_info = bank->driver_priv; | |||
struct non_cfi *non_cfi = non_cfi_flashes; | |||
if(cfi_info->x16_as_x8) | |||
if (cfi_info->x16_as_x8) | |||
mask = 0xFF; | |||
else | |||
mask = 0xFFFF; | |||
for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++) | |||
{ | |||
for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++) { | |||
if ((cfi_info->manufacturer == non_cfi->mfr) | |||
&& (cfi_info->device_id == (non_cfi->id & mask))) | |||
{ | |||
&& (cfi_info->device_id == (non_cfi->id & mask))) | |||
break; | |||
} | |||
} | |||
/* only fixup jedec flashs found in table */ | |||
@@ -554,14 +522,13 @@ void cfi_fixup_non_cfi(struct flash_bank *bank) | |||
cfi_info->status_poll_mask = non_cfi->status_poll_mask; | |||
cfi_info->num_erase_regions = non_cfi->num_erase_regions; | |||
size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) * | |||
cfi_info->num_erase_regions; | |||
cfi_info->num_erase_regions; | |||
cfi_info->erase_region_info = malloc(erase_region_info_size); | |||
memcpy(cfi_info->erase_region_info, | |||
non_cfi->erase_region_info, erase_region_info_size); | |||
non_cfi->erase_region_info, erase_region_info_size); | |||
cfi_info->dev_size = non_cfi->dev_size; | |||
if (cfi_info->pri_id == 0x2) | |||
{ | |||
if (cfi_info->pri_id == 0x2) { | |||
struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext)); | |||
pri_ext->pri[0] = 'P'; | |||
@@ -589,8 +556,7 @@ void cfi_fixup_non_cfi(struct flash_bank *bank) | |||
pri_ext->_reversed_geometry = 0; | |||
cfi_info->pri_ext = pri_ext; | |||
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3)) | |||
{ | |||
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3)) { | |||
LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported"); | |||
exit(-1); | |||
} | |||
@@ -17,11 +17,11 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef NON_CFI_H | |||
#define NON_CFI_H | |||
struct non_cfi | |||
{ | |||
struct non_cfi { | |||
uint16_t mfr; | |||
uint16_t id; | |||
uint16_t pri_id; | |||
@@ -17,6 +17,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -25,9 +26,7 @@ | |||
#include "ocl.h" | |||
#include <target/embeddedice.h> | |||
struct ocl_priv | |||
{ | |||
struct ocl_priv { | |||
struct arm_jtag *jtag_info; | |||
unsigned int buflen; | |||
unsigned int bufalign; | |||
@@ -50,9 +49,7 @@ FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command) | |||
struct ocl_priv *ocl; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
arm7_9 = target_to_arm7_9(bank->target); | |||
if (!is_arm7_9(arm7_9)) | |||
@@ -76,39 +73,36 @@ static int ocl_erase(struct flash_bank *bank, int first, int last) | |||
if (bank->num_sectors == 0) | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
if (bank->target->state != TARGET_RUNNING) | |||
{ | |||
if (bank->target->state != TARGET_RUNNING) { | |||
LOG_ERROR("target has to be running to communicate with the loader"); | |||
return ERROR_TARGET_NOT_RUNNING; | |||
} | |||
if ((first == 0) && (last == bank->num_sectors - 1)) | |||
{ | |||
if ((first == 0) && (last == bank->num_sectors - 1)) { | |||
dcc_buffer[0] = OCL_ERASE_ALL; | |||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
else | |||
{ | |||
} else { | |||
dcc_buffer[0] = OCL_ERASE_BLOCK; | |||
dcc_buffer[1] = first; | |||
dcc_buffer[2] = last; | |||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK)) | |||
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
/* wait for response, fixed timeout of 1 s */ | |||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK)) | |||
{ | |||
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
/* receive response */ | |||
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1) != ERROR_OK)) | |||
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (dcc_buffer[1] != OCL_CMD_DONE) | |||
{ | |||
if (dcc_buffer[1] != OCL_CMD_DONE) { | |||
if (dcc_buffer[0] == OCL_ERASE_ALL) | |||
LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]); | |||
else | |||
@@ -140,8 +134,7 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
if (ocl->buflen == 0 || ocl->bufalign == 0) | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
if (bank->target->state != TARGET_RUNNING) | |||
{ | |||
if (bank->target->state != TARGET_RUNNING) { | |||
LOG_ERROR("target has to be running to communicate with the loader"); | |||
return ERROR_TARGET_NOT_RUNNING; | |||
} | |||
@@ -149,8 +142,7 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
/* allocate buffer for max. ocl buffer + overhead */ | |||
dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3)); | |||
while (count) | |||
{ | |||
while (count) { | |||
if (count + (offset % ocl->bufalign) > ocl->buflen) | |||
runlen = ocl->buflen - (offset % ocl->bufalign); | |||
else | |||
@@ -165,10 +157,8 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
chksum = OCL_CHKS_INIT; | |||
/* copy data to DCC buffer in proper byte order and properly aligned */ | |||
for (i = 0; i < runlen; i++) | |||
{ | |||
switch (byteofs++) | |||
{ | |||
for (i = 0; i < runlen; i++) { | |||
switch (byteofs++) { | |||
case 0: | |||
*dcc_bufptr &= *(buffer++) | 0xffffff00; | |||
break; | |||
@@ -194,28 +184,27 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, | |||
*(dcc_bufptr++) = chksum; | |||
/* send the data */ | |||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK) | |||
{ | |||
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer); | |||
if (retval != ERROR_OK) { | |||
free(dcc_buffer); | |||
return retval; | |||
} | |||
/* wait for response, fixed timeout of 1 s */ | |||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK)) | |||
{ | |||
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000); | |||
if (retval != ERROR_OK) { | |||
free(dcc_buffer); | |||
return retval; | |||
} | |||
/* receive response */ | |||
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
{ | |||
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) { | |||
free(dcc_buffer); | |||
return retval; | |||
} | |||
if (dcc_buffer[0] != OCL_CMD_DONE) | |||
{ | |||
if (dcc_buffer[0] != OCL_CMD_DONE) { | |||
LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]); | |||
free(dcc_buffer); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
@@ -241,50 +230,61 @@ static int ocl_probe(struct flash_bank *bank) | |||
embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); | |||
dcc_buffer[0] = OCL_PROBE; | |||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* wait for response, fixed timeout of 1 s */ | |||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK)) | |||
{ | |||
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
/* receive response */ | |||
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (dcc_buffer[0] != OCL_CMD_DONE) | |||
{ | |||
if (dcc_buffer[0] != OCL_CMD_DONE) { | |||
LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* receive and fill in parameters, detection of loader is important, receive it one by one */ | |||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK) | |||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
bank->base = dcc_buffer[0]; | |||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK) | |||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
bank->size = dcc_buffer[0]; | |||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK) | |||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
bank->num_sectors = dcc_buffer[0]; | |||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK) | |||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK)) | |||
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
ocl->buflen = dcc_buffer[0] & 0xffff; | |||
ocl->bufalign = dcc_buffer[0] >> 16; | |||
bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors); | |||
if (bank->num_sectors == 0) | |||
{ | |||
if (bank->num_sectors == 0) { | |||
LOG_ERROR("number of sectors shall be non zero value"); | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
@@ -293,8 +293,7 @@ static int ocl_probe(struct flash_bank *bank) | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
sectsize = bank->size / bank->num_sectors; | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
bank->sectors[i].offset = i * sectsize; | |||
bank->sectors[i].size = sectsize; | |||
bank->sectors[i].is_erased = -1; | |||
@@ -304,20 +303,17 @@ static int ocl_probe(struct flash_bank *bank) | |||
if (ocl->bufalign == 0) | |||
ocl->bufalign = 1; | |||
if (ocl->buflen == 0) | |||
{ | |||
if (ocl->buflen == 0) { | |||
LOG_ERROR("buflen shall be non zero value"); | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) | |||
{ | |||
if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) { | |||
LOG_ERROR("buflen is not multiple of bufalign"); | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
if (ocl->buflen % 4) | |||
{ | |||
if (ocl->buflen % 4) { | |||
LOG_ERROR("buflen shall be divisible by 4"); | |||
return ERROR_FLASH_BANK_INVALID; | |||
} | |||
@@ -17,6 +17,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef OCL_H | |||
#define OCL_H | |||
@@ -23,6 +23,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -46,7 +47,7 @@ | |||
* Note: These macros only work for KSEG0/KSEG1 addresses. | |||
*/ | |||
#define Virt2Phys(v) ((v) & 0x1FFFFFFF) | |||
#define Virt2Phys(v) ((v) & 0x1FFFFFFF) | |||
/* pic32mx configuration register locations */ | |||
@@ -90,8 +91,7 @@ | |||
#define NVMKEY1 0xAA996655 | |||
#define NVMKEY2 0x556699AA | |||
struct pic32mx_flash_bank | |||
{ | |||
struct pic32mx_flash_bank { | |||
struct working_area *write_algorithm; | |||
int probed; | |||
}; | |||
@@ -171,9 +171,7 @@ FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command) | |||
struct pic32mx_flash_bank *pic32mx_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank)); | |||
bank->driver_priv = pic32mx_info; | |||
@@ -199,8 +197,7 @@ static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout) | |||
uint32_t status; | |||
/* wait for busy to clear */ | |||
while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) | |||
{ | |||
while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) { | |||
LOG_DEBUG("status: 0x%" PRIx32, status); | |||
alive_sleep(1); | |||
} | |||
@@ -240,8 +237,7 @@ static int pic32mx_protect_check(struct flash_bank *bank) | |||
int s; | |||
int num_pages; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -249,15 +245,13 @@ static int pic32mx_protect_check(struct flash_bank *bank) | |||
target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0); | |||
if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */ | |||
num_pages = 0xffff; /* All pages protected */ | |||
else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) | |||
{ | |||
num_pages = 0xffff; /* All pages protected */ | |||
else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) { | |||
if (devcfg0 & (1 << 24)) | |||
num_pages = 0; /* All pages unprotected */ | |||
num_pages = 0; /* All pages unprotected */ | |||
else | |||
num_pages = 0xffff; /* All pages protected */ | |||
} | |||
else /* pgm flash */ | |||
num_pages = 0xffff; /* All pages protected */ | |||
} else /* pgm flash */ | |||
num_pages = (~devcfg0 >> 12) & 0xff; | |||
for (s = 0; s < bank->num_sectors && s < num_pages; s++) | |||
@@ -274,15 +268,13 @@ static int pic32mx_erase(struct flash_bank *bank, int first, int last) | |||
int i; | |||
uint32_t status; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((first == 0) && (last == (bank->num_sectors - 1)) | |||
&& (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) | |||
{ | |||
&& (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) { | |||
/* this will only erase the Program Flash (PFM), not the Boot Flash (BFM) | |||
* we need to use the MTAP to perform a full erase */ | |||
LOG_DEBUG("Erasing entire program flash"); | |||
@@ -294,8 +286,7 @@ static int pic32mx_erase(struct flash_bank *bank, int first, int last) | |||
return ERROR_OK; | |||
} | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset)); | |||
status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10); | |||
@@ -314,8 +305,7 @@ static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last | |||
{ | |||
struct target *target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -381,7 +371,7 @@ static const uint32_t pic32mx_flash_write_code[] = { | |||
0x1600FFFD, /* bne $s0, $zero, waitflash */ | |||
0x00000000, /* nop */ | |||
0x00000000, /* nop */ | |||
0x00000000, /* nop */ | |||
0x00000000, /* nop */ | |||
0x00000000, /* nop */ | |||
0x00000000, /* nop */ | |||
0x8D510000, /* lw $s1, 0($t2) */ | |||
@@ -407,24 +397,20 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
/* flash write code */ | |||
if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), | |||
&pic32mx_info->write_algorithm) != ERROR_OK) | |||
{ | |||
&pic32mx_info->write_algorithm) != ERROR_OK) { | |||
LOG_WARNING("no working area available, can't do block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
if ((retval = target_write_buffer(target, | |||
pic32mx_info->write_algorithm->address, | |||
sizeof(pic32mx_flash_write_code), | |||
(uint8_t*)pic32mx_flash_write_code)) != ERROR_OK) | |||
retval = target_write_buffer(target, pic32mx_info->write_algorithm->address, | |||
sizeof(pic32mx_flash_write_code), (uint8_t *)pic32mx_flash_write_code); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
if (buffer_size <= 256) | |||
{ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a | |||
* buffer, free the algorithm */ | |||
if (pic32mx_info->write_algorithm) | |||
@@ -442,25 +428,24 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
init_reg_param(®_params[1], "a1", 32, PARAM_OUT); | |||
init_reg_param(®_params[2], "a2", 32, PARAM_OUT); | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
uint32_t status; | |||
uint32_t thisrun_count = (count > (buffer_size / 4)) ? | |||
(buffer_size / 4) : count; | |||
if ((retval = target_write_buffer(target, source->address, | |||
thisrun_count * 4, buffer)) != ERROR_OK) | |||
retval = target_write_buffer(target, source->address, | |||
thisrun_count * 4, buffer); | |||
if (retval != ERROR_OK) | |||
break; | |||
buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address)); | |||
buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address)); | |||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); | |||
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, | |||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params, | |||
pic32mx_info->write_algorithm->address, | |||
0, | |||
10000, &mips32_info)) != ERROR_OK) | |||
{ | |||
0, 10000, &mips32_info); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error executing pic32mx flash write algorithm"); | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
@@ -468,15 +453,13 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
status = buf_get_u32(reg_params[0].value, 0, 32); | |||
if (status & NVMCON_NVMERR) | |||
{ | |||
if (status & NVMCON_NVMERR) { | |||
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status); | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
} | |||
if (status & NVMCON_LVDERR) | |||
{ | |||
if (status & NVMCON_LVDERR) { | |||
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
@@ -516,8 +499,7 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
uint32_t status; | |||
int retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -525,53 +507,43 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 | |||
" count: 0x%8.8" PRIx32 "", bank->base, offset, count); | |||
if (offset & 0x3) | |||
{ | |||
if (offset & 0x3) { | |||
LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
/* multiple words (4-byte) to be programmed? */ | |||
if (words_remaining > 0) | |||
{ | |||
if (words_remaining > 0) { | |||
/* try using a block write */ | |||
if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
retval = pic32mx_write_block(bank, buffer, offset, words_remaining); | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
/* if block write failed (no sufficient working area), | |||
* we use normal (slow) single dword accesses */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
} | |||
else if (retval == ERROR_FLASH_OPERATION_FAILED) | |||
{ | |||
} else if (retval == ERROR_FLASH_OPERATION_FAILED) { | |||
LOG_ERROR("flash writing failed"); | |||
return retval; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
buffer += words_remaining * 4; | |||
address += words_remaining * 4; | |||
words_remaining = 0; | |||
} | |||
} | |||
while (words_remaining > 0) | |||
{ | |||
while (words_remaining > 0) { | |||
uint32_t value; | |||
memcpy(&value, buffer + bytes_written, sizeof(uint32_t)); | |||
status = pic32mx_write_word(bank, address, value); | |||
if (status & NVMCON_NVMERR) | |||
{ | |||
if (status & NVMCON_NVMERR) { | |||
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (status & NVMCON_LVDERR) | |||
{ | |||
if (status & NVMCON_LVDERR) { | |||
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -581,21 +553,18 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs | |||
address += 4; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint32_t value = 0xffffffff; | |||
memcpy(&value, buffer + bytes_written, bytes_remaining); | |||
status = pic32mx_write_word(bank, address, value); | |||
if (status & NVMCON_NVMERR) | |||
{ | |||
if (status & NVMCON_NVMERR) { | |||
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (status & NVMCON_LVDERR) | |||
{ | |||
if (status & NVMCON_LVDERR) { | |||
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -631,8 +600,7 @@ static int pic32mx_probe(struct flash_bank *bank) | |||
page_size = 4096; | |||
if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) | |||
{ | |||
if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) { | |||
/* 0x1FC00000: Boot flash size */ | |||
#if 0 | |||
/* for some reason this register returns 8k for the boot bank size | |||
@@ -646,9 +614,7 @@ static int pic32mx_probe(struct flash_bank *bank) | |||
/* fixed 12k boot bank - see comments above */ | |||
num_pages = (12 * 1024); | |||
#endif | |||
} | |||
else | |||
{ | |||
} else { | |||
/* read the flash size from the device */ | |||
if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) { | |||
LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash"); | |||
@@ -658,8 +624,7 @@ static int pic32mx_probe(struct flash_bank *bank) | |||
LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024); | |||
if (bank->sectors) | |||
{ | |||
if (bank->sectors) { | |||
free(bank->sectors); | |||
bank->sectors = NULL; | |||
} | |||
@@ -670,8 +635,7 @@ static int pic32mx_probe(struct flash_bank *bank) | |||
bank->num_sectors = num_pages; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); | |||
for (i = 0; i < (int)num_pages; i++) | |||
{ | |||
for (i = 0; i < (int)num_pages; i++) { | |||
bank->sectors[i].offset = i * page_size; | |||
bank->sectors[i].size = page_size; | |||
bank->sectors[i].is_erased = -1; | |||
@@ -709,17 +673,15 @@ static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
for (i = 0; pic32mx_devs[i].name != NULL; i++) | |||
{ | |||
for (i = 0; pic32mx_devs[i].name != NULL; i++) { | |||
if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) { | |||
printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name); | |||
break; | |||
} | |||
} | |||
if (pic32mx_devs[i].name == NULL) { | |||
if (pic32mx_devs[i].name == NULL) | |||
printed = snprintf(buf, buf_size, "Unknown"); | |||
} | |||
buf += printed; | |||
buf_size -= printed; | |||
@@ -735,9 +697,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command) | |||
int status, res; | |||
if (CMD_ARGC != 3) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); | |||
@@ -747,8 +707,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command) | |||
if (ERROR_OK != retval) | |||
return retval; | |||
if (address < bank->base || address >= (bank->base + bank->size)) | |||
{ | |||
if (address < bank->base || address >= (bank->base + bank->size)) { | |||
command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]); | |||
return ERROR_OK; | |||
} | |||
@@ -776,8 +735,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) | |||
struct mips_ejtag *ejtag_info; | |||
int timeout = 10; | |||
if (CMD_ARGC < 1) | |||
{ | |||
if (CMD_ARGC < 1) { | |||
command_print(CMD_CTX, "pic32mx unlock <bank>"); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
@@ -798,8 +756,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) | |||
/* first check status of device */ | |||
mchip_cmd = MCHP_STATUS; | |||
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); | |||
if (mchip_cmd & (1 << 7)) | |||
{ | |||
if (mchip_cmd & (1 << 7)) { | |||
/* device is not locked */ | |||
command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway"); | |||
} | |||
@@ -812,8 +769,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) | |||
do { | |||
mchip_cmd = MCHP_STATUS; | |||
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); | |||
if (timeout-- == 0) | |||
{ | |||
if (timeout-- == 0) { | |||
LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd); | |||
break; | |||
} | |||
@@ -91,15 +91,14 @@ | |||
static void stellaris_read_clock_info(struct flash_bank *bank); | |||
static int stellaris_mass_erase(struct flash_bank *bank); | |||
struct stellaris_flash_bank | |||
{ | |||
struct stellaris_flash_bank { | |||
/* chip id register */ | |||
uint32_t did0; | |||
uint32_t did1; | |||
uint32_t dc0; | |||
uint32_t dc1; | |||
const char * target_name; | |||
const char *target_name; | |||
uint8_t target_class; | |||
uint32_t sramsiz; | |||
@@ -123,8 +122,8 @@ struct stellaris_flash_bank | |||
const char *mck_desc; | |||
}; | |||
// Autogenerated by contrib/gen-stellaris-part-header.pl | |||
// From Stellaris Firmware Development Package revision 8049 | |||
/* Autogenerated by contrib/gen-stellaris-part-header.pl */ | |||
/* From Stellaris Firmware Development Package revision 8049 */ | |||
static struct { | |||
uint8_t class; | |||
uint8_t partno; | |||
@@ -415,8 +414,7 @@ static struct { | |||
{0xFF, 0x00, "Unknown Part"} | |||
}; | |||
static char * StellarisClassname[7] = | |||
{ | |||
static char *StellarisClassname[7] = { | |||
"Sandstorm", | |||
"Fury", | |||
"Unknown", | |||
@@ -437,9 +435,7 @@ FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command) | |||
struct stellaris_flash_bank *stellaris_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1); | |||
bank->base = 0x0; | |||
@@ -503,8 +499,7 @@ static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
if (stellaris_info->num_lockbits > 0) | |||
{ | |||
if (stellaris_info->num_lockbits > 0) { | |||
snprintf(buf, | |||
buf_size, | |||
"pagesize: %" PRIi32 ", pages: %d, " | |||
@@ -532,7 +527,7 @@ static void stellaris_set_flash_timing(struct flash_bank *bank) | |||
if (stellaris_info->target_class > 1) | |||
return; | |||
LOG_DEBUG("usecrl = %i",(int)(usecrl)); | |||
LOG_DEBUG("usecrl = %i", (int)(usecrl)); | |||
target_write_u32(target, SCB_BASE | USECRL, usecrl); | |||
} | |||
@@ -613,8 +608,7 @@ static void stellaris_read_clock_info(struct flash_bank *bank) | |||
stellaris_info->mck_desc = ""; | |||
switch (oscsrc) | |||
{ | |||
switch (oscsrc) { | |||
case 0: /* MOSC */ | |||
mainfreq = rcc_xtal[xtal]; | |||
break; | |||
@@ -670,22 +664,19 @@ static int stellaris_read_part_info(struct flash_bank *bank) | |||
did0, did1, stellaris_info->dc0, stellaris_info->dc1); | |||
ver = did0 >> 28; | |||
if ((ver != 0) && (ver != 1)) | |||
{ | |||
if ((ver != 0) && (ver != 1)) { | |||
LOG_WARNING("Unknown did0 version, cannot identify target"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (did1 == 0) | |||
{ | |||
if (did1 == 0) { | |||
LOG_WARNING("Cannot identify target as a Stellaris"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
ver = did1 >> 28; | |||
fam = (did1 >> 24) & 0xF; | |||
if (((ver != 0) && (ver != 1)) || (fam != 0)) | |||
{ | |||
if (((ver != 0) && (ver != 1)) || (fam != 0)) { | |||
LOG_WARNING("Unknown did1 version/family."); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -754,7 +745,7 @@ static int stellaris_read_part_info(struct flash_bank *bank) | |||
stellaris_info->did1 = did1; | |||
stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF); | |||
stellaris_info->num_pages = 2 *(1 + (stellaris_info->dc0 & 0xFFFF)); | |||
stellaris_info->num_pages = 2 * (1 + (stellaris_info->dc0 & 0xFFFF)); | |||
stellaris_info->pagesize = 1024; | |||
stellaris_info->pages_in_lockregion = 2; | |||
@@ -823,8 +814,7 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last) | |||
struct stellaris_flash_bank *stellaris_info = bank->driver_priv; | |||
struct target *target = bank->target; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -833,14 +823,10 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last) | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages)) | |||
{ | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
if ((first == 0) && (last == ((int)stellaris_info->num_pages-1))) | |||
{ | |||
return stellaris_mass_erase(bank); | |||
} | |||
/* Refresh flash controller timing */ | |||
stellaris_read_clock_info(bank); | |||
@@ -854,24 +840,21 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last) | |||
* it might want to process those IRQs. | |||
*/ | |||
for (banknr = first; banknr <= last; banknr++) | |||
{ | |||
for (banknr = first; banknr <= last; banknr++) { | |||
/* Address is first word in page */ | |||
target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize); | |||
/* Write erase command */ | |||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE); | |||
/* Wait until erase complete */ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, FLASH_FMC, &flash_fmc); | |||
} | |||
while (flash_fmc & FMC_ERASE); | |||
} while (flash_fmc & FMC_ERASE); | |||
/* Check acess violations */ | |||
target_read_u32(target, FLASH_CRIS, &flash_cris); | |||
if (flash_cris & (AMASK)) | |||
{ | |||
LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris); | |||
if (flash_cris & (AMASK)) { | |||
LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", | |||
banknr, flash_cris); | |||
target_write_u32(target, FLASH_CRIS, 0); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -890,14 +873,12 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la | |||
struct stellaris_flash_bank *stellaris_info = bank->driver_priv; | |||
struct target *target = bank->target; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (!set) | |||
{ | |||
if (!set) { | |||
LOG_ERROR("Hardware doesn't support page-level unprotect. " | |||
"Try the 'recover' command."); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
@@ -909,8 +890,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la | |||
/* lockregions are 2 pages ... must protect [even..odd] */ | |||
if ((first < 0) || (first & 1) | |||
|| (last < first) || !(last & 1) | |||
|| (last >= 2 * stellaris_info->num_lockbits)) | |||
{ | |||
|| (last >= 2 * stellaris_info->num_lockbits)) { | |||
LOG_ERROR("Can't protect unaligned or out-of-range pages."); | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
@@ -944,7 +924,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la | |||
* it might want to process those IRQs. | |||
*/ | |||
LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe); | |||
LOG_DEBUG("fmppe 0x%" PRIx32 "", fmppe); | |||
target_write_u32(target, SCB_BASE | FMPPE, fmppe); | |||
/* Commit FMPPE */ | |||
@@ -960,16 +940,13 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la | |||
/* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */ | |||
/* Wait until erase complete */ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, FLASH_FMC, &flash_fmc); | |||
} | |||
while (flash_fmc & FMC_COMT); | |||
} while (flash_fmc & FMC_COMT); | |||
/* Check acess violations */ | |||
target_read_u32(target, FLASH_CRIS, &flash_cris); | |||
if (flash_cris & (AMASK)) | |||
{ | |||
if (flash_cris & (AMASK)) { | |||
LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris); | |||
target_write_u32(target, FLASH_CRIS, 0); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
@@ -980,8 +957,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la | |||
/* see contib/loaders/flash/stellaris.s for src */ | |||
static const uint8_t stellaris_write_code[] = | |||
{ | |||
static const uint8_t stellaris_write_code[] = { | |||
/* | |||
Call with : | |||
r0 = buffer address | |||
@@ -995,28 +971,28 @@ static const uint8_t stellaris_write_code[] = | |||
r6 = bytes written | |||
r7 = temp reg | |||
*/ | |||
0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */ | |||
0x08,0x4C, /* ldr r4,FLASHWRITECMD */ | |||
0x01,0x25, /* movs r5, 1 */ | |||
0x00,0x26, /* movs r6, #0 */ | |||
0x07, 0x4B, /* ldr r3,pFLASH_CTRL_BASE */ | |||
0x08, 0x4C, /* ldr r4,FLASHWRITECMD */ | |||
0x01, 0x25, /* movs r5, 1 */ | |||
0x00, 0x26, /* movs r6, #0 */ | |||
/* mainloop: */ | |||
0x19,0x60, /* str r1, [r3, #0] */ | |||
0x87,0x59, /* ldr r7, [r0, r6] */ | |||
0x5F,0x60, /* str r7, [r3, #4] */ | |||
0x9C,0x60, /* str r4, [r3, #8] */ | |||
0x19, 0x60, /* str r1, [r3, #0] */ | |||
0x87, 0x59, /* ldr r7, [r0, r6] */ | |||
0x5F, 0x60, /* str r7, [r3, #4] */ | |||
0x9C, 0x60, /* str r4, [r3, #8] */ | |||
/* waitloop: */ | |||
0x9F,0x68, /* ldr r7, [r3, #8] */ | |||
0x2F,0x42, /* tst r7, r5 */ | |||
0xFC,0xD1, /* bne waitloop */ | |||
0x04,0x31, /* adds r1, r1, #4 */ | |||
0x04,0x36, /* adds r6, r6, #4 */ | |||
0x96,0x42, /* cmp r6, r2 */ | |||
0xF4,0xD1, /* bne mainloop */ | |||
0x00,0xBE, /* bkpt #0 */ | |||
0x9F, 0x68, /* ldr r7, [r3, #8] */ | |||
0x2F, 0x42, /* tst r7, r5 */ | |||
0xFC, 0xD1, /* bne waitloop */ | |||
0x04, 0x31, /* adds r1, r1, #4 */ | |||
0x04, 0x36, /* adds r6, r6, #4 */ | |||
0x96, 0x42, /* cmp r6, r2 */ | |||
0xF4, 0xD1, /* bne mainloop */ | |||
0x00, 0xBE, /* bkpt #0 */ | |||
/* pFLASH_CTRL_BASE: */ | |||
0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */ | |||
0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */ | |||
/* FLASHWRITECMD: */ | |||
0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */ | |||
0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */ | |||
}; | |||
static int stellaris_write_block(struct flash_bank *bank, | |||
@@ -1042,8 +1018,8 @@ static int stellaris_write_block(struct flash_bank *bank, | |||
bank, buffer, offset, wcount); | |||
/* flash write code */ | |||
if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK) | |||
{ | |||
if (target_alloc_working_area(target, sizeof(stellaris_write_code), | |||
&write_algorithm) != ERROR_OK) { | |||
LOG_DEBUG("no working area for block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
@@ -1053,11 +1029,9 @@ static int stellaris_write_block(struct flash_bank *bank, | |||
buffer_size = wcount * 4; | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
if (buffer_size <= buf_min) | |||
{ | |||
if (buffer_size <= buf_min) { | |||
target_free_working_area(target, write_algorithm); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
} | |||
@@ -1076,8 +1050,7 @@ static int stellaris_write_block(struct flash_bank *bank, | |||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); | |||
init_reg_param(®_params[2], "r2", 32, PARAM_OUT); | |||
while (wcount > 0) | |||
{ | |||
while (wcount > 0) { | |||
uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount; | |||
target_write_buffer(target, source->address, thisrun_count * 4, buffer); | |||
@@ -1093,8 +1066,7 @@ static int stellaris_write_block(struct flash_bank *bank, | |||
write_algorithm->address, | |||
0, | |||
10000, &armv7m_info); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error %d executing stellaris " | |||
"flash write algorithm", | |||
retval); | |||
@@ -1121,7 +1093,8 @@ static int stellaris_write_block(struct flash_bank *bank, | |||
return retval; | |||
} | |||
static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) | |||
static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t offset, uint32_t count) | |||
{ | |||
struct stellaris_flash_bank *stellaris_info = bank->driver_priv; | |||
struct target *target = bank->target; | |||
@@ -1132,8 +1105,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of | |||
uint32_t bytes_written = 0; | |||
int retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1144,8 +1116,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of | |||
if (stellaris_info->did1 == 0) | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
if (offset & 0x3) | |||
{ | |||
if (offset & 0x3) { | |||
LOG_WARNING("offset size must be word aligned"); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -1166,36 +1137,28 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of | |||
*/ | |||
/* multiple words to be programmed? */ | |||
if (words_remaining > 0) | |||
{ | |||
if (words_remaining > 0) { | |||
/* try using a block write */ | |||
retval = stellaris_write_block(bank, buffer, offset, | |||
words_remaining); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
LOG_DEBUG("writing flash word-at-a-time"); | |||
} | |||
else if (retval == ERROR_FLASH_OPERATION_FAILED) | |||
{ | |||
} else if (retval == ERROR_FLASH_OPERATION_FAILED) { | |||
/* if an error occured, we examine the reason, and quit */ | |||
target_read_u32(target, FLASH_CRIS, &flash_cris); | |||
LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
buffer += words_remaining * 4; | |||
address += words_remaining * 4; | |||
words_remaining = 0; | |||
} | |||
} | |||
while (words_remaining > 0) | |||
{ | |||
while (words_remaining > 0) { | |||
if (!(address & 0xff)) | |||
LOG_DEBUG("0x%" PRIx32 "", address); | |||
@@ -1205,8 +1168,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of | |||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE); | |||
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */ | |||
/* Wait until write complete */ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, FLASH_FMC, &flash_fmc); | |||
} while (flash_fmc & FMC_WRITE); | |||
@@ -1215,8 +1177,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of | |||
words_remaining--; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff}; | |||
/* copy the last remaining bytes into the write buffer */ | |||
@@ -1231,16 +1192,14 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of | |||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE); | |||
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */ | |||
/* Wait until write complete */ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, FLASH_FMC, &flash_fmc); | |||
} while (flash_fmc & FMC_WRITE); | |||
} | |||
/* Check access violations */ | |||
target_read_u32(target, FLASH_CRIS, &flash_cris); | |||
if (flash_cris & (AMASK)) | |||
{ | |||
if (flash_cris & (AMASK)) { | |||
LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -1266,8 +1225,7 @@ static int stellaris_probe(struct flash_bank *bank) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (bank->sectors) | |||
{ | |||
if (bank->sectors) { | |||
free(bank->sectors); | |||
bank->sectors = NULL; | |||
} | |||
@@ -1276,8 +1234,7 @@ static int stellaris_probe(struct flash_bank *bank) | |||
bank->size = 1024 * stellaris_info->num_pages; | |||
bank->num_sectors = stellaris_info->num_pages; | |||
bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector)); | |||
for (int i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (int i = 0; i < bank->num_sectors; i++) { | |||
bank->sectors[i].offset = i * stellaris_info->pagesize; | |||
bank->sectors[i].size = stellaris_info->pagesize; | |||
bank->sectors[i].is_erased = -1; | |||
@@ -1296,8 +1253,7 @@ static int stellaris_mass_erase(struct flash_bank *bank) | |||
stellaris_info = bank->driver_priv; | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1320,24 +1276,19 @@ static int stellaris_mass_erase(struct flash_bank *bank) | |||
target_write_u32(target, FLASH_FMA, 0); | |||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); | |||
/* Wait until erase complete */ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, FLASH_FMC, &flash_fmc); | |||
} | |||
while (flash_fmc & FMC_MERASE); | |||
} while (flash_fmc & FMC_MERASE); | |||
/* if device has > 128k, then second erase cycle is needed | |||
* this is only valid for older devices, but will not hurt */ | |||
if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) | |||
{ | |||
if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) { | |||
target_write_u32(target, FLASH_FMA, 0x20000); | |||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); | |||
/* Wait until erase complete */ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, FLASH_FMC, &flash_fmc); | |||
} | |||
while (flash_fmc & FMC_MERASE); | |||
} while (flash_fmc & FMC_MERASE); | |||
} | |||
return ERROR_OK; | |||
@@ -1348,29 +1299,21 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command) | |||
int i; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
if (ERROR_OK != retval) | |||
return retval; | |||
if (stellaris_mass_erase(bank) == ERROR_OK) | |||
{ | |||
if (stellaris_mass_erase(bank) == ERROR_OK) { | |||
/* set all sectors as erased */ | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
bank->sectors[i].is_erased = 1; | |||
} | |||
command_print(CMD_CTX, "stellaris mass erase complete"); | |||
} | |||
else | |||
{ | |||
} else | |||
command_print(CMD_CTX, "stellaris mass erase failed"); | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -23,6 +23,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -101,15 +102,13 @@ | |||
#define KEY1 0x45670123 | |||
#define KEY2 0xCDEF89AB | |||
struct stm32x_options | |||
{ | |||
struct stm32x_options { | |||
uint16_t RDP; | |||
uint16_t user_options; | |||
uint16_t protection[4]; | |||
}; | |||
struct stm32x_flash_bank | |||
{ | |||
struct stm32x_flash_bank { | |||
struct stm32x_options option_bytes; | |||
struct working_area *write_algorithm; | |||
int ppage_size; | |||
@@ -129,9 +128,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command) | |||
struct stm32x_flash_bank *stm32x_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); | |||
bank->driver_priv = stm32x_info; | |||
@@ -163,37 +160,32 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) | |||
int retval = ERROR_OK; | |||
/* wait for busy to clear */ | |||
for (;;) | |||
{ | |||
for (;;) { | |||
retval = stm32x_get_flash_status(bank, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
LOG_DEBUG("status: 0x%" PRIx32 "", status); | |||
if ((status & FLASH_BSY) == 0) | |||
break; | |||
if (timeout-- <= 0) | |||
{ | |||
if (timeout-- <= 0) { | |||
LOG_ERROR("timed out waiting for flash"); | |||
return ERROR_FAIL; | |||
} | |||
alive_sleep(1); | |||
} | |||
if (status & FLASH_WRPRTERR) | |||
{ | |||
if (status & FLASH_WRPRTERR) { | |||
LOG_ERROR("stm32x device protected"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (status & FLASH_PGERR) | |||
{ | |||
if (status & FLASH_PGERR) { | |||
LOG_ERROR("stm32x device programming failed"); | |||
retval = ERROR_FAIL; | |||
} | |||
/* Clear but report errors */ | |||
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) | |||
{ | |||
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) { | |||
/* If this operation fails, we ignore it and report the original | |||
* retval | |||
*/ | |||
@@ -209,8 +201,7 @@ int stm32x_check_operation_supported(struct flash_bank *bank) | |||
/* if we have a dual flash bank device then | |||
* we need to perform option byte stuff on bank0 only */ | |||
if (stm32x_info->register_base != FLASH_REG_BASE_B0) | |||
{ | |||
if (stm32x_info->register_base != FLASH_REG_BASE_B0) { | |||
LOG_ERROR("Option Byte Operation's must use bank0"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -395,8 +386,7 @@ static int stm32x_protect_check(struct flash_bank *bank) | |||
int num_bits; | |||
int set; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -415,8 +405,7 @@ static int stm32x_protect_check(struct flash_bank *bank) | |||
* high density - each protection bit is for 2 * 2K pages */ | |||
num_bits = (bank->num_sectors / stm32x_info->ppage_size); | |||
if (stm32x_info->ppage_size == 2) | |||
{ | |||
if (stm32x_info->ppage_size == 2) { | |||
/* high density flash/connectivity line protection */ | |||
set = 1; | |||
@@ -427,15 +416,12 @@ static int stm32x_protect_check(struct flash_bank *bank) | |||
/* bit 31 controls sector 62 - 255 protection for high density | |||
* bit 31 controls sector 62 - 127 protection for connectivity line */ | |||
for (s = 62; s < bank->num_sectors; s++) | |||
{ | |||
bank->sectors[s].is_protected = set; | |||
} | |||
if (bank->num_sectors > 61) | |||
num_bits = 31; | |||
for (i = 0; i < num_bits; i++) | |||
{ | |||
for (i = 0; i < num_bits; i++) { | |||
set = 1; | |||
if (protection & (1 << i)) | |||
@@ -444,12 +430,9 @@ static int stm32x_protect_check(struct flash_bank *bank) | |||
for (s = 0; s < stm32x_info->ppage_size; s++) | |||
bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
/* low/medium density flash protection */ | |||
for (i = 0; i < num_bits; i++) | |||
{ | |||
for (i = 0; i < num_bits; i++) { | |||
set = 1; | |||
if (protection & (1 << i)) | |||
@@ -468,16 +451,13 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last) | |||
struct target *target = bank->target; | |||
int i; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((first == 0) && (last == (bank->num_sectors - 1))) | |||
{ | |||
return stm32x_mass_erase(bank); | |||
} | |||
/* unlock flash registers */ | |||
int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1); | |||
@@ -487,8 +467,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
@@ -526,8 +505,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) | |||
stm32x_info = bank->driver_priv; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -536,14 +514,12 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) | |||
if (ERROR_OK != retval) | |||
return retval; | |||
if ((first % stm32x_info->ppage_size) != 0) | |||
{ | |||
if ((first % stm32x_info->ppage_size) != 0) { | |||
LOG_WARNING("aligned start protect sector to a %d sector boundary", | |||
stm32x_info->ppage_size); | |||
first = first - (first % stm32x_info->ppage_size); | |||
} | |||
if (((last + 1) % stm32x_info->ppage_size) != 0) | |||
{ | |||
if (((last + 1) % stm32x_info->ppage_size) != 0) { | |||
LOG_WARNING("aligned end protect sector to a %d sector boundary", | |||
stm32x_info->ppage_size); | |||
last++; | |||
@@ -562,13 +538,11 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) | |||
prot_reg[2] = (uint16_t)(protection >> 16); | |||
prot_reg[3] = (uint16_t)(protection >> 24); | |||
if (stm32x_info->ppage_size == 2) | |||
{ | |||
if (stm32x_info->ppage_size == 2) { | |||
/* high density flash */ | |||
/* bit 7 controls sector 62 - 255 protection */ | |||
if (last > 61) | |||
{ | |||
if (last > 61) { | |||
if (set) | |||
prot_reg[3] &= ~(1 << 7); | |||
else | |||
@@ -580,8 +554,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) | |||
if (last > 61) | |||
last = 61; | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
reg = (i / stm32x_info->ppage_size) / 8; | |||
bit = (i / stm32x_info->ppage_size) - (reg * 8); | |||
@@ -590,12 +563,9 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) | |||
else | |||
prot_reg[reg] |= (1 << bit); | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
/* medium density flash */ | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
reg = (i / stm32x_info->ppage_size) / 8; | |||
bit = (i / stm32x_info->ppage_size) - (reg * 8); | |||
@@ -606,7 +576,8 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) | |||
} | |||
} | |||
if ((status = stm32x_erase_options(bank)) != ERROR_OK) | |||
status = stm32x_erase_options(bank); | |||
if (status != ERROR_OK) | |||
return status; | |||
stm32x_info->option_bytes.protection[0] = prot_reg[0]; | |||
@@ -675,24 +646,21 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
/* flash write code */ | |||
if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), | |||
&stm32x_info->write_algorithm) != ERROR_OK) | |||
{ | |||
&stm32x_info->write_algorithm) != ERROR_OK) { | |||
LOG_WARNING("no working area available, can't do block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address, | |||
sizeof(stm32x_flash_write_code), | |||
(uint8_t*)stm32x_flash_write_code)) != ERROR_OK) | |||
retval = target_write_buffer(target, stm32x_info->write_algorithm->address, | |||
sizeof(stm32x_flash_write_code), (uint8_t *)stm32x_flash_write_code); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
buffer_size &= ~3UL; // Make sure it's 4 byte aligned | |||
if (buffer_size <= 256) | |||
{ | |||
buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a | |||
* buffer, free the algorithm */ | |||
if (stm32x_info->write_algorithm) | |||
@@ -736,35 +704,31 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
armv7m_info.core_mode = ARMV7M_MODE_ANY; | |||
/* Start up algorithm on target and let it idle while writing the first chunk */ | |||
if ((retval = target_start_algorithm(target, 0, NULL, 5, reg_params, | |||
retval = target_start_algorithm(target, 0, NULL, 5, reg_params, | |||
stm32x_info->write_algorithm->address, | |||
0, | |||
&armv7m_info)) != ERROR_OK) | |||
{ | |||
&armv7m_info); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error starting stm32x flash write algorithm"); | |||
goto cleanup; | |||
} | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
retval = target_read_u32(target, rp_addr, &rp); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("failed to get read pointer"); | |||
break; | |||
} | |||
LOG_DEBUG("count 0x%"PRIx32" wp 0x%"PRIx32" rp 0x%"PRIx32, count, wp, rp); | |||
if (rp == 0) | |||
{ | |||
if (rp == 0) { | |||
LOG_ERROR("flash write algorithm aborted by target"); | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
} | |||
if ((rp & 1) || rp < fifo_start_addr || rp >= fifo_end_addr) | |||
{ | |||
if ((rp & 1) || rp < fifo_start_addr || rp >= fifo_end_addr) { | |||
LOG_ERROR("corrupted fifo read pointer 0x%"PRIx32, rp); | |||
break; | |||
} | |||
@@ -780,8 +744,7 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
else | |||
thisrun_bytes = fifo_end_addr - wp - 2; | |||
if (thisrun_bytes == 0) | |||
{ | |||
if (thisrun_bytes == 0) { | |||
/* Throttle polling a bit if transfer is (much) faster than flash | |||
* programming. The exact delay shouldn't matter as long as it's | |||
* less than buffer size / flash speed. This is very unlikely to | |||
@@ -812,36 +775,29 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
break; | |||
} | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
/* abort flash write algorithm on target */ | |||
target_write_u32(target, wp_addr, 0); | |||
} | |||
int retval2; | |||
if ((retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params, | |||
0, | |||
10000, | |||
&armv7m_info)) != ERROR_OK) | |||
{ | |||
int retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params, | |||
0, 10000, &armv7m_info); | |||
if (retval2 != ERROR_OK) { | |||
LOG_ERROR("error waiting for stm32x flash write algorithm"); | |||
retval = retval2; | |||
} | |||
if (retval == ERROR_FLASH_OPERATION_FAILED) | |||
{ | |||
if (retval == ERROR_FLASH_OPERATION_FAILED) { | |||
LOG_ERROR("flash write failed at address 0x%"PRIx32, | |||
buf_get_u32(reg_params[4].value, 0, 32)); | |||
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) | |||
{ | |||
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) { | |||
LOG_ERROR("flash memory not erased before writing"); | |||
/* Clear but report errors */ | |||
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_PGERR); | |||
} | |||
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) | |||
{ | |||
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) { | |||
LOG_ERROR("flash memory write protected"); | |||
/* Clear but report errors */ | |||
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_WRPRTERR); | |||
@@ -871,14 +827,12 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t bytes_written = 0; | |||
int retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (offset & 0x1) | |||
{ | |||
if (offset & 0x1) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -892,20 +846,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
return retval; | |||
/* multiple half words (2-byte) to be programmed? */ | |||
if (words_remaining > 0) | |||
{ | |||
if (words_remaining > 0) { | |||
/* try using a block write */ | |||
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
retval = stm32x_write_block(bank, buffer, offset, words_remaining); | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
/* if block write failed (no sufficient working area), | |||
* we use normal (slow) single dword accesses */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
buffer += words_remaining * 2; | |||
address += words_remaining * 2; | |||
words_remaining = 0; | |||
@@ -915,8 +865,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)) | |||
return retval; | |||
while (words_remaining > 0) | |||
{ | |||
while (words_remaining > 0) { | |||
uint16_t value; | |||
memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); | |||
@@ -936,8 +885,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
address += 2; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint16_t value = 0xffff; | |||
memcpy(&value, buffer + bytes_written, bytes_remaining); | |||
@@ -977,8 +925,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
/* get flash size from target. */ | |||
retval = target_read_u16(target, 0x1FFFF7E0, &flash_size_in_kb); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
LOG_WARNING("failed reading flash size, default to max target family"); | |||
/* failed reading flash size, default to max target family */ | |||
flash_size_in_kb = 0xffff; | |||
@@ -991,8 +938,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
stm32x_info->ppage_size = 4; | |||
/* check for early silicon */ | |||
if (flash_size_in_kb == 0xffff) | |||
{ | |||
if (flash_size_in_kb == 0xffff) { | |||
/* number of sectors incorrect on revA */ | |||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash"); | |||
flash_size_in_kb = 128; | |||
@@ -1004,8 +950,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
stm32x_info->ppage_size = 4; | |||
/* check for early silicon */ | |||
if (flash_size_in_kb == 0xffff) | |||
{ | |||
if (flash_size_in_kb == 0xffff) { | |||
/* number of sectors incorrect on revA */ | |||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash"); | |||
flash_size_in_kb = 32; | |||
@@ -1017,8 +962,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
stm32x_info->ppage_size = 2; | |||
/* check for early silicon */ | |||
if (flash_size_in_kb == 0xffff) | |||
{ | |||
if (flash_size_in_kb == 0xffff) { | |||
/* number of sectors incorrect on revZ */ | |||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash"); | |||
flash_size_in_kb = 512; | |||
@@ -1030,8 +974,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
stm32x_info->ppage_size = 2; | |||
/* check for early silicon */ | |||
if (flash_size_in_kb == 0xffff) | |||
{ | |||
if (flash_size_in_kb == 0xffff) { | |||
/* number of sectors incorrect on revZ */ | |||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash"); | |||
flash_size_in_kb = 256; | |||
@@ -1043,8 +986,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
stm32x_info->ppage_size = 4; | |||
/* check for early silicon */ | |||
if (flash_size_in_kb == 0xffff) | |||
{ | |||
if (flash_size_in_kb == 0xffff) { | |||
/* number of sectors may be incorrrect on early silicon */ | |||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash"); | |||
flash_size_in_kb = 128; | |||
@@ -1056,8 +998,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
stm32x_info->ppage_size = 4; | |||
/* check for early silicon */ | |||
if (flash_size_in_kb == 0xffff) | |||
{ | |||
if (flash_size_in_kb == 0xffff) { | |||
/* number of sectors may be incorrrect on early silicon */ | |||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash"); | |||
flash_size_in_kb = 128; | |||
@@ -1070,29 +1011,23 @@ static int stm32x_probe(struct flash_bank *bank) | |||
stm32x_info->has_dual_banks = true; | |||
/* check for early silicon */ | |||
if (flash_size_in_kb == 0xffff) | |||
{ | |||
if (flash_size_in_kb == 0xffff) { | |||
/* number of sectors may be incorrrect on early silicon */ | |||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 1024k flash"); | |||
flash_size_in_kb = 1024; | |||
} | |||
/* split reported size into matching bank */ | |||
if (bank->base != 0x08080000) | |||
{ | |||
if (bank->base != 0x08080000) { | |||
/* bank 0 will be fixed 512k */ | |||
flash_size_in_kb = 512; | |||
} | |||
else | |||
{ | |||
} else { | |||
flash_size_in_kb -= 512; | |||
/* bank1 also uses a register offset */ | |||
stm32x_info->register_base = FLASH_REG_BASE_B1; | |||
base_address = 0x08080000; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
LOG_WARNING("Cannot identify target as a STM32 family."); | |||
return ERROR_FAIL; | |||
} | |||
@@ -1108,8 +1043,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
/* check that calculation result makes sense */ | |||
assert(num_pages > 0); | |||
if (bank->sectors) | |||
{ | |||
if (bank->sectors) { | |||
free(bank->sectors); | |||
bank->sectors = NULL; | |||
} | |||
@@ -1119,8 +1053,7 @@ static int stm32x_probe(struct flash_bank *bank) | |||
bank->num_sectors = num_pages; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); | |||
for (i = 0; i < num_pages; i++) | |||
{ | |||
for (i = 0; i < num_pages; i++) { | |||
bank->sectors[i].offset = i * page_size; | |||
bank->sectors[i].size = page_size; | |||
bank->sectors[i].is_erased = -1; | |||
@@ -1163,8 +1096,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x0000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -1190,8 +1122,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x1000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -1205,8 +1136,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x1000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -1224,8 +1154,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x1000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -1243,8 +1172,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x1000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -1262,8 +1190,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x1000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -1281,8 +1208,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x1000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -1291,9 +1217,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) | |||
snprintf(buf, buf_size, "unknown"); | |||
break; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
snprintf(buf, buf_size, "Cannot identify target as a stm32x\n"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -1307,9 +1231,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command) | |||
struct stm32x_flash_bank *stm32x_info = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1320,8 +1242,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command) | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1330,8 +1251,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command) | |||
if (ERROR_OK != retval) | |||
return retval; | |||
if (stm32x_erase_options(bank) != ERROR_OK) | |||
{ | |||
if (stm32x_erase_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "stm32x failed to erase options"); | |||
return ERROR_OK; | |||
} | |||
@@ -1339,8 +1259,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command) | |||
/* set readout protection */ | |||
stm32x_info->option_bytes.RDP = 0; | |||
if (stm32x_write_options(bank) != ERROR_OK) | |||
{ | |||
if (stm32x_write_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "stm32x failed to lock device"); | |||
return ERROR_OK; | |||
} | |||
@@ -1355,9 +1274,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) | |||
struct target *target = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1366,8 +1283,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1376,14 +1292,12 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) | |||
if (ERROR_OK != retval) | |||
return retval; | |||
if (stm32x_erase_options(bank) != ERROR_OK) | |||
{ | |||
if (stm32x_erase_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "stm32x failed to unlock device"); | |||
return ERROR_OK; | |||
} | |||
if (stm32x_write_options(bank) != ERROR_OK) | |||
{ | |||
if (stm32x_write_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "stm32x failed to lock device"); | |||
return ERROR_OK; | |||
} | |||
@@ -1402,9 +1316,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command) | |||
struct stm32x_flash_bank *stm32x_info = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1415,8 +1327,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command) | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1430,32 +1341,31 @@ COMMAND_HANDLER(stm32x_handle_options_read_command) | |||
return retval; | |||
command_print(CMD_CTX, "Option Byte: 0x%" PRIx32 "", optionbyte); | |||
if (buf_get_u32((uint8_t*)&optionbyte, OPT_ERROR, 1)) | |||
if (buf_get_u32((uint8_t *)&optionbyte, OPT_ERROR, 1)) | |||
command_print(CMD_CTX, "Option Byte Complement Error"); | |||
if (buf_get_u32((uint8_t*)&optionbyte, OPT_READOUT, 1)) | |||
if (buf_get_u32((uint8_t *)&optionbyte, OPT_READOUT, 1)) | |||
command_print(CMD_CTX, "Readout Protection On"); | |||
else | |||
command_print(CMD_CTX, "Readout Protection Off"); | |||
if (buf_get_u32((uint8_t*)&optionbyte, OPT_RDWDGSW, 1)) | |||
if (buf_get_u32((uint8_t *)&optionbyte, OPT_RDWDGSW, 1)) | |||
command_print(CMD_CTX, "Software Watchdog"); | |||
else | |||
command_print(CMD_CTX, "Hardware Watchdog"); | |||
if (buf_get_u32((uint8_t*)&optionbyte, OPT_RDRSTSTOP, 1)) | |||
if (buf_get_u32((uint8_t *)&optionbyte, OPT_RDRSTSTOP, 1)) | |||
command_print(CMD_CTX, "Stop: No reset generated"); | |||
else | |||
command_print(CMD_CTX, "Stop: Reset generated"); | |||
if (buf_get_u32((uint8_t*)&optionbyte, OPT_RDRSTSTDBY, 1)) | |||
if (buf_get_u32((uint8_t *)&optionbyte, OPT_RDRSTSTDBY, 1)) | |||
command_print(CMD_CTX, "Standby: No reset generated"); | |||
else | |||
command_print(CMD_CTX, "Standby: Reset generated"); | |||
if (stm32x_info->has_dual_banks) | |||
{ | |||
if (buf_get_u32((uint8_t*)&optionbyte, OPT_BFB2, 1)) | |||
if (stm32x_info->has_dual_banks) { | |||
if (buf_get_u32((uint8_t *)&optionbyte, OPT_BFB2, 1)) | |||
command_print(CMD_CTX, "Boot: Bank 0"); | |||
else | |||
command_print(CMD_CTX, "Boot: Bank 1"); | |||
@@ -1471,9 +1381,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command) | |||
uint16_t optionbyte = 0xF8; | |||
if (CMD_ARGC < 4) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1484,8 +1392,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command) | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1500,57 +1407,38 @@ COMMAND_HANDLER(stm32x_handle_options_write_command) | |||
/* OPT_RDWDGSW */ | |||
if (strcmp(CMD_ARGV[1], "SWWDG") == 0) | |||
{ | |||
optionbyte |= (1 << 0); | |||
} | |||
else /* REVISIT must be "HWWDG" then ... */ | |||
{ | |||
optionbyte &= ~(1 << 0); | |||
} | |||
/* OPT_RDRSTSTOP */ | |||
if (strcmp(CMD_ARGV[2], "NORSTSTOP") == 0) | |||
{ | |||
optionbyte |= (1 << 1); | |||
} | |||
else /* REVISIT must be "RSTSTNDBY" then ... */ | |||
{ | |||
optionbyte &= ~(1 << 1); | |||
} | |||
/* OPT_RDRSTSTDBY */ | |||
if (strcmp(CMD_ARGV[3], "NORSTSTNDBY") == 0) | |||
{ | |||
optionbyte |= (1 << 2); | |||
} | |||
else /* REVISIT must be "RSTSTOP" then ... */ | |||
{ | |||
optionbyte &= ~(1 << 2); | |||
} | |||
if (CMD_ARGC > 4 && stm32x_info->has_dual_banks) | |||
{ | |||
if (CMD_ARGC > 4 && stm32x_info->has_dual_banks) { | |||
/* OPT_BFB2 */ | |||
if (strcmp(CMD_ARGV[4], "BOOT0") == 0) | |||
{ | |||
optionbyte |= (1 << 3); | |||
} | |||
else | |||
{ | |||
optionbyte &= ~(1 << 3); | |||
} | |||
} | |||
if (stm32x_erase_options(bank) != ERROR_OK) | |||
{ | |||
if (stm32x_erase_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "stm32x failed to erase options"); | |||
return ERROR_OK; | |||
} | |||
stm32x_info->option_bytes.user_options = optionbyte; | |||
if (stm32x_write_options(bank) != ERROR_OK) | |||
{ | |||
if (stm32x_write_options(bank) != ERROR_OK) { | |||
command_print(CMD_CTX, "stm32x failed to write options"); | |||
return ERROR_OK; | |||
} | |||
@@ -1566,8 +1454,7 @@ static int stm32x_mass_erase(struct flash_bank *bank) | |||
{ | |||
struct target *target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1584,7 +1471,8 @@ static int stm32x_mass_erase(struct flash_bank *bank) | |||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER | FLASH_STRT); | |||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), | |||
FLASH_MER | FLASH_STRT); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
@@ -1604,9 +1492,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command) | |||
int i; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1614,20 +1500,14 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command) | |||
return retval; | |||
retval = stm32x_mass_erase(bank); | |||
if (retval == ERROR_OK) | |||
{ | |||
if (retval == ERROR_OK) { | |||
/* set all sectors as erased */ | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
bank->sectors[i].is_erased = 1; | |||
} | |||
command_print(CMD_CTX, "stm32x mass erase complete"); | |||
} | |||
else | |||
{ | |||
} else | |||
command_print(CMD_CTX, "stm32x mass erase failed"); | |||
} | |||
return retval; | |||
} | |||
@@ -23,6 +23,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -70,7 +71,8 @@ | |||
* http://www.st.com/internet/mcu/product/250192.jsp | |||
* | |||
* PM0059 | |||
* www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/PROGRAMMING_MANUAL/CD00233952.pdf | |||
* www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/ | |||
* PROGRAMMING_MANUAL/CD00233952.pdf | |||
* | |||
* STM32F1x series - notice that this code was copy, pasted and knocked | |||
* into a stm32f2x driver, so in case something has been converted or | |||
@@ -85,11 +87,10 @@ | |||
* | |||
*/ | |||
// Erase time can be as high as 1000ms, 10x this and it's toast... | |||
/* Erase time can be as high as 1000ms, 10x this and it's toast... */ | |||
#define FLASH_ERASE_TIMEOUT 10000 | |||
#define FLASH_WRITE_TIMEOUT 5 | |||
#define STM32_FLASH_BASE 0x40023c00 | |||
#define STM32_FLASH_ACR 0x40023c00 | |||
#define STM32_FLASH_KEYR 0x40023c04 | |||
@@ -99,8 +100,6 @@ | |||
#define STM32_FLASH_OPTCR 0x40023c14 | |||
#define STM32_FLASH_OBR 0x40023c1C | |||
/* option byte location */ | |||
#define STM32_OB_RDP 0x1FFFF800 | |||
@@ -122,19 +121,19 @@ | |||
#define FLASH_PSIZE_16 (1 << 8) | |||
#define FLASH_PSIZE_32 (2 << 8) | |||
#define FLASH_PSIZE_64 (3 << 8) | |||
#define FLASH_SNB(a) ((a) << 3) | |||
#define FLASH_SNB(a) ((a) << 3) | |||
#define FLASH_LOCK (1 << 31) | |||
/* FLASH_SR register bits */ | |||
#define FLASH_BSY (1 << 16) | |||
#define FLASH_PGSERR (1 << 7) // Programming sequence error | |||
#define FLASH_PGPERR (1 << 6) // Programming parallelism error | |||
#define FLASH_PGAERR (1 << 5) // Programming alignment error | |||
#define FLASH_WRPERR (1 << 4) // Write protection error | |||
#define FLASH_OPERR (1 << 1) // Operation error | |||
#define FLASH_PGSERR (1 << 7) /* Programming sequence error */ | |||
#define FLASH_PGPERR (1 << 6) /* Programming parallelism error */ | |||
#define FLASH_PGAERR (1 << 5) /* Programming alignment error */ | |||
#define FLASH_WRPERR (1 << 4) /* Write protection error */ | |||
#define FLASH_OPERR (1 << 1) /* Operation error */ | |||
#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR| FLASH_WRPERR| FLASH_OPERR) | |||
#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR) | |||
/* STM32_FLASH_OBR bit definitions (reading) */ | |||
@@ -150,8 +149,7 @@ | |||
#define KEY1 0x45670123 | |||
#define KEY2 0xCDEF89AB | |||
struct stm32x_flash_bank | |||
{ | |||
struct stm32x_flash_bank { | |||
struct working_area *write_algorithm; | |||
int probed; | |||
}; | |||
@@ -164,9 +162,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command) | |||
struct stm32x_flash_bank *stm32x_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); | |||
bank->driver_priv = stm32x_info; | |||
@@ -195,16 +191,14 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) | |||
int retval = ERROR_OK; | |||
/* wait for busy to clear */ | |||
for (;;) | |||
{ | |||
for (;;) { | |||
retval = stm32x_get_flash_status(bank, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
LOG_DEBUG("status: 0x%" PRIx32 "", status); | |||
if ((status & FLASH_BSY) == 0) | |||
break; | |||
if (timeout-- <= 0) | |||
{ | |||
if (timeout-- <= 0) { | |||
LOG_ERROR("timed out waiting for flash"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -212,15 +206,13 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) | |||
} | |||
if (status & FLASH_WRPERR) | |||
{ | |||
if (status & FLASH_WRPERR) { | |||
LOG_ERROR("stm32x device protected"); | |||
retval = ERROR_FAIL; | |||
} | |||
/* Clear but report errors */ | |||
if (status & FLASH_ERROR) | |||
{ | |||
if (status & FLASH_ERROR) { | |||
/* If this operation fails, we ignore it and report the original | |||
* retval | |||
*/ | |||
@@ -275,8 +267,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last) | |||
struct target *target = bank->target; | |||
int i; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -297,8 +288,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last) | |||
4. Wait for the BSY bit to be cleared | |||
*/ | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
retval = target_write_u32(target, | |||
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT); | |||
if (retval != ERROR_OK) | |||
@@ -361,30 +351,27 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
/* Flip endian */ | |||
uint8_t stm32x_flash_write_code[sizeof(stm32x_flash_write_code_16)*2]; | |||
for (unsigned i = 0; i < sizeof(stm32x_flash_write_code_16) / 2; i++) | |||
{ | |||
for (unsigned i = 0; i < sizeof(stm32x_flash_write_code_16) / 2; i++) { | |||
stm32x_flash_write_code[i*2 + 0] = stm32x_flash_write_code_16[i] & 0xff; | |||
stm32x_flash_write_code[i*2 + 1] = (stm32x_flash_write_code_16[i] >> 8) & 0xff; | |||
} | |||
if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), | |||
&stm32x_info->write_algorithm) != ERROR_OK) | |||
{ | |||
&stm32x_info->write_algorithm) != ERROR_OK) { | |||
LOG_WARNING("no working area available, can't do block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address, | |||
retval = target_write_buffer(target, stm32x_info->write_algorithm->address, | |||
sizeof(stm32x_flash_write_code), | |||
(uint8_t*)stm32x_flash_write_code)) != ERROR_OK) | |||
(uint8_t *)stm32x_flash_write_code); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
if (buffer_size <= 256) | |||
{ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a | |||
* buffer, free the algorithm */ | |||
if (stm32x_info->write_algorithm) | |||
@@ -404,28 +391,27 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT); | |||
init_reg_param(®_params[4], "r4", 32, PARAM_OUT); | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
uint32_t thisrun_count = (count > (buffer_size / 2)) ? | |||
(buffer_size / 2) : count; | |||
if ((retval = target_write_buffer(target, source->address, | |||
thisrun_count * 2, buffer)) != ERROR_OK) | |||
retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer); | |||
if (retval != ERROR_OK) | |||
break; | |||
buf_set_u32(reg_params[0].value, 0, 32, source->address); | |||
buf_set_u32(reg_params[1].value, 0, 32, address); | |||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); | |||
// R3 is a return value only | |||
/* R3 is a return value only */ | |||
buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE); | |||
if ((retval = target_run_algorithm(target, 0, NULL, | |||
retval = target_run_algorithm(target, 0, NULL, | |||
sizeof(reg_params) / sizeof(*reg_params), | |||
reg_params, | |||
stm32x_info->write_algorithm->address, | |||
0, | |||
10000, &armv7m_info)) != ERROR_OK) | |||
{ | |||
10000, &armv7m_info); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error executing stm32x flash write algorithm"); | |||
break; | |||
} | |||
@@ -433,12 +419,9 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t error = buf_get_u32(reg_params[3].value, 0, 32) & FLASH_ERROR; | |||
if (error & FLASH_WRPERR) | |||
{ | |||
LOG_ERROR("flash memory write protected"); | |||
} | |||
if (error != 0) | |||
{ | |||
if (error != 0) { | |||
LOG_ERROR("flash write failed = %08x", error); | |||
/* Clear but report errors */ | |||
target_write_u32(target, STM32_FLASH_SR, error); | |||
@@ -473,14 +456,12 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t bytes_written = 0; | |||
int retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (offset & 0x1) | |||
{ | |||
if (offset & 0x1) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
@@ -490,20 +471,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
return retval; | |||
/* multiple half words (2-byte) to be programmed? */ | |||
if (words_remaining > 0) | |||
{ | |||
if (words_remaining > 0) { | |||
/* try using a block write */ | |||
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
retval = stm32x_write_block(bank, buffer, offset, words_remaining); | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
/* if block write failed (no sufficient working area), | |||
* we use normal (slow) single dword accesses */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
buffer += words_remaining * 2; | |||
address += words_remaining * 2; | |||
words_remaining = 0; | |||
@@ -529,8 +506,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
Double word access in case of x64 parallelism | |||
Wait for the BSY bit to be cleared | |||
*/ | |||
while (words_remaining > 0) | |||
{ | |||
while (words_remaining > 0) { | |||
uint16_t value; | |||
memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); | |||
@@ -552,8 +528,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
address += 2; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), | |||
FLASH_PG | FLASH_PSIZE_8); | |||
if (retval != ERROR_OK) | |||
@@ -572,8 +547,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer, | |||
static void setup_sector(struct flash_bank *bank, int start, int num, int size) | |||
{ | |||
for (int i = start; i < (start + num) ; i++) | |||
{ | |||
for (int i = start; i < (start + num) ; i++) { | |||
bank->sectors[i].offset = bank->size; | |||
bank->sectors[i].size = size; | |||
bank->size += bank->sectors[i].size; | |||
@@ -23,6 +23,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -117,8 +118,7 @@ static int stm32lx_enable_write_half_page(struct flash_bank *bank); | |||
static int stm32lx_erase_sector(struct flash_bank *bank, int sector); | |||
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank); | |||
struct stm32lx_flash_bank | |||
{ | |||
struct stm32lx_flash_bank { | |||
struct working_area *write_algorithm; | |||
int probed; | |||
}; | |||
@@ -129,16 +129,13 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command) | |||
{ | |||
struct stm32lx_flash_bank *stm32lx_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
// Create the bank structure | |||
/* Create the bank structure */ | |||
stm32lx_info = malloc(sizeof(struct stm32lx_flash_bank)); | |||
// Check allocation | |||
if (stm32lx_info == NULL) | |||
{ | |||
/* Check allocation */ | |||
if (stm32lx_info == NULL) { | |||
LOG_ERROR("failed to allocate bank structure"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -158,8 +155,7 @@ static int stm32lx_protect_check(struct flash_bank *bank) | |||
uint32_t wrpr; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -172,16 +168,11 @@ static int stm32lx_protect_check(struct flash_bank *bank) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
for (int i = 0; i < 32; i++) | |||
{ | |||
for (int i = 0; i < 32; i++) { | |||
if (wrpr & (1 << i)) | |||
{ | |||
bank->sectors[i].is_protected = 1; | |||
} | |||
else | |||
{ | |||
bank->sectors[i].is_protected = 0; | |||
} | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -195,8 +186,7 @@ static int stm32lx_erase(struct flash_bank *bank, int first, int last) | |||
* erased, but it is not implemented yet. | |||
*/ | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -204,8 +194,7 @@ static int stm32lx_erase(struct flash_bank *bank, int first, int last) | |||
/* | |||
* Loop over the selected sectors and erase them | |||
*/ | |||
for (int i = first; i <= last; i++) | |||
{ | |||
for (int i = first; i <= last; i++) { | |||
retval = stm32lx_erase_sector(bank, i); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
@@ -238,72 +227,66 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, | |||
/* see contib/loaders/flash/stm32lx.s for src */ | |||
static const uint16_t stm32lx_flash_write_code_16[] = | |||
{ | |||
// 00000000 <write_word-0x4>: | |||
0x2300, // 0: 2300 movs r3, #0 | |||
0xe004, // 2: e004 b.n e <test_done> | |||
static const uint16_t stm32lx_flash_write_code_16[] = { | |||
/* 00000000 <write_word-0x4>: */ | |||
0x2300, /* 0: 2300 movs r3, #0 */ | |||
0xe004, /* 2: e004 b.n e <test_done> */ | |||
// 00000004 <write_word>: | |||
0xf851, 0xcb04, // 4: f851 cb04 ldr.w ip, [r1], #4 | |||
0xf840, 0xcb04, // 8: f840 cb04 str.w ip, [r0], #4 | |||
0x3301, // c: 3301 adds r3, #1 | |||
/* 00000004 <write_word>: */ | |||
0xf851, 0xcb04, /* 4: f851 cb04 ldr.w ip, [r1], #4 */ | |||
0xf840, 0xcb04, /* 8: f840 cb04 str.w ip, [r0], #4 */ | |||
0x3301, /* c: 3301 adds r3, #1 */ | |||
// 0000000e <test_done>: | |||
0x4293, // e: 4293 cmp r3, r2 | |||
0xd3f8, // 10: d3f8 bcc.n 4 <write_word> | |||
0xbe00, // 12: be00 bkpt 0x0000 | |||
/* 0000000e <test_done>: */ | |||
0x4293, /* e: 4293 cmp r3, r2 */ | |||
0xd3f8, /* 10: d3f8 bcc.n 4 <write_word> */ | |||
0xbe00, /* 12: be00 bkpt 0x0000 */ | |||
}; | |||
// Flip endian | |||
/* Flip endian */ | |||
uint8_t stm32lx_flash_write_code[sizeof(stm32lx_flash_write_code_16)]; | |||
for (unsigned int i = 0; i < sizeof(stm32lx_flash_write_code_16) / 2; i++) | |||
{ | |||
for (unsigned int i = 0; i < sizeof(stm32lx_flash_write_code_16) / 2; i++) { | |||
stm32lx_flash_write_code[i * 2 + 0] = stm32lx_flash_write_code_16[i] | |||
& 0xff; | |||
stm32lx_flash_write_code[i * 2 + 1] = (stm32lx_flash_write_code_16[i] | |||
>> 8) & 0xff; | |||
} | |||
// Check if there is an even number of half pages (128bytes) | |||
if (count % 128) | |||
{ | |||
/* Check if there is an even number of half pages (128bytes) */ | |||
if (count % 128) { | |||
LOG_ERROR("there should be an even number " | |||
"of half pages = 128 bytes (count = %" PRIi32 " bytes)", count); | |||
return ERROR_FAIL; | |||
} | |||
// Allocate working area | |||
/* Allocate working area */ | |||
reg32 = sizeof(stm32lx_flash_write_code); | |||
// Add bytes to make 4byte aligned | |||
/* Add bytes to make 4byte aligned */ | |||
reg32 += (4 - (reg32 % 4)) % 4; | |||
retval = target_alloc_working_area(target, reg32, | |||
&stm32lx_info->write_algorithm); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
// Write the flashing code | |||
/* Write the flashing code */ | |||
retval = target_write_buffer(target, | |||
stm32lx_info->write_algorithm->address, | |||
sizeof(stm32lx_flash_write_code), | |||
(uint8_t*) stm32lx_flash_write_code); | |||
if (retval != ERROR_OK) | |||
{ | |||
(uint8_t *)stm32lx_flash_write_code); | |||
if (retval != ERROR_OK) { | |||
target_free_working_area(target, stm32lx_info->write_algorithm); | |||
return retval; | |||
} | |||
// Allocate half pages memory | |||
/* Allocate half pages memory */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) | |||
!= ERROR_OK) | |||
{ | |||
!= ERROR_OK) { | |||
if (buffer_size > 1024) | |||
buffer_size -= 1024; | |||
else | |||
buffer_size /= 2; | |||
if (buffer_size <= 256) | |||
{ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a | |||
* buffer, free the algorithm */ | |||
if (stm32lx_info->write_algorithm) | |||
@@ -323,11 +306,9 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, | |||
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT); | |||
init_reg_param(®_params[4], "r4", 32, PARAM_OUT); | |||
// Enable half-page write | |||
/* Enable half-page write */ | |||
retval = stm32lx_enable_write_half_page(bank); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
target_free_working_area(target, source); | |||
target_free_working_area(target, stm32lx_info->write_algorithm); | |||
@@ -335,38 +316,36 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, | |||
destroy_reg_param(®_params[1]); | |||
destroy_reg_param(®_params[2]); | |||
destroy_reg_param(®_params[3]); | |||
return retval; | |||
} | |||
// Loop while there are bytes to write | |||
while (count > 0) | |||
{ | |||
/* Loop while there are bytes to write */ | |||
while (count > 0) { | |||
uint32_t this_count; | |||
this_count = (count > buffer_size) ? buffer_size : count; | |||
// Write the next half pages | |||
/* Write the next half pages */ | |||
retval = target_write_buffer(target, source->address, this_count, | |||
buffer); | |||
if (retval != ERROR_OK) | |||
break; | |||
// 4: Store useful information in the registers | |||
// the destination address of the copy (R0) | |||
/* 4: Store useful information in the registers */ | |||
/* the destination address of the copy (R0) */ | |||
buf_set_u32(reg_params[0].value, 0, 32, address); | |||
// The source address of the copy (R1) | |||
/* The source address of the copy (R1) */ | |||
buf_set_u32(reg_params[1].value, 0, 32, source->address); | |||
// The length of the copy (R2) | |||
/* The length of the copy (R2) */ | |||
buf_set_u32(reg_params[2].value, 0, 32, this_count / 4); | |||
// 5: Execute the bunch of code | |||
/* 5: Execute the bunch of code */ | |||
retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params) | |||
/ sizeof(*reg_params), reg_params, | |||
stm32lx_info->write_algorithm->address, 0, 20000, &armv7m_info); | |||
if (retval != ERROR_OK) | |||
break; | |||
// 6: Wait while busy | |||
/* 6: Wait while busy */ | |||
retval = stm32lx_wait_until_bsy_clear(bank); | |||
if (retval != ERROR_OK) | |||
break; | |||
@@ -401,34 +380,28 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t bytes_written = 0; | |||
int retval; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (offset & 0x1) | |||
{ | |||
if (offset & 0x1) { | |||
LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
// Check if there are some full half pages | |||
if (((offset % 128) == 0) && (count >= 128)) | |||
{ | |||
/* Check if there are some full half pages */ | |||
if (((offset % 128) == 0) && (count >= 128)) { | |||
halfpages_number = count / 128; | |||
words_remaining = (count - 128 * halfpages_number) / 4; | |||
bytes_remaining = (count & 0x3); | |||
} | |||
else | |||
{ | |||
} else { | |||
halfpages_number = 0; | |||
words_remaining = (count / 4); | |||
bytes_remaining = (count & 0x3); | |||
} | |||
if (halfpages_number) | |||
{ | |||
if (halfpages_number) { | |||
retval = stm32lx_write_half_pages(bank, buffer, offset, 128 | |||
* halfpages_number); | |||
if (retval != ERROR_OK) | |||
@@ -441,12 +414,11 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer, | |||
if (retval != ERROR_OK) | |||
return retval; | |||
while (words_remaining > 0) | |||
{ | |||
while (words_remaining > 0) { | |||
uint32_t value; | |||
uint8_t* p = buffer + bytes_written; | |||
uint8_t *p = buffer + bytes_written; | |||
// Prepare the word, Little endian conversion | |||
/* Prepare the word, Little endian conversion */ | |||
value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); | |||
retval = target_write_u32(target, address, value); | |||
@@ -462,8 +434,7 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer, | |||
return retval; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff}; | |||
/* copy the last remaining bytes into the write buffer */ | |||
@@ -508,14 +479,13 @@ static int stm32lx_probe(struct flash_bank *bank) | |||
return ERROR_FAIL; | |||
} | |||
// Read the RDP byte and check if it is 0xAA | |||
/* Read the RDP byte and check if it is 0xAA */ | |||
uint8_t rdp; | |||
retval = target_read_u32(target, FLASH_OBR, ®32); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
rdp = reg32 & 0xFF; | |||
if (rdp != 0xAA) | |||
{ | |||
if (rdp != 0xAA) { | |||
/* | |||
* Unlocking the option byte is done by unlocking the PECR, then | |||
* by writing the 2 option byte keys to OPTKEYR | |||
@@ -549,19 +519,18 @@ static int stm32lx_probe(struct flash_bank *bank) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (reg32 & FLASH_PECR__OPTLOCK) | |||
{ | |||
if (reg32 & FLASH_PECR__OPTLOCK) { | |||
LOG_ERROR("OPTLOCK is not cleared"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
// Then, write RDP to 0x00 to set level 1 | |||
/* Then, write RDP to 0x00 to set level 1 */ | |||
reg32 = ((~0xAA) << 16) | (0xAA); | |||
retval = target_write_u32(target, OB_RDP, reg32); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
// Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR | |||
/* Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR */ | |||
reg32 = FLASH_PECR__OBL_LAUNCH; | |||
retval = target_write_u32(target, FLASH_PECR, reg32); | |||
if (retval != ERROR_OK) | |||
@@ -574,8 +543,7 @@ static int stm32lx_probe(struct flash_bank *bank) | |||
return retval; | |||
/* check for valid flash size */ | |||
if (flash_size == 0xffff) | |||
{ | |||
if (flash_size == 0xffff) { | |||
/* number of sectors incorrect on revA */ | |||
LOG_ERROR("STM32 flash size failed, probe inaccurate"); | |||
return ERROR_FAIL; | |||
@@ -588,8 +556,7 @@ static int stm32lx_probe(struct flash_bank *bank) | |||
int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE; | |||
LOG_INFO("flash size = %dkbytes", flash_size); | |||
if (bank->sectors) | |||
{ | |||
if (bank->sectors) { | |||
free(bank->sectors); | |||
bank->sectors = NULL; | |||
} | |||
@@ -598,14 +565,12 @@ static int stm32lx_probe(struct flash_bank *bank) | |||
bank->size = flash_size * 1024; | |||
bank->num_sectors = num_sectors; | |||
bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); | |||
if (bank->sectors == NULL) | |||
{ | |||
if (bank->sectors == NULL) { | |||
LOG_ERROR("failed to allocate bank sectors"); | |||
return ERROR_FAIL; | |||
} | |||
for (i = 0; i < num_sectors; i++) | |||
{ | |||
for (i = 0; i < num_sectors; i++) { | |||
bank->sectors[i].offset = i * FLASH_SECTOR_SIZE; | |||
bank->sectors[i].size = FLASH_SECTOR_SIZE; | |||
bank->sectors[i].is_erased = -1; | |||
@@ -622,9 +587,7 @@ static int stm32lx_auto_probe(struct flash_bank *bank) | |||
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; | |||
if (stm32lx_info->probed) | |||
{ | |||
return ERROR_OK; | |||
} | |||
return stm32lx_probe(bank); | |||
} | |||
@@ -637,60 +600,51 @@ static int stm32lx_erase_check(struct flash_bank *bank) | |||
uint32_t nBytes; | |||
int retval = ERROR_OK; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
uint8_t *buffer = malloc(buffer_size); | |||
if (buffer == NULL) | |||
{ | |||
if (buffer == NULL) { | |||
LOG_ERROR("failed to allocate read buffer"); | |||
return ERROR_FAIL; | |||
} | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
uint32_t j; | |||
bank->sectors[i].is_erased = 1; | |||
// Loop chunk by chunk over the sector | |||
for (j = 0; j < bank->sectors[i].size; j += buffer_size) | |||
{ | |||
/* Loop chunk by chunk over the sector */ | |||
for (j = 0; j < bank->sectors[i].size; j += buffer_size) { | |||
uint32_t chunk; | |||
chunk = buffer_size; | |||
if (chunk > (j - bank->sectors[i].size)) | |||
{ | |||
chunk = (j - bank->sectors[i].size); | |||
} | |||
retval = target_read_memory(target, bank->base | |||
+ bank->sectors[i].offset + j, 4, chunk / 4, buffer); | |||
if (retval != ERROR_OK) | |||
break; | |||
for (nBytes = 0; nBytes < chunk; nBytes++) | |||
{ | |||
if (buffer[nBytes] != 0x00) | |||
{ | |||
for (nBytes = 0; nBytes < chunk; nBytes++) { | |||
if (buffer[nBytes] != 0x00) { | |||
bank->sectors[i].is_erased = 0; | |||
break; | |||
} | |||
} | |||
} | |||
if (retval != ERROR_OK) | |||
{ | |||
break; | |||
} | |||
} | |||
free(buffer); | |||
return retval; | |||
} | |||
static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) | |||
{ | |||
// This method must return a string displaying information about the bank | |||
/* This method must return a string displaying information about the bank */ | |||
struct target *target = bank->target; | |||
uint32_t device_id; | |||
@@ -706,8 +660,7 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) | |||
buf += printed; | |||
buf_size -= printed; | |||
switch (device_id >> 16) | |||
{ | |||
switch (device_id >> 16) { | |||
case 0x1000: | |||
snprintf(buf, buf_size, "A"); | |||
break; | |||
@@ -719,9 +672,7 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) | |||
snprintf(buf, buf_size, "unknown"); | |||
break; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
snprintf(buf, buf_size, "Cannot identify target as a stm32lx"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -729,13 +680,11 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) | |||
return ERROR_OK; | |||
} | |||
static const struct command_registration stm32lx_exec_command_handlers[] = | |||
{ | |||
static const struct command_registration stm32lx_exec_command_handlers[] = { | |||
COMMAND_REGISTRATION_DONE | |||
}; | |||
static const struct command_registration stm32lx_command_handlers[] = | |||
{ | |||
static const struct command_registration stm32lx_command_handlers[] = { | |||
{ | |||
.name = "stm32lx", | |||
.mode = COMMAND_ANY, | |||
@@ -746,8 +695,7 @@ static const struct command_registration stm32lx_command_handlers[] = | |||
COMMAND_REGISTRATION_DONE | |||
}; | |||
struct flash_driver stm32lx_flash = | |||
{ | |||
struct flash_driver stm32lx_flash = { | |||
.name = "stm32lx", | |||
.commands = stm32lx_command_handlers, | |||
.flash_bank_command = stm32lx_flash_bank_command, | |||
@@ -762,8 +710,7 @@ struct flash_driver stm32lx_flash = | |||
.info = stm32lx_get_info, | |||
}; | |||
// Static methods implementation | |||
/* Static methods implementation */ | |||
static int stm32lx_unlock_program_memory(struct flash_bank *bank) | |||
{ | |||
struct target *target = bank->target; | |||
@@ -789,8 +736,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (reg32 & FLASH_PECR__PELOCK) | |||
{ | |||
if (reg32 & FLASH_PECR__PELOCK) { | |||
LOG_ERROR("PELOCK is not cleared :("); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -807,8 +753,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (reg32 & FLASH_PECR__PRGLOCK) | |||
{ | |||
if (reg32 & FLASH_PECR__PRGLOCK) { | |||
LOG_ERROR("PRGLOCK is not cleared :("); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -892,8 +837,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
for (int page = 0; page < FLASH_PAGES_PER_SECTOR; page++) | |||
{ | |||
for (int page = 0; page < FLASH_PAGES_PER_SECTOR; page++) { | |||
reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE; | |||
retval = target_write_u32(target, FLASH_PECR, reg32); | |||
if (retval != ERROR_OK) | |||
@@ -929,32 +873,26 @@ static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank) | |||
int timeout = 100; | |||
/* wait for busy to clear */ | |||
for (;;) | |||
{ | |||
for (;;) { | |||
retval = target_read_u32(target, FLASH_SR, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if ((status & FLASH_SR__BSY) == 0) | |||
{ | |||
break; | |||
} | |||
if (timeout-- <= 0) | |||
{ | |||
if (timeout-- <= 0) { | |||
LOG_ERROR("timed out waiting for flash"); | |||
return ERROR_FAIL; | |||
} | |||
alive_sleep(1); | |||
} | |||
if (status & FLASH_SR__WRPERR) | |||
{ | |||
if (status & FLASH_SR__WRPERR) { | |||
LOG_ERROR("access denied / write protected"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (status & FLASH_SR__PGAERR) | |||
{ | |||
if (status & FLASH_SR__PGAERR) { | |||
LOG_ERROR("invalid program address"); | |||
retval = ERROR_FAIL; | |||
} | |||
@@ -43,33 +43,33 @@ | |||
#include <helper/time_support.h> | |||
#define SMI_READ_REG(a) (_SMI_READ_REG(a)) | |||
#define _SMI_READ_REG(a) \ | |||
{ \ | |||
int __a; \ | |||
uint32_t __v; \ | |||
\ | |||
#define _SMI_READ_REG(a) \ | |||
{ \ | |||
int __a; \ | |||
uint32_t __v; \ | |||
\ | |||
__a = target_read_u32(target, io_base + (a), &__v); \ | |||
if (__a != ERROR_OK) \ | |||
return __a; \ | |||
__v; \ | |||
if (__a != ERROR_OK) \ | |||
return __a; \ | |||
__v; \ | |||
} | |||
#define SMI_WRITE_REG(a,v) \ | |||
{ \ | |||
int __r; \ | |||
\ | |||
#define SMI_WRITE_REG(a, v) \ | |||
{ \ | |||
int __r; \ | |||
\ | |||
__r = target_write_u32(target, io_base + (a), (v)); \ | |||
if (__r != ERROR_OK) \ | |||
return __r; \ | |||
if (__r != ERROR_OK) \ | |||
return __r; \ | |||
} | |||
#define SMI_POLL_TFF(timeout) \ | |||
{ \ | |||
int __r; \ | |||
\ | |||
#define SMI_POLL_TFF(timeout) \ | |||
{ \ | |||
int __r; \ | |||
\ | |||
__r = poll_tff(target, io_base, timeout); \ | |||
if (__r != ERROR_OK) \ | |||
return __r; \ | |||
if (__r != ERROR_OK) \ | |||
return __r; \ | |||
} | |||
#define SMI_SET_SW_MODE() SMI_WRITE_REG(SMI_CR1, \ | |||
@@ -117,8 +117,7 @@ | |||
#define SMI_PROBE_TIMEOUT (100) | |||
#define SMI_MAX_TIMEOUT (3000) | |||
struct stmsmi_flash_bank | |||
{ | |||
struct stmsmi_flash_bank { | |||
int probed; | |||
uint32_t io_base; | |||
uint32_t bank_num; | |||
@@ -202,16 +201,13 @@ FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command) | |||
{ | |||
struct stmsmi_flash_bank *stmsmi_info; | |||
LOG_DEBUG("%s", __FUNCTION__); | |||
LOG_DEBUG("%s", __func__); | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank)); | |||
if (stmsmi_info == NULL) | |||
{ | |||
if (stmsmi_info == NULL) { | |||
LOG_ERROR("not enough memory"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -279,17 +275,17 @@ static int wait_till_ready(struct flash_bank *bank, int timeout) | |||
int retval; | |||
long long endtime; | |||
endtime = timeval_ms() + timeout; | |||
do { | |||
/* read flash status register */ | |||
retval = read_status_reg(bank, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
endtime = timeval_ms() + timeout; | |||
do { | |||
/* read flash status register */ | |||
retval = read_status_reg(bank, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if ((status & SMI_WIP_BIT) == 0) | |||
return ERROR_OK; | |||
alive_sleep(1); | |||
} while (timeval_ms() < endtime); | |||
} while (timeval_ms() < endtime); | |||
LOG_ERROR("timeout"); | |||
return ERROR_FAIL; | |||
@@ -324,8 +320,7 @@ static int smi_write_enable(struct flash_bank *bank) | |||
return retval; | |||
/* Check write enabled */ | |||
if ((status & SMI_WEL_BIT) == 0) | |||
{ | |||
if ((status & SMI_WEL_BIT) == 0) { | |||
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status); | |||
return ERROR_FAIL; | |||
} | |||
@@ -391,37 +386,31 @@ static int stmsmi_erase(struct flash_bank *bank, int first, int last) | |||
int retval = ERROR_OK; | |||
int sector; | |||
LOG_DEBUG("%s: from sector %d to sector %d", __FUNCTION__, first, last); | |||
LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last); | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) | |||
{ | |||
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { | |||
LOG_ERROR("Flash sector invalid"); | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
if (!(stmsmi_info->probed)) | |||
{ | |||
if (!(stmsmi_info->probed)) { | |||
LOG_ERROR("Flash bank not probed"); | |||
return ERROR_FLASH_BANK_NOT_PROBED; | |||
} | |||
for (sector = first; sector <= last; sector++) | |||
{ | |||
if (bank->sectors[sector].is_protected) | |||
{ | |||
for (sector = first; sector <= last; sector++) { | |||
if (bank->sectors[sector].is_protected) { | |||
LOG_ERROR("Flash sector %d protected", sector); | |||
return ERROR_FAIL; | |||
} | |||
} | |||
for (sector = first; sector <= last; sector++) | |||
{ | |||
for (sector = first; sector <= last; sector++) { | |||
retval = smi_erase_sector(bank, sector); | |||
if (retval != ERROR_OK) | |||
break; | |||
@@ -452,7 +441,7 @@ static int smi_write_buffer(struct flash_bank *bank, uint8_t *buffer, | |||
int retval; | |||
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32, | |||
__FUNCTION__, address, len); | |||
__func__, address, len); | |||
retval = smi_write_enable(bank); | |||
if (retval != ERROR_OK) | |||
@@ -479,30 +468,26 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer, | |||
int retval = ERROR_OK; | |||
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, | |||
__FUNCTION__, offset, count); | |||
__func__, offset, count); | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (offset + count > stmsmi_info->dev->size_in_bytes) | |||
{ | |||
if (offset + count > stmsmi_info->dev->size_in_bytes) { | |||
LOG_WARNING("Write pasts end of flash. Extra data discarded."); | |||
count = stmsmi_info->dev->size_in_bytes - offset; | |||
} | |||
/* Check sector protection */ | |||
for (sector = 0; sector < bank->num_sectors; sector++) | |||
{ | |||
for (sector = 0; sector < bank->num_sectors; sector++) { | |||
/* Start offset in or before this sector? */ | |||
/* End offset in or behind this sector? */ | |||
if ( (offset < | |||
if ((offset < | |||
(bank->sectors[sector].offset + bank->sectors[sector].size)) | |||
&& ((offset + count - 1) >= bank->sectors[sector].offset) | |||
&& bank->sectors[sector].is_protected ) | |||
{ | |||
&& bank->sectors[sector].is_protected) { | |||
LOG_ERROR("Flash sector %d protected", sector); | |||
return ERROR_FAIL; | |||
} | |||
@@ -511,8 +496,7 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer, | |||
page_size = stmsmi_info->dev->pagesize; | |||
/* unaligned buffer head */ | |||
if (count > 0 && (offset & 3) != 0) | |||
{ | |||
if (count > 0 && (offset & 3) != 0) { | |||
cur_count = 4 - (offset & 3); | |||
if (cur_count > count) | |||
cur_count = count; | |||
@@ -527,8 +511,7 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer, | |||
page_offset = offset % page_size; | |||
/* central part, aligned words */ | |||
while (count >= 4) | |||
{ | |||
while (count >= 4) { | |||
/* clip block at page boundary */ | |||
if (page_offset + count > page_size) | |||
cur_count = page_size - page_offset; | |||
@@ -567,8 +550,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id) | |||
uint32_t io_base = stmsmi_info->io_base; | |||
int retval; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -614,18 +596,16 @@ static int stmsmi_probe(struct flash_bank *bank) | |||
free(bank->sectors); | |||
stmsmi_info->probed = 0; | |||
for (target_device=target_devices ; target_device->name ; ++target_device) | |||
for (target_device = target_devices ; target_device->name ; ++target_device) | |||
if (target_device->tap_idcode == target->tap->idcode) | |||
break; | |||
if (!target_device->name) | |||
{ | |||
if (!target_device->name) { | |||
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable", | |||
target->tap->idcode); | |||
return ERROR_FAIL; | |||
} | |||
switch (bank->base - target_device->smi_base) | |||
{ | |||
switch (bank->base - target_device->smi_base) { | |||
case 0: | |||
stmsmi_info->bank_num = SMI_SEL_BANK0; | |||
break; | |||
@@ -661,8 +641,7 @@ static int stmsmi_probe(struct flash_bank *bank) | |||
break; | |||
} | |||
if (!stmsmi_info->dev) | |||
{ | |||
if (!stmsmi_info->dev) { | |||
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); | |||
return ERROR_FAIL; | |||
} | |||
@@ -677,14 +656,12 @@ static int stmsmi_probe(struct flash_bank *bank) | |||
bank->num_sectors = | |||
stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize; | |||
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); | |||
if (sectors == NULL) | |||
{ | |||
if (sectors == NULL) { | |||
LOG_ERROR("not enough memory"); | |||
return ERROR_FAIL; | |||
} | |||
for (int sector = 0; sector < bank->num_sectors; sector++) | |||
{ | |||
for (int sector = 0; sector < bank->num_sectors; sector++) { | |||
sectors[sector].offset = sector * stmsmi_info->dev->sectorsize; | |||
sectors[sector].size = stmsmi_info->dev->sectorsize; | |||
sectors[sector].is_erased = -1; | |||
@@ -714,8 +691,7 @@ static int get_stmsmi_info(struct flash_bank *bank, char *buf, int buf_size) | |||
{ | |||
struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; | |||
if (!(stmsmi_info->probed)) | |||
{ | |||
if (!(stmsmi_info->probed)) { | |||
snprintf(buf, buf_size, | |||
"\nSMI flash bank not probed yet\n"); | |||
return ERROR_OK; | |||
@@ -23,6 +23,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -32,7 +33,6 @@ | |||
#include <helper/binarybuffer.h> | |||
#include <target/algorithm.h> | |||
/* Flash registers */ | |||
#define FLASH_CR0 0x00000000 | |||
@@ -85,8 +85,7 @@ | |||
#define FLASH_ERR 0x00000001 | |||
struct str7x_flash_bank | |||
{ | |||
struct str7x_flash_bank { | |||
uint32_t *sector_bits; | |||
uint32_t disable_bit; | |||
uint32_t busy_bits; | |||
@@ -100,8 +99,7 @@ struct str7x_mem_layout { | |||
uint32_t sector_bit; | |||
}; | |||
enum str7x_status_codes | |||
{ | |||
enum str7x_status_codes { | |||
STR7X_CMD_SUCCESS = 0, | |||
STR7X_INVALID_COMMAND = 1, | |||
STR7X_SRC_ADDR_ERROR = 2, | |||
@@ -135,7 +133,7 @@ static struct str7x_mem_layout mem_layout_str7bank1[] = { | |||
static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg) | |||
{ | |||
struct str7x_flash_bank *str7x_info = bank->driver_priv; | |||
return (str7x_info->register_base | reg); | |||
return str7x_info->register_base | reg; | |||
} | |||
static int str7x_build_block_list(struct flash_bank *bank) | |||
@@ -146,8 +144,7 @@ static int str7x_build_block_list(struct flash_bank *bank) | |||
int num_sectors; | |||
int b0_sectors = 0, b1_sectors = 0; | |||
switch (bank->size) | |||
{ | |||
switch (bank->size) { | |||
case 16 * 1024: | |||
b1_sectors = 2; | |||
break; | |||
@@ -173,8 +170,7 @@ static int str7x_build_block_list(struct flash_bank *bank) | |||
num_sectors = 0; | |||
for (i = 0; i < b0_sectors; i++) | |||
{ | |||
for (i = 0; i < b0_sectors; i++) { | |||
bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start; | |||
bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size; | |||
bank->sectors[num_sectors].is_erased = -1; | |||
@@ -185,8 +181,7 @@ static int str7x_build_block_list(struct flash_bank *bank) | |||
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit; | |||
} | |||
for (i = 0; i < b1_sectors; i++) | |||
{ | |||
for (i = 0; i < b1_sectors; i++) { | |||
bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start; | |||
bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size; | |||
bank->sectors[num_sectors].is_erased = -1; | |||
@@ -207,9 +202,7 @@ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command) | |||
struct str7x_flash_bank *str7x_info; | |||
if (CMD_ARGC < 7) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
str7x_info = malloc(sizeof(struct str7x_flash_bank)); | |||
bank->driver_priv = str7x_info; | |||
@@ -219,21 +212,14 @@ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command) | |||
str7x_info->disable_bit = (1 << 1); | |||
if (strcmp(CMD_ARGV[6], "STR71x") == 0) | |||
{ | |||
str7x_info->register_base = 0x40100000; | |||
} | |||
else if (strcmp(CMD_ARGV[6], "STR73x") == 0) | |||
{ | |||
else if (strcmp(CMD_ARGV[6], "STR73x") == 0) { | |||
str7x_info->register_base = 0x80100000; | |||
str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0); | |||
} | |||
else if (strcmp(CMD_ARGV[6], "STR75x") == 0) | |||
{ | |||
} else if (strcmp(CMD_ARGV[6], "STR75x") == 0) { | |||
str7x_info->register_base = 0x20100000; | |||
str7x_info->disable_bit = (1 << 0); | |||
} | |||
else | |||
{ | |||
} else { | |||
LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]); | |||
free(str7x_info); | |||
return ERROR_FLASH_BANK_INVALID; | |||
@@ -263,8 +249,7 @@ static int str7x_waitbusy(struct flash_bank *bank) | |||
struct target *target = bank->target; | |||
struct str7x_flash_bank *str7x_info = bank->driver_priv; | |||
for (i = 0 ; i < 10000; i++) | |||
{ | |||
for (i = 0 ; i < 10000; i++) { | |||
uint32_t retval; | |||
err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval); | |||
if (err != ERROR_OK) | |||
@@ -290,35 +275,28 @@ static int str7x_result(struct flash_bank *bank) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (flash_flags & FLASH_WPF) | |||
{ | |||
if (flash_flags & FLASH_WPF) { | |||
LOG_ERROR("str7x hw write protection set"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (flash_flags & FLASH_RESER) | |||
{ | |||
if (flash_flags & FLASH_RESER) { | |||
LOG_ERROR("str7x suspended program erase not resumed"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (flash_flags & FLASH_10ER) | |||
{ | |||
if (flash_flags & FLASH_10ER) { | |||
LOG_ERROR("str7x trying to set bit to 1 when it is already 0"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (flash_flags & FLASH_PGER) | |||
{ | |||
if (flash_flags & FLASH_PGER) { | |||
LOG_ERROR("str7x program error"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (flash_flags & FLASH_ERER) | |||
{ | |||
if (flash_flags & FLASH_ERER) { | |||
LOG_ERROR("str7x erase error"); | |||
retval = ERROR_FAIL; | |||
} | |||
if (retval == ERROR_OK) | |||
{ | |||
if (flash_flags & FLASH_ERR) | |||
{ | |||
if (retval == ERROR_OK) { | |||
if (flash_flags & FLASH_ERR) { | |||
/* this should always be set if one of the others are set... */ | |||
LOG_ERROR("str7x write operation failed / bad setup"); | |||
retval = ERROR_FAIL; | |||
@@ -336,8 +314,7 @@ static int str7x_protect_check(struct flash_bank *bank) | |||
int i; | |||
uint32_t flash_flags; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -347,8 +324,7 @@ static int str7x_protect_check(struct flash_bank *bank) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
if (flash_flags & str7x_info->sector_bits[i]) | |||
bank->sectors[i].is_protected = 0; | |||
else | |||
@@ -368,16 +344,13 @@ static int str7x_erase(struct flash_bank *bank, int first, int last) | |||
uint32_t sectors = 0; | |||
int err; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
for (i = first; i <= last; i++) | |||
{ | |||
sectors |= str7x_info->sector_bits[i]; | |||
} | |||
LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors); | |||
@@ -423,16 +396,14 @@ static int str7x_protect(struct flash_bank *bank, int set, int first, int last) | |||
uint32_t cmd; | |||
uint32_t protect_blocks; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
protect_blocks = 0xFFFFFFFF; | |||
if (set) | |||
{ | |||
if (set) { | |||
for (i = first; i <= last; i++) | |||
protect_blocks &= ~(str7x_info->sector_bits[i]); | |||
} | |||
@@ -499,7 +470,7 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
0xe582400c, /* str r4, [r2, #0xc] */ | |||
0xe3a04209, /* mov r4, #0x90000000 */ | |||
0xe5824000, /* str r4, [r2, #0x0] */ | |||
/* busy: */ | |||
/* busy: */ | |||
0xe5924000, /* ldr r4, [r2, #0x0] */ | |||
0xe1140005, /* tst r4, r5 */ | |||
0x1afffffc, /* bne busy */ | |||
@@ -516,21 +487,18 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
/* flash write code */ | |||
if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code), | |||
&str7x_info->write_algorithm) != ERROR_OK) | |||
{ | |||
&str7x_info->write_algorithm) != ERROR_OK) { | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
target_write_buffer(target, str7x_info->write_algorithm->address, | |||
sizeof(str7x_flash_write_code), | |||
(uint8_t*)str7x_flash_write_code); | |||
(uint8_t *)str7x_flash_write_code); | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
if (buffer_size <= 256) | |||
{ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a | |||
* buffer, free the algorithm */ | |||
if (str7x_info->write_algorithm) | |||
@@ -552,8 +520,7 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
init_reg_param(®_params[4], "r4", 32, PARAM_IN); | |||
init_reg_param(®_params[5], "r5", 32, PARAM_OUT); | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count; | |||
target_write_buffer(target, source->address, thisrun_count * 8, buffer); | |||
@@ -564,16 +531,14 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer, | |||
buf_set_u32(reg_params[3].value, 0, 32, thisrun_count); | |||
buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits); | |||
if ((retval = target_run_algorithm(target, 0, NULL, 6, reg_params, | |||
retval = target_run_algorithm(target, 0, NULL, 6, reg_params, | |||
str7x_info->write_algorithm->address, | |||
str7x_info->write_algorithm->address + (sizeof(str7x_flash_write_code) - 4), | |||
10000, &armv4_5_info)) != ERROR_OK) | |||
{ | |||
10000, &armv4_5_info); | |||
if (retval != ERROR_OK) | |||
break; | |||
} | |||
if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00) | |||
{ | |||
if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00) { | |||
retval = str7x_result(bank); | |||
break; | |||
} | |||
@@ -609,26 +574,22 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer, | |||
uint32_t check_address = offset; | |||
int i; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (offset & 0x7) | |||
{ | |||
if (offset & 0x7) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
uint32_t sec_start = bank->sectors[i].offset; | |||
uint32_t sec_end = sec_start + bank->sectors[i].size; | |||
/* check if destination falls within the current sector */ | |||
if ((check_address >= sec_start) && (check_address < sec_end)) | |||
{ | |||
if ((check_address >= sec_start) && (check_address < sec_end)) { | |||
/* check if destination ends in the current sector */ | |||
if (offset + count < sec_end) | |||
check_address = offset + count; | |||
@@ -644,32 +605,25 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer, | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0); | |||
/* multiple dwords (8-byte) to be programmed? */ | |||
if (dwords_remaining > 0) | |||
{ | |||
if (dwords_remaining > 0) { | |||
/* try using a block write */ | |||
if ((retval = str7x_write_block(bank, buffer, offset, | |||
dwords_remaining)) != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
retval = str7x_write_block(bank, buffer, offset, dwords_remaining); | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
/* if block write failed (no sufficient working area), | |||
* we use normal (slow) single dword accesses */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
} else | |||
{ | |||
} else { | |||
return retval; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
buffer += dwords_remaining * 8; | |||
address += dwords_remaining * 8; | |||
dwords_remaining = 0; | |||
} | |||
} | |||
while (dwords_remaining > 0) | |||
{ | |||
while (dwords_remaining > 0) { | |||
/* command */ | |||
cmd = FLASH_DWPG; | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd); | |||
@@ -704,8 +658,7 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer, | |||
address += 8; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |||
/* copy the last remaining bytes into the write buffer */ | |||
@@ -777,9 +730,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command) | |||
uint16_t ProtectionRegs; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -790,8 +741,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command) | |||
target = bank->target; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -801,30 +751,24 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command) | |||
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), ®); | |||
if (!(reg & str7x_info->disable_bit)) | |||
{ | |||
ProtectionLevel = 1; | |||
} | |||
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), ®); | |||
ProtectionRegs = ~(reg >> 16); | |||
while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) | |||
{ | |||
while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) { | |||
ProtectionRegs >>= 1; | |||
ProtectionLevel++; | |||
} | |||
if (ProtectionLevel == 0) | |||
{ | |||
if (ProtectionLevel == 0) { | |||
flash_cmd = FLASH_SPR; | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8); | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD); | |||
flash_cmd = FLASH_SPR | FLASH_WMS; | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); | |||
} | |||
else | |||
{ | |||
} else { | |||
flash_cmd = FLASH_SPR; | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd); | |||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC); | |||
@@ -23,6 +23,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -31,7 +32,6 @@ | |||
#include <target/arm966e.h> | |||
#include <target/algorithm.h> | |||
/* Flash registers */ | |||
#define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */ | |||
@@ -42,17 +42,14 @@ | |||
#define FLASH_SR 0x5400001C /* Status Register */ | |||
#define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */ | |||
struct str9x_flash_bank | |||
{ | |||
struct str9x_flash_bank { | |||
uint32_t *sector_bits; | |||
int variant; | |||
int bank1; | |||
struct working_area *write_algorithm; | |||
}; | |||
enum str9x_status_codes | |||
{ | |||
enum str9x_status_codes { | |||
STR9X_CMD_SUCCESS = 0, | |||
STR9X_INVALID_COMMAND = 1, | |||
STR9X_SRC_ADDR_ERROR = 2, | |||
@@ -82,8 +79,7 @@ static int str9x_build_block_list(struct flash_bank *bank) | |||
str9x_info->variant = 0; | |||
str9x_info->bank1 = 0; | |||
switch (bank->size) | |||
{ | |||
switch (bank->size) { | |||
case (256 * 1024): | |||
b0_sectors = 4; | |||
break; | |||
@@ -124,8 +120,7 @@ static int str9x_build_block_list(struct flash_bank *bank) | |||
num_sectors = 0; | |||
for (i = 0; i < b0_sectors; i++) | |||
{ | |||
for (i = 0; i < b0_sectors; i++) { | |||
bank->sectors[num_sectors].offset = offset; | |||
bank->sectors[num_sectors].size = 0x10000; | |||
offset += bank->sectors[i].size; | |||
@@ -134,8 +129,7 @@ static int str9x_build_block_list(struct flash_bank *bank) | |||
str9x_info->sector_bits[num_sectors++] = (1 << i); | |||
} | |||
for (i = 0; i < b1_sectors; i++) | |||
{ | |||
for (i = 0; i < b1_sectors; i++) { | |||
bank->sectors[num_sectors].offset = offset; | |||
bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000; | |||
offset += bank->sectors[i].size; | |||
@@ -157,9 +151,7 @@ FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command) | |||
struct str9x_flash_bank *str9x_info; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
str9x_info = malloc(sizeof(struct str9x_flash_bank)); | |||
bank->driver_priv = str9x_info; | |||
@@ -182,64 +174,49 @@ static int str9x_protect_check(struct flash_bank *bank) | |||
uint32_t status = 0; | |||
uint16_t hstatus = 0; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
/* read level one protection */ | |||
if (str9x_info->variant) | |||
{ | |||
if (str9x_info->bank1) | |||
{ | |||
if (str9x_info->variant) { | |||
if (str9x_info->bank1) { | |||
adr = bank1start + 0x18; | |||
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0x90); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK) | |||
{ | |||
retval = target_read_u16(target, adr, &hstatus); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
status = hstatus; | |||
} | |||
else | |||
{ | |||
} else { | |||
adr = bank1start + 0x14; | |||
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0x90); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
if ((retval = target_read_u32(target, adr, &status)) != ERROR_OK) | |||
{ | |||
retval = target_read_u32(target, adr, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
adr = bank1start + 0x10; | |||
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0x90); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK) | |||
{ | |||
retval = target_read_u16(target, adr, &hstatus); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
status = hstatus; | |||
} | |||
/* read array command */ | |||
if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0xFF); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
if (status & str9x_info->sector_bits[i]) | |||
bank->sectors[i].is_protected = 1; | |||
else | |||
@@ -258,22 +235,18 @@ static int str9x_erase(struct flash_bank *bank, int first, int last) | |||
uint8_t erase_cmd; | |||
int total_timeout; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
/* Check if we can erase whole bank */ | |||
if ((first == 0) && (last == (bank->num_sectors - 1))) | |||
{ | |||
if ((first == 0) && (last == (bank->num_sectors - 1))) { | |||
/* Optimize to run erase bank command instead of sector */ | |||
erase_cmd = 0x80; | |||
/* Add timeout duration since erase bank takes more time */ | |||
/* Add timeout duration since erase bank takes more time */ | |||
total_timeout = 1000 * bank->num_sectors; | |||
} | |||
else | |||
{ | |||
} else { | |||
/* Erase sector command */ | |||
erase_cmd = 0x20; | |||
total_timeout = 1000; | |||
@@ -282,58 +255,48 @@ static int str9x_erase(struct flash_bank *bank, int first, int last) | |||
/* this is so the compiler can *know* */ | |||
assert(total_timeout > 0); | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
int retval; | |||
adr = bank->base + bank->sectors[i].offset; | |||
/* erase sectors or block */ | |||
if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, erase_cmd); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0xD0); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
/* get status */ | |||
if ((retval = target_write_u16(target, adr, 0x70)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0x70); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
int timeout; | |||
for (timeout = 0; timeout < total_timeout; timeout++) | |||
{ | |||
if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK) | |||
{ | |||
for (timeout = 0; timeout < total_timeout; timeout++) { | |||
retval = target_read_u8(target, adr, &status); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
if (status & 0x80) | |||
break; | |||
alive_sleep(1); | |||
} | |||
if (timeout == total_timeout) | |||
{ | |||
if (timeout == total_timeout) { | |||
LOG_ERROR("erase timed out"); | |||
return ERROR_FAIL; | |||
} | |||
/* clear status, also clear read array */ | |||
if ((retval = target_write_u16(target, adr, 0x50)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0x50); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
/* read array command */ | |||
if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK) | |||
{ | |||
retval = target_write_u16(target, adr, 0xFF); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
} | |||
if (status & 0x22) | |||
{ | |||
if (status & 0x22) { | |||
LOG_ERROR("error erasing flash bank, status: 0x%x", status); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -357,14 +320,12 @@ static int str9x_protect(struct flash_bank *bank, | |||
uint32_t adr; | |||
uint8_t status; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
/* Level One Protection */ | |||
adr = bank->base + bank->sectors[i].offset; | |||
@@ -429,22 +390,19 @@ static int str9x_write_block(struct flash_bank *bank, | |||
/* flash write code */ | |||
if (target_alloc_working_area(target, sizeof(str9x_flash_write_code), | |||
&str9x_info->write_algorithm) != ERROR_OK) | |||
{ | |||
&str9x_info->write_algorithm) != ERROR_OK) { | |||
LOG_WARNING("no working area available, can't do block memory writes"); | |||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | |||
}; | |||
target_write_buffer(target, str9x_info->write_algorithm->address, | |||
sizeof(str9x_flash_write_code), | |||
(uint8_t*)str9x_flash_write_code); | |||
(uint8_t *)str9x_flash_write_code); | |||
/* memory buffer */ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) | |||
{ | |||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { | |||
buffer_size /= 2; | |||
if (buffer_size <= 256) | |||
{ | |||
if (buffer_size <= 256) { | |||
/* if we already allocated the writing code, but failed to get a | |||
* buffer, free the algorithm */ | |||
if (str9x_info->write_algorithm) | |||
@@ -464,8 +422,7 @@ static int str9x_write_block(struct flash_bank *bank, | |||
init_reg_param(®_params[2], "r2", 32, PARAM_OUT); | |||
init_reg_param(®_params[3], "r3", 32, PARAM_IN); | |||
while (count > 0) | |||
{ | |||
while (count > 0) { | |||
uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; | |||
target_write_buffer(target, source->address, thisrun_count * 2, buffer); | |||
@@ -474,17 +431,16 @@ static int str9x_write_block(struct flash_bank *bank, | |||
buf_set_u32(reg_params[1].value, 0, 32, address); | |||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); | |||
if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, | |||
retval = target_run_algorithm(target, 0, NULL, 4, reg_params, | |||
str9x_info->write_algorithm->address, | |||
0, 10000, &armv4_5_info)) != ERROR_OK) | |||
{ | |||
0, 10000, &armv4_5_info); | |||
if (retval != ERROR_OK) { | |||
LOG_ERROR("error executing str9x flash write algorithm"); | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
} | |||
if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80) | |||
{ | |||
if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80) { | |||
retval = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
} | |||
@@ -519,26 +475,22 @@ static int str9x_write(struct flash_bank *bank, | |||
uint32_t bank_adr; | |||
int i; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (offset & 0x1) | |||
{ | |||
if (offset & 0x1) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
uint32_t sec_start = bank->sectors[i].offset; | |||
uint32_t sec_end = sec_start + bank->sectors[i].size; | |||
/* check if destination falls within the current sector */ | |||
if ((check_address >= sec_start) && (check_address < sec_end)) | |||
{ | |||
if ((check_address >= sec_start) && (check_address < sec_end)) { | |||
/* check if destination ends in the current sector */ | |||
if (offset + count < sec_end) | |||
check_address = offset + count; | |||
@@ -551,33 +503,26 @@ static int str9x_write(struct flash_bank *bank, | |||
return ERROR_FLASH_DST_OUT_OF_BANK; | |||
/* multiple half words (2-byte) to be programmed? */ | |||
if (words_remaining > 0) | |||
{ | |||
if (words_remaining > 0) { | |||
/* try using a block write */ | |||
if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) | |||
{ | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) | |||
{ | |||
retval = str9x_write_block(bank, buffer, offset, words_remaining); | |||
if (retval != ERROR_OK) { | |||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { | |||
/* if block write failed (no sufficient working area), | |||
* we use normal (slow) single dword accesses */ | |||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); | |||
} | |||
else if (retval == ERROR_FLASH_OPERATION_FAILED) | |||
{ | |||
} else if (retval == ERROR_FLASH_OPERATION_FAILED) { | |||
LOG_ERROR("flash writing failed"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
buffer += words_remaining * 2; | |||
address += words_remaining * 2; | |||
words_remaining = 0; | |||
} | |||
} | |||
while (words_remaining > 0) | |||
{ | |||
while (words_remaining > 0) { | |||
bank_adr = address & ~0x03; | |||
/* write data command */ | |||
@@ -588,15 +533,13 @@ static int str9x_write(struct flash_bank *bank, | |||
target_write_u16(target, bank_adr, 0x70); | |||
int timeout; | |||
for (timeout = 0; timeout < 1000; timeout++) | |||
{ | |||
for (timeout = 0; timeout < 1000; timeout++) { | |||
target_read_u8(target, bank_adr, &status); | |||
if (status & 0x80) | |||
break; | |||
alive_sleep(1); | |||
} | |||
if (timeout == 1000) | |||
{ | |||
if (timeout == 1000) { | |||
LOG_ERROR("write timed out"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -615,8 +558,7 @@ static int str9x_write(struct flash_bank *bank, | |||
address += 2; | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint8_t last_halfword[2] = {0xff, 0xff}; | |||
/* copy the last remaining bytes into the write buffer */ | |||
@@ -632,15 +574,13 @@ static int str9x_write(struct flash_bank *bank, | |||
target_write_u16(target, bank_adr, 0x70); | |||
int timeout; | |||
for (timeout = 0; timeout < 1000; timeout++) | |||
{ | |||
for (timeout = 0; timeout < 1000; timeout++) { | |||
target_read_u8(target, bank_adr, &status); | |||
if (status & 0x80) | |||
break; | |||
alive_sleep(1); | |||
} | |||
if (timeout == 1000) | |||
{ | |||
if (timeout == 1000) { | |||
LOG_ERROR("write timed out"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -681,9 +621,7 @@ COMMAND_HANDLER(str9x_handle_flash_config_command) | |||
struct target *target = NULL; | |||
if (CMD_ARGC < 5) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -698,8 +636,7 @@ COMMAND_HANDLER(str9x_handle_flash_config_command) | |||
target = bank->target; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -20,6 +20,7 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
@@ -27,7 +28,6 @@ | |||
#include "imp.h" | |||
#include <target/arm7_9_common.h> | |||
/* ISC commands */ | |||
#define ISC_IDCODE 0xFE | |||
@@ -61,16 +61,14 @@ | |||
#define STR9XPEC_OPT_LVDWARNBIT 51 | |||
#define STR9XPEC_OPT_OTPBIT 63 | |||
enum str9xpec_status_codes | |||
{ | |||
enum str9xpec_status_codes { | |||
STR9XPEC_INVALID_COMMAND = 1, | |||
STR9XPEC_ISC_SUCCESS = 2, | |||
STR9XPEC_ISC_DISABLED = 3, | |||
STR9XPEC_ISC_INTFAIL = 32, | |||
}; | |||
struct str9xpec_flash_controller | |||
{ | |||
struct str9xpec_flash_controller { | |||
struct jtag_tap *tap; | |||
uint32_t *sector_bits; | |||
int chain_pos; | |||
@@ -84,16 +82,14 @@ static int str9xpec_write_options(struct flash_bank *bank); | |||
static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) | |||
{ | |||
if (tap == NULL) { | |||
if (tap == NULL) | |||
return ERROR_TARGET_INVALID; | |||
} | |||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) | |||
{ | |||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { | |||
struct scan_field field; | |||
field.num_bits = tap->ir_length; | |||
void * t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); | |||
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); | |||
field.out_value = t; | |||
buf_set_u32(t, 0, field.num_bits, new_instr); | |||
field.in_value = NULL; | |||
@@ -147,8 +143,7 @@ static int str9xpec_isc_enable(struct flash_bank *bank) | |||
/* check ISC status */ | |||
status = str9xpec_isc_status(tap); | |||
if (status & ISC_STATUS_MODE) | |||
{ | |||
if (status & ISC_STATUS_MODE) { | |||
/* we have entered isc mode */ | |||
str9xpec_info->isc_enable = 1; | |||
LOG_DEBUG("ISC_MODE Enabled"); | |||
@@ -176,8 +171,7 @@ static int str9xpec_isc_disable(struct flash_bank *bank) | |||
/* check ISC status */ | |||
status = str9xpec_isc_status(tap); | |||
if (!(status & ISC_STATUS_MODE)) | |||
{ | |||
if (!(status & ISC_STATUS_MODE)) { | |||
/* we have left isc mode */ | |||
str9xpec_info->isc_enable = 0; | |||
LOG_DEBUG("ISC_MODE Disabled"); | |||
@@ -224,8 +218,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank) | |||
uint32_t offset = 0; | |||
int b1_size = 0x2000; | |||
switch (bank->size) | |||
{ | |||
switch (bank->size) { | |||
case (256 * 1024): | |||
b0_sectors = 4; | |||
break; | |||
@@ -258,8 +251,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank) | |||
num_sectors = 0; | |||
for (i = 0; i < b0_sectors; i++) | |||
{ | |||
for (i = 0; i < b0_sectors; i++) { | |||
bank->sectors[num_sectors].offset = offset; | |||
bank->sectors[num_sectors].size = 0x10000; | |||
offset += bank->sectors[i].size; | |||
@@ -268,8 +260,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank) | |||
str9xpec_info->sector_bits[num_sectors++] = i; | |||
} | |||
for (i = 0; i < b1_sectors; i++) | |||
{ | |||
for (i = 0; i < b1_sectors; i++) { | |||
bank->sectors[num_sectors].offset = offset; | |||
bank->sectors[num_sectors].size = b1_size; | |||
offset += bank->sectors[i].size; | |||
@@ -291,9 +282,7 @@ FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command) | |||
struct arm_jtag *jtag_info = NULL; | |||
if (CMD_ARGC < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller)); | |||
bank->driver_priv = str9xpec_info; | |||
@@ -329,21 +318,18 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last) | |||
tap = str9xpec_info->tap; | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
str9xpec_isc_enable(bank); | |||
} | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
buffer = calloc(DIV_ROUND_UP(64, 8), 1); | |||
LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last); | |||
for (i = first; i <= last; i++) { | |||
for (i = first; i <= last; i++) | |||
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1); | |||
} | |||
/* execute ISC_BLANK_CHECK command */ | |||
str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE); | |||
@@ -365,8 +351,7 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last) | |||
status = str9xpec_isc_status(tap); | |||
for (i = first; i <= last; i++) | |||
{ | |||
for (i = first; i <= last; i++) { | |||
if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1)) | |||
bank->sectors[i].is_erased = 0; | |||
else | |||
@@ -391,8 +376,7 @@ static int str9xpec_protect_check(struct flash_bank *bank) | |||
status = str9xpec_read_config(bank); | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1)) | |||
bank->sectors[i].is_protected = 1; | |||
else | |||
@@ -416,13 +400,11 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) | |||
tap = str9xpec_info->tap; | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
str9xpec_isc_enable(bank); | |||
} | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
return ISC_STATUS_ERROR; | |||
} | |||
buffer = calloc(DIV_ROUND_UP(64, 8), 1); | |||
@@ -430,21 +412,14 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) | |||
/* last bank: 0xFF signals a full erase (unlock complete device) */ | |||
/* last bank: 0xFE signals a option byte erase */ | |||
if (last == 0xFF) | |||
{ | |||
for (i = 0; i < 64; i++) { | |||
if (last == 0xFF) { | |||
for (i = 0; i < 64; i++) | |||
buf_set_u32(buffer, i, 1, 1); | |||
} | |||
} | |||
else if (last == 0xFE) | |||
{ | |||
} else if (last == 0xFE) | |||
buf_set_u32(buffer, 49, 1, 1); | |||
} | |||
else | |||
{ | |||
for (i = first; i <= last; i++) { | |||
else { | |||
for (i = first; i <= last; i++) | |||
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1); | |||
} | |||
} | |||
LOG_DEBUG("ISC_ERASE"); | |||
@@ -462,9 +437,8 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) | |||
jtag_add_sleep(10); | |||
/* wait for erase completion */ | |||
while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) { | |||
while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) | |||
alive_sleep(1); | |||
} | |||
free(buffer); | |||
@@ -495,13 +469,11 @@ static int str9xpec_lock_device(struct flash_bank *bank) | |||
str9xpec_info = bank->driver_priv; | |||
tap = str9xpec_info->tap; | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
str9xpec_isc_enable(bank); | |||
} | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
return ISC_STATUS_ERROR; | |||
} | |||
/* set security address */ | |||
str9xpec_set_address(bank, 0x80); | |||
@@ -550,22 +522,15 @@ static int str9xpec_protect(struct flash_bank *bank, int set, int first, int las | |||
LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last); | |||
/* last bank: 0xFF signals a full device protect */ | |||
if (last == 0xFF) | |||
{ | |||
if (last == 0xFF) { | |||
if (set) | |||
{ | |||
status = str9xpec_lock_device(bank); | |||
} | |||
else | |||
{ | |||
else { | |||
/* perform full erase to unlock device */ | |||
status = str9xpec_unlock_device(bank); | |||
} | |||
} | |||
else | |||
{ | |||
for (i = first; i <= last; i++) | |||
{ | |||
} else { | |||
for (i = first; i <= last; i++) { | |||
if (set) | |||
buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1); | |||
else | |||
@@ -619,28 +584,23 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, | |||
tap = str9xpec_info->tap; | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
str9xpec_isc_enable(bank); | |||
} | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (offset & 0x7) | |||
{ | |||
if (offset & 0x7) { | |||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset); | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
} | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
for (i = 0; i < bank->num_sectors; i++) { | |||
uint32_t sec_start = bank->sectors[i].offset; | |||
uint32_t sec_end = sec_start + bank->sectors[i].size; | |||
/* check if destination falls within the current sector */ | |||
if ((check_address >= sec_start) && (check_address < sec_end)) | |||
{ | |||
if ((check_address >= sec_start) && (check_address < sec_end)) { | |||
/* check if destination ends in the current sector */ | |||
if (offset + count < sec_end) | |||
check_address = offset + count; | |||
@@ -648,13 +608,11 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, | |||
check_address = sec_end; | |||
} | |||
if ((offset >= sec_start) && (offset < sec_end)) { | |||
if ((offset >= sec_start) && (offset < sec_end)) | |||
first_sector = i; | |||
} | |||
if ((offset + count >= sec_start) && (offset + count < sec_end)) { | |||
if ((offset + count >= sec_start) && (offset + count < sec_end)) | |||
last_sector = i; | |||
} | |||
} | |||
if (check_address != offset + count) | |||
@@ -666,15 +624,13 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, | |||
LOG_DEBUG("ISC_PROGRAM"); | |||
for (i = first_sector; i <= last_sector; i++) | |||
{ | |||
for (i = first_sector; i <= last_sector; i++) { | |||
str9xpec_set_address(bank, str9xpec_info->sector_bits[i]); | |||
dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) | |||
? dwords_remaining : (bank->sectors[i].size/8); | |||
while (dwords_remaining > 0) | |||
{ | |||
while (dwords_remaining > 0) { | |||
str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); | |||
field.num_bits = 64; | |||
@@ -711,8 +667,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, | |||
} | |||
} | |||
if (bytes_remaining) | |||
{ | |||
if (bytes_remaining) { | |||
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |||
/* copy the last remaining bytes into the write buffer */ | |||
@@ -818,9 +773,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_read_command) | |||
struct str9xpec_flash_controller *str9xpec_info = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -883,13 +836,11 @@ static int str9xpec_write_options(struct flash_bank *bank) | |||
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) | |||
return status; | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
str9xpec_isc_enable(bank); | |||
} | |||
if (!str9xpec_info->isc_enable) { | |||
if (!str9xpec_info->isc_enable) | |||
return ISC_STATUS_ERROR; | |||
} | |||
/* according to data 64th bit has to be set */ | |||
buf_set_u32(str9xpec_info->options, 63, 1, 1); | |||
@@ -931,9 +882,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command) | |||
uint8_t status; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -957,9 +906,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command) | |||
struct str9xpec_flash_controller *str9xpec_info = NULL; | |||
if (CMD_ARGC < 2) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -969,13 +916,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command) | |||
str9xpec_info = bank->driver_priv; | |||
if (strcmp(CMD_ARGV[1], "bank1") == 0) | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1); | |||
} | |||
else | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0); | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -985,9 +928,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command) | |||
struct str9xpec_flash_controller *str9xpec_info = NULL; | |||
if (CMD_ARGC < 2) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -997,13 +938,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command) | |||
str9xpec_info = bank->driver_priv; | |||
if (strcmp(CMD_ARGV[1], "2.7v") == 0) | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1); | |||
} | |||
else | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0); | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -1013,9 +950,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command) | |||
struct str9xpec_flash_controller *str9xpec_info = NULL; | |||
if (CMD_ARGC < 2) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1025,13 +960,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command) | |||
str9xpec_info = bank->driver_priv; | |||
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0) | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1); | |||
} | |||
else | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0); | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -1041,9 +972,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command) | |||
struct str9xpec_flash_controller *str9xpec_info = NULL; | |||
if (CMD_ARGC < 2) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1053,13 +982,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command) | |||
str9xpec_info = bank->driver_priv; | |||
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0) | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1); | |||
} | |||
else | |||
{ | |||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0); | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -1069,9 +994,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_lock_command) | |||
uint8_t status; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1091,9 +1014,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_unlock_command) | |||
uint8_t status; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1120,9 +1041,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command) | |||
struct str9xpec_flash_controller *str9xpec_info = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1135,23 +1054,22 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command) | |||
/* remove arm core from chain - enter turbo mode */ | |||
tap1 = tap0->next_tap; | |||
if (tap1 == NULL) | |||
{ | |||
if (tap1 == NULL) { | |||
/* things are *WRONG* */ | |||
command_print(CMD_CTX,"**STR9FLASH** (tap1) invalid chain?"); | |||
command_print(CMD_CTX, "**STR9FLASH** (tap1) invalid chain?"); | |||
return ERROR_OK; | |||
} | |||
tap2 = tap1->next_tap; | |||
if (tap2 == NULL) | |||
{ | |||
if (tap2 == NULL) { | |||
/* things are *WRONG* */ | |||
command_print(CMD_CTX,"**STR9FLASH** (tap2) invalid chain?"); | |||
command_print(CMD_CTX, "**STR9FLASH** (tap2) invalid chain?"); | |||
return ERROR_OK; | |||
} | |||
/* enable turbo mode - TURBO-PROG-ENABLE */ | |||
str9xpec_set_instr(tap2, 0xD, TAP_IDLE); | |||
if ((retval = jtag_execute_queue()) != ERROR_OK) | |||
retval = jtag_execute_queue(); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* modify scan chain - str9 core has been removed */ | |||
@@ -1166,9 +1084,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command) | |||
struct str9xpec_flash_controller *str9xpec_info = NULL; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *bank; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); | |||
@@ -1187,9 +1103,8 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command) | |||
jtag_execute_queue(); | |||
/* restore previous scan chain */ | |||
if (tap->next_tap) { | |||
if (tap->next_tap) | |||
tap->next_tap->enabled = 1; | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -32,7 +32,7 @@ | |||
*/ | |||
COMMAND_HELPER(flash_command_get_bank, unsigned name_index, | |||
struct flash_bank **bank) | |||
struct flash_bank **bank) | |||
{ | |||
const char *name = CMD_ARGV[name_index]; | |||
int retval = get_flash_bank_by_name(name, bank); | |||
@@ -47,7 +47,6 @@ COMMAND_HELPER(flash_command_get_bank, unsigned name_index, | |||
return get_flash_bank_by_num(bank_num, bank); | |||
} | |||
COMMAND_HANDLER(handle_flash_info_command) | |||
{ | |||
struct flash_bank *p; | |||
@@ -61,12 +60,12 @@ COMMAND_HANDLER(handle_flash_info_command) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (p != NULL) | |||
{ | |||
if (p != NULL) { | |||
char buf[1024]; | |||
/* attempt auto probe */ | |||
if ((retval = p->driver->auto_probe(p)) != ERROR_OK) | |||
retval = p->driver->auto_probe(p); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* We must query the hardware to avoid printing stale information! */ | |||
@@ -75,15 +74,15 @@ COMMAND_HANDLER(handle_flash_info_command) | |||
return retval; | |||
command_print(CMD_CTX, | |||
"#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", buswidth %i, chipwidth %i", | |||
p->bank_number, | |||
p->driver->name, | |||
p->base, | |||
p->size, | |||
p->bus_width, | |||
p->chip_width); | |||
for (j = 0; j < p->num_sectors; j++) | |||
{ | |||
"#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 | |||
", buswidth %i, chipwidth %i", | |||
p->bank_number, | |||
p->driver->name, | |||
p->base, | |||
p->size, | |||
p->bus_width, | |||
p->chip_width); | |||
for (j = 0; j < p->num_sectors; j++) { | |||
char *protect_state; | |||
if (p->sectors[j].is_protected == 0) | |||
@@ -94,15 +93,16 @@ COMMAND_HANDLER(handle_flash_info_command) | |||
protect_state = "protection state unknown"; | |||
command_print(CMD_CTX, | |||
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", | |||
j, | |||
p->sectors[j].offset, | |||
p->sectors[j].size, | |||
p->sectors[j].size >> 10, | |||
protect_state); | |||
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", | |||
j, | |||
p->sectors[j].offset, | |||
p->sectors[j].size, | |||
p->sectors[j].size >> 10, | |||
protect_state); | |||
} | |||
*buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */ | |||
*buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver | |||
*function fails */ | |||
retval = p->driver->info(p, buf, sizeof(buf)); | |||
command_print(CMD_CTX, "%s", buf); | |||
if (retval != ERROR_OK) | |||
@@ -118,23 +118,20 @@ COMMAND_HANDLER(handle_flash_probe_command) | |||
int retval; | |||
if (CMD_ARGC != 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
if (p) | |||
{ | |||
if ((retval = p->driver->probe(p)) == ERROR_OK) | |||
{ | |||
command_print(CMD_CTX, "flash '%s' found at 0x%8.8" PRIx32, p->driver->name, p->base); | |||
} | |||
} | |||
else | |||
{ | |||
if (p) { | |||
retval = p->driver->probe(p); | |||
if (retval == ERROR_OK) | |||
command_print(CMD_CTX, | |||
"flash '%s' found at 0x%8.8" PRIx32, | |||
p->driver->name, | |||
p->base); | |||
} else { | |||
command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]); | |||
retval = ERROR_FAIL; | |||
} | |||
@@ -145,9 +142,7 @@ COMMAND_HANDLER(handle_flash_probe_command) | |||
COMMAND_HANDLER(handle_flash_erase_check_command) | |||
{ | |||
if (CMD_ARGC != 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
struct flash_bank *p; | |||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); | |||
@@ -155,18 +150,17 @@ COMMAND_HANDLER(handle_flash_erase_check_command) | |||
return retval; | |||
int j; | |||
if ((retval = p->driver->erase_check(p)) == ERROR_OK) | |||
{ | |||
retval = p->driver->erase_check(p); | |||
if (retval == ERROR_OK) | |||
command_print(CMD_CTX, "successfully checked erase state"); | |||
} | |||
else | |||
{ | |||
command_print(CMD_CTX, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32, | |||
CMD_ARGV[0], p->base); | |||
else { | |||
command_print(CMD_CTX, | |||
"unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32, | |||
CMD_ARGV[0], | |||
p->base); | |||
} | |||
for (j = 0; j < p->num_sectors; j++) | |||
{ | |||
for (j = 0; j < p->num_sectors; j++) { | |||
char *erase_state; | |||
if (p->sectors[j].is_erased == 0) | |||
@@ -177,12 +171,12 @@ COMMAND_HANDLER(handle_flash_erase_check_command) | |||
erase_state = "erase state unknown"; | |||
command_print(CMD_CTX, | |||
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", | |||
j, | |||
p->sectors[j].offset, | |||
p->sectors[j].size, | |||
p->sectors[j].size >> 10, | |||
erase_state); | |||
"\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", | |||
j, | |||
p->sectors[j].offset, | |||
p->sectors[j].size, | |||
p->sectors[j].size >> 10, | |||
erase_state); | |||
} | |||
return retval; | |||
@@ -198,35 +192,27 @@ COMMAND_HANDLER(handle_flash_erase_address_command) | |||
bool do_unlock = false; | |||
struct target *target = get_current_target(CMD_CTX); | |||
while (CMD_ARGC >= 3) | |||
{ | |||
while (CMD_ARGC >= 3) { | |||
/* Optionally pad out the address range to block/sector | |||
* boundaries. We can't know if there's data in that part | |||
* of the flash; only do padding if we're told to. | |||
*/ | |||
if (strcmp("pad", CMD_ARGV[0]) == 0) | |||
{ | |||
do_pad = true; | |||
} else if (strcmp("unlock", CMD_ARGV[0]) == 0) | |||
{ | |||
else if (strcmp("unlock", CMD_ARGV[0]) == 0) | |||
do_unlock = true; | |||
} else | |||
{ | |||
else | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
CMD_ARGC--; | |||
CMD_ARGV++; | |||
} | |||
if (CMD_ARGC != 2) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); | |||
if (length <= 0) | |||
{ | |||
if (length <= 0) { | |||
command_print(CMD_CTX, "Length must be >0"); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
@@ -235,44 +221,40 @@ COMMAND_HANDLER(handle_flash_erase_address_command) | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* We can't know if we did a resume + halt, in which case we no longer know the erased state */ | |||
/* We can't know if we did a resume + halt, in which case we no longer know the erased state | |||
**/ | |||
flash_set_dirty(); | |||
struct duration bench; | |||
duration_start(&bench); | |||
if (do_unlock) | |||
{ | |||
retval = flash_unlock_address_range(target, address, length); | |||
} | |||
if (retval == ERROR_OK) | |||
{ | |||
retval = flash_erase_address_range(target, do_pad, address, length); | |||
} | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) | |||
{ | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { | |||
command_print(CMD_CTX, "erased address 0x%8.8x (length %i)" | |||
" in %fs (%0.3f KiB/s)", address, length, | |||
duration_elapsed(&bench), duration_kbps(&bench, length)); | |||
" in %fs (%0.3f KiB/s)", address, length, | |||
duration_elapsed(&bench), duration_kbps(&bench, length)); | |||
} | |||
return retval; | |||
} | |||
static int flash_check_sector_parameters(struct command_context *cmd_ctx, | |||
uint32_t first, uint32_t last, uint32_t num_sectors) | |||
uint32_t first, uint32_t last, uint32_t num_sectors) | |||
{ | |||
if (!(first <= last)) { | |||
command_print(cmd_ctx, "ERROR: " | |||
"first sector must be <= last sector"); | |||
"first sector must be <= last sector"); | |||
return ERROR_FAIL; | |||
} | |||
if (!(last <= (num_sectors - 1))) { | |||
command_print(cmd_ctx, "ERROR: last sector must be <= %d", | |||
(int) num_sectors - 1); | |||
(int) num_sectors - 1); | |||
return ERROR_FAIL; | |||
} | |||
@@ -300,8 +282,8 @@ COMMAND_HANDLER(handle_flash_erase_command) | |||
else | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); | |||
if ((retval = flash_check_sector_parameters(CMD_CTX, | |||
first, last, p->num_sectors)) != ERROR_OK) | |||
retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
struct duration bench; | |||
@@ -309,11 +291,10 @@ COMMAND_HANDLER(handle_flash_erase_command) | |||
retval = flash_driver_erase(p, first, last); | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) | |||
{ | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { | |||
command_print(CMD_CTX, "erased sectors %" PRIu32 " " | |||
"through %" PRIu32" on flash bank %" PRIu32 " " | |||
"in %fs", first, last, p->bank_number, duration_elapsed(&bench)); | |||
"through %" PRIu32 " on flash bank %" PRIu32 " " | |||
"in %fs", first, last, p->bank_number, duration_elapsed(&bench)); | |||
} | |||
return ERROR_OK; | |||
@@ -343,14 +324,14 @@ COMMAND_HANDLER(handle_flash_protect_command) | |||
bool set; | |||
COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set); | |||
if ((retval = flash_check_sector_parameters(CMD_CTX, | |||
first, last, p->num_sectors)) != ERROR_OK) | |||
retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
retval = flash_driver_protect(p, set, first, last); | |||
if (retval == ERROR_OK) { | |||
command_print(CMD_CTX, "%s protection for sectors %i " | |||
"through %i on flash bank %" PRIu32 "", | |||
"through %i on flash bank %" PRIu32 "", | |||
(set) ? "set" : "cleared", (int) first, | |||
(int) last, p->bank_number); | |||
} | |||
@@ -368,41 +349,31 @@ COMMAND_HANDLER(handle_flash_write_image_command) | |||
int retval; | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
/* flash auto-erase is disabled by default*/ | |||
int auto_erase = 0; | |||
bool auto_unlock = false; | |||
for (;;) | |||
{ | |||
if (strcmp(CMD_ARGV[0], "erase") == 0) | |||
{ | |||
for (;; ) { | |||
if (strcmp(CMD_ARGV[0], "erase") == 0) { | |||
auto_erase = 1; | |||
CMD_ARGV++; | |||
CMD_ARGC--; | |||
command_print(CMD_CTX, "auto erase enabled"); | |||
} else if (strcmp(CMD_ARGV[0], "unlock") == 0) | |||
{ | |||
} else if (strcmp(CMD_ARGV[0], "unlock") == 0) { | |||
auto_unlock = true; | |||
CMD_ARGV++; | |||
CMD_ARGC--; | |||
command_print(CMD_CTX, "auto unlock enabled"); | |||
} else | |||
{ | |||
break; | |||
} | |||
} | |||
if (CMD_ARGC < 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
if (!target) | |||
{ | |||
if (!target) { | |||
LOG_ERROR("no target selected"); | |||
return ERROR_FAIL; | |||
} | |||
@@ -410,13 +381,10 @@ COMMAND_HANDLER(handle_flash_write_image_command) | |||
struct duration bench; | |||
duration_start(&bench); | |||
if (CMD_ARGC >= 2) | |||
{ | |||
if (CMD_ARGC >= 2) { | |||
image.base_address_set = 1; | |||
COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address); | |||
} | |||
else | |||
{ | |||
} else { | |||
image.base_address_set = 0; | |||
image.base_address = 0x0; | |||
} | |||
@@ -425,22 +393,18 @@ COMMAND_HANDLER(handle_flash_write_image_command) | |||
retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); | |||
if (retval != ERROR_OK) | |||
{ | |||
return retval; | |||
} | |||
retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
image_close(&image); | |||
return retval; | |||
} | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) | |||
{ | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { | |||
command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s " | |||
"in %fs (%0.3f KiB/s)", written, CMD_ARGV[0], | |||
duration_elapsed(&bench), duration_kbps(&bench, written)); | |||
"in %fs (%0.3f KiB/s)", written, CMD_ARGV[0], | |||
duration_elapsed(&bench), duration_kbps(&bench, written)); | |||
} | |||
image_close(&image); | |||
@@ -468,20 +432,17 @@ COMMAND_HANDLER(handle_flash_fill_command) | |||
return ERROR_FAIL; | |||
uint8_t *readback = malloc(chunksize); | |||
if (readback == NULL) | |||
{ | |||
if (readback == NULL) { | |||
free(chunk); | |||
return ERROR_FAIL; | |||
} | |||
if (CMD_ARGC != 3) | |||
{ | |||
if (CMD_ARGC != 3) { | |||
retval = ERROR_COMMAND_SYNTAX_ERROR; | |||
goto done; | |||
} | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern); | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count); | |||
@@ -489,88 +450,79 @@ COMMAND_HANDLER(handle_flash_fill_command) | |||
if (count == 0) | |||
goto done; | |||
switch (CMD_NAME[4]) | |||
{ | |||
case 'w': | |||
wordsize = 4; | |||
break; | |||
case 'h': | |||
wordsize = 2; | |||
break; | |||
case 'b': | |||
wordsize = 1; | |||
break; | |||
default: | |||
retval = ERROR_COMMAND_SYNTAX_ERROR; | |||
goto done; | |||
switch (CMD_NAME[4]) { | |||
case 'w': | |||
wordsize = 4; | |||
break; | |||
case 'h': | |||
wordsize = 2; | |||
break; | |||
case 'b': | |||
wordsize = 1; | |||
break; | |||
default: | |||
retval = ERROR_COMMAND_SYNTAX_ERROR; | |||
goto done; | |||
} | |||
chunk_count = MIN(count, (chunksize / wordsize)); | |||
switch (wordsize) | |||
{ | |||
case 4: | |||
for (i = 0; i < chunk_count; i++) | |||
{ | |||
target_buffer_set_u32(target, chunk + i * wordsize, pattern); | |||
} | |||
break; | |||
case 2: | |||
for (i = 0; i < chunk_count; i++) | |||
{ | |||
target_buffer_set_u16(target, chunk + i * wordsize, pattern); | |||
} | |||
break; | |||
case 1: | |||
memset(chunk, pattern, chunk_count); | |||
break; | |||
default: | |||
LOG_ERROR("BUG: can't happen"); | |||
exit(-1); | |||
switch (wordsize) { | |||
case 4: | |||
for (i = 0; i < chunk_count; i++) | |||
target_buffer_set_u32(target, chunk + i * wordsize, pattern); | |||
break; | |||
case 2: | |||
for (i = 0; i < chunk_count; i++) | |||
target_buffer_set_u16(target, chunk + i * wordsize, pattern); | |||
break; | |||
case 1: | |||
memset(chunk, pattern, chunk_count); | |||
break; | |||
default: | |||
LOG_ERROR("BUG: can't happen"); | |||
exit(-1); | |||
} | |||
struct duration bench; | |||
duration_start(&bench); | |||
for (wrote = 0; wrote < (count*wordsize); wrote += cur_size) | |||
{ | |||
for (wrote = 0; wrote < (count*wordsize); wrote += cur_size) { | |||
struct flash_bank *bank; | |||
retval = get_flash_bank_by_addr(target, address, true, &bank ); | |||
retval = get_flash_bank_by_addr(target, address, true, &bank); | |||
if (retval != ERROR_OK) | |||
goto done; | |||
cur_size = MIN((count * wordsize - wrote), chunksize); | |||
err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size); | |||
if (err != ERROR_OK) | |||
{ | |||
if (err != ERROR_OK) { | |||
retval = err; | |||
goto done; | |||
} | |||
err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size); | |||
if (err != ERROR_OK) | |||
{ | |||
if (err != ERROR_OK) { | |||
retval = err; | |||
goto done; | |||
} | |||
for (i = 0; i < cur_size; i++) | |||
{ | |||
if (readback[i]!=chunk[i]) | |||
{ | |||
LOG_ERROR("Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x", | |||
address + wrote + i, readback[i], chunk[i]); | |||
for (i = 0; i < cur_size; i++) { | |||
if (readback[i] != chunk[i]) { | |||
LOG_ERROR( | |||
"Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x", | |||
address + wrote + i, | |||
readback[i], | |||
chunk[i]); | |||
retval = ERROR_FAIL; | |||
goto done; | |||
} | |||
} | |||
} | |||
if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) | |||
{ | |||
if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) { | |||
command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32 | |||
" in %fs (%0.3f KiB/s)", wrote, address, | |||
duration_elapsed(&bench), duration_kbps(&bench, wrote)); | |||
" in %fs (%0.3f KiB/s)", wrote, address, | |||
duration_elapsed(&bench), duration_kbps(&bench, wrote)); | |||
} | |||
done: | |||
@@ -600,28 +552,23 @@ COMMAND_HANDLER(handle_flash_write_bank_command) | |||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); | |||
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) | |||
{ | |||
return ERROR_OK; | |||
} | |||
int filesize; | |||
retval = fileio_size(&fileio, &filesize); | |||
if (retval != ERROR_OK) | |||
{ | |||
if (retval != ERROR_OK) { | |||
fileio_close(&fileio); | |||
return retval; | |||
} | |||
buffer = malloc(filesize); | |||
if (buffer == NULL) | |||
{ | |||
if (buffer == NULL) { | |||
fileio_close(&fileio); | |||
LOG_ERROR("Out of memory"); | |||
return ERROR_FAIL; | |||
} | |||
size_t buf_cnt; | |||
if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) | |||
{ | |||
if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { | |||
free(buffer); | |||
fileio_close(&fileio); | |||
return ERROR_OK; | |||
@@ -632,12 +579,11 @@ COMMAND_HANDLER(handle_flash_write_bank_command) | |||
free(buffer); | |||
buffer = NULL; | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) | |||
{ | |||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { | |||
command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u" | |||
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", | |||
(long)filesize, CMD_ARGV[1], p->bank_number, offset, | |||
duration_elapsed(&bench), duration_kbps(&bench, filesize)); | |||
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", | |||
(long)filesize, CMD_ARGV[1], p->bank_number, offset, | |||
duration_elapsed(&bench), duration_kbps(&bench, filesize)); | |||
} | |||
fileio_close(&fileio); | |||
@@ -651,12 +597,9 @@ void flash_set_dirty(void) | |||
int i; | |||
/* set all flash to require erasing */ | |||
for (c = flash_bank_list(); c; c = c->next) | |||
{ | |||
for (c = flash_bank_list(); c; c = c->next) { | |||
for (i = 0; i < c->num_sectors; i++) | |||
{ | |||
c->sectors[i].is_erased = 0; | |||
} | |||
} | |||
} | |||
@@ -770,49 +713,43 @@ static int flash_init_drivers(struct command_context *cmd_ctx) | |||
COMMAND_HANDLER(handle_flash_bank_command) | |||
{ | |||
if (CMD_ARGC < 7) | |||
{ | |||
if (CMD_ARGC < 7) { | |||
LOG_ERROR("usage: flash bank <name> <driver> " | |||
"<base> <size> <chip_width> <bus_width> <target>"); | |||
"<base> <size> <chip_width> <bus_width> <target>"); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
// save bank name and advance arguments for compatibility | |||
/* save bank name and advance arguments for compatibility */ | |||
const char *bank_name = *CMD_ARGV++; | |||
CMD_ARGC--; | |||
struct target *target; | |||
if ((target = get_target(CMD_ARGV[5])) == NULL) | |||
{ | |||
struct target *target = get_target(CMD_ARGV[5]); | |||
if (target == NULL) { | |||
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]); | |||
return ERROR_FAIL; | |||
} | |||
const char *driver_name = CMD_ARGV[0]; | |||
struct flash_driver *driver = flash_driver_find_by_name(driver_name); | |||
if (NULL == driver) | |||
{ | |||
if (NULL == driver) { | |||
/* no matching flash driver found */ | |||
LOG_ERROR("flash driver '%s' not found", driver_name); | |||
return ERROR_FAIL; | |||
} | |||
/* check the flash bank name is unique */ | |||
if (get_flash_bank_by_name_noprobe(bank_name) != NULL) | |||
{ | |||
if (get_flash_bank_by_name_noprobe(bank_name) != NULL) { | |||
/* flash bank name already exists */ | |||
LOG_ERROR("flash bank name '%s' already exists", bank_name); | |||
return ERROR_FAIL; | |||
} | |||
/* register flash specific commands */ | |||
if (NULL != driver->commands) | |||
{ | |||
if (NULL != driver->commands) { | |||
int retval = register_commands(CMD_CTX, NULL, | |||
driver->commands); | |||
if (ERROR_OK != retval) | |||
{ | |||
if (ERROR_OK != retval) { | |||
LOG_ERROR("couldn't register '%s' commands", | |||
driver_name); | |||
driver_name); | |||
return ERROR_FAIL; | |||
} | |||
} | |||
@@ -832,10 +769,9 @@ COMMAND_HANDLER(handle_flash_bank_command) | |||
int retval; | |||
retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c); | |||
if (ERROR_OK != retval) | |||
{ | |||
if (ERROR_OK != retval) { | |||
LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "Usage %s", | |||
driver_name, c->base, driver->usage); | |||
driver_name, c->base, driver->usage); | |||
free(c); | |||
return retval; | |||
} | |||
@@ -854,8 +790,7 @@ COMMAND_HANDLER(handle_flash_banks_command) | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
unsigned n = 0; | |||
for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) | |||
{ | |||
for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) { | |||
LOG_USER("#%" PRIu32 " : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", " | |||
"buswidth %u, chipwidth %u", p->bank_number, | |||
p->name, p->driver->name, p->base, p->size, | |||
@@ -864,19 +799,17 @@ COMMAND_HANDLER(handle_flash_banks_command) | |||
return ERROR_OK; | |||
} | |||
static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |||
static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv) | |||
{ | |||
if (argc != 1) | |||
{ | |||
if (argc != 1) { | |||
Jim_WrongNumArgs(interp, 1, argv, | |||
"no arguments to 'flash list' command"); | |||
"no arguments to 'flash list' command"); | |||
return JIM_ERR; | |||
} | |||
Jim_Obj *list = Jim_NewListObj(interp, NULL, 0); | |||
for (struct flash_bank *p = flash_bank_list(); p; p = p->next) | |||
{ | |||
for (struct flash_bank *p = flash_bank_list(); p; p = p->next) { | |||
Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0); | |||
Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1)); | |||
@@ -898,15 +831,13 @@ static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |||
return JIM_OK; | |||
} | |||
COMMAND_HANDLER(handle_flash_init_command) | |||
{ | |||
if (CMD_ARGC != 0) | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
static bool flash_initialized = false; | |||
if (flash_initialized) | |||
{ | |||
static bool flash_initialized; | |||
if (flash_initialized) { | |||
LOG_INFO("'flash init' has already been called"); | |||
return ERROR_OK; | |||
} | |||
@@ -17,19 +17,18 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include "imp.h" | |||
/* ---------------------------------------------------------------------- | |||
Internal Support, Helpers | |||
---------------------------------------------------------------------- */ | |||
* Internal Support, Helpers | |||
* ---------------------------------------------------------------------- */ | |||
struct tms470_flash_bank | |||
{ | |||
struct tms470_flash_bank { | |||
unsigned ordinal; | |||
/* device identification register */ | |||
@@ -38,7 +37,7 @@ struct tms470_flash_bank | |||
uint32_t technology_family; | |||
uint32_t rom_flash; | |||
uint32_t part_number; | |||
const char * part_name; | |||
const char *part_name; | |||
}; | |||
@@ -134,15 +133,14 @@ static int tms470_read_part_info(struct flash_bank *bank) | |||
/* we shall not rely on the caller in this test, this function allocates memory, | |||
thus and executing the code more than once may cause memory leak */ | |||
if (tms470_info->device_ident_reg) | |||
return ERROR_OK; | |||
return ERROR_OK; | |||
/* read and parse the device identification register */ | |||
target_read_u32(target, 0xFFFFFFF0, &device_ident_reg); | |||
LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg); | |||
if ((device_ident_reg & 7) == 0) | |||
{ | |||
if ((device_ident_reg & 7) == 0) { | |||
LOG_WARNING("Cannot identify target as a TMS470 family."); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -152,8 +150,7 @@ static int tms470_read_part_info(struct flash_bank *bank) | |||
rom_flash = (device_ident_reg >> 10) & 1; | |||
part_number = (device_ident_reg >> 3) & 0x7f; | |||
if (bank->sectors) | |||
{ | |||
if (bank->sectors) { | |||
free(bank->sectors); | |||
bank->sectors = NULL; | |||
} | |||
@@ -164,116 +161,100 @@ static int tms470_read_part_info(struct flash_bank *bank) | |||
* ranges. Then fixup/complete the remaining fields of the flash | |||
* bank structure. | |||
*/ | |||
switch (part_number) | |||
{ | |||
case 0x0a: | |||
part_name = "TMS470R1A256"; | |||
if (bank->base >= 0x00040000) | |||
{ | |||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
tms470_info->ordinal = 0; | |||
bank->base = 0x00000000; | |||
bank->size = 256 * 1024; | |||
bank->num_sectors = TMS470R1A256_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS)); | |||
if (!bank->sectors) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS)); | |||
break; | |||
case 0x2b: | |||
part_name = "TMS470R1A288"; | |||
if (bank->base < 0x00008000) | |||
{ | |||
tms470_info->ordinal = 0; | |||
bank->base = 0x00000000; | |||
bank->size = 32 * 1024; | |||
bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS)); | |||
if (!bank->sectors) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS, sizeof(TMS470R1A288_BANK0_SECTORS)); | |||
} | |||
else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) | |||
{ | |||
tms470_info->ordinal = 1; | |||
bank->base = 0x00040000; | |||
bank->size = 256 * 1024; | |||
bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS)); | |||
if (!bank->sectors) | |||
{ | |||
switch (part_number) { | |||
case 0x0a: | |||
part_name = "TMS470R1A256"; | |||
if (bank->base >= 0x00040000) { | |||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", | |||
part_name, | |||
bank->base); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, sizeof(TMS470R1A288_BANK1_SECTORS)); | |||
} | |||
else | |||
{ | |||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
break; | |||
case 0x2d: | |||
part_name = "TMS470R1A384"; | |||
if (bank->base < 0x00020000) | |||
{ | |||
tms470_info->ordinal = 0; | |||
bank->base = 0x00000000; | |||
bank->size = 128 * 1024; | |||
bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS)); | |||
bank->size = 256 * 1024; | |||
bank->num_sectors = TMS470R1A256_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS)); | |||
if (!bank->sectors) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS, sizeof(TMS470R1A384_BANK0_SECTORS)); | |||
} | |||
else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) | |||
{ | |||
tms470_info->ordinal = 1; | |||
bank->base = 0x00020000; | |||
bank->size = 128 * 1024; | |||
bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS)); | |||
if (!bank->sectors) | |||
{ | |||
(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS)); | |||
break; | |||
case 0x2b: | |||
part_name = "TMS470R1A288"; | |||
if (bank->base < 0x00008000) { | |||
tms470_info->ordinal = 0; | |||
bank->base = 0x00000000; | |||
bank->size = 32 * 1024; | |||
bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS)); | |||
if (!bank->sectors) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS, | |||
sizeof(TMS470R1A288_BANK0_SECTORS)); | |||
} else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) { | |||
tms470_info->ordinal = 1; | |||
bank->base = 0x00040000; | |||
bank->size = 256 * 1024; | |||
bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS)); | |||
if (!bank->sectors) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, | |||
sizeof(TMS470R1A288_BANK1_SECTORS)); | |||
} else { | |||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", | |||
part_name, bank->base); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS, sizeof(TMS470R1A384_BANK1_SECTORS)); | |||
} | |||
else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) | |||
{ | |||
tms470_info->ordinal = 2; | |||
bank->base = 0x00040000; | |||
bank->size = 128 * 1024; | |||
bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS)); | |||
if (!bank->sectors) | |||
{ | |||
break; | |||
case 0x2d: | |||
part_name = "TMS470R1A384"; | |||
if (bank->base < 0x00020000) { | |||
tms470_info->ordinal = 0; | |||
bank->base = 0x00000000; | |||
bank->size = 128 * 1024; | |||
bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS)); | |||
if (!bank->sectors) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS, | |||
sizeof(TMS470R1A384_BANK0_SECTORS)); | |||
} else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) { | |||
tms470_info->ordinal = 1; | |||
bank->base = 0x00020000; | |||
bank->size = 128 * 1024; | |||
bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS)); | |||
if (!bank->sectors) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS, | |||
sizeof(TMS470R1A384_BANK1_SECTORS)); | |||
} else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) { | |||
tms470_info->ordinal = 2; | |||
bank->base = 0x00040000; | |||
bank->size = 128 * 1024; | |||
bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS; | |||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS)); | |||
if (!bank->sectors) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, | |||
sizeof(TMS470R1A384_BANK2_SECTORS)); | |||
} else { | |||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", | |||
part_name, bank->base); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, sizeof(TMS470R1A384_BANK2_SECTORS)); | |||
} | |||
else | |||
{ | |||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
break; | |||
break; | |||
default: | |||
LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", (unsigned)part_number); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
default: | |||
LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", | |||
(unsigned)part_number); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* turn off memory selects */ | |||
@@ -284,10 +265,10 @@ static int tms470_read_part_info(struct flash_bank *bank) | |||
bank->bus_width = 32; | |||
LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.", | |||
part_name, | |||
(int)(silicon_version), | |||
(technology_family ? "1.8v" : "3.3v"), | |||
(rom_flash ? "rom" : "flash")); | |||
part_name, | |||
(int)(silicon_version), | |||
(technology_family ? "1.8v" : "3.3v"), | |||
(rom_flash ? "rom" : "flash")); | |||
tms470_info->device_ident_reg = device_ident_reg; | |||
tms470_info->silicon_version = silicon_version; | |||
@@ -306,67 +287,57 @@ static int tms470_read_part_info(struct flash_bank *bank) | |||
/* ---------------------------------------------------------------------- */ | |||
static uint32_t keysSet = 0; | |||
static uint32_t keysSet; | |||
static uint32_t flashKeys[4]; | |||
COMMAND_HANDLER(tms470_handle_flash_keyset_command) | |||
{ | |||
if (CMD_ARGC > 4) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
else if (CMD_ARGC == 4) | |||
{ | |||
else if (CMD_ARGC == 4) { | |||
int i; | |||
for (i = 0; i < 4; i++) | |||
{ | |||
for (i = 0; i < 4; i++) { | |||
int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0; | |||
if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) | |||
{ | |||
command_print(CMD_CTX, "could not process flash key %s", CMD_ARGV[i]); | |||
if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) { | |||
command_print(CMD_CTX, "could not process flash key %s", | |||
CMD_ARGV[i]); | |||
LOG_ERROR("could not process flash key %s", CMD_ARGV[i]); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
} | |||
keysSet = 1; | |||
} | |||
else if (CMD_ARGC != 0) | |||
{ | |||
} else if (CMD_ARGC != 0) { | |||
command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>"); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
if (keysSet) | |||
{ | |||
command_print(CMD_CTX, "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "", | |||
flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3]); | |||
} | |||
else | |||
{ | |||
if (keysSet) { | |||
command_print(CMD_CTX, | |||
"using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "", | |||
flashKeys[0], | |||
flashKeys[1], | |||
flashKeys[2], | |||
flashKeys[3]); | |||
} else | |||
command_print(CMD_CTX, "flash keys not set"); | |||
} | |||
return ERROR_OK; | |||
} | |||
static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF, | |||
0xFFFFFFFF, 0xFFFFFFFF, | |||
}; | |||
0xFFFFFFFF, 0xFFFFFFFF,}; | |||
static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000, | |||
0x00000000, 0x00000000, | |||
}; | |||
0x00000000, 0x00000000,}; | |||
static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff, | |||
0xf0fff0ff, 0xf0fff0ff | |||
}; | |||
0xf0fff0ff, 0xf0fff0ff}; | |||
static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff, | |||
0x0000ffff, 0x0000ffff | |||
}; | |||
0x0000ffff, 0x0000ffff}; | |||
/* ---------------------------------------------------------------------- */ | |||
@@ -375,16 +346,11 @@ static int oscMHz = 12; | |||
COMMAND_HANDLER(tms470_handle_osc_megahertz_command) | |||
{ | |||
if (CMD_ARGC > 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
else if (CMD_ARGC == 1) | |||
{ | |||
sscanf(CMD_ARGV[0], "%d", &oscMHz); | |||
} | |||
if (oscMHz <= 0) | |||
{ | |||
if (oscMHz <= 0) { | |||
LOG_ERROR("osc_megahertz must be positive and non-zero!"); | |||
command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!"); | |||
oscMHz = 12; | |||
@@ -398,16 +364,13 @@ COMMAND_HANDLER(tms470_handle_osc_megahertz_command) | |||
/* ---------------------------------------------------------------------- */ | |||
static int plldis = 0; | |||
static int plldis; | |||
COMMAND_HANDLER(tms470_handle_plldis_command) | |||
{ | |||
if (CMD_ARGC > 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
else if (CMD_ARGC == 1) | |||
{ | |||
else if (CMD_ARGC == 1) { | |||
sscanf(CMD_ARGV[0], "%d", &plldis); | |||
plldis = plldis ? 1 : 0; | |||
} | |||
@@ -419,18 +382,20 @@ COMMAND_HANDLER(tms470_handle_plldis_command) | |||
/* ---------------------------------------------------------------------- */ | |||
static int tms470_check_flash_unlocked(struct target * target) | |||
static int tms470_check_flash_unlocked(struct target *target) | |||
{ | |||
uint32_t fmbbusy; | |||
target_read_u32(target, 0xFFE89C08, &fmbbusy); | |||
LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s", fmbbusy, fmbbusy & 0x8000 ? "unlocked" : "LOCKED"); | |||
LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s", | |||
fmbbusy, | |||
fmbbusy & 0x8000 ? "unlocked" : "LOCKED"); | |||
return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* ---------------------------------------------------------------------- */ | |||
static int tms470_try_flash_keys(struct target * target, const uint32_t * key_set) | |||
static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set) | |||
{ | |||
uint32_t glbctrl, fmmstat; | |||
int retval = ERROR_FLASH_OPERATION_FAILED; | |||
@@ -441,20 +406,17 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se | |||
/* only perform the key match when 3VSTAT is clear */ | |||
target_read_u32(target, 0xFFE8BC0C, &fmmstat); | |||
if (!(fmmstat & 0x08)) | |||
{ | |||
if (!(fmmstat & 0x08)) { | |||
unsigned i; | |||
uint32_t fmbptr, fmbac2, orig_fmregopt; | |||
target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07); | |||
/* wait for pump ready */ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, 0xFFE8A814, &fmbptr); | |||
alive_sleep(1); | |||
} | |||
while (!(fmbptr & 0x0200)); | |||
} while (!(fmbptr & 0x0200)); | |||
/* force max wait states */ | |||
target_read_u32(target, 0xFFE88004, &fmbac2); | |||
@@ -464,8 +426,7 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se | |||
target_read_u32(target, 0xFFE89C00, &orig_fmregopt); | |||
target_write_u32(target, 0xFFE89C00, 0x00); | |||
for (i = 0; i < 4; i++) | |||
{ | |||
for (i = 0; i < 4; i++) { | |||
uint32_t tmp; | |||
/* There is no point displaying the value of tmp, it is | |||
@@ -478,15 +439,13 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se | |||
target_write_u32(target, 0xFFE89C0C, key_set[i]); | |||
} | |||
if (ERROR_OK == tms470_check_flash_unlocked(target)) | |||
{ | |||
if (ERROR_OK == tms470_check_flash_unlocked(target)) { | |||
/* | |||
* There seems to be a side-effect of reading the FMPKEY | |||
* register in that it re-enables the protection. So we | |||
* re-enable it. | |||
*/ | |||
for (i = 0; i < 4; i++) | |||
{ | |||
for (i = 0; i < 4; i++) { | |||
uint32_t tmp; | |||
target_read_u32(target, 0x00001FF0 + 4 * i, &tmp); | |||
@@ -514,17 +473,14 @@ static int tms470_unlock_flash(struct flash_bank *bank) | |||
const uint32_t *p_key_sets[5]; | |||
unsigned i, key_set_count; | |||
if (keysSet) | |||
{ | |||
if (keysSet) { | |||
key_set_count = 5; | |||
p_key_sets[0] = flashKeys; | |||
p_key_sets[1] = FLASH_KEYS_ALL_ONES; | |||
p_key_sets[2] = FLASH_KEYS_ALL_ZEROS; | |||
p_key_sets[3] = FLASH_KEYS_MIX1; | |||
p_key_sets[4] = FLASH_KEYS_MIX2; | |||
} | |||
else | |||
{ | |||
} else { | |||
key_set_count = 4; | |||
p_key_sets[0] = FLASH_KEYS_ALL_ONES; | |||
p_key_sets[1] = FLASH_KEYS_ALL_ZEROS; | |||
@@ -532,10 +488,8 @@ static int tms470_unlock_flash(struct flash_bank *bank) | |||
p_key_sets[3] = FLASH_KEYS_MIX2; | |||
} | |||
for (i = 0; i < key_set_count; i++) | |||
{ | |||
if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) | |||
{ | |||
for (i = 0; i < key_set_count; i++) { | |||
if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) { | |||
LOG_INFO("tms470 flash is unlocked"); | |||
return ERROR_OK; | |||
} | |||
@@ -594,14 +548,11 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban | |||
* configure VHV | |||
*/ | |||
target_read_u32(target, 0xFFE8A080, &fmmaxep); | |||
if (fmmaxep == 0xf000) | |||
{ | |||
if (fmmaxep == 0xf000) { | |||
fmmaxep = 0xf000 + 4095; | |||
target_write_u32(target, 0xFFE8A80C, 0x9964); | |||
LOG_DEBUG("set fmptr3 = 0x9964"); | |||
} | |||
else | |||
{ | |||
} else { | |||
fmmaxep = 0xa000 + 4095; | |||
target_write_u32(target, 0xFFE8A80C, 0x9b64); | |||
LOG_DEBUG("set fmptr3 = 0x9b64"); | |||
@@ -692,44 +643,37 @@ static int tms470_flash_status(struct flash_bank *bank) | |||
target_read_u32(target, 0xFFE8BC0C, &fmmstat); | |||
LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat); | |||
if (fmmstat & 0x0080) | |||
{ | |||
if (fmmstat & 0x0080) { | |||
LOG_WARNING("tms470 flash command: erase still active after busy clear."); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (fmmstat & 0x0040) | |||
{ | |||
if (fmmstat & 0x0040) { | |||
LOG_WARNING("tms470 flash command: program still active after busy clear."); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (fmmstat & 0x0020) | |||
{ | |||
if (fmmstat & 0x0020) { | |||
LOG_WARNING("tms470 flash command: invalid data command."); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (fmmstat & 0x0010) | |||
{ | |||
if (fmmstat & 0x0010) { | |||
LOG_WARNING("tms470 flash command: program, erase or validate sector failed."); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (fmmstat & 0x0008) | |||
{ | |||
if (fmmstat & 0x0008) { | |||
LOG_WARNING("tms470 flash command: voltage instability detected."); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (fmmstat & 0x0006) | |||
{ | |||
if (fmmstat & 0x0006) { | |||
LOG_WARNING("tms470 flash command: command suspend detected."); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
if (fmmstat & 0x0001) | |||
{ | |||
if (fmmstat & 0x0001) { | |||
LOG_WARNING("tms470 flash command: sector was locked."); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -765,14 +709,11 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector) | |||
* Select one or more bits in FMBSEA or FMBSEB to disable Level 1 | |||
* protection for the particular sector to be erased/written. | |||
*/ | |||
if (sector < 16) | |||
{ | |||
if (sector < 16) { | |||
target_read_u32(target, 0xFFE88008, &fmbsea); | |||
target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector)); | |||
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector)); | |||
} | |||
else | |||
{ | |||
} else { | |||
target_read_u32(target, 0xFFE8800C, &fmbseb); | |||
target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16))); | |||
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16))); | |||
@@ -793,26 +734,19 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector) | |||
* Monitor FMMSTAT, busy until clear, then check and other flags for | |||
* ultimate result of the operation. | |||
*/ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, 0xFFE8BC0C, &fmmstat); | |||
if (fmmstat & 0x0100) | |||
{ | |||
alive_sleep(1); | |||
} | |||
} | |||
while (fmmstat & 0x0100); | |||
} while (fmmstat & 0x0100); | |||
result = tms470_flash_status(bank); | |||
if (sector < 16) | |||
{ | |||
if (sector < 16) { | |||
target_write_u32(target, 0xFFE88008, fmbsea); | |||
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea); | |||
bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1; | |||
} | |||
else | |||
{ | |||
} else { | |||
target_write_u32(target, 0xFFE8800C, fmbseb); | |||
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb); | |||
bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1; | |||
@@ -823,16 +757,14 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector) | |||
LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl); | |||
if (result == ERROR_OK) | |||
{ | |||
bank->sectors[sector].is_erased = 1; | |||
} | |||
return result; | |||
} | |||
/* ---------------------------------------------------------------------- | |||
Implementation of Flash Driver Interfaces | |||
---------------------------------------------------------------------- */ | |||
/*---------------------------------------------------------------------- | |||
* Implementation of Flash Driver Interfaces | |||
*---------------------------------------------------------------------- */ | |||
static const struct command_registration tms470_any_command_handlers[] = { | |||
{ | |||
@@ -876,41 +808,33 @@ static int tms470_erase(struct flash_bank *bank, int first, int last) | |||
struct tms470_flash_bank *tms470_info = bank->driver_priv; | |||
int sector, result = ERROR_OK; | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
tms470_read_part_info(bank); | |||
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last)) | |||
{ | |||
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || | |||
(last >= bank->num_sectors) || (first > last)) { | |||
LOG_ERROR("Sector range %d to %d invalid.", first, last); | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
result = tms470_unlock_flash(bank); | |||
if (result != ERROR_OK) | |||
{ | |||
return result; | |||
} | |||
for (sector = first; sector <= last; sector++) | |||
{ | |||
for (sector = first; sector <= last; sector++) { | |||
LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector); | |||
result = tms470_erase_sector(bank, sector); | |||
if (result != ERROR_OK) | |||
{ | |||
if (result != ERROR_OK) { | |||
LOG_ERROR("tms470 could not erase flash sector."); | |||
break; | |||
} | |||
else | |||
{ | |||
} else | |||
LOG_INFO("sector erased successfully."); | |||
} | |||
} | |||
return result; | |||
@@ -925,16 +849,15 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last) | |||
uint32_t fmmac2, fmbsea, fmbseb; | |||
int sector; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
tms470_read_part_info(bank); | |||
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last)) | |||
{ | |||
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || | |||
(last >= bank->num_sectors) || (first > last)) { | |||
LOG_ERROR("Sector range %d to %d invalid.", first, last); | |||
return ERROR_FLASH_SECTOR_INVALID; | |||
} | |||
@@ -947,16 +870,13 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last) | |||
target_read_u32(target, 0xFFE88008, &fmbsea); | |||
target_read_u32(target, 0xFFE8800C, &fmbseb); | |||
for (sector = 0; sector < bank->num_sectors; sector++) | |||
{ | |||
if (sector < 16) | |||
{ | |||
for (sector = 0; sector < bank->num_sectors; sector++) { | |||
if (sector < 16) { | |||
fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector); | |||
bank->sectors[sector].is_protected = set ? 1 : 0; | |||
} | |||
else | |||
{ | |||
fmbseb = set ? fmbseb & ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16)); | |||
} else { | |||
fmbseb = set ? fmbseb & | |||
~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16)); | |||
bank->sectors[sector].is_protected = set ? 1 : 0; | |||
} | |||
} | |||
@@ -970,22 +890,22 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last) | |||
/* ---------------------------------------------------------------------- */ | |||
static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offset, uint32_t count) | |||
static int tms470_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) | |||
{ | |||
struct target *target = bank->target; | |||
uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat; | |||
int result = ERROR_OK; | |||
uint32_t i; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
tms470_read_part_info(bank); | |||
LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base + offset); | |||
LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base + | |||
offset); | |||
/* set GLBCTRL.4 */ | |||
target_read_u32(target, 0xFFFFFFDC, &glbctrl); | |||
@@ -1012,13 +932,11 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs | |||
/* read MAXPP */ | |||
target_read_u32(target, 0xFFE8A07C, &fmmaxpp); | |||
for (i = 0; i < count; i += 2) | |||
{ | |||
for (i = 0; i < count; i += 2) { | |||
uint32_t addr = bank->base + offset + i; | |||
uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1]; | |||
if (word != 0xffff) | |||
{ | |||
if (word != 0xffff) { | |||
LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr); | |||
/* clear status register */ | |||
@@ -1032,28 +950,23 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs | |||
* Monitor FMMSTAT, busy until clear, then check and other flags | |||
* for ultimate result of the operation. | |||
*/ | |||
do | |||
{ | |||
do { | |||
target_read_u32(target, 0xFFE8BC0C, &fmmstat); | |||
if (fmmstat & 0x0100) | |||
{ | |||
alive_sleep(1); | |||
} | |||
} | |||
while (fmmstat & 0x0100); | |||
} while (fmmstat & 0x0100); | |||
if (fmmstat & 0x3ff) | |||
{ | |||
if (fmmstat & 0x3ff) { | |||
LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat); | |||
LOG_ERROR("Could not program word 0x%04x at address 0x%08" PRIx32 ".", word, addr); | |||
LOG_ERROR( | |||
"Could not program word 0x%04x at address 0x%08" PRIx32 ".", | |||
word, | |||
addr); | |||
result = ERROR_FLASH_OPERATION_FAILED; | |||
break; | |||
} | |||
} | |||
else | |||
{ | |||
} else | |||
LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr); | |||
} | |||
} | |||
/* restore */ | |||
@@ -1070,8 +983,7 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs | |||
static int tms470_probe(struct flash_bank *bank) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) | |||
{ | |||
if (bank->target->state != TARGET_HALTED) { | |||
LOG_WARNING("Cannot communicate... target not halted."); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
@@ -1098,16 +1010,13 @@ static int tms470_erase_check(struct flash_bank *bank) | |||
uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt; | |||
static uint8_t buffer[64 * 1024]; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (!tms470_info->device_ident_reg) | |||
{ | |||
tms470_read_part_info(bank); | |||
} | |||
/* set GLBCTRL.4 */ | |||
target_read_u32(target, 0xFFFFFFDC, &glbctrl); | |||
@@ -1136,10 +1045,8 @@ static int tms470_erase_check(struct flash_bank *bank) | |||
* word at a time. Here we read an entire sector and inspect it in | |||
* an attempt to reduce the JTAG overhead. | |||
*/ | |||
for (sector = 0; sector < bank->num_sectors; sector++) | |||
{ | |||
if (bank->sectors[sector].is_erased != 1) | |||
{ | |||
for (sector = 0; sector < bank->num_sectors; sector++) { | |||
if (bank->sectors[sector].is_erased != 1) { | |||
uint32_t i, addr = bank->base + bank->sectors[sector].offset; | |||
LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector); | |||
@@ -1147,27 +1054,26 @@ static int tms470_erase_check(struct flash_bank *bank) | |||
target_read_buffer(target, addr, bank->sectors[sector].size, buffer); | |||
bank->sectors[sector].is_erased = 1; | |||
for (i = 0; i < bank->sectors[sector].size; i++) | |||
{ | |||
if (buffer[i] != 0xff) | |||
{ | |||
LOG_WARNING("tms470 bank %d, sector %d, not erased.", tms470_info->ordinal, sector); | |||
LOG_WARNING("at location 0x%08" PRIx32 ": flash data is 0x%02x.", addr + i, buffer[i]); | |||
for (i = 0; i < bank->sectors[sector].size; i++) { | |||
if (buffer[i] != 0xff) { | |||
LOG_WARNING("tms470 bank %d, sector %d, not erased.", | |||
tms470_info->ordinal, | |||
sector); | |||
LOG_WARNING( | |||
"at location 0x%08" PRIx32 ": flash data is 0x%02x.", | |||
addr + i, | |||
buffer[i]); | |||
bank->sectors[sector].is_erased = 0; | |||
break; | |||
} | |||
} | |||
} | |||
if (bank->sectors[sector].is_erased != 1) | |||
{ | |||
if (bank->sectors[sector].is_erased != 1) { | |||
result = ERROR_FLASH_SECTOR_NOT_ERASED; | |||
break; | |||
} | |||
else | |||
{ | |||
} else | |||
LOG_INFO("sector erased"); | |||
} | |||
} | |||
/* reset TEZ, wait states, read mode, GLBCTRL.4 */ | |||
@@ -1188,16 +1094,13 @@ static int tms470_protect_check(struct flash_bank *bank) | |||
int sector, result = ERROR_OK; | |||
uint32_t fmmac2, fmbsea, fmbseb; | |||
if (target->state != TARGET_HALTED) | |||
{ | |||
if (target->state != TARGET_HALTED) { | |||
LOG_ERROR("Target not halted"); | |||
return ERROR_TARGET_NOT_HALTED; | |||
} | |||
if (!tms470_info->device_ident_reg) | |||
{ | |||
tms470_read_part_info(bank); | |||
} | |||
/* enable the appropriate bank */ | |||
target_read_u32(target, 0xFFE8BC04, &fmmac2); | |||
@@ -1206,22 +1109,21 @@ static int tms470_protect_check(struct flash_bank *bank) | |||
target_read_u32(target, 0xFFE88008, &fmbsea); | |||
target_read_u32(target, 0xFFE8800C, &fmbseb); | |||
for (sector = 0; sector < bank->num_sectors; sector++) | |||
{ | |||
for (sector = 0; sector < bank->num_sectors; sector++) { | |||
int protected; | |||
if (sector < 16) | |||
{ | |||
if (sector < 16) { | |||
protected = fmbsea & (1 << sector) ? 0 : 1; | |||
bank->sectors[sector].is_protected = protected; | |||
} | |||
else | |||
{ | |||
} else { | |||
protected = fmbseb & (1 << (sector - 16)) ? 0 : 1; | |||
bank->sectors[sector].is_protected = protected; | |||
} | |||
LOG_DEBUG("bank %d sector %d is %s", tms470_info->ordinal, sector, protected ? "protected" : "not protected"); | |||
LOG_DEBUG("bank %d sector %d is %s", | |||
tms470_info->ordinal, | |||
sector, | |||
protected ? "protected" : "not protected"); | |||
} | |||
return result; | |||
@@ -1235,21 +1137,21 @@ static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size) | |||
struct tms470_flash_bank *tms470_info = bank->driver_priv; | |||
if (!tms470_info->device_ident_reg) | |||
{ | |||
tms470_read_part_info(bank); | |||
} | |||
if (!tms470_info->device_ident_reg) | |||
{ | |||
if (!tms470_info->device_ident_reg) { | |||
(void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n"); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
used = snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n", tms470_info->part_name); | |||
used = | |||
snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n", | |||
tms470_info->part_name); | |||
buf += used; | |||
buf_size -= used; | |||
snprintf(buf, buf_size, "Flash protection level 2 is %s\n", tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled"); | |||
snprintf(buf, buf_size, "Flash protection level 2 is %s\n", | |||
tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled"); | |||
return ERROR_OK; | |||
} | |||
@@ -1266,9 +1168,7 @@ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command) | |||
bank->driver_priv = malloc(sizeof(struct tms470_flash_bank)); | |||
if (!bank->driver_priv) | |||
{ | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
(void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank)); | |||
@@ -17,20 +17,20 @@ | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include "imp.h" | |||
static struct flash_bank* virtual_get_master_bank(struct flash_bank *bank) | |||
static struct flash_bank *virtual_get_master_bank(struct flash_bank *bank) | |||
{ | |||
struct flash_bank* master_bank; | |||
struct flash_bank *master_bank; | |||
master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv); | |||
if (master_bank == NULL) { | |||
LOG_ERROR("master flash bank '%s' does not exist", (char*)bank->driver_priv); | |||
} | |||
if (master_bank == NULL) | |||
LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv); | |||
return master_bank; | |||
} | |||
@@ -39,9 +39,8 @@ static void virtual_update_bank_info(struct flash_bank *bank) | |||
{ | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return; | |||
} | |||
/* update the info we do not have */ | |||
bank->size = master_bank->size; | |||
@@ -54,16 +53,13 @@ static void virtual_update_bank_info(struct flash_bank *bank) | |||
FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command) | |||
{ | |||
if (CMD_ARGC < 7) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
/* get the master flash bank */ | |||
const char *bank_name = CMD_ARGV[6]; | |||
struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name); | |||
if (master_bank == NULL) | |||
{ | |||
if (master_bank == NULL) { | |||
LOG_ERROR("master flash bank '%s' does not exist", bank_name); | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
@@ -79,13 +75,12 @@ static int virtual_protect(struct flash_bank *bank, int set, int first, int last | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->protect(master_bank, set, | |||
first, last)) != ERROR_OK) | |||
retval = master_bank->driver->protect(master_bank, set, first, last); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return ERROR_OK; | |||
@@ -96,12 +91,12 @@ static int virtual_protect_check(struct flash_bank *bank) | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->protect_check(master_bank)) != ERROR_OK) | |||
retval = master_bank->driver->protect_check(master_bank); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return ERROR_OK; | |||
@@ -112,13 +107,12 @@ static int virtual_erase(struct flash_bank *bank, int first, int last) | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->erase(master_bank, | |||
first, last)) != ERROR_OK) | |||
retval = master_bank->driver->erase(master_bank, first, last); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return ERROR_OK; | |||
@@ -130,13 +124,12 @@ static int virtual_write(struct flash_bank *bank, uint8_t *buffer, | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->write(master_bank, buffer, | |||
offset, count)) != ERROR_OK) | |||
retval = master_bank->driver->write(master_bank, buffer, offset, count); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return ERROR_OK; | |||
@@ -147,12 +140,12 @@ static int virtual_probe(struct flash_bank *bank) | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->probe(master_bank)) != ERROR_OK) | |||
retval = master_bank->driver->probe(master_bank); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* update the info we do not have */ | |||
@@ -166,12 +159,12 @@ static int virtual_auto_probe(struct flash_bank *bank) | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->auto_probe(master_bank)) != ERROR_OK) | |||
retval = master_bank->driver->auto_probe(master_bank); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
/* update the info we do not have */ | |||
@@ -184,9 +177,8 @@ static int virtual_info(struct flash_bank *bank, char *buf, int buf_size) | |||
{ | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "", | |||
bank->driver->name, master_bank->name, master_bank->base); | |||
@@ -199,12 +191,12 @@ static int virtual_blank_check(struct flash_bank *bank) | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->erase_check(master_bank)) != ERROR_OK) | |||
retval = master_bank->driver->erase_check(master_bank); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return ERROR_OK; | |||
@@ -216,13 +208,12 @@ static int virtual_flash_read(struct flash_bank *bank, | |||
struct flash_bank *master_bank = virtual_get_master_bank(bank); | |||
int retval; | |||
if (master_bank == NULL) { | |||
if (master_bank == NULL) | |||
return ERROR_FLASH_OPERATION_FAILED; | |||
} | |||
/* call master handler */ | |||
if ((retval = master_bank->driver->read(master_bank, buffer, | |||
offset, count)) != ERROR_OK) | |||
retval = master_bank->driver->read(master_bank, buffer, offset, count); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return ERROR_OK; | |||