build: cleanup src/flash/nor directory
Change-Id: Ic299de969ce566282c055ba4dd8b94892c4c4311 Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/420 Tested-by: jenkins__archive__
parent
fab0dcd7e6
commit
9f0cba528a
|
@ -29,9 +29,8 @@
|
||||||
#include <target/algorithm.h>
|
#include <target/algorithm.h>
|
||||||
#include <target/arm.h>
|
#include <target/arm.h>
|
||||||
|
|
||||||
|
|
||||||
static int aduc702x_build_sector_list(struct flash_bank *bank);
|
static int aduc702x_build_sector_list(struct flash_bank *bank);
|
||||||
static int aduc702x_check_flash_completion(struct target* target, unsigned int timeout_ms);
|
static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms);
|
||||||
static int aduc702x_set_write_enable(struct target *target, int enable);
|
static int aduc702x_set_write_enable(struct target *target, int enable);
|
||||||
|
|
||||||
#define ADUC702x_FLASH 0xfffff800
|
#define ADUC702x_FLASH 0xfffff800
|
||||||
|
@ -57,7 +56,7 @@ FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
|
||||||
nbank = malloc(sizeof(struct aduc702x_flash_bank));
|
nbank = malloc(sizeof(struct aduc702x_flash_bank));
|
||||||
|
|
||||||
bank->base = 0x80000;
|
bank->base = 0x80000;
|
||||||
bank->size = 0xF800; // top 4k not accessible
|
bank->size = 0xF800; /* top 4k not accessible */
|
||||||
bank->driver_priv = nbank;
|
bank->driver_priv = nbank;
|
||||||
|
|
||||||
aduc702x_build_sector_list(bank);
|
aduc702x_build_sector_list(bank);
|
||||||
|
@ -67,16 +66,15 @@ FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
|
||||||
|
|
||||||
static int aduc702x_build_sector_list(struct flash_bank *bank)
|
static int aduc702x_build_sector_list(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
//aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv;
|
/* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
// sector size is 512
|
/* sector size is 512 */
|
||||||
bank->num_sectors = bank->size / 512;
|
bank->num_sectors = bank->size / 512;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
for (i = 0; i < bank->num_sectors; ++i)
|
for (i = 0; i < bank->num_sectors; ++i) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 512;
|
bank->sectors[i].size = 512;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -95,10 +93,10 @@ static int aduc702x_protect_check(struct flash_bank *bank)
|
||||||
|
|
||||||
static int aduc702x_erase(struct flash_bank *bank, int first, int last)
|
static int aduc702x_erase(struct flash_bank *bank, int first, int last)
|
||||||
{
|
{
|
||||||
//int res;
|
/* int res; */
|
||||||
int x;
|
int x;
|
||||||
int count;
|
int count;
|
||||||
//uint32_t v;
|
/* uint32_t v; */
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
|
||||||
aduc702x_set_write_enable(target, 1);
|
aduc702x_set_write_enable(target, 1);
|
||||||
|
@ -110,8 +108,7 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
|
||||||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
|
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
|
||||||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);
|
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);
|
||||||
|
|
||||||
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK)
|
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("mass erase failed");
|
LOG_ERROR("mass erase failed");
|
||||||
aduc702x_set_write_enable(target, 0);
|
aduc702x_set_write_enable(target, 0);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
@ -123,15 +120,13 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
|
||||||
unsigned long adr;
|
unsigned long adr;
|
||||||
|
|
||||||
count = last - first + 1;
|
count = last - first + 1;
|
||||||
for (x = 0; x < count; ++x)
|
for (x = 0; x < count; ++x) {
|
||||||
{
|
|
||||||
adr = bank->base + ((first + x) * 512);
|
adr = bank->base + ((first + x) * 512);
|
||||||
|
|
||||||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
|
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
|
||||||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);
|
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);
|
||||||
|
|
||||||
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK)
|
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
|
LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
|
||||||
aduc702x_set_write_enable(target, 0);
|
aduc702x_set_write_enable(target, 0);
|
||||||
return ERROR_FLASH_SECTOR_NOT_ERASED;
|
return ERROR_FLASH_SECTOR_NOT_ERASED;
|
||||||
|
@ -157,7 +152,10 @@ static int aduc702x_protect(struct flash_bank *bank, int set, int first, int las
|
||||||
*
|
*
|
||||||
* Caller should not check for other return values specifically
|
* Caller should not check for other return values specifically
|
||||||
*/
|
*/
|
||||||
static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
static int aduc702x_write_block(struct flash_bank *bank,
|
||||||
|
uint8_t *buffer,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t count)
|
||||||
{
|
{
|
||||||
struct aduc702x_flash_bank *aduc702x_info = bank->driver_priv;
|
struct aduc702x_flash_bank *aduc702x_info = bank->driver_priv;
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
@ -168,8 +166,7 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
|
||||||
struct arm_algorithm armv4_5_info;
|
struct arm_algorithm armv4_5_info;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
if (((count%2)!=0)||((offset%2)!=0))
|
if (((count%2) != 0) || ((offset%2) != 0)) {
|
||||||
{
|
|
||||||
LOG_ERROR("write block must be multiple of two bytes in offset & length");
|
LOG_ERROR("write block must be multiple of two bytes in offset & length");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -189,50 +186,46 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
|
||||||
|
|
||||||
*/
|
*/
|
||||||
static const uint32_t aduc702x_flash_write_code[] = {
|
static const uint32_t aduc702x_flash_write_code[] = {
|
||||||
//<_start>:
|
/* <_start>: */
|
||||||
0xe3a05008, // mov r5, #8 ; 0x8
|
0xe3a05008, /* mov r5, #8 ; 0x8 */
|
||||||
0xe5845004, // str r5, [r4, #4]
|
0xe5845004, /* str r5, [r4, #4] */
|
||||||
0xe3a06002, // mov r6, #2 ; 0x2
|
0xe3a06002, /* mov r6, #2 ; 0x2 */
|
||||||
//<next>:
|
/* <next>: */
|
||||||
0xe1c421b0, // strh r2, [r4, #16]
|
0xe1c421b0, /* strh r2, [r4, #16] */
|
||||||
0xe0d050b2, // ldrh r5, [r0], #2
|
0xe0d050b2, /* ldrh r5, [r0], #2 */
|
||||||
0xe1c450bc, // strh r5, [r4, #12]
|
0xe1c450bc, /* strh r5, [r4, #12] */
|
||||||
0xe5c46008, // strb r6, [r4, #8]
|
0xe5c46008, /* strb r6, [r4, #8] */
|
||||||
//<wait_complete>:
|
/* <wait_complete>: */
|
||||||
0xe1d430b0, // ldrh r3, [r4]
|
0xe1d430b0, /* ldrh r3, [r4] */
|
||||||
0xe3130004, // tst r3, #4 ; 0x4
|
0xe3130004, /* tst r3, #4 ; 0x4 */
|
||||||
0x1afffffc, // bne 1001c <wait_complete>
|
0x1afffffc, /* bne 1001c <wait_complete> */
|
||||||
0xe2822002, // add r2, r2, #2 ; 0x2
|
0xe2822002, /* add r2, r2, #2 ; 0x2 */
|
||||||
0xe2511001, // subs r1, r1, #1 ; 0x1
|
0xe2511001, /* subs r1, r1, #1 ; 0x1 */
|
||||||
0x0a000001, // beq 1003c <done>
|
0x0a000001, /* beq 1003c <done> */
|
||||||
0xe3130001, // tst r3, #1 ; 0x1
|
0xe3130001, /* tst r3, #1 ; 0x1 */
|
||||||
0x1afffff3, // bne 1000c <next>
|
0x1afffff3, /* bne 1000c <next> */
|
||||||
//<done>:
|
/* <done>: */
|
||||||
0xeafffffe // b 1003c <done>
|
0xeafffffe /* b 1003c <done> */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* flash write code */
|
/* flash write code */
|
||||||
if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
|
if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
|
||||||
&aduc702x_info->write_algorithm) != ERROR_OK)
|
&aduc702x_info->write_algorithm) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("no working area available, can't do block memory writes");
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
|
||||||
|
|
||||||
retval=target_write_buffer(target, aduc702x_info->write_algorithm->address,
|
|
||||||
sizeof(aduc702x_flash_write_code), (uint8_t*)aduc702x_flash_write_code);
|
|
||||||
if (retval!=ERROR_OK)
|
|
||||||
{
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
/* if we already allocated the writing code, but failed to get a buffer,
|
||||||
/* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
|
*free the algorithm */
|
||||||
if (aduc702x_info->write_algorithm)
|
if (aduc702x_info->write_algorithm)
|
||||||
target_free_working_area(target, aduc702x_info->write_algorithm);
|
target_free_working_area(target, aduc702x_info->write_algorithm);
|
||||||
|
|
||||||
|
@ -251,32 +244,29 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
|
||||||
init_reg_param(®_params[3], "r3", 32, PARAM_IN);
|
init_reg_param(®_params[3], "r3", 32, PARAM_IN);
|
||||||
init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
|
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;
|
uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
|
||||||
|
|
||||||
retval=target_write_buffer(target, source->address, thisrun_count, buffer);
|
retval = target_write_buffer(target, source->address, thisrun_count, buffer);
|
||||||
if (retval!=ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
||||||
buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
|
buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, address);
|
buf_set_u32(reg_params[2].value, 0, 32, address);
|
||||||
buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
|
buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 5,
|
retval = target_run_algorithm(target, 0, NULL, 5,
|
||||||
reg_params, aduc702x_info->write_algorithm->address,
|
reg_params, aduc702x_info->write_algorithm->address,
|
||||||
aduc702x_info->write_algorithm->address + sizeof(aduc702x_flash_write_code) - 4,
|
aduc702x_info->write_algorithm->address +
|
||||||
10000, &armv4_5_info)) != ERROR_OK)
|
sizeof(aduc702x_flash_write_code) - 4,
|
||||||
{
|
10000, &armv4_5_info);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("error executing aduc702x flash write algorithm");
|
LOG_ERROR("error executing aduc702x flash write algorithm");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1)
|
if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) {
|
||||||
{
|
|
||||||
/* FIX!!!! what does this mean??? replace w/sensible error message */
|
/* FIX!!!! what does this mean??? replace w/sensible error message */
|
||||||
LOG_ERROR("aduc702x detected error writing flash");
|
LOG_ERROR("aduc702x detected error writing flash");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
|
@ -302,7 +292,10 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
|
||||||
|
|
||||||
/* All-JTAG, single-access method. Very slow. Used only if there is no
|
/* All-JTAG, single-access method. Very slow. Used only if there is no
|
||||||
* working area available. */
|
* working area available. */
|
||||||
static int aduc702x_write_single(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
static int aduc702x_write_single(struct flash_bank *bank,
|
||||||
|
uint8_t *buffer,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t count)
|
||||||
{
|
{
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
|
@ -311,26 +304,24 @@ static int aduc702x_write_single(struct flash_bank *bank, uint8_t *buffer, uint3
|
||||||
aduc702x_set_write_enable(target, 1);
|
aduc702x_set_write_enable(target, 1);
|
||||||
|
|
||||||
for (x = 0; x < count; x += 2) {
|
for (x = 0; x < count; x += 2) {
|
||||||
// FEEADR = address
|
/* FEEADR = address */
|
||||||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x);
|
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x);
|
||||||
|
|
||||||
// set up data
|
/* set up data */
|
||||||
if ((x + 1) == count)
|
if ((x + 1) == count) {
|
||||||
{
|
/* last byte */
|
||||||
// last byte
|
|
||||||
target_read_u8(target, offset + x + 1, &b);
|
target_read_u8(target, offset + x + 1, &b);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
b = buffer[x + 1];
|
b = buffer[x + 1];
|
||||||
|
|
||||||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8));
|
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8));
|
||||||
|
|
||||||
// do single-write command
|
/* do single-write command */
|
||||||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02);
|
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02);
|
||||||
|
|
||||||
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK)
|
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) {
|
||||||
{
|
LOG_ERROR("single write failed for address 0x%08lX",
|
||||||
LOG_ERROR("single write failed for address 0x%08lX", (unsigned long)(offset + x));
|
(unsigned long)(offset + x));
|
||||||
aduc702x_set_write_enable(target, 0);
|
aduc702x_set_write_enable(target, 0);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -348,16 +339,15 @@ static int aduc702x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
if ((retval = aduc702x_write_block(bank, buffer, offset, count)) != ERROR_OK)
|
retval = aduc702x_write_block(bank, buffer, offset, count);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
{
|
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
* use normal (slow) JTAG method */
|
* use normal (slow) JTAG method */
|
||||||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
||||||
|
|
||||||
if ((retval = aduc702x_write_single(bank, buffer, offset, count)) != ERROR_OK)
|
retval = aduc702x_write_single(bank, buffer, offset, count);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("slow write failed");
|
LOG_ERROR("slow write failed");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -382,7 +372,7 @@ static int aduc702x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
* enable = 1 enables writes & erases, 0 disables them */
|
* enable = 1 enables writes & erases, 0 disables them */
|
||||||
static int aduc702x_set_write_enable(struct target *target, int enable)
|
static int aduc702x_set_write_enable(struct target *target, int enable)
|
||||||
{
|
{
|
||||||
// don't bother to preserve int enable bit here
|
/* don't bother to preserve int enable bit here */
|
||||||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);
|
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -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),
|
* 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 */
|
* 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;
|
uint8_t v = 4;
|
||||||
|
|
||||||
long long endtime = timeval_ms() + timeout_ms;
|
long long endtime = timeval_ms() + timeout_ms;
|
||||||
while (1) {
|
while (1) {
|
||||||
target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
|
target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
|
||||||
if ((v & 4) == 0) break;
|
if ((v & 4) == 0)
|
||||||
|
break;
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
if (timeval_ms() >= endtime) break;
|
if (timeval_ms() >= endtime)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v & 2) return ERROR_FAIL;
|
if (v & 2)
|
||||||
// if a command is ignored, both the success and fail bits may be 0
|
return ERROR_FAIL;
|
||||||
else if ((v & 3) == 0) return ERROR_FAIL;
|
/* if a command is ignored, both the success and fail bits may be 0 */
|
||||||
else return ERROR_OK;
|
else if ((v & 3) == 0)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
else
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct flash_driver aduc702x_flash = {
|
struct flash_driver aduc702x_flash = {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -52,7 +52,6 @@
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include <helper/binarybuffer.h>
|
#include <helper/binarybuffer.h>
|
||||||
|
|
||||||
|
|
||||||
/* AT91SAM7 control registers */
|
/* AT91SAM7 control registers */
|
||||||
#define DBGU_CIDR 0xFFFFF240
|
#define DBGU_CIDR 0xFFFFF240
|
||||||
#define CKGR_MCFR 0xFFFFFC24
|
#define CKGR_MCFR 0xFFFFFC24
|
||||||
|
@ -98,9 +97,9 @@
|
||||||
#define FLASH_SIZE_1024KB 12
|
#define FLASH_SIZE_1024KB 12
|
||||||
#define FLASH_SIZE_2048KB 14
|
#define FLASH_SIZE_2048KB 14
|
||||||
|
|
||||||
|
|
||||||
static int at91sam7_protect_check(struct flash_bank *bank);
|
static int at91sam7_protect_check(struct flash_bank *bank);
|
||||||
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
|
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
|
uint32_t count);
|
||||||
|
|
||||||
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number);
|
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number);
|
||||||
static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode);
|
static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode);
|
||||||
|
@ -111,10 +110,11 @@ static uint32_t MC_FMR[4] = { 0xFFFFFF60, 0xFFFFFF70, 0xFFFFFF80, 0xFFFFFF90 };
|
||||||
static uint32_t MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 };
|
static uint32_t MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 };
|
||||||
static uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };
|
static uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };
|
||||||
|
|
||||||
static char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
|
static char *EPROC[8] = {
|
||||||
|
"Unknown", "ARM946-E", "ARM7TDMI", "Unknown", "ARM920T", "ARM926EJ-S", "Unknown", "Unknown"
|
||||||
|
};
|
||||||
|
|
||||||
struct at91sam7_flash_bank
|
struct at91sam7_flash_bank {
|
||||||
{
|
|
||||||
/* chip id register */
|
/* chip id register */
|
||||||
uint32_t cidr;
|
uint32_t cidr;
|
||||||
uint16_t cidr_ext;
|
uint16_t cidr_ext;
|
||||||
|
@ -178,7 +178,6 @@ static long SRAMSIZ[16] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number)
|
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number)
|
||||||
{
|
{
|
||||||
uint32_t fsr;
|
uint32_t fsr;
|
||||||
|
@ -206,8 +205,7 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
|
||||||
|
|
||||||
at91sam7_info->mck_valid = 0;
|
at91sam7_info->mck_valid = 0;
|
||||||
at91sam7_info->mck_freq = 0;
|
at91sam7_info->mck_freq = 0;
|
||||||
switch (mckr & PMC_MCKR_CSS)
|
switch (mckr & PMC_MCKR_CSS) {
|
||||||
{
|
|
||||||
case 0: /* Slow Clock */
|
case 0: /* Slow Clock */
|
||||||
at91sam7_info->mck_valid = 1;
|
at91sam7_info->mck_valid = 1;
|
||||||
tmp = RC_FREQ;
|
tmp = RC_FREQ;
|
||||||
|
@ -215,13 +213,10 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
|
||||||
|
|
||||||
case 1: /* Main Clock */
|
case 1: /* Main Clock */
|
||||||
if ((mcfr & CKGR_MCFR_MAINRDY) &&
|
if ((mcfr & CKGR_MCFR_MAINRDY) &&
|
||||||
(at91sam7_info->ext_freq == 0))
|
(at91sam7_info->ext_freq == 0)) {
|
||||||
{
|
|
||||||
at91sam7_info->mck_valid = 1;
|
at91sam7_info->mck_valid = 1;
|
||||||
tmp = RC_FREQ / 16ul * (mcfr & 0xffff);
|
tmp = RC_FREQ / 16ul * (mcfr & 0xffff);
|
||||||
}
|
} else if (at91sam7_info->ext_freq != 0) {
|
||||||
else if (at91sam7_info->ext_freq != 0)
|
|
||||||
{
|
|
||||||
at91sam7_info->mck_valid = 1;
|
at91sam7_info->mck_valid = 1;
|
||||||
tmp = at91sam7_info->ext_freq;
|
tmp = at91sam7_info->ext_freq;
|
||||||
}
|
}
|
||||||
|
@ -232,8 +227,7 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
|
||||||
|
|
||||||
case 3: /* PLL Clock */
|
case 3: /* PLL Clock */
|
||||||
if ((mcfr & CKGR_MCFR_MAINRDY) &&
|
if ((mcfr & CKGR_MCFR_MAINRDY) &&
|
||||||
(at91sam7_info->ext_freq == 0))
|
(at91sam7_info->ext_freq == 0)) {
|
||||||
{
|
|
||||||
target_read_u32(target, CKGR_PLLR, &pllr);
|
target_read_u32(target, CKGR_PLLR, &pllr);
|
||||||
if (!(pllr & CKGR_PLLR_DIV))
|
if (!(pllr & CKGR_PLLR_DIV))
|
||||||
break; /* 0 Hz */
|
break; /* 0 Hz */
|
||||||
|
@ -243,10 +237,8 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
|
||||||
* as long as PLL is properly configured. */
|
* as long as PLL is properly configured. */
|
||||||
tmp = mainfreq / (pllr & CKGR_PLLR_DIV)*
|
tmp = mainfreq / (pllr & CKGR_PLLR_DIV)*
|
||||||
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
|
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
|
||||||
}
|
} else if ((at91sam7_info->ext_freq != 0) &&
|
||||||
else if ((at91sam7_info->ext_freq != 0) &&
|
((pllr&CKGR_PLLR_DIV) != 0)) {
|
||||||
((pllr&CKGR_PLLR_DIV) != 0))
|
|
||||||
{
|
|
||||||
at91sam7_info->mck_valid = 1;
|
at91sam7_info->mck_valid = 1;
|
||||||
tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)*
|
tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)*
|
||||||
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
|
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
|
||||||
|
@ -255,12 +247,10 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prescaler adjust */
|
/* Prescaler adjust */
|
||||||
if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0))
|
if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0)) {
|
||||||
{
|
|
||||||
at91sam7_info->mck_valid = 0;
|
at91sam7_info->mck_valid = 0;
|
||||||
at91sam7_info->mck_freq = 0;
|
at91sam7_info->mck_freq = 0;
|
||||||
}
|
} else if (((mckr & PMC_MCKR_PRES) >> 2) != 0)
|
||||||
else if (((mckr & PMC_MCKR_PRES) >> 2) != 0)
|
|
||||||
at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
|
at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
|
||||||
else
|
else
|
||||||
at91sam7_info->mck_freq = tmp;
|
at91sam7_info->mck_freq = tmp;
|
||||||
|
@ -273,24 +263,17 @@ static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode)
|
||||||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
|
||||||
if (mode && (mode != at91sam7_info->flashmode))
|
if (mode && (mode != at91sam7_info->flashmode)) {
|
||||||
{
|
|
||||||
/* Always round up (ceil) */
|
/* Always round up (ceil) */
|
||||||
if (mode == FMR_TIMING_NVBITS)
|
if (mode == FMR_TIMING_NVBITS) {
|
||||||
{
|
if (at91sam7_info->cidr_arch == 0x60) {
|
||||||
if (at91sam7_info->cidr_arch == 0x60)
|
|
||||||
{
|
|
||||||
/* AT91SAM7A3 uses master clocks in 100 ns */
|
/* AT91SAM7A3 uses master clocks in 100 ns */
|
||||||
fmcn = (at91sam7_info->mck_freq/10000000ul) + 1;
|
fmcn = (at91sam7_info->mck_freq/10000000ul) + 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* master clocks in 1uS for ARCH 0x7 types */
|
/* master clocks in 1uS for ARCH 0x7 types */
|
||||||
fmcn = (at91sam7_info->mck_freq/1000000ul) + 1;
|
fmcn = (at91sam7_info->mck_freq/1000000ul) + 1;
|
||||||
}
|
}
|
||||||
}
|
} else if (mode == FMR_TIMING_FLASH) {
|
||||||
else if (mode == FMR_TIMING_FLASH)
|
|
||||||
{
|
|
||||||
/* main clocks in 1.5uS */
|
/* main clocks in 1.5uS */
|
||||||
fmcn = (at91sam7_info->mck_freq/1000000ul)+
|
fmcn = (at91sam7_info->mck_freq/1000000ul)+
|
||||||
(at91sam7_info->mck_freq/2000000ul) + 1;
|
(at91sam7_info->mck_freq/2000000ul) + 1;
|
||||||
|
@ -319,16 +302,15 @@ static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t wait
|
||||||
{
|
{
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
while ((!((status = at91sam7_get_flash_status(bank->target, bank->bank_number)) & waitbits)) && (timeout-- > 0))
|
while ((!((status = at91sam7_get_flash_status(bank->target,
|
||||||
{
|
bank->bank_number)) & waitbits)) && (timeout-- > 0)) {
|
||||||
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status);
|
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status);
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status);
|
LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status);
|
||||||
|
|
||||||
if (status & 0x0C)
|
if (status & 0x0C) {
|
||||||
{
|
|
||||||
LOG_ERROR("status register: 0x%" PRIx32 "", status);
|
LOG_ERROR("status register: 0x%" PRIx32 "", status);
|
||||||
if (status & 0x4)
|
if (status & 0x4)
|
||||||
LOG_ERROR("Lock Error Bit Detected, Operation Abort");
|
LOG_ERROR("Lock Error Bit Detected, Operation Abort");
|
||||||
|
@ -350,22 +332,20 @@ static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t
|
||||||
|
|
||||||
fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd;
|
fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd;
|
||||||
target_write_u32(target, MC_FCR[bank->bank_number], fcr);
|
target_write_u32(target, MC_FCR[bank->bank_number], fcr);
|
||||||
LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u", fcr, bank->bank_number + 1, pagen);
|
LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u",
|
||||||
|
fcr,
|
||||||
|
bank->bank_number + 1,
|
||||||
|
pagen);
|
||||||
|
|
||||||
if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB)))
|
if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB))) {
|
||||||
{
|
|
||||||
/* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */
|
/* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */
|
||||||
if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C)
|
if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C)
|
if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -392,14 +372,12 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
|
|
||||||
at91sam7_info = t_bank->driver_priv;
|
at91sam7_info = t_bank->driver_priv;
|
||||||
|
|
||||||
if (at91sam7_info->cidr != 0)
|
if (at91sam7_info->cidr != 0) {
|
||||||
{
|
|
||||||
/* flash already configured, update clock and check for protected sectors */
|
/* flash already configured, update clock and check for protected sectors */
|
||||||
struct flash_bank *fb = bank;
|
struct flash_bank *fb = bank;
|
||||||
t_bank = fb;
|
t_bank = fb;
|
||||||
|
|
||||||
while (t_bank)
|
while (t_bank) {
|
||||||
{
|
|
||||||
/* re-calculate master clock frequency */
|
/* re-calculate master clock frequency */
|
||||||
at91sam7_read_clock_info(t_bank);
|
at91sam7_read_clock_info(t_bank);
|
||||||
|
|
||||||
|
@ -418,19 +396,16 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
|
|
||||||
/* Read and parse chip identification register */
|
/* Read and parse chip identification register */
|
||||||
target_read_u32(target, DBGU_CIDR, &cidr);
|
target_read_u32(target, DBGU_CIDR, &cidr);
|
||||||
if (cidr == 0)
|
if (cidr == 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("Cannot identify target as an AT91SAM");
|
LOG_WARNING("Cannot identify target as an AT91SAM");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (at91sam7_info->flash_autodetection == 0)
|
if (at91sam7_info->flash_autodetection == 0) {
|
||||||
{
|
|
||||||
/* banks and sectors are already created, based on data from input file */
|
/* banks and sectors are already created, based on data from input file */
|
||||||
struct flash_bank *fb = bank;
|
struct flash_bank *fb = bank;
|
||||||
t_bank = fb;
|
t_bank = fb;
|
||||||
while (t_bank)
|
while (t_bank) {
|
||||||
{
|
|
||||||
at91sam7_info = t_bank->driver_priv;
|
at91sam7_info = t_bank->driver_priv;
|
||||||
|
|
||||||
at91sam7_info->cidr = cidr;
|
at91sam7_info->cidr = cidr;
|
||||||
|
@ -462,8 +437,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
arch = (cidr >> 20)&0x00FF;
|
arch = (cidr >> 20)&0x00FF;
|
||||||
|
|
||||||
/* check flash size */
|
/* check flash size */
|
||||||
switch ((cidr >> 8)&0x000F)
|
switch ((cidr >> 8)&0x000F) {
|
||||||
{
|
|
||||||
case FLASH_SIZE_8KB:
|
case FLASH_SIZE_8KB:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -473,8 +447,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
pages_per_sector = 32;
|
pages_per_sector = 32;
|
||||||
page_size = 64;
|
page_size = 64;
|
||||||
base_address = 0x00100000;
|
base_address = 0x00100000;
|
||||||
if (arch == 0x70)
|
if (arch == 0x70) {
|
||||||
{
|
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name_t = "AT91SAM7S161/16";
|
target_name_t = "AT91SAM7S161/16";
|
||||||
}
|
}
|
||||||
|
@ -486,13 +459,11 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
pages_per_sector = 32;
|
pages_per_sector = 32;
|
||||||
page_size = 128;
|
page_size = 128;
|
||||||
base_address = 0x00100000;
|
base_address = 0x00100000;
|
||||||
if (arch == 0x70)
|
if (arch == 0x70) {
|
||||||
{
|
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name_t = "AT91SAM7S321/32";
|
target_name_t = "AT91SAM7S321/32";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7SE32";
|
target_name_t = "AT91SAM7SE32";
|
||||||
}
|
}
|
||||||
|
@ -504,8 +475,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
pages_per_sector = 32;
|
pages_per_sector = 32;
|
||||||
page_size = 128;
|
page_size = 128;
|
||||||
base_address = 0x00100000;
|
base_address = 0x00100000;
|
||||||
if (arch == 0x70)
|
if (arch == 0x70) {
|
||||||
{
|
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name_t = "AT91SAM7S64";
|
target_name_t = "AT91SAM7S64";
|
||||||
}
|
}
|
||||||
|
@ -517,23 +487,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
pages_per_sector = 64;
|
pages_per_sector = 64;
|
||||||
page_size = 256;
|
page_size = 256;
|
||||||
base_address = 0x00100000;
|
base_address = 0x00100000;
|
||||||
if (arch == 0x70)
|
if (arch == 0x70) {
|
||||||
{
|
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name_t = "AT91SAM7S128";
|
target_name_t = "AT91SAM7S128";
|
||||||
}
|
}
|
||||||
if (arch == 0x71)
|
if (arch == 0x71) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7XC128";
|
target_name_t = "AT91SAM7XC128";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7SE128";
|
target_name_t = "AT91SAM7SE128";
|
||||||
}
|
}
|
||||||
if (arch == 0x75)
|
if (arch == 0x75) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7X128";
|
target_name_t = "AT91SAM7X128";
|
||||||
}
|
}
|
||||||
|
@ -545,28 +511,23 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
pages_per_sector = 64;
|
pages_per_sector = 64;
|
||||||
page_size = 256;
|
page_size = 256;
|
||||||
base_address = 0x00100000;
|
base_address = 0x00100000;
|
||||||
if (arch == 0x60)
|
if (arch == 0x60) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7A3";
|
target_name_t = "AT91SAM7A3";
|
||||||
}
|
}
|
||||||
if (arch == 0x70)
|
if (arch == 0x70) {
|
||||||
{
|
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name_t = "AT91SAM7S256";
|
target_name_t = "AT91SAM7S256";
|
||||||
}
|
}
|
||||||
if (arch == 0x71)
|
if (arch == 0x71) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7XC256";
|
target_name_t = "AT91SAM7XC256";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7SE256";
|
target_name_t = "AT91SAM7SE256";
|
||||||
}
|
}
|
||||||
if (arch == 0x75)
|
if (arch == 0x75) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7X256";
|
target_name_t = "AT91SAM7X256";
|
||||||
}
|
}
|
||||||
|
@ -578,23 +539,19 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
pages_per_sector = 64;
|
pages_per_sector = 64;
|
||||||
page_size = 256;
|
page_size = 256;
|
||||||
base_address = 0x00100000;
|
base_address = 0x00100000;
|
||||||
if (arch == 0x70)
|
if (arch == 0x70) {
|
||||||
{
|
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name_t = "AT91SAM7S512";
|
target_name_t = "AT91SAM7S512";
|
||||||
}
|
}
|
||||||
if (arch == 0x71)
|
if (arch == 0x71) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7XC512";
|
target_name_t = "AT91SAM7XC512";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7SE512";
|
target_name_t = "AT91SAM7SE512";
|
||||||
}
|
}
|
||||||
if (arch == 0x75)
|
if (arch == 0x75) {
|
||||||
{
|
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name_t = "AT91SAM7X512";
|
target_name_t = "AT91SAM7X512";
|
||||||
}
|
}
|
||||||
|
@ -607,9 +564,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(target_name_t, "Unknown") == 0)
|
if (strcmp(target_name_t, "Unknown") == 0) {
|
||||||
{
|
LOG_ERROR(
|
||||||
LOG_ERROR("Target autodetection failed! Please specify target parameters in configuration file");
|
"Target autodetection failed! Please specify target parameters in configuration file");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,10 +575,8 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
/* calculate bank size */
|
/* calculate bank size */
|
||||||
bank_size = sectors_num * pages_per_sector * page_size;
|
bank_size = sectors_num * pages_per_sector * page_size;
|
||||||
|
|
||||||
for (bnk = 0; bnk < banks_num; bnk++)
|
for (bnk = 0; bnk < banks_num; bnk++) {
|
||||||
{
|
if (bnk > 0) {
|
||||||
if (bnk > 0)
|
|
||||||
{
|
|
||||||
if (!t_bank->next) {
|
if (!t_bank->next) {
|
||||||
/* create a new flash bank element */
|
/* create a new flash bank element */
|
||||||
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
|
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
|
||||||
|
@ -646,8 +601,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
|
|
||||||
/* allocate sectors */
|
/* allocate sectors */
|
||||||
t_bank->sectors = malloc(sectors_num * sizeof(struct flash_sector));
|
t_bank->sectors = malloc(sectors_num * sizeof(struct flash_sector));
|
||||||
for (sec = 0; sec < sectors_num; sec++)
|
for (sec = 0; sec < sectors_num; sec++) {
|
||||||
{
|
|
||||||
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
|
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
|
||||||
t_bank->sectors[sec].size = pages_per_sector * page_size;
|
t_bank->sectors[sec].size = pages_per_sector * page_size;
|
||||||
t_bank->sectors[sec].is_erased = -1;
|
t_bank->sectors[sec].is_erased = -1;
|
||||||
|
@ -684,7 +638,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
at91sam7_protect_check(t_bank);
|
at91sam7_protect_check(t_bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch);
|
LOG_DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x",
|
||||||
|
at91sam7_info->cidr_nvptyp,
|
||||||
|
at91sam7_info->cidr_arch);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -699,8 +655,7 @@ static int at91sam7_erase_check(struct flash_bank *bank)
|
||||||
uint16_t nSector;
|
uint16_t nSector;
|
||||||
uint16_t nByte;
|
uint16_t nByte;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -710,12 +665,12 @@ static int at91sam7_erase_check(struct flash_bank *bank)
|
||||||
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
|
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
|
||||||
|
|
||||||
fast_check = 1;
|
fast_check = 1;
|
||||||
for (nSector = 0; nSector < bank->num_sectors; nSector++)
|
for (nSector = 0; nSector < bank->num_sectors; nSector++) {
|
||||||
{
|
retval = target_blank_check_memory(target,
|
||||||
retval = target_blank_check_memory(target, bank->base + bank->sectors[nSector].offset,
|
bank->base + bank->sectors[nSector].offset,
|
||||||
bank->sectors[nSector].size, &blank);
|
bank->sectors[nSector].size,
|
||||||
if (retval != ERROR_OK)
|
&blank);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
fast_check = 0;
|
fast_check = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -726,25 +681,20 @@ static int at91sam7_erase_check(struct flash_bank *bank)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fast_check)
|
if (fast_check)
|
||||||
{
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
|
||||||
|
|
||||||
LOG_USER("Running slow fallback erase check - add working memory");
|
LOG_USER("Running slow fallback erase check - add working memory");
|
||||||
|
|
||||||
buffer = malloc(bank->sectors[0].size);
|
buffer = malloc(bank->sectors[0].size);
|
||||||
for (nSector = 0; nSector < bank->num_sectors; nSector++)
|
for (nSector = 0; nSector < bank->num_sectors; nSector++) {
|
||||||
{
|
|
||||||
bank->sectors[nSector].is_erased = 1;
|
bank->sectors[nSector].is_erased = 1;
|
||||||
retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4,
|
retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4,
|
||||||
bank->sectors[nSector].size/4, buffer);
|
bank->sectors[nSector].size/4, buffer);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++)
|
for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) {
|
||||||
{
|
if (buffer[nByte] != 0xFF) {
|
||||||
if (buffer[nByte] != 0xFF)
|
|
||||||
{
|
|
||||||
bank->sectors[nSector].is_erased = 0;
|
bank->sectors[nSector].is_erased = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -763,11 +713,8 @@ static int at91sam7_protect_check(struct flash_bank *bank)
|
||||||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
||||||
|
|
||||||
if (at91sam7_info->cidr == 0)
|
if (at91sam7_info->cidr == 0)
|
||||||
{
|
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
if (bank->target->state != TARGET_HALTED)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -776,14 +723,11 @@ static int at91sam7_protect_check(struct flash_bank *bank)
|
||||||
at91sam7_info->lockbits = (status >> 16);
|
at91sam7_info->lockbits = (status >> 16);
|
||||||
|
|
||||||
at91sam7_info->num_lockbits_on = 0;
|
at91sam7_info->num_lockbits_on = 0;
|
||||||
for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++)
|
for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) {
|
||||||
{
|
if (((status >> (16 + lock_pos))&(0x0001)) == 1) {
|
||||||
if (((status >> (16 + lock_pos))&(0x0001)) == 1)
|
|
||||||
{
|
|
||||||
at91sam7_info->num_lockbits_on++;
|
at91sam7_info->num_lockbits_on++;
|
||||||
bank->sectors[lock_pos].is_protected = 1;
|
bank->sectors[lock_pos].is_protected = 1;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
bank->sectors[lock_pos].is_protected = 0;
|
bank->sectors[lock_pos].is_protected = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,13 +738,10 @@ static int at91sam7_protect_check(struct flash_bank *bank)
|
||||||
at91sam7_info->nvmbits = (status >> 8)&0xFF;
|
at91sam7_info->nvmbits = (status >> 8)&0xFF;
|
||||||
|
|
||||||
at91sam7_info->num_nvmbits_on = 0;
|
at91sam7_info->num_nvmbits_on = 0;
|
||||||
for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++)
|
for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++) {
|
||||||
{
|
|
||||||
if (((status >> (8 + gpnvm_pos))&(0x01)) == 1)
|
if (((status >> (8 + gpnvm_pos))&(0x01)) == 1)
|
||||||
{
|
|
||||||
at91sam7_info->num_nvmbits_on++;
|
at91sam7_info->num_nvmbits_on++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -837,8 +778,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
||||||
at91sam7_info->ext_freq = 0;
|
at91sam7_info->ext_freq = 0;
|
||||||
at91sam7_info->flash_autodetection = 0;
|
at91sam7_info->flash_autodetection = 0;
|
||||||
|
|
||||||
if (CMD_ARGC < 13)
|
if (CMD_ARGC < 13) {
|
||||||
{
|
|
||||||
at91sam7_info->flash_autodetection = 1;
|
at91sam7_info->flash_autodetection = 1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -862,8 +802,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bus_width == 0) || (banks_num == 0) || (num_sectors == 0) ||
|
if ((bus_width == 0) || (banks_num == 0) || (num_sectors == 0) ||
|
||||||
(pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0))
|
(pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0)) {
|
||||||
{
|
|
||||||
at91sam7_info->flash_autodetection = 1;
|
at91sam7_info->flash_autodetection = 1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -874,10 +813,8 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
||||||
/* calculate bank size */
|
/* calculate bank size */
|
||||||
bank_size = num_sectors * pages_per_sector * page_size;
|
bank_size = num_sectors * pages_per_sector * page_size;
|
||||||
|
|
||||||
for (bnk = 0; bnk < banks_num; bnk++)
|
for (bnk = 0; bnk < banks_num; bnk++) {
|
||||||
{
|
if (bnk > 0) {
|
||||||
if (bnk > 0)
|
|
||||||
{
|
|
||||||
if (!t_bank->next) {
|
if (!t_bank->next) {
|
||||||
/* create a new bank element */
|
/* create a new bank element */
|
||||||
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
|
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
|
||||||
|
@ -902,8 +839,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
||||||
|
|
||||||
/* allocate sectors */
|
/* allocate sectors */
|
||||||
t_bank->sectors = malloc(num_sectors * sizeof(struct flash_sector));
|
t_bank->sectors = malloc(num_sectors * sizeof(struct flash_sector));
|
||||||
for (sec = 0; sec < num_sectors; sec++)
|
for (sec = 0; sec < num_sectors; sec++) {
|
||||||
{
|
|
||||||
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
|
t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
|
||||||
t_bank->sectors[sec].size = pages_per_sector * page_size;
|
t_bank->sectors[sec].size = pages_per_sector * page_size;
|
||||||
t_bank->sectors[sec].is_erased = -1;
|
t_bank->sectors[sec].is_erased = -1;
|
||||||
|
@ -933,61 +869,43 @@ static int at91sam7_erase(struct flash_bank *bank, int first, int last)
|
||||||
uint8_t erase_all;
|
uint8_t erase_all;
|
||||||
|
|
||||||
if (at91sam7_info->cidr == 0)
|
if (at91sam7_info->cidr == 0)
|
||||||
{
|
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
||||||
{
|
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
|
||||||
|
|
||||||
erase_all = 0;
|
erase_all = 0;
|
||||||
if ((first == 0) && (last == (bank->num_sectors-1)))
|
if ((first == 0) && (last == (bank->num_sectors-1)))
|
||||||
{
|
|
||||||
erase_all = 1;
|
erase_all = 1;
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure the flash controller timing */
|
/* Configure the flash controller timing */
|
||||||
at91sam7_read_clock_info(bank);
|
at91sam7_read_clock_info(bank);
|
||||||
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
|
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
|
||||||
|
|
||||||
if (erase_all)
|
if (erase_all) {
|
||||||
{
|
|
||||||
if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK)
|
if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* allocate and clean buffer */
|
/* allocate and clean buffer */
|
||||||
nbytes = (last - first + 1) * bank->sectors[first].size;
|
nbytes = (last - first + 1) * bank->sectors[first].size;
|
||||||
buffer = malloc(nbytes * sizeof(uint8_t));
|
buffer = malloc(nbytes * sizeof(uint8_t));
|
||||||
for (pos = 0; pos < nbytes; pos++)
|
for (pos = 0; pos < nbytes; pos++)
|
||||||
{
|
|
||||||
buffer[pos] = 0xFF;
|
buffer[pos] = 0xFF;
|
||||||
}
|
|
||||||
|
|
||||||
if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK)
|
if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark erased sectors */
|
/* mark erased sectors */
|
||||||
for (sec = first; sec <= last; sec++)
|
for (sec = first; sec <= last; sec++)
|
||||||
{
|
|
||||||
bank->sectors[sec].is_erased = 1;
|
bank->sectors[sec].is_erased = 1;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1001,27 +919,21 @@ static int at91sam7_protect(struct flash_bank *bank, int set, int first, int las
|
||||||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
||||||
|
|
||||||
if (at91sam7_info->cidr == 0)
|
if (at91sam7_info->cidr == 0)
|
||||||
{
|
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
||||||
{
|
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure the flash controller timing */
|
/* Configure the flash controller timing */
|
||||||
at91sam7_read_clock_info(bank);
|
at91sam7_read_clock_info(bank);
|
||||||
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
|
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
|
||||||
|
|
||||||
for (sector = first; sector <= last; sector++)
|
for (sector = first; sector <= last; sector++) {
|
||||||
{
|
|
||||||
if (set)
|
if (set)
|
||||||
cmd = SLB;
|
cmd = SLB;
|
||||||
else
|
else
|
||||||
|
@ -1032,10 +944,8 @@ static int at91sam7_protect(struct flash_bank *bank, int set, int first, int las
|
||||||
pagen = sector * at91sam7_info->pages_per_sector;
|
pagen = sector * at91sam7_info->pages_per_sector;
|
||||||
|
|
||||||
if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
|
if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
at91sam7_protect_check(bank);
|
at91sam7_protect_check(bank);
|
||||||
|
|
||||||
|
@ -1051,12 +961,9 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
|
||||||
uint32_t first_page, last_page, pagen, buffer_pos;
|
uint32_t first_page, last_page, pagen, buffer_pos;
|
||||||
|
|
||||||
if (at91sam7_info->cidr == 0)
|
if (at91sam7_info->cidr == 0)
|
||||||
{
|
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1066,9 +973,10 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
|
||||||
|
|
||||||
dst_min_alignment = at91sam7_info->pagesize;
|
dst_min_alignment = at91sam7_info->pagesize;
|
||||||
|
|
||||||
if (offset % dst_min_alignment)
|
if (offset % dst_min_alignment) {
|
||||||
{
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, dst_min_alignment);
|
offset,
|
||||||
|
dst_min_alignment);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,14 +986,16 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
|
||||||
first_page = offset/dst_min_alignment;
|
first_page = offset/dst_min_alignment;
|
||||||
last_page = DIV_ROUND_UP(offset + count, dst_min_alignment);
|
last_page = DIV_ROUND_UP(offset + count, dst_min_alignment);
|
||||||
|
|
||||||
LOG_DEBUG("first_page: %i, last_page: %i, count %i", (int)first_page, (int)last_page, (int)count);
|
LOG_DEBUG("first_page: %i, last_page: %i, count %i",
|
||||||
|
(int)first_page,
|
||||||
|
(int)last_page,
|
||||||
|
(int)count);
|
||||||
|
|
||||||
/* Configure the flash controller timing */
|
/* Configure the flash controller timing */
|
||||||
at91sam7_read_clock_info(bank);
|
at91sam7_read_clock_info(bank);
|
||||||
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
|
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
|
||||||
|
|
||||||
for (pagen = first_page; pagen < last_page; pagen++)
|
for (pagen = first_page; pagen < last_page; pagen++) {
|
||||||
{
|
|
||||||
if (bytes_remaining < dst_min_alignment)
|
if (bytes_remaining < dst_min_alignment)
|
||||||
count = bytes_remaining;
|
count = bytes_remaining;
|
||||||
else
|
else
|
||||||
|
@ -1094,17 +1004,15 @@ static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off
|
||||||
|
|
||||||
/* Write one block to the PageWriteBuffer */
|
/* Write one block to the PageWriteBuffer */
|
||||||
buffer_pos = (pagen-first_page)*dst_min_alignment;
|
buffer_pos = (pagen-first_page)*dst_min_alignment;
|
||||||
wcount = DIV_ROUND_UP(count,4);
|
wcount = DIV_ROUND_UP(count, 4);
|
||||||
if ((retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4, wcount, buffer + buffer_pos)) != ERROR_OK)
|
retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4,
|
||||||
{
|
wcount, buffer + buffer_pos);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* Send Write Page command to Flash Controller */
|
/* Send Write Page command to Flash Controller */
|
||||||
if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
|
if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
LOG_DEBUG("Write flash bank:%i page number:%" PRIi32 "", bank->bank_number, pagen);
|
LOG_DEBUG("Write flash bank:%i page number:%" PRIi32 "", bank->bank_number, pagen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1117,8 +1025,7 @@ static int at91sam7_probe(struct flash_bank *bank)
|
||||||
* if this is an at91sam7, it has the configured flash */
|
* if this is an at91sam7, it has the configured flash */
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1136,9 +1043,7 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
||||||
|
|
||||||
if (at91sam7_info->cidr == 0)
|
if (at91sam7_info->cidr == 0)
|
||||||
{
|
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
|
||||||
|
|
||||||
printed = snprintf(buf, buf_size,
|
printed = snprintf(buf, buf_size,
|
||||||
"\n at91sam7 driver information: Chip is %s\n",
|
"\n at91sam7 driver information: Chip is %s\n",
|
||||||
|
@ -1149,7 +1054,8 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
|
|
||||||
printed = snprintf(buf,
|
printed = snprintf(buf,
|
||||||
buf_size,
|
buf_size,
|
||||||
" Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | Flashsize: 0x%8.8" PRIx32 "\n",
|
" Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | "
|
||||||
|
"Flashsize: 0x%8.8" PRIx32 "\n",
|
||||||
at91sam7_info->cidr,
|
at91sam7_info->cidr,
|
||||||
at91sam7_info->cidr_arch,
|
at91sam7_info->cidr_arch,
|
||||||
EPROC[at91sam7_info->cidr_eproc],
|
EPROC[at91sam7_info->cidr_eproc],
|
||||||
|
@ -1161,15 +1067,20 @@ static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
|
|
||||||
printed = snprintf(buf, buf_size,
|
printed = snprintf(buf, buf_size,
|
||||||
" Master clock (estimated): %u KHz | External clock: %u KHz\n",
|
" Master clock (estimated): %u KHz | External clock: %u KHz\n",
|
||||||
(unsigned)(at91sam7_info->mck_freq / 1000), (unsigned)(at91sam7_info->ext_freq / 1000));
|
(unsigned)(at91sam7_info->mck_freq / 1000),
|
||||||
|
(unsigned)(at91sam7_info->ext_freq / 1000));
|
||||||
|
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
printed = snprintf(buf, buf_size,
|
printed = snprintf(buf,
|
||||||
" Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i \n",
|
buf_size,
|
||||||
at91sam7_info->pagesize, bank->num_sectors, at91sam7_info->num_lockbits_on,
|
" Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i\n",
|
||||||
at91sam7_info->lockbits, at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on);
|
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 += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
@ -1202,53 +1113,40 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (CMD_ARGC != 2)
|
if (CMD_ARGC != 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
bank = get_flash_bank_by_num_noprobe(0);
|
bank = get_flash_bank_by_num_noprobe(0);
|
||||||
if (bank == NULL)
|
if (bank == NULL)
|
||||||
{
|
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
if (strcmp(bank->driver->name, "at91sam7")) {
|
||||||
if (strcmp(bank->driver->name, "at91sam7"))
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "not an at91sam7 flash bank '%s'", CMD_ARGV[0]);
|
command_print(CMD_CTX, "not an at91sam7 flash bank '%s'", CMD_ARGV[0]);
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("target has to be halted to perform flash operation");
|
LOG_ERROR("target has to be halted to perform flash operation");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[1], "set") == 0)
|
if (strcmp(CMD_ARGV[1], "set") == 0)
|
||||||
{
|
|
||||||
flashcmd = SGPB;
|
flashcmd = SGPB;
|
||||||
}
|
|
||||||
else if (strcmp(CMD_ARGV[1], "clear") == 0)
|
else if (strcmp(CMD_ARGV[1], "clear") == 0)
|
||||||
{
|
|
||||||
flashcmd = CGPB;
|
flashcmd = CGPB;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
at91sam7_info = bank->driver_priv;
|
at91sam7_info = bank->driver_priv;
|
||||||
if (at91sam7_info->cidr == 0)
|
if (at91sam7_info->cidr == 0) {
|
||||||
{
|
|
||||||
retval = at91sam7_read_part_info(bank);
|
retval = at91sam7_read_part_info(bank);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit);
|
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit);
|
||||||
if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits))
|
if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) {
|
||||||
{
|
command_print(CMD_CTX,
|
||||||
command_print(CMD_CTX, "gpnvm bit '#%s' is out of bounds for target %s", CMD_ARGV[0], at91sam7_info->target_name);
|
"gpnvm bit '#%s' is out of bounds for target %s",
|
||||||
|
CMD_ARGV[0],
|
||||||
|
at91sam7_info->target_name);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,13 +1155,14 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
|
||||||
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
|
at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
|
||||||
|
|
||||||
if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK)
|
if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
|
/* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
|
||||||
status = at91sam7_get_flash_status(bank->target, 0);
|
status = at91sam7_get_flash_status(bank->target, 0);
|
||||||
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32, flashcmd, bit, status);
|
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32,
|
||||||
|
flashcmd,
|
||||||
|
bit,
|
||||||
|
status);
|
||||||
|
|
||||||
/* check protect state */
|
/* check protect state */
|
||||||
at91sam7_protect_check(bank);
|
at91sam7_protect_check(bank);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,22 +25,21 @@
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include <target/avrt.h>
|
#include <target/avrt.h>
|
||||||
|
|
||||||
|
|
||||||
/* AVR_JTAG_Instructions */
|
/* AVR_JTAG_Instructions */
|
||||||
#define AVR_JTAG_INS_LEN 4
|
#define AVR_JTAG_INS_LEN 4
|
||||||
// Public Instructions:
|
/* Public Instructions: */
|
||||||
#define AVR_JTAG_INS_EXTEST 0x00
|
#define AVR_JTAG_INS_EXTEST 0x00
|
||||||
#define AVR_JTAG_INS_IDCODE 0x01
|
#define AVR_JTAG_INS_IDCODE 0x01
|
||||||
#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02
|
#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02
|
||||||
#define AVR_JTAG_INS_BYPASS 0x0F
|
#define AVR_JTAG_INS_BYPASS 0x0F
|
||||||
// AVR Specified Public Instructions:
|
/* AVR Specified Public Instructions: */
|
||||||
#define AVR_JTAG_INS_AVR_RESET 0x0C
|
#define AVR_JTAG_INS_AVR_RESET 0x0C
|
||||||
#define AVR_JTAG_INS_PROG_ENABLE 0x04
|
#define AVR_JTAG_INS_PROG_ENABLE 0x04
|
||||||
#define AVR_JTAG_INS_PROG_COMMANDS 0x05
|
#define AVR_JTAG_INS_PROG_COMMANDS 0x05
|
||||||
#define AVR_JTAG_INS_PROG_PAGELOAD 0x06
|
#define AVR_JTAG_INS_PROG_PAGELOAD 0x06
|
||||||
#define AVR_JTAG_INS_PROG_PAGEREAD 0x07
|
#define AVR_JTAG_INS_PROG_PAGEREAD 0x07
|
||||||
|
|
||||||
// Data Registers:
|
/* Data Registers: */
|
||||||
#define AVR_JTAG_REG_Bypass_Len 1
|
#define AVR_JTAG_REG_Bypass_Len 1
|
||||||
#define AVR_JTAG_REG_DeviceID_Len 32
|
#define AVR_JTAG_REG_DeviceID_Len 32
|
||||||
|
|
||||||
|
@ -49,8 +49,7 @@
|
||||||
#define AVR_JTAG_REG_ProgrammingCommand_Len 15
|
#define AVR_JTAG_REG_ProgrammingCommand_Len 15
|
||||||
#define AVR_JTAG_REG_FlashDataByte_Len 16
|
#define AVR_JTAG_REG_FlashDataByte_Len 16
|
||||||
|
|
||||||
struct avrf_type
|
struct avrf_type {
|
||||||
{
|
|
||||||
char name[15];
|
char name[15];
|
||||||
uint16_t chip_id;
|
uint16_t chip_id;
|
||||||
int flash_page_size;
|
int flash_page_size;
|
||||||
|
@ -59,14 +58,12 @@ struct avrf_type
|
||||||
int eeprom_page_num;
|
int eeprom_page_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avrf_flash_bank
|
struct avrf_flash_bank {
|
||||||
{
|
|
||||||
int ppage_size;
|
int ppage_size;
|
||||||
int probed;
|
int probed;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct avrf_type avft_chips_info[] =
|
static struct avrf_type avft_chips_info[] = {
|
||||||
{
|
|
||||||
/* name, chip_id, flash_page_size, flash_page_num,
|
/* name, chip_id, flash_page_size, flash_page_num,
|
||||||
* eeprom_page_size, eeprom_page_num
|
* eeprom_page_size, eeprom_page_num
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +75,7 @@ static struct avrf_type avft_chips_info[] =
|
||||||
static int avr_jtag_reset(struct avr_common *avr, uint32_t reset)
|
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_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;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -127,43 +124,49 @@ static int avr_jtagprg_chiperase(struct avr_common *avr)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
poll_value = 0;
|
poll_value = 0;
|
||||||
avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len);
|
avr_jtag_senddat(avr->jtag_info.tap,
|
||||||
|
&poll_value,
|
||||||
|
0x3380,
|
||||||
|
AVR_JTAG_REG_ProgrammingCommand_Len);
|
||||||
if (ERROR_OK != mcu_execute_queue())
|
if (ERROR_OK != mcu_execute_queue())
|
||||||
{
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
|
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
|
||||||
} while (!(poll_value & 0x0200));
|
} while (!(poll_value & 0x0200));
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avr_jtagprg_writeflashpage(struct avr_common *avr, uint8_t *page_buf, uint32_t buf_size, uint32_t addr, uint32_t page_size)
|
static int avr_jtagprg_writeflashpage(struct avr_common *avr,
|
||||||
|
uint8_t *page_buf,
|
||||||
|
uint32_t buf_size,
|
||||||
|
uint32_t addr,
|
||||||
|
uint32_t page_size)
|
||||||
{
|
{
|
||||||
uint32_t i, poll_value;
|
uint32_t i, poll_value;
|
||||||
|
|
||||||
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
|
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
|
||||||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len);
|
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len);
|
||||||
|
|
||||||
// load addr high byte
|
/* load addr high byte */
|
||||||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0700 | ((addr >> 9) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len);
|
avr_jtag_senddat(avr->jtag_info.tap,
|
||||||
|
NULL,
|
||||||
|
0x0700 | ((addr >> 9) & 0xFF),
|
||||||
|
AVR_JTAG_REG_ProgrammingCommand_Len);
|
||||||
|
|
||||||
// load addr low byte
|
/* load addr low byte */
|
||||||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x0300 | ((addr >> 1) & 0xFF), AVR_JTAG_REG_ProgrammingCommand_Len);
|
avr_jtag_senddat(avr->jtag_info.tap,
|
||||||
|
NULL,
|
||||||
|
0x0300 | ((addr >> 1) & 0xFF),
|
||||||
|
AVR_JTAG_REG_ProgrammingCommand_Len);
|
||||||
|
|
||||||
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGELOAD);
|
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGELOAD);
|
||||||
|
|
||||||
for (i = 0; i < page_size; i++)
|
for (i = 0; i < page_size; i++) {
|
||||||
{
|
|
||||||
if (i < buf_size)
|
if (i < buf_size)
|
||||||
{
|
|
||||||
avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8);
|
avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8);
|
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
|
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
|
||||||
|
|
||||||
|
@ -174,11 +177,12 @@ static int avr_jtagprg_writeflashpage(struct avr_common *avr, uint8_t *page_buf,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
poll_value = 0;
|
poll_value = 0;
|
||||||
avr_jtag_senddat(avr->jtag_info.tap, &poll_value, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len);
|
avr_jtag_senddat(avr->jtag_info.tap,
|
||||||
|
&poll_value,
|
||||||
|
0x3700,
|
||||||
|
AVR_JTAG_REG_ProgrammingCommand_Len);
|
||||||
if (ERROR_OK != mcu_execute_queue())
|
if (ERROR_OK != mcu_execute_queue())
|
||||||
{
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
|
LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
|
||||||
} while (!(poll_value & 0x0200));
|
} while (!(poll_value & 0x0200));
|
||||||
|
|
||||||
|
@ -190,9 +194,7 @@ FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command)
|
||||||
struct avrf_flash_bank *avrf_info;
|
struct avrf_flash_bank *avrf_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
avrf_info = malloc(sizeof(struct avrf_flash_bank));
|
avrf_info = malloc(sizeof(struct avrf_flash_bank));
|
||||||
bank->driver_priv = avrf_info;
|
bank->driver_priv = avrf_info;
|
||||||
|
@ -208,10 +210,9 @@ static int avrf_erase(struct flash_bank *bank, int first, int last)
|
||||||
struct avr_common *avr = target->arch_info;
|
struct avr_common *avr = target->arch_info;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +230,7 @@ static int avrf_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
static int avrf_protect(struct flash_bank *bank, int set, int first, int last)
|
static int avrf_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
{
|
{
|
||||||
LOG_INFO("%s", __FUNCTION__);
|
LOG_INFO("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,16 +240,16 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
struct avr_common *avr = target->arch_info;
|
struct avr_common *avr = target->arch_info;
|
||||||
uint32_t cur_size, cur_buffer_size, page_size;
|
uint32_t cur_size, cur_buffer_size, page_size;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
page_size = bank->sectors[0].size;
|
page_size = bank->sectors[0].size;
|
||||||
if ((offset % page_size) != 0)
|
if ((offset % page_size) != 0) {
|
||||||
{
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment", offset, page_size);
|
offset,
|
||||||
|
page_size);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,22 +257,19 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
LOG_DEBUG("count is %" PRId32 "", count);
|
LOG_DEBUG("count is %" PRId32 "", count);
|
||||||
|
|
||||||
if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
|
if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
|
||||||
{
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
cur_size = 0;
|
cur_size = 0;
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
if (count > page_size)
|
if (count > page_size)
|
||||||
{
|
|
||||||
cur_buffer_size = page_size;
|
cur_buffer_size = page_size;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
cur_buffer_size = count;
|
cur_buffer_size = count;
|
||||||
}
|
avr_jtagprg_writeflashpage(avr,
|
||||||
avr_jtagprg_writeflashpage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size);
|
buffer + cur_size,
|
||||||
|
cur_buffer_size,
|
||||||
|
offset + cur_size,
|
||||||
|
page_size);
|
||||||
count -= cur_buffer_size;
|
count -= cur_buffer_size;
|
||||||
cur_size += cur_buffer_size;
|
cur_size += cur_buffer_size;
|
||||||
|
|
||||||
|
@ -284,6 +282,7 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
|
#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
|
||||||
#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
|
#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
|
||||||
#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
|
#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
|
||||||
|
|
||||||
static int avrf_probe(struct flash_bank *bank)
|
static int avrf_probe(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
@ -293,8 +292,7 @@ static int avrf_probe(struct flash_bank *bank)
|
||||||
int i;
|
int i;
|
||||||
uint32_t device_id;
|
uint32_t device_id;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -303,42 +301,35 @@ static int avrf_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
avr_jtag_read_jtagid(avr, &device_id);
|
avr_jtag_read_jtagid(avr, &device_id);
|
||||||
if (ERROR_OK != mcu_execute_queue())
|
if (ERROR_OK != mcu_execute_queue())
|
||||||
{
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
|
LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
|
||||||
if (EXTRACT_MFG(device_id) != 0x1F)
|
if (EXTRACT_MFG(device_id) != 0x1F)
|
||||||
{
|
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
|
||||||
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F);
|
EXTRACT_MFG(device_id),
|
||||||
}
|
0x1F);
|
||||||
|
|
||||||
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++)
|
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
|
||||||
{
|
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
|
||||||
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id))
|
|
||||||
{
|
|
||||||
avr_info = &avft_chips_info[i];
|
avr_info = &avft_chips_info[i];
|
||||||
LOG_INFO("target device is %s", avr_info->name);
|
LOG_INFO("target device is %s", avr_info->name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avr_info != NULL)
|
if (avr_info != NULL) {
|
||||||
{
|
if (bank->sectors) {
|
||||||
if (bank->sectors)
|
|
||||||
{
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chip found
|
/* chip found */
|
||||||
bank->base = 0x00000000;
|
bank->base = 0x00000000;
|
||||||
bank->size = (avr_info->flash_page_size * avr_info->flash_page_num);
|
bank->size = (avr_info->flash_page_size * avr_info->flash_page_num);
|
||||||
bank->num_sectors = avr_info->flash_page_num;
|
bank->num_sectors = avr_info->flash_page_num;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num);
|
bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num);
|
||||||
|
|
||||||
for (i = 0; i < avr_info->flash_page_num; i++)
|
for (i = 0; i < avr_info->flash_page_num; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = i * avr_info->flash_page_size;
|
bank->sectors[i].offset = i * avr_info->flash_page_size;
|
||||||
bank->sectors[i].size = avr_info->flash_page_size;
|
bank->sectors[i].size = avr_info->flash_page_size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
|
@ -347,10 +338,8 @@ static int avrf_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
avrf_info->probed = 1;
|
avrf_info->probed = 1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else {
|
||||||
else
|
/* chip not supported */
|
||||||
{
|
|
||||||
// chip not supported
|
|
||||||
LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id));
|
LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id));
|
||||||
|
|
||||||
avrf_info->probed = 1;
|
avrf_info->probed = 1;
|
||||||
|
@ -368,7 +357,7 @@ static int avrf_auto_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
static int avrf_protect_check(struct flash_bank *bank)
|
static int avrf_protect_check(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
LOG_INFO("%s", __FUNCTION__);
|
LOG_INFO("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,28 +369,23 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
int i;
|
int i;
|
||||||
uint32_t device_id;
|
uint32_t device_id;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
avr_jtag_read_jtagid(avr, &device_id);
|
avr_jtag_read_jtagid(avr, &device_id);
|
||||||
if (ERROR_OK != mcu_execute_queue())
|
if (ERROR_OK != mcu_execute_queue())
|
||||||
{
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
|
LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
|
||||||
if (EXTRACT_MFG(device_id) != 0x1F)
|
if (EXTRACT_MFG(device_id) != 0x1F)
|
||||||
{
|
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
|
||||||
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F);
|
EXTRACT_MFG(device_id),
|
||||||
}
|
0x1F);
|
||||||
|
|
||||||
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++)
|
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
|
||||||
{
|
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
|
||||||
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id))
|
|
||||||
{
|
|
||||||
avr_info = &avft_chips_info[i];
|
avr_info = &avft_chips_info[i];
|
||||||
LOG_INFO("target device is %s", avr_info->name);
|
LOG_INFO("target device is %s", avr_info->name);
|
||||||
|
|
||||||
|
@ -409,15 +393,13 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avr_info != NULL)
|
if (avr_info != NULL) {
|
||||||
{
|
/* chip found */
|
||||||
// chip found
|
snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name,
|
||||||
snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name, EXTRACT_VER(device_id));
|
EXTRACT_VER(device_id));
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else {
|
||||||
else
|
/* chip not supported */
|
||||||
{
|
|
||||||
// chip not supported
|
|
||||||
snprintf(buf, buf_size, "Cannot identify target as a avr\n");
|
snprintf(buf, buf_size, "Cannot identify target as a avr\n");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -428,8 +410,7 @@ static int avrf_mass_erase(struct flash_bank *bank)
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
struct avr_common *avr = target->arch_info;
|
struct avr_common *avr = target->arch_info;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -437,9 +418,7 @@ static int avrf_mass_erase(struct flash_bank *bank)
|
||||||
if ((ERROR_OK != avr_jtagprg_enterprogmode(avr))
|
if ((ERROR_OK != avr_jtagprg_enterprogmode(avr))
|
||||||
|| (ERROR_OK != avr_jtagprg_chiperase(avr))
|
|| (ERROR_OK != avr_jtagprg_chiperase(avr))
|
||||||
|| (ERROR_OK != avr_jtagprg_leaveprogmode(avr)))
|
|| (ERROR_OK != avr_jtagprg_leaveprogmode(avr)))
|
||||||
{
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -449,31 +428,23 @@ COMMAND_HANDLER(avrf_handle_mass_erase_command)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (avrf_mass_erase(bank) == ERROR_OK)
|
if (avrf_mass_erase(bank) == ERROR_OK) {
|
||||||
{
|
|
||||||
/* set all sectors as erased */
|
/* set all sectors as erased */
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++)
|
||||||
{
|
|
||||||
bank->sectors[i].is_erased = 1;
|
bank->sectors[i].is_erased = 1;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "avr mass erase complete");
|
command_print(CMD_CTX, "avr mass erase complete");
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "avr mass erase failed");
|
command_print(CMD_CTX, "avr mass erase failed");
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1296
src/flash/nor/cfi.c
1296
src/flash/nor/cfi.c
File diff suppressed because it is too large
Load Diff
|
@ -17,14 +17,14 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef CFI_H
|
#ifndef CFI_H
|
||||||
#define CFI_H
|
#define CFI_H
|
||||||
|
|
||||||
#define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */
|
#define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */
|
||||||
#define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */
|
#define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */
|
||||||
|
|
||||||
struct cfi_flash_bank
|
struct cfi_flash_bank {
|
||||||
{
|
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
|
|
||||||
int x16_as_x8;
|
int x16_as_x8;
|
||||||
|
@ -80,8 +80,7 @@ struct cfi_flash_bank
|
||||||
* as defined for the Advanced+ Boot Block Flash Memory (C3)
|
* as defined for the Advanced+ Boot Block Flash Memory (C3)
|
||||||
* and used by the linux kernel cfi driver (as of 2.6.14)
|
* and used by the linux kernel cfi driver (as of 2.6.14)
|
||||||
*/
|
*/
|
||||||
struct cfi_intel_pri_ext
|
struct cfi_intel_pri_ext {
|
||||||
{
|
|
||||||
uint8_t pri[3];
|
uint8_t pri[3];
|
||||||
uint8_t major_version;
|
uint8_t major_version;
|
||||||
uint8_t minor_version;
|
uint8_t minor_version;
|
||||||
|
@ -100,8 +99,7 @@ struct cfi_intel_pri_ext
|
||||||
/* Spansion primary extended query table as defined for and used by
|
/* Spansion primary extended query table as defined for and used by
|
||||||
* the linux kernel cfi driver (as of 2.6.15)
|
* the linux kernel cfi driver (as of 2.6.15)
|
||||||
*/
|
*/
|
||||||
struct cfi_spansion_pri_ext
|
struct cfi_spansion_pri_ext {
|
||||||
{
|
|
||||||
uint8_t pri[3];
|
uint8_t pri[3];
|
||||||
uint8_t major_version;
|
uint8_t major_version;
|
||||||
uint8_t minor_version;
|
uint8_t minor_version;
|
||||||
|
@ -124,8 +122,7 @@ struct cfi_spansion_pri_ext
|
||||||
/* Atmel primary extended query table as defined for and used by
|
/* Atmel primary extended query table as defined for and used by
|
||||||
* the linux kernel cfi driver (as of 2.6.20+)
|
* the linux kernel cfi driver (as of 2.6.20+)
|
||||||
*/
|
*/
|
||||||
struct cfi_atmel_pri_ext
|
struct cfi_atmel_pri_ext {
|
||||||
{
|
|
||||||
uint8_t pri[3];
|
uint8_t pri[3];
|
||||||
uint8_t major_version;
|
uint8_t major_version;
|
||||||
uint8_t minor_version;
|
uint8_t minor_version;
|
||||||
|
@ -140,14 +137,12 @@ enum {
|
||||||
CFI_UNLOCK_5555_2AAA,
|
CFI_UNLOCK_5555_2AAA,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cfi_unlock_addresses
|
struct cfi_unlock_addresses {
|
||||||
{
|
|
||||||
uint32_t unlock1;
|
uint32_t unlock1;
|
||||||
uint32_t unlock2;
|
uint32_t unlock2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cfi_fixup
|
struct cfi_fixup {
|
||||||
{
|
|
||||||
uint16_t mfr;
|
uint16_t mfr;
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
void (*fixup)(struct flash_bank *bank, void *param);
|
void (*fixup)(struct flash_bank *bank, void *param);
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include <flash/nor/imp.h>
|
#include <flash/nor/imp.h>
|
||||||
#include <target/image.h>
|
#include <target/image.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Upper level of NOR flash framework.
|
* Upper level of NOR flash framework.
|
||||||
|
@ -45,9 +44,7 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
retval = bank->driver->erase(bank, first, last);
|
retval = bank->driver->erase(bank, first, last);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
LOG_ERROR("failed erasing sectors %d to %d", first, last);
|
LOG_ERROR("failed erasing sectors %d to %d", first, last);
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -57,8 +54,7 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* callers may not supply illegal parameters ... */
|
/* callers may not supply illegal parameters ... */
|
||||||
if (first < 0 || first > last || last >= bank->num_sectors)
|
if (first < 0 || first > last || last >= bank->num_sectors) {
|
||||||
{
|
|
||||||
LOG_ERROR("illegal sector range");
|
LOG_ERROR("illegal sector range");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -79,9 +75,7 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
*/
|
*/
|
||||||
retval = bank->driver->protect(bank, set, first, last);
|
retval = bank->driver->protect(bank, set, first, last);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
LOG_ERROR("failed setting protection for areas %d to %d", first, last);
|
LOG_ERROR("failed setting protection for areas %d to %d", first, last);
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -92,10 +86,11 @@ int flash_driver_write(struct flash_bank *bank,
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = bank->driver->write(bank, buffer, offset, count);
|
retval = bank->driver->write(bank, buffer, offset, count);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
LOG_ERROR(
|
||||||
LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
|
"error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
|
||||||
bank->base, offset);
|
bank->base,
|
||||||
|
offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -109,10 +104,11 @@ int flash_driver_read(struct flash_bank *bank,
|
||||||
LOG_DEBUG("call flash_driver_read()");
|
LOG_DEBUG("call flash_driver_read()");
|
||||||
|
|
||||||
retval = bank->driver->read(bank, buffer, offset, count);
|
retval = bank->driver->read(bank, buffer, offset, count);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
LOG_ERROR(
|
||||||
LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
|
"error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
|
||||||
bank->base, offset);
|
bank->base,
|
||||||
|
offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -128,19 +124,16 @@ void flash_bank_add(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
/* put flash bank in linked list */
|
/* put flash bank in linked list */
|
||||||
unsigned bank_num = 0;
|
unsigned bank_num = 0;
|
||||||
if (flash_banks)
|
if (flash_banks) {
|
||||||
{
|
|
||||||
/* find last flash bank */
|
/* find last flash bank */
|
||||||
struct flash_bank *p = flash_banks;
|
struct flash_bank *p = flash_banks;
|
||||||
while (NULL != p->next)
|
while (NULL != p->next) {
|
||||||
{
|
|
||||||
bank_num += 1;
|
bank_num += 1;
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
p->next = bank;
|
p->next = bank;
|
||||||
bank_num += 1;
|
bank_num += 1;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
flash_banks = bank;
|
flash_banks = bank;
|
||||||
|
|
||||||
bank->bank_number = bank_num;
|
bank->bank_number = bank_num;
|
||||||
|
@ -156,13 +149,10 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num)
|
||||||
struct flash_bank *p;
|
struct flash_bank *p;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (p = flash_banks; p; p = p->next)
|
for (p = flash_banks; p; p = p->next) {
|
||||||
{
|
|
||||||
if (i++ == num)
|
if (i++ == num)
|
||||||
{
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
LOG_ERROR("flash bank %d does not exist", num);
|
LOG_ERROR("flash bank %d does not exist", num);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -172,9 +162,7 @@ int flash_get_bank_count(void)
|
||||||
struct flash_bank *p;
|
struct flash_bank *p;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (p = flash_banks; p; p = p->next)
|
for (p = flash_banks; p; p = p->next)
|
||||||
{
|
|
||||||
i++;
|
i++;
|
||||||
}
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +172,7 @@ struct flash_bank *get_flash_bank_by_name_noprobe(const char *name)
|
||||||
unsigned found = 0;
|
unsigned found = 0;
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
for (bank = flash_banks; NULL != bank; bank = bank->next)
|
for (bank = flash_banks; NULL != bank; bank = bank->next) {
|
||||||
{
|
|
||||||
if (strcmp(bank->name, name) == 0)
|
if (strcmp(bank->name, name) == 0)
|
||||||
return bank;
|
return bank;
|
||||||
if (!flash_driver_name_matches(bank->driver->name, name))
|
if (!flash_driver_name_matches(bank->driver->name, name))
|
||||||
|
@ -203,12 +190,10 @@ int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
bank = get_flash_bank_by_name_noprobe(name);
|
bank = get_flash_bank_by_name_noprobe(name);
|
||||||
if (bank != NULL)
|
if (bank != NULL) {
|
||||||
{
|
|
||||||
retval = bank->driver->auto_probe(bank);
|
retval = bank->driver->auto_probe(bank);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("auto_probe failed");
|
LOG_ERROR("auto_probe failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -224,14 +209,11 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
{
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
retval = p->driver->auto_probe(p);
|
retval = p->driver->auto_probe(p);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("auto_probe failed");
|
LOG_ERROR("auto_probe failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -241,31 +223,30 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank)
|
||||||
|
|
||||||
/* lookup flash bank by address, bank not found is success, but
|
/* lookup flash bank by address, bank not found is success, but
|
||||||
* result_bank is set to NULL. */
|
* result_bank is set to NULL. */
|
||||||
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank)
|
int get_flash_bank_by_addr(struct target *target,
|
||||||
|
uint32_t addr,
|
||||||
|
bool check,
|
||||||
|
struct flash_bank **result_bank)
|
||||||
{
|
{
|
||||||
struct flash_bank *c;
|
struct flash_bank *c;
|
||||||
|
|
||||||
/* cycle through bank list */
|
/* cycle through bank list */
|
||||||
for (c = flash_banks; c; c = c->next)
|
for (c = flash_banks; c; c = c->next) {
|
||||||
{
|
|
||||||
int retval;
|
int retval;
|
||||||
retval = c->driver->auto_probe(c);
|
retval = c->driver->auto_probe(c);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("auto_probe failed");
|
LOG_ERROR("auto_probe failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
/* check whether address belongs to this flash bank */
|
/* check whether address belongs to this flash bank */
|
||||||
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target)
|
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target) {
|
||||||
{
|
|
||||||
*result_bank = c;
|
*result_bank = c;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*result_bank = NULL;
|
*result_bank = NULL;
|
||||||
if (check)
|
if (check) {
|
||||||
{
|
|
||||||
LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
|
LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -280,38 +261,33 @@ int default_flash_mem_blank_check(struct flash_bank *bank)
|
||||||
uint32_t nBytes;
|
uint32_t nBytes;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *buffer = malloc(buffer_size);
|
uint8_t *buffer = malloc(buffer_size);
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
uint32_t j;
|
uint32_t j;
|
||||||
bank->sectors[i].is_erased = 1;
|
bank->sectors[i].is_erased = 1;
|
||||||
|
|
||||||
for (j = 0; j < bank->sectors[i].size; j += buffer_size)
|
for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
|
||||||
{
|
|
||||||
uint32_t chunk;
|
uint32_t chunk;
|
||||||
chunk = buffer_size;
|
chunk = buffer_size;
|
||||||
if (chunk > (j - bank->sectors[i].size))
|
if (chunk > (j - bank->sectors[i].size))
|
||||||
{
|
|
||||||
chunk = (j - bank->sectors[i].size);
|
chunk = (j - bank->sectors[i].size);
|
||||||
}
|
|
||||||
|
|
||||||
retval = target_read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk/4, buffer);
|
retval = target_read_memory(target,
|
||||||
|
bank->base + bank->sectors[i].offset + j,
|
||||||
|
4,
|
||||||
|
chunk/4,
|
||||||
|
buffer);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
|
|
||||||
for (nBytes = 0; nBytes < chunk; nBytes++)
|
for (nBytes = 0; nBytes < chunk; nBytes++) {
|
||||||
{
|
if (buffer[nBytes] != 0xFF) {
|
||||||
if (buffer[nBytes] != 0xFF)
|
|
||||||
{
|
|
||||||
bank->sectors[i].is_erased = 0;
|
bank->sectors[i].is_erased = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -319,7 +295,7 @@ int default_flash_mem_blank_check(struct flash_bank *bank)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -333,20 +309,17 @@ int default_flash_blank_check(struct flash_bank *bank)
|
||||||
int fast_check = 0;
|
int fast_check = 0;
|
||||||
uint32_t blank;
|
uint32_t blank;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
uint32_t address = bank->base + bank->sectors[i].offset;
|
uint32_t address = bank->base + bank->sectors[i].offset;
|
||||||
uint32_t size = bank->sectors[i].size;
|
uint32_t size = bank->sectors[i].size;
|
||||||
|
|
||||||
retval = target_blank_check_memory(target, address, size, &blank);
|
retval = target_blank_check_memory(target, address, size, &blank);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
fast_check = 0;
|
fast_check = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -357,8 +330,7 @@ int default_flash_blank_check(struct flash_bank *bank)
|
||||||
fast_check = 1;
|
fast_check = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fast_check)
|
if (!fast_check) {
|
||||||
{
|
|
||||||
LOG_USER("Running slow fallback erase check - add working memory");
|
LOG_USER("Running slow fallback erase check - add working memory");
|
||||||
return default_flash_mem_blank_check(bank);
|
return default_flash_mem_blank_check(bank);
|
||||||
}
|
}
|
||||||
|
@ -394,17 +366,14 @@ static int flash_iterate_address_range_inner(struct target *target,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (c->size == 0 || c->num_sectors == 0)
|
if (c->size == 0 || c->num_sectors == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Bank is invalid");
|
LOG_ERROR("Bank is invalid");
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0) {
|
||||||
{
|
|
||||||
/* special case, erase whole bank when length is zero */
|
/* special case, erase whole bank when length is zero */
|
||||||
if (addr != c->base)
|
if (addr != c->base) {
|
||||||
{
|
|
||||||
LOG_ERROR("Whole bank access must start at beginning of bank.");
|
LOG_ERROR("Whole bank access must start at beginning of bank.");
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
@ -413,8 +382,7 @@ static int flash_iterate_address_range_inner(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check whether it all fits in this bank */
|
/* check whether it all fits in this bank */
|
||||||
if (addr + length - 1 > c->base + c->size - 1)
|
if (addr + length - 1 > c->base + c->size - 1) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash access does not fit into bank.");
|
LOG_ERROR("Flash access does not fit into bank.");
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
@ -424,8 +392,7 @@ static int flash_iterate_address_range_inner(struct target *target,
|
||||||
addr -= c->base;
|
addr -= c->base;
|
||||||
last_addr -= c->base;
|
last_addr -= c->base;
|
||||||
|
|
||||||
for (i = 0; i < c->num_sectors; i++)
|
for (i = 0; i < c->num_sectors; i++) {
|
||||||
{
|
|
||||||
struct flash_sector *f = c->sectors + i;
|
struct flash_sector *f = c->sectors + i;
|
||||||
uint32_t end = f->offset + f->size;
|
uint32_t end = f->offset + f->size;
|
||||||
|
|
||||||
|
@ -510,16 +477,14 @@ static int flash_iterate_address_range(struct target *target,
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
/* Danger! zero-length iterations means entire bank! */
|
/* Danger! zero-length iterations means entire bank! */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
retval = get_flash_bank_by_addr(target, addr, true, &c);
|
retval = get_flash_bank_by_addr(target, addr, true, &c);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
uint32_t cur_length = length;
|
uint32_t cur_length = length;
|
||||||
/* check whether it all fits in this bank */
|
/* check whether it all fits in this bank */
|
||||||
if (addr + length - 1 > c->base + c->size - 1)
|
if (addr + length - 1 > c->base + c->size - 1) {
|
||||||
{
|
|
||||||
LOG_DEBUG("iterating over more than one flash bank.");
|
LOG_DEBUG("iterating over more than one flash bank.");
|
||||||
cur_length = c->base + c->size - addr;
|
cur_length = c->base + c->size - addr;
|
||||||
}
|
}
|
||||||
|
@ -558,25 +523,20 @@ int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t le
|
||||||
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;
|
struct imagesection *b1, *b2;
|
||||||
b1=*((struct imagesection **)a);
|
b1 = *((struct imagesection **)a);
|
||||||
b2=*((struct imagesection **)b);
|
b2 = *((struct imagesection **)b);
|
||||||
|
|
||||||
if (b1->base_address == b2->base_address)
|
if (b1->base_address == b2->base_address)
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (b1->base_address > b2->base_address)
|
else if (b1->base_address > b2->base_address)
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int flash_write_unlock(struct target *target, struct image *image,
|
int flash_write_unlock(struct target *target, struct image *image,
|
||||||
uint32_t *written, int erase, bool unlock)
|
uint32_t *written, int erase, bool unlock)
|
||||||
{
|
{
|
||||||
|
@ -593,8 +553,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
if (written)
|
if (written)
|
||||||
*written = 0;
|
*written = 0;
|
||||||
|
|
||||||
if (erase)
|
if (erase) {
|
||||||
{
|
|
||||||
/* assume all sectors need erasing - stops any problems
|
/* assume all sectors need erasing - stops any problems
|
||||||
* when flash_write is called multiple times */
|
* when flash_write is called multiple times */
|
||||||
|
|
||||||
|
@ -610,16 +569,13 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
image->num_sections);
|
image->num_sections);
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < image->num_sections; i++)
|
for (i = 0; i < image->num_sections; i++)
|
||||||
{
|
|
||||||
sections[i] = &image->sections[i];
|
sections[i] = &image->sections[i];
|
||||||
}
|
|
||||||
|
|
||||||
qsort(sections, image->num_sections, sizeof(struct imagesection *),
|
qsort(sections, image->num_sections, sizeof(struct imagesection *),
|
||||||
compare_section);
|
compare_section);
|
||||||
|
|
||||||
/* loop until we reach end of the image */
|
/* loop until we reach end of the image */
|
||||||
while (section < image->num_sections)
|
while (section < image->num_sections) {
|
||||||
{
|
|
||||||
uint32_t buffer_size;
|
uint32_t buffer_size;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
int section_last;
|
int section_last;
|
||||||
|
@ -627,8 +583,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
uint32_t run_size = sections[section]->size - section_offset;
|
uint32_t run_size = sections[section]->size - section_offset;
|
||||||
int pad_bytes = 0;
|
int pad_bytes = 0;
|
||||||
|
|
||||||
if (sections[section]->size == 0)
|
if (sections[section]->size == 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("empty section %d", section);
|
LOG_WARNING("empty section %d", section);
|
||||||
section++;
|
section++;
|
||||||
section_offset = 0;
|
section_offset = 0;
|
||||||
|
@ -638,11 +593,8 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
/* find the corresponding flash bank */
|
/* find the corresponding flash bank */
|
||||||
retval = get_flash_bank_by_addr(target, run_address, false, &c);
|
retval = get_flash_bank_by_addr(target, run_address, false, &c);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
if (c == NULL) {
|
||||||
if (c == NULL)
|
|
||||||
{
|
|
||||||
section++; /* and skip it */
|
section++; /* and skip it */
|
||||||
section_offset = 0;
|
section_offset = 0;
|
||||||
continue;
|
continue;
|
||||||
|
@ -651,13 +603,11 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
/* collect consecutive sections which fall into the same bank */
|
/* collect consecutive sections which fall into the same bank */
|
||||||
section_last = section;
|
section_last = section;
|
||||||
padding[section] = 0;
|
padding[section] = 0;
|
||||||
while ((run_address + run_size - 1 < c->base + c->size - 1)
|
while ((run_address + run_size - 1 < c->base + c->size - 1) &&
|
||||||
&& (section_last + 1 < image->num_sections))
|
(section_last + 1 < image->num_sections)) {
|
||||||
{
|
|
||||||
/* sections are sorted */
|
/* sections are sorted */
|
||||||
assert(sections[section_last + 1]->base_address >= c->base);
|
assert(sections[section_last + 1]->base_address >= c->base);
|
||||||
if (sections[section_last + 1]->base_address >= (c->base + c->size))
|
if (sections[section_last + 1]->base_address >= (c->base + c->size)) {
|
||||||
{
|
|
||||||
/* Done with this bank */
|
/* Done with this bank */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -685,11 +635,12 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
run_size += pad_bytes;
|
run_size += pad_bytes;
|
||||||
|
|
||||||
if (pad_bytes > 0)
|
if (pad_bytes > 0)
|
||||||
LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
|
LOG_INFO("Padding image section %d with %d bytes",
|
||||||
|
section_last-1,
|
||||||
|
pad_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run_address + run_size - 1 > c->base + c->size - 1)
|
if (run_address + run_size - 1 > c->base + c->size - 1) {
|
||||||
{
|
|
||||||
/* If we have more than one flash chip back to back, then we limit
|
/* If we have more than one flash chip back to back, then we limit
|
||||||
* the current write operation to the current chip.
|
* the current write operation to the current chip.
|
||||||
*/
|
*/
|
||||||
|
@ -722,8 +673,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
|
|
||||||
/* allocate buffer */
|
/* allocate buffer */
|
||||||
buffer = malloc(run_size);
|
buffer = malloc(run_size);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("Out of memory for flash bank buffer");
|
LOG_ERROR("Out of memory for flash bank buffer");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -731,8 +681,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
buffer_size = 0;
|
buffer_size = 0;
|
||||||
|
|
||||||
/* read sections to the buffer */
|
/* read sections to the buffer */
|
||||||
while (buffer_size < run_size)
|
while (buffer_size < run_size) {
|
||||||
{
|
|
||||||
size_t size_read;
|
size_t size_read;
|
||||||
|
|
||||||
size_read = run_size - buffer_size;
|
size_read = run_size - buffer_size;
|
||||||
|
@ -747,12 +696,13 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
|
intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
|
||||||
int t_section_num = diff / sizeof(struct imagesection);
|
int t_section_num = diff / sizeof(struct imagesection);
|
||||||
|
|
||||||
LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d",
|
LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, "
|
||||||
(int)section,
|
"section_offset = %d, buffer_size = %d, size_read = %d",
|
||||||
(int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read);
|
(int)section, (int)t_section_num, (int)section_offset,
|
||||||
if ((retval = image_read_section(image, t_section_num, section_offset,
|
(int)buffer_size, (int)size_read);
|
||||||
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
|
retval = image_read_section(image, t_section_num, section_offset,
|
||||||
{
|
size_read, buffer + buffer_size, &size_read);
|
||||||
|
if (retval != ERROR_OK || size_read == 0) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -764,8 +714,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
buffer_size += size_read;
|
buffer_size += size_read;
|
||||||
section_offset += size_read;
|
section_offset += size_read;
|
||||||
|
|
||||||
if (section_offset >= sections[section]->size)
|
if (section_offset >= sections[section]->size) {
|
||||||
{
|
|
||||||
section++;
|
section++;
|
||||||
section_offset = 0;
|
section_offset = 0;
|
||||||
}
|
}
|
||||||
|
@ -774,29 +723,23 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
retval = ERROR_OK;
|
retval = ERROR_OK;
|
||||||
|
|
||||||
if (unlock)
|
if (unlock)
|
||||||
{
|
|
||||||
retval = flash_unlock_address_range(target, run_address, run_size);
|
retval = flash_unlock_address_range(target, run_address, run_size);
|
||||||
}
|
if (retval == ERROR_OK) {
|
||||||
if (retval == ERROR_OK)
|
if (erase) {
|
||||||
{
|
|
||||||
if (erase)
|
|
||||||
{
|
|
||||||
/* calculate and erase sectors */
|
/* calculate and erase sectors */
|
||||||
retval = flash_erase_address_range(target,
|
retval = flash_erase_address_range(target,
|
||||||
true, run_address, run_size);
|
true, run_address, run_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK) {
|
||||||
{
|
|
||||||
/* write flash sectors */
|
/* write flash sectors */
|
||||||
retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
|
retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
/* abort operation */
|
/* abort operation */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -805,7 +748,6 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||||
*written += run_size; /* add run size to total written counter */
|
*written += run_size; /* add run size to total written counter */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free(sections);
|
free(sections);
|
||||||
free(padding);
|
free(padding);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef FLASH_NOR_CORE_H
|
#ifndef FLASH_NOR_CORE_H
|
||||||
#define FLASH_NOR_CORE_H
|
#define FLASH_NOR_CORE_H
|
||||||
|
|
||||||
|
@ -39,11 +40,10 @@ struct image;
|
||||||
* within a flash bank. A single bank typically consists of multiple
|
* within a flash bank. A single bank typically consists of multiple
|
||||||
* sectors, each of which can be erased and protected independently.
|
* sectors, each of which can be erased and protected independently.
|
||||||
*/
|
*/
|
||||||
struct flash_sector
|
struct flash_sector {
|
||||||
{
|
/** Bus offset from start of the flash chip (in bytes). */
|
||||||
/// Bus offset from start of the flash chip (in bytes).
|
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
/// Number of bytes in this flash sector.
|
/** Number of bytes in this flash sector. */
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
/**
|
/**
|
||||||
* Indication of erasure status: 0 = not erased, 1 = erased,
|
* Indication of erasure status: 0 = not erased, 1 = erased,
|
||||||
|
@ -72,8 +72,7 @@ struct flash_sector
|
||||||
* may use the @c driver_priv member to store additional data on a
|
* may use the @c driver_priv member to store additional data on a
|
||||||
* per-bank basis, if required.
|
* per-bank basis, if required.
|
||||||
*/
|
*/
|
||||||
struct flash_bank
|
struct flash_bank {
|
||||||
{
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
struct target *target; /**< Target to which this bank belongs. */
|
struct target *target; /**< Target to which this bank belongs. */
|
||||||
|
@ -94,13 +93,13 @@ struct flash_bank
|
||||||
* some non-zero value during "probe()" or "auto_probe()".
|
* some non-zero value during "probe()" or "auto_probe()".
|
||||||
*/
|
*/
|
||||||
int num_sectors;
|
int num_sectors;
|
||||||
/// Array of sectors, allocated and initilized by the flash driver
|
/** Array of sectors, allocated and initilized by the flash driver */
|
||||||
struct flash_sector *sectors;
|
struct flash_sector *sectors;
|
||||||
|
|
||||||
struct flash_bank *next; /**< The next flash bank on this chip */
|
struct flash_bank *next; /**< The next flash bank on this chip */
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Registers the 'flash' subsystem commands
|
/** Registers the 'flash' subsystem commands */
|
||||||
int flash_register_commands(struct command_context *cmd_ctx);
|
int flash_register_commands(struct command_context *cmd_ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,7 +133,7 @@ int flash_write(struct target *target,
|
||||||
* This routine must be called when the system may modify the status.
|
* This routine must be called when the system may modify the status.
|
||||||
*/
|
*/
|
||||||
void flash_set_dirty(void);
|
void flash_set_dirty(void);
|
||||||
/// @returns The number of flash banks currently defined.
|
/** @returns The number of flash banks currently defined. */
|
||||||
int flash_get_bank_count(void);
|
int flash_get_bank_count(void);
|
||||||
/**
|
/**
|
||||||
* Provides default read implementation for flash memory.
|
* Provides default read implementation for flash memory.
|
||||||
|
@ -209,6 +208,7 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num);
|
||||||
* @param check return ERROR_OK and result_bank NULL if the bank does not exist
|
* @param check return ERROR_OK and result_bank NULL if the bank does not exist
|
||||||
* @returns The struct flash_bank located at @a addr, or NULL.
|
* @returns The struct flash_bank located at @a addr, or NULL.
|
||||||
*/
|
*/
|
||||||
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank);
|
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check,
|
||||||
|
struct flash_bank **result_bank);
|
||||||
|
|
||||||
#endif // FLASH_NOR_CORE_H
|
#endif /* FLASH_NOR_CORE_H */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef FLASH_NOR_DRIVER_H
|
#ifndef FLASH_NOR_DRIVER_H
|
||||||
#define FLASH_NOR_DRIVER_H
|
#define FLASH_NOR_DRIVER_H
|
||||||
|
|
||||||
|
@ -48,8 +49,7 @@ struct flash_bank;
|
||||||
* corresponding static <code>flash_driver_<i>callback</i>()</code>
|
* corresponding static <code>flash_driver_<i>callback</i>()</code>
|
||||||
* routine in flash.c.
|
* routine in flash.c.
|
||||||
*/
|
*/
|
||||||
struct flash_driver
|
struct flash_driver {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Gives a human-readable name of this flash driver,
|
* Gives a human-readable name of this flash driver,
|
||||||
* This field is used to select and initialize the driver.
|
* This field is used to select and initialize the driver.
|
||||||
|
@ -213,7 +213,8 @@ struct flash_driver
|
||||||
int (*auto_probe)(struct flash_bank *bank);
|
int (*auto_probe)(struct flash_bank *bank);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FLASH_BANK_COMMAND_HANDLER(name) static __FLASH_BANK_COMMAND(name)
|
#define FLASH_BANK_COMMAND_HANDLER(name) \
|
||||||
|
static __FLASH_BANK_COMMAND(name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a NOR flash driver by its name.
|
* Find a NOR flash driver by its name.
|
||||||
|
@ -222,4 +223,4 @@ struct flash_driver
|
||||||
*/
|
*/
|
||||||
struct flash_driver *flash_driver_find_by_name(const char *name);
|
struct flash_driver *flash_driver_find_by_name(const char *name);
|
||||||
|
|
||||||
#endif // FLASH_NOR_DRIVER_H
|
#endif /* FLASH_NOR_DRIVER_H */
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,8 +85,7 @@ static struct flash_driver *flash_drivers[] = {
|
||||||
|
|
||||||
struct flash_driver *flash_driver_find_by_name(const char *name)
|
struct flash_driver *flash_driver_find_by_name(const char *name)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; flash_drivers[i]; i++)
|
for (unsigned i = 0; flash_drivers[i]; i++) {
|
||||||
{
|
|
||||||
if (strcmp(name, flash_drivers[i]->name) == 0)
|
if (strcmp(name, flash_drivers[i]->name) == 0)
|
||||||
return flash_drivers[i];
|
return flash_drivers[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,8 @@ static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
|
||||||
/**
|
/**
|
||||||
* Protection funcionality is not implemented.
|
* Protection funcionality is not implemented.
|
||||||
* The current implementation applies/removes security on the chip.
|
* The current implementation applies/removes security on the chip.
|
||||||
* The chip is effectively secured/unsecured after the first reset following the execution of this function.
|
* The chip is effectively secured/unsecured after the first reset
|
||||||
|
* following the execution of this function.
|
||||||
*
|
*
|
||||||
* @param bank
|
* @param bank
|
||||||
* @param set Apply or remove security on the chip.
|
* @param set Apply or remove security on the chip.
|
||||||
|
@ -154,7 +155,8 @@ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dsp5680xx use word addressing. The "/2" that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing.
|
* The dsp5680xx use word addressing. The "/2" that appear in the following code
|
||||||
|
* are a workaround for the fact that OpenOCD uses byte addressing.
|
||||||
*
|
*
|
||||||
* @param bank
|
* @param bank
|
||||||
* @param buffer Data to write to flash.
|
* @param buffer Data to write to flash.
|
||||||
|
@ -178,24 +180,18 @@ static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t * buffer,
|
||||||
* This chip uses word addressing, Openocd only supports byte addressing.
|
* This chip uses word addressing, Openocd only supports byte addressing.
|
||||||
* The workaround results in disabling writing to odd byte addresses
|
* The workaround results in disabling writing to odd byte addresses
|
||||||
*/
|
*/
|
||||||
LOG_ERROR
|
LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
|
||||||
("%s: Writing to odd addresses not supported for this target",
|
|
||||||
__func__);
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
retval =
|
retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
|
||||||
dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count,
|
|
||||||
0);
|
|
||||||
uint32_t addr_word;
|
uint32_t addr_word;
|
||||||
|
|
||||||
for (addr_word = bank->base + offset / 2; addr_word < count / 2;
|
for (addr_word = bank->base + offset / 2; addr_word < count / 2;
|
||||||
addr_word += (HFM_SECTOR_SIZE / 2)) {
|
addr_word += (HFM_SECTOR_SIZE / 2)) {
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
bank->sectors[addr_word /
|
bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0;
|
||||||
(HFM_SECTOR_SIZE / 2)].is_erased = 0;
|
|
||||||
else
|
else
|
||||||
bank->sectors[addr_word /
|
bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1;
|
||||||
(HFM_SECTOR_SIZE / 2)].is_erased = -1;
|
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -215,8 +211,11 @@ static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The flash module (FM) on the dsp5680xx supports both individual sector and mass erase of the flash memory.
|
* The flash module (FM) on the dsp5680xx supports both individual sector
|
||||||
* If this function is called with @first == @last == 0 or if @first is the first sector (#0) and @last is the last sector then the mass erase command is executed (much faster than erasing each sector individually).
|
* and mass erase of the flash memory.
|
||||||
|
* If this function is called with @first == @last == 0 or if @first is the
|
||||||
|
* first sector (#0) and @last is the last sector then the mass erase command
|
||||||
|
* is executed (much faster than erasing each sector individually).
|
||||||
*
|
*
|
||||||
* @param bank
|
* @param bank
|
||||||
* @param first
|
* @param first
|
||||||
|
@ -228,10 +227,8 @@ static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval =
|
retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
|
||||||
dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
|
if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
|
||||||
if ((!(first | last))
|
|
||||||
|| ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
|
|
||||||
last = HFM_SECTOR_COUNT - 1;
|
last = HFM_SECTOR_COUNT - 1;
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
for (int i = first; i <= last; i++)
|
for (int i = first; i <= last; i++)
|
||||||
|
@ -264,8 +261,7 @@ static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
|
||||||
|
|
||||||
for (i = 0; i < HFM_SECTOR_COUNT; i++) {
|
for (i = 0; i < HFM_SECTOR_COUNT; i++) {
|
||||||
if (bank->sectors[i].is_erased == -1) {
|
if (bank->sectors[i].is_erased == -1) {
|
||||||
retval =
|
retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
|
||||||
dsp5680xx_f_erase_check(bank->target, &erased, i);
|
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,16 +27,15 @@
|
||||||
#include <target/algorithm.h>
|
#include <target/algorithm.h>
|
||||||
#include <target/image.h>
|
#include <target/image.h>
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static uint32_t ecosflash_get_flash_status(struct flash_bank *bank);
|
static uint32_t ecosflash_get_flash_status(struct flash_bank *bank);
|
||||||
static void ecosflash_set_flash_mode(struct flash_bank *bank,int mode);
|
static void ecosflash_set_flash_mode(struct flash_bank *bank, int mode);
|
||||||
static uint32_t ecosflash_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout);
|
static uint32_t ecosflash_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout);
|
||||||
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc);
|
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx,
|
||||||
|
char *cmd, char **args, int argc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct ecosflash_flash_bank
|
struct ecosflash_flash_bank {
|
||||||
{
|
|
||||||
struct target *target;
|
struct target *target;
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
struct working_area *erase_check_algorithm;
|
struct working_area *erase_check_algorithm;
|
||||||
|
@ -45,8 +45,7 @@ struct ecosflash_flash_bank
|
||||||
|
|
||||||
static const int sectorSize = 0x10000;
|
static const int sectorSize = 0x10000;
|
||||||
|
|
||||||
char *
|
char *flash_errmsg(int err);
|
||||||
flash_errmsg(int err);
|
|
||||||
|
|
||||||
#ifndef __ECOS
|
#ifndef __ECOS
|
||||||
#define FLASH_ERR_OK 0x00 /* No error - operation complete */
|
#define FLASH_ERR_OK 0x00 /* No error - operation complete */
|
||||||
|
@ -65,8 +64,7 @@ flash_errmsg(int err);
|
||||||
#define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support device */
|
#define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support device */
|
||||||
#define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */
|
#define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */
|
||||||
|
|
||||||
char *
|
char *flash_errmsg(int err)
|
||||||
flash_errmsg(int err)
|
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case FLASH_ERR_OK:
|
case FLASH_ERR_OK:
|
||||||
|
@ -110,13 +108,10 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
|
||||||
struct ecosflash_flash_bank *info;
|
struct ecosflash_flash_bank *info;
|
||||||
|
|
||||||
if (CMD_ARGC < 7)
|
if (CMD_ARGC < 7)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
info = malloc(sizeof(struct ecosflash_flash_bank));
|
info = malloc(sizeof(struct ecosflash_flash_bank));
|
||||||
if (info == NULL)
|
if (info == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("no memory for flash bank info");
|
LOG_ERROR("no memory for flash bank info");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
@ -131,8 +126,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
bank->num_sectors = bank->size/sectorSize;
|
bank->num_sectors = bank->size/sectorSize;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = sectorSize;
|
bank->sectors[i].size = sectorSize;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -141,8 +135,7 @@ FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
info->target = get_target(CMD_ARGV[5]);
|
info->target = get_target(CMD_ARGV[5]);
|
||||||
if (info->target == NULL)
|
if (info->target == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
|
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -160,20 +153,18 @@ static int loadDriver(struct ecosflash_flash_bank *info)
|
||||||
struct target *target = info->target;
|
struct target *target = info->target;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if ((retval = image_open(&image, info->driverPath, NULL)) != ERROR_OK)
|
retval = image_open(&image, info->driverPath, NULL);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
info->start_address = image.start_address;
|
info->start_address = image.start_address;
|
||||||
|
|
||||||
image_size = 0x0;
|
image_size = 0x0;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < image.num_sections; i++)
|
for (i = 0; i < image.num_sections; i++) {
|
||||||
{
|
|
||||||
void *buffer = malloc(image.sections[i].size);
|
void *buffer = malloc(image.sections[i].size);
|
||||||
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
|
retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
image_close(&image);
|
image_close(&image);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -191,7 +182,7 @@ static int loadDriver(struct ecosflash_flash_bank *info)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int const OFFSET_ERASE = 0x0;
|
static int const OFFSET_ERASE;
|
||||||
static int const OFFSET_ERASE_SIZE = 0x8;
|
static int const OFFSET_ERASE_SIZE = 0x8;
|
||||||
static int const OFFSET_FLASH = 0xc;
|
static int const OFFSET_FLASH = 0xc;
|
||||||
static int const OFFSET_FLASH_SIZE = 0x8;
|
static int const OFFSET_FLASH_SIZE = 0x8;
|
||||||
|
@ -220,12 +211,9 @@ static int runCode(struct ecosflash_flash_bank *info,
|
||||||
buf_set_u32(reg_params[1].value, 0, 32, r1);
|
buf_set_u32(reg_params[1].value, 0, 32, r1);
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, r2);
|
buf_set_u32(reg_params[2].value, 0, 32, r2);
|
||||||
|
|
||||||
int retval;
|
int retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
codeStart, codeStop, timeout, &armv4_5_info);
|
||||||
codeStart,
|
if (retval != ERROR_OK) {
|
||||||
codeStop, timeout,
|
|
||||||
&armv4_5_info)) != ERROR_OK)
|
|
||||||
{
|
|
||||||
LOG_ERROR("error executing eCos flash algorithm");
|
LOG_ERROR("error executing eCos flash algorithm");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -257,12 +245,11 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address,
|
||||||
0,
|
0,
|
||||||
&flashErr,
|
&flashErr,
|
||||||
timeout
|
timeout
|
||||||
);
|
);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (flashErr != 0x0)
|
if (flashErr != 0x0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
|
LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +257,10 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32_t address, uint32_t len)
|
static int eCosBoard_flash(struct ecosflash_flash_bank *info,
|
||||||
|
void *data,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t len)
|
||||||
{
|
{
|
||||||
struct target *target = info->target;
|
struct target *target = info->target;
|
||||||
const int chunk = 8192;
|
const int chunk = 8192;
|
||||||
|
@ -295,13 +285,10 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32
|
||||||
|
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < len; i += chunk)
|
for (i = 0; i < len; i += chunk) {
|
||||||
{
|
|
||||||
int t = len-i;
|
int t = len-i;
|
||||||
if (t > chunk)
|
if (t > chunk)
|
||||||
{
|
|
||||||
t = chunk;
|
t = chunk;
|
||||||
}
|
|
||||||
|
|
||||||
retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
|
retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -319,9 +306,9 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (flashErr != 0x0)
|
if (flashErr != 0x0) {
|
||||||
{
|
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr,
|
||||||
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
|
flash_errmsg(flashErr));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,20 +326,13 @@ static void command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
|
||||||
struct ecosflash_flash_bank *info = bank->driver_priv;
|
struct ecosflash_flash_bank *info = bank->driver_priv;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (info->target->endianness == TARGET_LITTLE_ENDIAN)
|
if (info->target->endianness == TARGET_LITTLE_ENDIAN) {
|
||||||
{
|
|
||||||
for (i = bank->bus_width; i > 0; i--)
|
for (i = bank->bus_width; i > 0; i--)
|
||||||
{
|
|
||||||
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
|
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 1; i <= bank->bus_width; i++)
|
for (i = 1; i <= bank->bus_width; i++)
|
||||||
{
|
|
||||||
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
|
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -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)
|
static uint32_t ecosflash_address(struct flash_bank *bank, uint32_t address)
|
||||||
{
|
{
|
||||||
uint32_t retval = 0;
|
uint32_t retval = 0;
|
||||||
switch (bank->bus_width)
|
switch (bank->bus_width) {
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
retval = address & 0xfffffffc;
|
retval = address & 0xfffffffc;
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -386,7 +365,8 @@ static int ecosflash_protect(struct flash_bank *bank, int set, int first, int la
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ecosflash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
static int ecosflash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
|
uint32_t count)
|
||||||
{
|
{
|
||||||
struct ecosflash_flash_bank *info = bank->driver_priv;
|
struct ecosflash_flash_bank *info = bank->driver_priv;
|
||||||
struct flash_bank *c = bank;
|
struct flash_bank *c = bank;
|
||||||
|
@ -411,7 +391,7 @@ static uint32_t ecosflash_get_flash_status(struct flash_bank *bank)
|
||||||
return ERROR_OK;
|
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;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char *cmd, char **args, int argc)
|
static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx,
|
||||||
|
char *cmd,
|
||||||
|
char **args,
|
||||||
|
int argc)
|
||||||
{
|
{
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -79,15 +80,13 @@
|
||||||
#define KEY1 0x45670123
|
#define KEY1 0x45670123
|
||||||
#define KEY2 0xCDEF89AB
|
#define KEY2 0xCDEF89AB
|
||||||
|
|
||||||
struct em357_options
|
struct em357_options {
|
||||||
{
|
|
||||||
uint16_t RDP;
|
uint16_t RDP;
|
||||||
uint16_t user_options;
|
uint16_t user_options;
|
||||||
uint16_t protection[3];
|
uint16_t protection[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct em357_flash_bank
|
struct em357_flash_bank {
|
||||||
{
|
|
||||||
struct em357_options option_bytes;
|
struct em357_options option_bytes;
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
int ppage_size;
|
int ppage_size;
|
||||||
|
@ -103,9 +102,7 @@ FLASH_BANK_COMMAND_HANDLER(em357_flash_bank_command)
|
||||||
struct em357_flash_bank *em357_info;
|
struct em357_flash_bank *em357_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
em357_info = malloc(sizeof(struct em357_flash_bank));
|
em357_info = malloc(sizeof(struct em357_flash_bank));
|
||||||
bank->driver_priv = em357_info;
|
bank->driver_priv = em357_info;
|
||||||
|
@ -129,37 +126,32 @@ static int em357_wait_status_busy(struct flash_bank *bank, int timeout)
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
/* wait for busy to clear */
|
/* wait for busy to clear */
|
||||||
for (;;)
|
for (;; ) {
|
||||||
{
|
|
||||||
retval = em357_get_flash_status(bank, &status);
|
retval = em357_get_flash_status(bank, &status);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||||
if ((status & FLASH_BSY) == 0)
|
if ((status & FLASH_BSY) == 0)
|
||||||
break;
|
break;
|
||||||
if (timeout-- <= 0)
|
if (timeout-- <= 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("timed out waiting for flash");
|
LOG_ERROR("timed out waiting for flash");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & FLASH_WRPRTERR)
|
if (status & FLASH_WRPRTERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("em357 device protected");
|
LOG_ERROR("em357 device protected");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & FLASH_PGERR)
|
if (status & FLASH_PGERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("em357 device programming failed");
|
LOG_ERROR("em357 device programming failed");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
if (status & (FLASH_WRPRTERR | FLASH_PGERR))
|
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) {
|
||||||
{
|
|
||||||
/* If this operation fails, we ignore it and report the original
|
/* If this operation fails, we ignore it and report the original
|
||||||
* retval
|
* retval
|
||||||
*/
|
*/
|
||||||
|
@ -330,8 +322,7 @@ static int em357_protect_check(struct flash_bank *bank)
|
||||||
int num_bits;
|
int num_bits;
|
||||||
int set;
|
int set;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -344,8 +335,7 @@ static int em357_protect_check(struct flash_bank *bank)
|
||||||
/* each protection bit is for 4 * 2K pages */
|
/* each protection bit is for 4 * 2K pages */
|
||||||
num_bits = (bank->num_sectors / em357_info->ppage_size);
|
num_bits = (bank->num_sectors / em357_info->ppage_size);
|
||||||
|
|
||||||
for (i = 0; i < num_bits; i++)
|
for (i = 0; i < num_bits; i++) {
|
||||||
{
|
|
||||||
set = 1;
|
set = 1;
|
||||||
if (protection & (1 << i))
|
if (protection & (1 << i))
|
||||||
set = 0;
|
set = 0;
|
||||||
|
@ -362,16 +352,13 @@ static int em357_erase(struct flash_bank *bank, int first, int last)
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first == 0) && (last == (bank->num_sectors - 1)))
|
if ((first == 0) && (last == (bank->num_sectors - 1)))
|
||||||
{
|
|
||||||
return em357_mass_erase(bank);
|
return em357_mass_erase(bank);
|
||||||
}
|
|
||||||
|
|
||||||
/* unlock flash registers */
|
/* unlock flash registers */
|
||||||
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
|
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
|
||||||
|
@ -381,8 +368,7 @@ static int em357_erase(struct flash_bank *bank, int first, int last)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER);
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -419,20 +405,17 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
|
|
||||||
em357_info = bank->driver_priv;
|
em357_info = bank->driver_priv;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first % em357_info->ppage_size) != 0)
|
if ((first % em357_info->ppage_size) != 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("aligned start protect sector to a %d sector boundary",
|
LOG_WARNING("aligned start protect sector to a %d sector boundary",
|
||||||
em357_info->ppage_size);
|
em357_info->ppage_size);
|
||||||
first = first - (first % em357_info->ppage_size);
|
first = first - (first % em357_info->ppage_size);
|
||||||
}
|
}
|
||||||
if (((last + 1) % em357_info->ppage_size) != 0)
|
if (((last + 1) % em357_info->ppage_size) != 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("aligned end protect sector to a %d sector boundary",
|
LOG_WARNING("aligned end protect sector to a %d sector boundary",
|
||||||
em357_info->ppage_size);
|
em357_info->ppage_size);
|
||||||
last++;
|
last++;
|
||||||
|
@ -449,8 +432,7 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
prot_reg[1] = (uint16_t)(protection >> 8);
|
prot_reg[1] = (uint16_t)(protection >> 8);
|
||||||
prot_reg[2] = (uint16_t)(protection >> 16);
|
prot_reg[2] = (uint16_t)(protection >> 16);
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
reg = (i / em357_info->ppage_size) / 8;
|
reg = (i / em357_info->ppage_size) / 8;
|
||||||
bit = (i / em357_info->ppage_size) - (reg * 8);
|
bit = (i / em357_info->ppage_size) - (reg * 8);
|
||||||
|
|
||||||
|
@ -461,7 +443,8 @@ static int em357_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
prot_reg[reg] |= (1 << bit);
|
prot_reg[reg] |= (1 << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status = em357_erase_options(bank)) != ERROR_OK)
|
status = em357_erase_options(bank);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
em357_info->option_bytes.protection[0] = prot_reg[0];
|
em357_info->option_bytes.protection[0] = prot_reg[0];
|
||||||
|
@ -487,18 +470,20 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
* a modified *_FLASH_BASE */
|
* a modified *_FLASH_BASE */
|
||||||
|
|
||||||
static const uint8_t em357_flash_write_code[] = {
|
static const uint8_t em357_flash_write_code[] = {
|
||||||
/* #define EM357_FLASH_CR_OFFSET 0x10 */
|
/* #define EM357_FLASH_CR_OFFSET 0x10
|
||||||
/* #define EM357_FLASH_SR_OFFSET 0x0C */
|
* #define EM357_FLASH_SR_OFFSET 0x0C
|
||||||
/* write: */
|
* write: */
|
||||||
0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */
|
0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */
|
||||||
0x1c, 0x44, /* add r4, r3 */
|
0x1c, 0x44, /* add r4, r3 */
|
||||||
/* write_half_word: */
|
/* write_half_word: */
|
||||||
0x01, 0x23, /* movs r3, #0x01 */
|
0x01, 0x23, /* movs r3, #0x01 */
|
||||||
0x23, 0x61, /* str r3, [r4, #EM357_FLASH_CR_OFFSET] */
|
0x23, 0x61, /* str r3, [r4,
|
||||||
|
*#EM357_FLASH_CR_OFFSET] */
|
||||||
0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
|
0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
|
||||||
0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
|
0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
|
||||||
/* busy: */
|
/* busy: */
|
||||||
0xe3, 0x68, /* ldr r3, [r4, #EM357_FLASH_SR_OFFSET] */
|
0xe3, 0x68, /* ldr r3, [r4,
|
||||||
|
*#EM357_FLASH_SR_OFFSET] */
|
||||||
0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
|
0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
|
||||||
0xfb, 0xd0, /* beq busy */
|
0xfb, 0xd0, /* beq busy */
|
||||||
0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
|
0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
|
||||||
|
@ -512,32 +497,32 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
/* flash write code */
|
/* flash write code */
|
||||||
if (target_alloc_working_area(target, sizeof(em357_flash_write_code),
|
if (target_alloc_working_area(target, sizeof(em357_flash_write_code),
|
||||||
&em357_info->write_algorithm) != ERROR_OK)
|
&em357_info->write_algorithm) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("no working area available, can't do block memory writes");
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
if ((retval = target_write_buffer(target, em357_info->write_algorithm->address,
|
retval = target_write_buffer(target, em357_info->write_algorithm->address,
|
||||||
sizeof(em357_flash_write_code),
|
sizeof(em357_flash_write_code), (uint8_t *)em357_flash_write_code);
|
||||||
(uint8_t*)em357_flash_write_code)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
|
||||||
/* if we already allocated the writing code, but failed to get a
|
/* if we already allocated the writing code, but failed to get a
|
||||||
* buffer, free the algorithm */
|
* buffer, free the algorithm */
|
||||||
if (em357_info->write_algorithm)
|
if (em357_info->write_algorithm)
|
||||||
target_free_working_area(target, em357_info->write_algorithm);
|
target_free_working_area(target, em357_info->write_algorithm);
|
||||||
|
|
||||||
LOG_WARNING("no large enough working area available, can't do block memory writes");
|
LOG_WARNING(
|
||||||
|
"no large enough working area available, can't do block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||||
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
||||||
|
@ -547,13 +532,12 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
|
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
|
||||||
init_reg_param(®_params[3], "r3", 32, PARAM_IN_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)) ?
|
uint32_t thisrun_count = (count > (buffer_size / 2)) ?
|
||||||
(buffer_size / 2) : count;
|
(buffer_size / 2) : count;
|
||||||
|
|
||||||
if ((retval = target_write_buffer(target, source->address,
|
retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
|
||||||
thisrun_count * 2, buffer)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
||||||
|
@ -561,17 +545,14 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
||||||
buf_set_u32(reg_params[3].value, 0, 32, 0);
|
buf_set_u32(reg_params[3].value, 0, 32, 0);
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
|
||||||
em357_info->write_algorithm->address,
|
em357_info->write_algorithm->address, 0, 10000, &armv7m_info);
|
||||||
0,
|
if (retval != ERROR_OK) {
|
||||||
10000, &armv7m_info)) != ERROR_OK)
|
|
||||||
{
|
|
||||||
LOG_ERROR("error executing em357 flash write algorithm");
|
LOG_ERROR("error executing em357 flash write algorithm");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR)
|
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("flash memory not erased before writing");
|
LOG_ERROR("flash memory not erased before writing");
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
target_write_u32(target, EM357_FLASH_SR, FLASH_PGERR);
|
target_write_u32(target, EM357_FLASH_SR, FLASH_PGERR);
|
||||||
|
@ -579,8 +560,7 @@ static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR)
|
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("flash memory write protected");
|
LOG_ERROR("flash memory write protected");
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR);
|
target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR);
|
||||||
|
@ -614,14 +594,12 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
uint32_t bytes_written = 0;
|
uint32_t bytes_written = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset & 0x1)
|
if (offset & 0x1) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
@ -635,20 +613,17 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* multiple half words (2-byte) to be programmed? */
|
/* multiple half words (2-byte) to be programmed? */
|
||||||
if (words_remaining > 0)
|
if (words_remaining > 0) {
|
||||||
{
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
if ((retval = em357_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
|
retval = em357_write_block(bank, buffer, offset, words_remaining);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
{
|
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
* we use normal (slow) single dword accesses */
|
* we use normal (slow) single dword accesses */
|
||||||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
LOG_WARNING(
|
||||||
|
"couldn't use block writes, falling back to single memory accesses");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer += words_remaining * 2;
|
buffer += words_remaining * 2;
|
||||||
address += words_remaining * 2;
|
address += words_remaining * 2;
|
||||||
words_remaining = 0;
|
words_remaining = 0;
|
||||||
|
@ -658,8 +633,7 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
|
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
while (words_remaining > 0)
|
while (words_remaining > 0) {
|
||||||
{
|
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
|
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
|
||||||
|
|
||||||
|
@ -679,8 +653,7 @@ static int em357_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
address += 2;
|
address += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint16_t value = 0xffff;
|
uint16_t value = 0xffff;
|
||||||
memcpy(&value, buffer + bytes_written, bytes_remaining);
|
memcpy(&value, buffer + bytes_written, bytes_remaining);
|
||||||
|
|
||||||
|
@ -721,8 +694,7 @@ static int em357_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024);
|
LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024);
|
||||||
|
|
||||||
if (bank->sectors)
|
if (bank->sectors) {
|
||||||
{
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
}
|
}
|
||||||
|
@ -732,8 +704,7 @@ static int em357_probe(struct flash_bank *bank)
|
||||||
bank->num_sectors = num_pages;
|
bank->num_sectors = num_pages;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
||||||
|
|
||||||
for (i = 0; i < num_pages; i++)
|
for (i = 0; i < num_pages; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = i * page_size;
|
bank->sectors[i].offset = i * page_size;
|
||||||
bank->sectors[i].size = page_size;
|
bank->sectors[i].size = page_size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
|
@ -766,9 +737,7 @@ COMMAND_HANDLER(em357_handle_lock_command)
|
||||||
struct em357_flash_bank *em357_info = NULL;
|
struct em357_flash_bank *em357_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -779,14 +748,12 @@ COMMAND_HANDLER(em357_handle_lock_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (em357_erase_options(bank) != ERROR_OK)
|
if (em357_erase_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "em357 failed to erase options");
|
command_print(CMD_CTX, "em357 failed to erase options");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -794,8 +761,7 @@ COMMAND_HANDLER(em357_handle_lock_command)
|
||||||
/* set readout protection */
|
/* set readout protection */
|
||||||
em357_info->option_bytes.RDP = 0;
|
em357_info->option_bytes.RDP = 0;
|
||||||
|
|
||||||
if (em357_write_options(bank) != ERROR_OK)
|
if (em357_write_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "em357 failed to lock device");
|
command_print(CMD_CTX, "em357 failed to lock device");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -810,9 +776,7 @@ COMMAND_HANDLER(em357_handle_unlock_command)
|
||||||
struct target *target = NULL;
|
struct target *target = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -821,20 +785,17 @@ COMMAND_HANDLER(em357_handle_unlock_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (em357_erase_options(bank) != ERROR_OK)
|
if (em357_erase_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "em357 failed to unlock device");
|
command_print(CMD_CTX, "em357 failed to unlock device");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (em357_write_options(bank) != ERROR_OK)
|
if (em357_write_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "em357 failed to lock device");
|
command_print(CMD_CTX, "em357 failed to lock device");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -850,8 +811,7 @@ static int em357_mass_erase(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -888,9 +848,7 @@ COMMAND_HANDLER(em357_handle_mass_erase_command)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -898,20 +856,14 @@ COMMAND_HANDLER(em357_handle_mass_erase_command)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = em357_mass_erase(bank);
|
retval = em357_mass_erase(bank);
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK) {
|
||||||
{
|
|
||||||
/* set all sectors as erased */
|
/* set all sectors as erased */
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++)
|
||||||
{
|
|
||||||
bank->sectors[i].is_erased = 1;
|
bank->sectors[i].is_erased = 1;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "em357 mass erase complete");
|
command_print(CMD_CTX, "em357 mass erase complete");
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "em357 mass erase failed");
|
command_print(CMD_CTX, "em357 mass erase failed");
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,9 +26,7 @@
|
||||||
#include <target/image.h>
|
#include <target/image.h>
|
||||||
#include "hello.h"
|
#include "hello.h"
|
||||||
|
|
||||||
|
struct faux_flash_bank {
|
||||||
struct faux_flash_bank
|
|
||||||
{
|
|
||||||
struct target *target;
|
struct target *target;
|
||||||
uint8_t *memory;
|
uint8_t *memory;
|
||||||
uint32_t start_address;
|
uint32_t start_address;
|
||||||
|
@ -43,19 +42,15 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
|
||||||
struct faux_flash_bank *info;
|
struct faux_flash_bank *info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
info = malloc(sizeof(struct faux_flash_bank));
|
info = malloc(sizeof(struct faux_flash_bank));
|
||||||
if (info == NULL)
|
if (info == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("no memory for flash bank info");
|
LOG_ERROR("no memory for flash bank info");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
info->memory = malloc(bank->size);
|
info->memory = malloc(bank->size);
|
||||||
if (info == NULL)
|
if (info == NULL) {
|
||||||
{
|
|
||||||
free(info);
|
free(info);
|
||||||
LOG_ERROR("no memory for flash bank info");
|
LOG_ERROR("no memory for flash bank info");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -67,8 +62,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
bank->num_sectors = bank->size/sectorSize;
|
bank->num_sectors = bank->size/sectorSize;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = sectorSize;
|
bank->sectors[i].size = sectorSize;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -77,8 +71,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
info->target = get_target(CMD_ARGV[5]);
|
info->target = get_target(CMD_ARGV[5]);
|
||||||
if (info->target == NULL)
|
if (info->target == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
|
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
|
||||||
free(info->memory);
|
free(info->memory);
|
||||||
free(info);
|
free(info);
|
||||||
|
@ -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)
|
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;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,7 @@
|
||||||
#define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */
|
#define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */
|
||||||
#define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */
|
#define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */
|
||||||
|
|
||||||
enum fm3_variant
|
enum fm3_variant {
|
||||||
{
|
|
||||||
mb9bfxx1, /* Flash Type '1' */
|
mb9bfxx1, /* Flash Type '1' */
|
||||||
mb9bfxx2,
|
mb9bfxx2,
|
||||||
mb9bfxx3,
|
mb9bfxx3,
|
||||||
|
@ -47,15 +46,13 @@ enum fm3_variant
|
||||||
mb9afxx6
|
mb9afxx6
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fm3_flash_type
|
enum fm3_flash_type {
|
||||||
{
|
|
||||||
fm3_no_flash_type = 0,
|
fm3_no_flash_type = 0,
|
||||||
fm3_flash_type1 = 1,
|
fm3_flash_type1 = 1,
|
||||||
fm3_flash_type2 = 2
|
fm3_flash_type2 = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fm3_flash_bank
|
struct fm3_flash_bank {
|
||||||
{
|
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
enum fm3_variant variant;
|
enum fm3_variant variant;
|
||||||
enum fm3_flash_type flashtype;
|
enum fm3_flash_type flashtype;
|
||||||
|
|
|
@ -16,13 +16,14 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef FLASH_NOR_IMP_H
|
#ifndef FLASH_NOR_IMP_H
|
||||||
#define FLASH_NOR_IMP_H
|
#define FLASH_NOR_IMP_H
|
||||||
|
|
||||||
// this is an internal header
|
/* this is an internal header */
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
// almost all drivers will need this file
|
/* almost all drivers will need this file */
|
||||||
#include <target/target.h>
|
#include <target/target.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,4 +48,4 @@ int flash_driver_read(struct flash_bank *bank,
|
||||||
int flash_write_unlock(struct target *target, struct image *image,
|
int flash_write_unlock(struct target *target, struct image *image,
|
||||||
uint32_t *written, int erase, bool unlock);
|
uint32_t *written, int erase, bool unlock);
|
||||||
|
|
||||||
#endif // FLASH_NOR_IMP_H
|
#endif /* FLASH_NOR_IMP_H */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,9 +52,8 @@ static int kinetis_update_bank_info(struct flash_bank *bank)
|
||||||
|
|
||||||
result = kinetis_get_master_bank(bank, &master_bank);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
/* update the info we do not have */
|
/* update the info we do not have */
|
||||||
bank->size = master_bank->size;
|
bank->size = master_bank->size;
|
||||||
|
@ -69,9 +69,8 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
|
||||||
{
|
{
|
||||||
struct kinetis_flash_bank *bank_info;
|
struct kinetis_flash_bank *bank_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6) {
|
if (CMD_ARGC < 6)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("add flash_bank kinetis %s", bank->name);
|
LOG_INFO("add flash_bank kinetis %s", bank->name);
|
||||||
|
|
||||||
|
@ -92,9 +91,8 @@ static int kinetis_protect(struct flash_bank *bank, int set, int first,
|
||||||
|
|
||||||
result = kinetis_get_master_bank(bank, &master_bank);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
LOG_WARNING("kinetis_protect not supported yet");
|
LOG_WARNING("kinetis_protect not supported yet");
|
||||||
|
|
||||||
|
@ -121,16 +119,14 @@ static int kinetis_protect_check(struct flash_bank *bank)
|
||||||
|
|
||||||
result = kinetis_get_master_bank(bank, &master_bank);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
/* read protection register FTFL_FPROT */
|
/* read protection register FTFL_FPROT */
|
||||||
result = target_read_memory(bank->target, 0x40020010, 1, 4, buffer);
|
result = target_read_memory(bank->target, 0x40020010, 1, 4, buffer);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
fprot = target_buffer_get_u32(bank->target, buffer);
|
fprot = target_buffer_get_u32(bank->target, buffer);
|
||||||
|
|
||||||
|
@ -167,9 +163,8 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
|
||||||
result =
|
result =
|
||||||
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);
|
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer[0] & 0x80)
|
if (buffer[0] & 0x80)
|
||||||
break;
|
break;
|
||||||
|
@ -182,10 +177,9 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
|
||||||
buffer[0] = 0x30;
|
buffer[0] = 0x30;
|
||||||
result =
|
result =
|
||||||
target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
|
target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
target_buffer_set_u32(bank->target, buffer, w0);
|
target_buffer_set_u32(bank->target, buffer, w0);
|
||||||
target_buffer_set_u32(bank->target, buffer + 4, w1);
|
target_buffer_set_u32(bank->target, buffer + 4, w1);
|
||||||
|
@ -193,25 +187,22 @@ static int kinetis_ftfl_command(struct flash_bank *bank, uint32_t w0,
|
||||||
|
|
||||||
result = target_write_memory(bank->target, 0x40020004, 4, 3, buffer);
|
result = target_write_memory(bank->target, 0x40020004, 4, 3, buffer);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
/* start command */
|
/* start command */
|
||||||
buffer[0] = 0x80;
|
buffer[0] = 0x80;
|
||||||
result = target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
|
result = target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
/* wait for done */
|
/* wait for done */
|
||||||
for (i = 0; i < 50; i++) {
|
for (i = 0; i < 50; i++) {
|
||||||
result =
|
result =
|
||||||
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);
|
target_read_memory(bank->target, 0x40020000, 1, 1, buffer);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer[0] & 0x80)
|
if (buffer[0] & 0x80)
|
||||||
break;
|
break;
|
||||||
|
@ -243,13 +234,11 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
result = kinetis_get_master_bank(bank, &master_bank);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
if ((first > bank->num_sectors) || (last > bank->num_sectors)) {
|
if ((first > bank->num_sectors) || (last > bank->num_sectors))
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = first; i <= last; i++) {
|
for (i = first; i <= last; i++) {
|
||||||
/* set command and sector address */
|
/* set command and sector address */
|
||||||
|
@ -273,14 +262,14 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
|
static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
uint32_t offset, uint32_t count)
|
uint32_t offset, uint32_t count)
|
||||||
{
|
{
|
||||||
struct flash_bank *master_bank;
|
struct flash_bank *master_bank;
|
||||||
unsigned int i, result, fallback = 0, nvm = 0;
|
unsigned int i, result, fallback = 0, nvm = 0;
|
||||||
uint8_t buf[8];
|
uint8_t buf[8];
|
||||||
uint32_t wc, w0 = 0, w1 = 0, w2 = 0;
|
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;
|
bank->driver_priv;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED) {
|
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);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
if (offset >= kbank->nvm_start)
|
if (offset >= kbank->nvm_start)
|
||||||
nvm = 1;
|
nvm = 1;
|
||||||
|
@ -366,11 +354,10 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
|
||||||
|
|
||||||
result = kinetis_ftfl_command(bank, w0, w1, w2);
|
result = kinetis_ftfl_command(bank, w0, w1, w2);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* program longword command */
|
/* program longword command */
|
||||||
else {
|
else {
|
||||||
for (i = 0; i < count; i += 4) {
|
for (i = 0; i < count; i += 4) {
|
||||||
|
@ -381,11 +368,10 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer,
|
||||||
|
|
||||||
result = kinetis_ftfl_command(bank, w0, w1, w2);
|
result = kinetis_ftfl_command(bank, w0, w1, w2);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -405,24 +391,20 @@ static int kinetis_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
result = kinetis_get_master_bank(bank, &master_bank);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
result = target_read_memory(bank->target, 0x40048024, 1, 4, buf);
|
result = target_read_memory(bank->target, 0x40048024, 1, 4, buf);
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
sim_sdid = target_buffer_get_u32(bank->target, buf);
|
sim_sdid = target_buffer_get_u32(bank->target, buf);
|
||||||
result = target_read_memory(bank->target, 0x4004804c, 1, 4, buf);
|
result = target_read_memory(bank->target, 0x4004804c, 1, 4, buf);
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
sim_fcfg1 = target_buffer_get_u32(bank->target, buf);
|
sim_fcfg1 = target_buffer_get_u32(bank->target, buf);
|
||||||
result = target_read_memory(bank->target, 0x40048050, 1, 4, buf);
|
result = target_read_memory(bank->target, 0x40048050, 1, 4, buf);
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
sim_fcfg2 = target_buffer_get_u32(bank->target, buf);
|
sim_fcfg2 = target_buffer_get_u32(bank->target, buf);
|
||||||
|
|
||||||
LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", sim_sdid, sim_fcfg1,
|
LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", sim_sdid, sim_fcfg1,
|
||||||
|
@ -526,9 +508,8 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
|
|
||||||
result = kinetis_get_master_bank(bank, &master_bank);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, buf_size,
|
snprintf(buf, buf_size,
|
||||||
"%s driver for flash bank %s at 0x%8.8" PRIx32 "",
|
"%s driver for flash bank %s at 0x%8.8" PRIx32 "",
|
||||||
|
@ -551,15 +532,14 @@ static int kinetis_blank_check(struct flash_bank *bank)
|
||||||
|
|
||||||
result = kinetis_get_master_bank(bank, &master_bank);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kinetis_flash_read(struct flash_bank *bank,
|
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;
|
int result;
|
||||||
struct flash_bank *master_bank;
|
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);
|
result = kinetis_get_master_bank(bank, &master_bank);
|
||||||
|
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,15 +61,13 @@
|
||||||
* - 176x (tested with LPC1768)
|
* - 176x (tested with LPC1768)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
|
||||||
lpc2000_v1,
|
lpc2000_v1,
|
||||||
lpc2000_v2,
|
lpc2000_v2,
|
||||||
lpc1700
|
lpc1700
|
||||||
} lpc2000_variant;
|
} lpc2000_variant;
|
||||||
|
|
||||||
struct lpc2000_flash_bank
|
struct lpc2000_flash_bank {
|
||||||
{
|
|
||||||
lpc2000_variant variant;
|
lpc2000_variant variant;
|
||||||
struct working_area *iap_working_area;
|
struct working_area *iap_working_area;
|
||||||
uint32_t cclk;
|
uint32_t cclk;
|
||||||
|
@ -81,8 +79,7 @@ struct lpc2000_flash_bank
|
||||||
int checksum_vector;
|
int checksum_vector;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lpc2000_status_codes
|
enum lpc2000_status_codes {
|
||||||
{
|
|
||||||
LPC2000_CMD_SUCCESS = 0,
|
LPC2000_CMD_SUCCESS = 0,
|
||||||
LPC2000_INVALID_COMMAND = 1,
|
LPC2000_INVALID_COMMAND = 1,
|
||||||
LPC2000_SRC_ADDR_ERROR = 2,
|
LPC2000_SRC_ADDR_ERROR = 2,
|
||||||
|
@ -114,63 +111,50 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
||||||
/* default to a 4096 write buffer */
|
/* default to a 4096 write buffer */
|
||||||
lpc2000_info->cmd51_max_buffer = 4096;
|
lpc2000_info->cmd51_max_buffer = 4096;
|
||||||
|
|
||||||
if (lpc2000_info->variant == lpc2000_v1)
|
if (lpc2000_info->variant == lpc2000_v1) {
|
||||||
{
|
|
||||||
/* variant 1 has different layout for 128kb and 256kb flashes */
|
/* variant 1 has different layout for 128kb and 256kb flashes */
|
||||||
if (bank->size == 128 * 1024)
|
if (bank->size == 128 * 1024) {
|
||||||
{
|
|
||||||
bank->num_sectors = 16;
|
bank->num_sectors = 16;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * 16);
|
bank->sectors = malloc(sizeof(struct flash_sector) * 16);
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 8 * 1024;
|
bank->sectors[i].size = 8 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
}
|
} else if (bank->size == 256 * 1024) {
|
||||||
else if (bank->size == 256 * 1024)
|
|
||||||
{
|
|
||||||
bank->num_sectors = 18;
|
bank->num_sectors = 18;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * 18);
|
bank->sectors = malloc(sizeof(struct flash_sector) * 18);
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 8 * 1024;
|
bank->sectors[i].size = 8 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
for (i = 8; i < 10; i++)
|
for (i = 8; i < 10; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 64 * 1024;
|
bank->sectors[i].size = 64 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
for (i = 10; i < 18; i++)
|
for (i = 10; i < 18; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 8 * 1024;
|
bank->sectors[i].size = 8 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: unknown bank->size encountered");
|
LOG_ERROR("BUG: unknown bank->size encountered");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
} else if (lpc2000_info->variant == lpc2000_v2) {
|
||||||
else if (lpc2000_info->variant == lpc2000_v2)
|
|
||||||
{
|
|
||||||
/* variant 2 has a uniform layout, only number of sectors differs */
|
/* variant 2 has a uniform layout, only number of sectors differs */
|
||||||
switch (bank->size)
|
switch (bank->size) {
|
||||||
{
|
|
||||||
case 4 * 1024:
|
case 4 * 1024:
|
||||||
lpc2000_info->cmd51_max_buffer = 1024;
|
lpc2000_info->cmd51_max_buffer = 1024;
|
||||||
bank->num_sectors = 1;
|
bank->num_sectors = 1;
|
||||||
|
@ -209,26 +193,20 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
||||||
|
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
if (i < 8) {
|
||||||
if (i < 8)
|
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 4 * 1024;
|
bank->sectors[i].size = 4 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
} else if (i < 22) {
|
||||||
else if (i < 22)
|
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 32 * 1024;
|
bank->sectors[i].size = 32 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
} else if (i < 28) {
|
||||||
else if (i < 28)
|
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 4 * 1024;
|
bank->sectors[i].size = 4 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -236,11 +214,8 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (lpc2000_info->variant == lpc1700) {
|
||||||
else if (lpc2000_info->variant == lpc1700)
|
switch (bank->size) {
|
||||||
{
|
|
||||||
switch(bank->size)
|
|
||||||
{
|
|
||||||
case 32 * 1024:
|
case 32 * 1024:
|
||||||
bank->num_sectors = 8;
|
bank->num_sectors = 8;
|
||||||
break;
|
break;
|
||||||
|
@ -263,18 +238,16 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
||||||
|
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
|
|
||||||
for(i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
|
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx
|
||||||
bank->sectors[i].size = (i < 16)? 4 * 1024 : 32 * 1024;
|
*devices */
|
||||||
|
bank->sectors[i].size = (i < 16) ? 4 * 1024 : 32 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
|
LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
@ -289,7 +262,10 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
||||||
* 0x20 to 0x33: command result table (1+4 words)
|
* 0x20 to 0x33: command result table (1+4 words)
|
||||||
* 0x34 to 0xb3: stack (only 128b needed)
|
* 0x34 to 0xb3: stack (only 128b needed)
|
||||||
*/
|
*/
|
||||||
static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_table[5], uint32_t result_table[4])
|
static int lpc2000_iap_call(struct flash_bank *bank,
|
||||||
|
int code,
|
||||||
|
uint32_t param_table[5],
|
||||||
|
uint32_t result_table[4])
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
||||||
|
@ -302,25 +278,21 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
||||||
uint32_t iap_entry_point = 0; /* to make compiler happier */
|
uint32_t iap_entry_point = 0; /* to make compiler happier */
|
||||||
|
|
||||||
/* regrab previously allocated working_area, or allocate a new one */
|
/* regrab previously allocated working_area, or allocate a new one */
|
||||||
if (!lpc2000_info->iap_working_area)
|
if (!lpc2000_info->iap_working_area) {
|
||||||
{
|
|
||||||
uint8_t jump_gate[8];
|
uint8_t jump_gate[8];
|
||||||
|
|
||||||
/* make sure we have a working area */
|
/* make sure we have a working area */
|
||||||
if (target_alloc_working_area(target, 180, &lpc2000_info->iap_working_area) != ERROR_OK)
|
if (target_alloc_working_area(target, 180,
|
||||||
{
|
&lpc2000_info->iap_working_area) != ERROR_OK) {
|
||||||
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
|
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write IAP code to working area */
|
/* write IAP code to working area */
|
||||||
switch(lpc2000_info->variant)
|
switch (lpc2000_info->variant) {
|
||||||
{
|
|
||||||
case lpc1700:
|
case lpc1700:
|
||||||
target_buffer_set_u32(target, jump_gate,
|
target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
|
||||||
ARMV4_5_T_BX(12));
|
target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
|
||||||
target_buffer_set_u32(target, jump_gate + 4,
|
|
||||||
ARMV5_T_BKPT(0));
|
|
||||||
break;
|
break;
|
||||||
case lpc2000_v1:
|
case lpc2000_v1:
|
||||||
case lpc2000_v2:
|
case lpc2000_v2:
|
||||||
|
@ -332,15 +304,17 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval = target_write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK)
|
retval = target_write_memory(target,
|
||||||
{
|
lpc2000_info->iap_working_area->address, 4, 2, jump_gate);
|
||||||
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", lpc2000_info->iap_working_area->address);
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR(
|
||||||
|
"Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)",
|
||||||
|
lpc2000_info->iap_working_area->address);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(lpc2000_info->variant)
|
switch (lpc2000_info->variant) {
|
||||||
{
|
|
||||||
case lpc1700:
|
case lpc1700:
|
||||||
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||||
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
||||||
|
@ -359,7 +333,8 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
||||||
}
|
}
|
||||||
|
|
||||||
/* command parameter table */
|
/* command parameter table */
|
||||||
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4, PARAM_OUT);
|
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4,
|
||||||
|
PARAM_OUT);
|
||||||
target_buffer_set_u32(target, mem_params[0].value, code);
|
target_buffer_set_u32(target, mem_params[0].value, code);
|
||||||
target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
|
target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
|
||||||
target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
|
target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
|
||||||
|
@ -371,7 +346,10 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
||||||
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);
|
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);
|
||||||
|
|
||||||
/* command result table */
|
/* command result table */
|
||||||
init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 5 * 4, PARAM_IN);
|
init_mem_param(&mem_params[1],
|
||||||
|
lpc2000_info->iap_working_area->address + 0x20,
|
||||||
|
5 * 4,
|
||||||
|
PARAM_IN);
|
||||||
|
|
||||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
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);
|
buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
|
||||||
|
@ -380,30 +358,38 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
||||||
init_reg_param(®_params[2], "r12", 32, PARAM_OUT);
|
init_reg_param(®_params[2], "r12", 32, PARAM_OUT);
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
|
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
|
||||||
|
|
||||||
switch(lpc2000_info->variant)
|
switch (lpc2000_info->variant) {
|
||||||
{
|
|
||||||
case lpc1700:
|
case lpc1700:
|
||||||
/* IAP stack */
|
/* IAP stack */
|
||||||
init_reg_param(®_params[3], "sp", 32, PARAM_OUT);
|
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 */
|
/* return address */
|
||||||
init_reg_param(®_params[4], "lr", 32, PARAM_OUT);
|
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;
|
break;
|
||||||
case lpc2000_v1:
|
case lpc2000_v1:
|
||||||
case lpc2000_v2:
|
case lpc2000_v2:
|
||||||
/* IAP stack */
|
/* IAP stack */
|
||||||
init_reg_param(®_params[3], "sp_svc", 32, PARAM_OUT);
|
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 */
|
/* return address */
|
||||||
init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("BUG: unknown lpc2000->variant encountered");
|
LOG_ERROR("BUG: unknown lpc2000->variant encountered");
|
||||||
|
@ -416,8 +402,11 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
||||||
result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
|
result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
|
||||||
result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);
|
result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);
|
||||||
|
|
||||||
LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32") completed with result = %8.8" PRIx32,
|
LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32
|
||||||
code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code);
|
", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8"
|
||||||
|
PRIx32 ") completed with result = %8.8" PRIx32,
|
||||||
|
code, param_table[0], param_table[1], param_table[2],
|
||||||
|
param_table[3], param_table[4], status_code);
|
||||||
|
|
||||||
destroy_mem_param(&mem_params[0]);
|
destroy_mem_param(&mem_params[0]);
|
||||||
destroy_mem_param(&mem_params[1]);
|
destroy_mem_param(&mem_params[1]);
|
||||||
|
@ -441,14 +430,12 @@ static int lpc2000_iap_blank_check(struct flash_bank *bank, int first, int last)
|
||||||
if ((first < 0) || (last >= bank->num_sectors))
|
if ((first < 0) || (last >= bank->num_sectors))
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
/* check single sector */
|
/* check single sector */
|
||||||
param_table[0] = param_table[1] = i;
|
param_table[0] = param_table[1] = i;
|
||||||
status_code = lpc2000_iap_call(bank, 53, param_table, result_table);
|
status_code = lpc2000_iap_call(bank, 53, param_table, result_table);
|
||||||
|
|
||||||
switch (status_code)
|
switch (status_code) {
|
||||||
{
|
|
||||||
case ERROR_FLASH_OPERATION_FAILED:
|
case ERROR_FLASH_OPERATION_FAILED:
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
case LPC2000_CMD_SUCCESS:
|
case LPC2000_CMD_SUCCESS:
|
||||||
|
@ -480,39 +467,30 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
|
||||||
struct lpc2000_flash_bank *lpc2000_info;
|
struct lpc2000_flash_bank *lpc2000_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 8)
|
if (CMD_ARGC < 8)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
lpc2000_info = malloc(sizeof(struct lpc2000_flash_bank));
|
lpc2000_info = malloc(sizeof(struct lpc2000_flash_bank));
|
||||||
bank->driver_priv = lpc2000_info;
|
bank->driver_priv = lpc2000_info;
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0)
|
if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0) {
|
||||||
{
|
|
||||||
lpc2000_info->variant = lpc2000_v1;
|
lpc2000_info->variant = lpc2000_v1;
|
||||||
lpc2000_info->cmd51_dst_boundary = 512;
|
lpc2000_info->cmd51_dst_boundary = 512;
|
||||||
lpc2000_info->cmd51_can_256b = 0;
|
lpc2000_info->cmd51_can_256b = 0;
|
||||||
lpc2000_info->cmd51_can_8192b = 1;
|
lpc2000_info->cmd51_can_8192b = 1;
|
||||||
lpc2000_info->checksum_vector = 5;
|
lpc2000_info->checksum_vector = 5;
|
||||||
}
|
} else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0) {
|
||||||
else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0)
|
|
||||||
{
|
|
||||||
lpc2000_info->variant = lpc2000_v2;
|
lpc2000_info->variant = lpc2000_v2;
|
||||||
lpc2000_info->cmd51_dst_boundary = 256;
|
lpc2000_info->cmd51_dst_boundary = 256;
|
||||||
lpc2000_info->cmd51_can_256b = 1;
|
lpc2000_info->cmd51_can_256b = 1;
|
||||||
lpc2000_info->cmd51_can_8192b = 0;
|
lpc2000_info->cmd51_can_8192b = 0;
|
||||||
lpc2000_info->checksum_vector = 5;
|
lpc2000_info->checksum_vector = 5;
|
||||||
}
|
} else if (strcmp(CMD_ARGV[6], "lpc1700") == 0) {
|
||||||
else if (strcmp(CMD_ARGV[6], "lpc1700") == 0)
|
|
||||||
{
|
|
||||||
lpc2000_info->variant = lpc1700;
|
lpc2000_info->variant = lpc1700;
|
||||||
lpc2000_info->cmd51_dst_boundary = 256;
|
lpc2000_info->cmd51_dst_boundary = 256;
|
||||||
lpc2000_info->cmd51_can_256b = 1;
|
lpc2000_info->cmd51_can_256b = 1;
|
||||||
lpc2000_info->cmd51_can_8192b = 0;
|
lpc2000_info->cmd51_can_8192b = 0;
|
||||||
lpc2000_info->checksum_vector = 7;
|
lpc2000_info->checksum_vector = 7;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]);
|
LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]);
|
||||||
free(lpc2000_info);
|
free(lpc2000_info);
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
|
@ -523,8 +501,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
|
||||||
lpc2000_info->calc_checksum = 0;
|
lpc2000_info->calc_checksum = 0;
|
||||||
lpc2000_build_sector_list(bank);
|
lpc2000_build_sector_list(bank);
|
||||||
|
|
||||||
if (CMD_ARGC >= 9)
|
if (CMD_ARGC >= 9) {
|
||||||
{
|
|
||||||
if (strcmp(CMD_ARGV[8], "calc_checksum") == 0)
|
if (strcmp(CMD_ARGV[8], "calc_checksum") == 0)
|
||||||
lpc2000_info->calc_checksum = 1;
|
lpc2000_info->calc_checksum = 1;
|
||||||
}
|
}
|
||||||
|
@ -539,8 +516,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)
|
||||||
uint32_t result_table[4];
|
uint32_t result_table[4];
|
||||||
int status_code;
|
int status_code;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -551,8 +527,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
/* Prepare sectors */
|
/* Prepare sectors */
|
||||||
status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
|
status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
|
||||||
switch (status_code)
|
switch (status_code) {
|
||||||
{
|
|
||||||
case ERROR_FLASH_OPERATION_FAILED:
|
case ERROR_FLASH_OPERATION_FAILED:
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
case LPC2000_CMD_SUCCESS:
|
case LPC2000_CMD_SUCCESS:
|
||||||
|
@ -567,8 +542,7 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
/* Erase sectors */
|
/* Erase sectors */
|
||||||
status_code = lpc2000_iap_call(bank, 52, param_table, result_table);
|
status_code = lpc2000_iap_call(bank, 52, param_table, result_table);
|
||||||
switch (status_code)
|
switch (status_code) {
|
||||||
{
|
|
||||||
case ERROR_FLASH_OPERATION_FAILED:
|
case ERROR_FLASH_OPERATION_FAILED:
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
case LPC2000_CMD_SUCCESS:
|
case LPC2000_CMD_SUCCESS:
|
||||||
|
@ -606,8 +580,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
struct working_area *download_area;
|
struct working_area *download_area;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -617,55 +590,56 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
|
|
||||||
dst_min_alignment = lpc2000_info->cmd51_dst_boundary;
|
dst_min_alignment = lpc2000_info->cmd51_dst_boundary;
|
||||||
|
|
||||||
if (offset % dst_min_alignment)
|
if (offset % dst_min_alignment) {
|
||||||
{
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32,
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, offset, dst_min_alignment);
|
offset,
|
||||||
|
dst_min_alignment);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
if (offset >= bank->sectors[i].offset)
|
if (offset >= bank->sectors[i].offset)
|
||||||
first_sector = i;
|
first_sector = i;
|
||||||
if (offset + DIV_ROUND_UP(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset)
|
if (offset + DIV_ROUND_UP(count, dst_min_alignment)
|
||||||
|
* dst_min_alignment > bank->sectors[i].offset)
|
||||||
last_sector = i;
|
last_sector = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
|
LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
|
||||||
|
|
||||||
/* check if exception vectors should be flashed */
|
/* check if exception vectors should be flashed */
|
||||||
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
|
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) {
|
||||||
{
|
|
||||||
uint32_t checksum = 0;
|
uint32_t checksum = 0;
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++) {
|
||||||
{
|
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4,
|
||||||
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
|
buf_get_u32(buffer + (i * 4), 0, 32));
|
||||||
if (i != lpc2000_info->checksum_vector)
|
if (i != lpc2000_info->checksum_vector)
|
||||||
checksum += buf_get_u32(buffer + (i * 4), 0, 32);
|
checksum += buf_get_u32(buffer + (i * 4), 0, 32);
|
||||||
}
|
}
|
||||||
checksum = 0 - checksum;
|
checksum = 0 - checksum;
|
||||||
LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);
|
LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);
|
||||||
|
|
||||||
uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32);
|
uint32_t original_value = buf_get_u32(buffer +
|
||||||
if (original_value != checksum)
|
(lpc2000_info->checksum_vector * 4), 0, 32);
|
||||||
{
|
if (original_value != checksum) {
|
||||||
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is different from calculated vector checksum (0x%8.8" PRIx32 ").",
|
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") "
|
||||||
original_value, checksum);
|
"to be written to flash is different from calculated vector "
|
||||||
LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
|
"checksum (0x%8.8" PRIx32 ").", original_value, checksum);
|
||||||
|
LOG_WARNING("To remove this warning modify build tools on developer PC "
|
||||||
|
"to inject correct LPC vector checksum.");
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
|
buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a working area */
|
/* allocate a working area */
|
||||||
if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, &download_area) != ERROR_OK)
|
if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer,
|
||||||
{
|
&download_area) != ERROR_OK) {
|
||||||
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
|
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bytes_remaining > 0)
|
while (bytes_remaining > 0) {
|
||||||
{
|
|
||||||
uint32_t thisrun_bytes;
|
uint32_t thisrun_bytes;
|
||||||
if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
|
if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
|
||||||
thisrun_bytes = lpc2000_info->cmd51_max_buffer;
|
thisrun_bytes = lpc2000_info->cmd51_max_buffer;
|
||||||
|
@ -680,8 +654,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
param_table[0] = first_sector;
|
param_table[0] = first_sector;
|
||||||
param_table[1] = last_sector;
|
param_table[1] = last_sector;
|
||||||
status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
|
status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
|
||||||
switch (status_code)
|
switch (status_code) {
|
||||||
{
|
|
||||||
case ERROR_FLASH_OPERATION_FAILED:
|
case ERROR_FLASH_OPERATION_FAILED:
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
|
@ -700,24 +673,28 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (bytes_remaining >= thisrun_bytes)
|
if (bytes_remaining >= thisrun_bytes) {
|
||||||
{
|
retval = target_write_buffer(bank->target, download_area->address,
|
||||||
if ((retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written)) != ERROR_OK)
|
thisrun_bytes, buffer + bytes_written);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t *last_buffer = malloc(thisrun_bytes);
|
uint8_t *last_buffer = malloc(thisrun_bytes);
|
||||||
memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
|
memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
|
||||||
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining);
|
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes -
|
||||||
target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer);
|
bytes_remaining);
|
||||||
|
target_write_buffer(bank->target,
|
||||||
|
download_area->address,
|
||||||
|
thisrun_bytes,
|
||||||
|
last_buffer);
|
||||||
free(last_buffer);
|
free(last_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32 , thisrun_bytes, bank->base + offset + bytes_written);
|
LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32,
|
||||||
|
thisrun_bytes,
|
||||||
|
bank->base + offset + bytes_written);
|
||||||
|
|
||||||
/* Write data */
|
/* Write data */
|
||||||
param_table[0] = bank->base + offset + bytes_written;
|
param_table[0] = bank->base + offset + bytes_written;
|
||||||
|
@ -725,8 +702,7 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
param_table[2] = thisrun_bytes;
|
param_table[2] = thisrun_bytes;
|
||||||
param_table[3] = lpc2000_info->cclk;
|
param_table[3] = lpc2000_info->cclk;
|
||||||
status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
|
status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
|
||||||
switch (status_code)
|
switch (status_code) {
|
||||||
{
|
|
||||||
case ERROR_FLASH_OPERATION_FAILED:
|
case ERROR_FLASH_OPERATION_FAILED:
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
|
@ -767,8 +743,7 @@ static int lpc2000_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
static int lpc2000_erase_check(struct flash_bank *bank)
|
static int lpc2000_erase_check(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +761,11 @@ static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
||||||
|
|
||||||
snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz" , lpc2000_info->variant, lpc2000_info->cclk);
|
snprintf(buf,
|
||||||
|
buf_size,
|
||||||
|
"lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz",
|
||||||
|
lpc2000_info->variant,
|
||||||
|
lpc2000_info->cclk);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -798,34 +777,28 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command)
|
||||||
int status_code;
|
int status_code;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0)
|
status_code = lpc2000_iap_call(bank, 54, param_table, result_table);
|
||||||
{
|
if (status_code != 0x0) {
|
||||||
if (status_code == ERROR_FLASH_OPERATION_FAILED)
|
if (status_code == ERROR_FLASH_OPERATION_FAILED) {
|
||||||
{
|
command_print(CMD_CTX,
|
||||||
command_print(CMD_CTX, "no sufficient working area specified, can't access LPC2000 IAP interface");
|
"no sufficient working area specified, can't access LPC2000 IAP interface");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code);
|
command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code);
|
||||||
}
|
} else
|
||||||
else
|
command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, result_table[0]);
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32 , result_table[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include <helper/binarybuffer.h>
|
#include <helper/binarybuffer.h>
|
||||||
|
|
||||||
|
|
||||||
#define LOAD_TIMER_ERASE 0
|
#define LOAD_TIMER_ERASE 0
|
||||||
#define LOAD_TIMER_WRITE 1
|
#define LOAD_TIMER_WRITE 1
|
||||||
|
|
||||||
|
@ -47,15 +46,18 @@
|
||||||
#define F_STAT 0x80102004 /* Flash status register RO 0x45 */
|
#define F_STAT 0x80102004 /* Flash status register RO 0x45 */
|
||||||
#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
|
#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
|
||||||
#define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
|
#define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
|
||||||
#define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 */
|
#define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0
|
||||||
|
**/
|
||||||
#define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
|
#define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
|
||||||
#define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
|
#define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
|
||||||
#define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
|
#define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
|
||||||
#define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
|
#define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
|
||||||
#define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
|
#define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
|
||||||
#define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
|
#define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
|
||||||
#define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power savings. R/W 1*/
|
#define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power
|
||||||
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from Power Down mode. R/W -*/
|
*savings. R/W 1*/
|
||||||
|
#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from
|
||||||
|
*Power Down mode. R/W -*/
|
||||||
|
|
||||||
/* F_CTRL bits */
|
/* F_CTRL bits */
|
||||||
#define FC_CS 0x0001
|
#define FC_CS 0x0001
|
||||||
|
@ -84,14 +86,13 @@
|
||||||
/* F_CLK_TIME */
|
/* F_CLK_TIME */
|
||||||
#define FCT_CLK_DIV_MASK 0x0FFF
|
#define FCT_CLK_DIV_MASK 0x0FFF
|
||||||
|
|
||||||
struct lpc288x_flash_bank
|
struct lpc288x_flash_bank {
|
||||||
{
|
|
||||||
uint32_t working_area;
|
uint32_t working_area;
|
||||||
uint32_t working_area_size;
|
uint32_t working_area_size;
|
||||||
|
|
||||||
/* chip id register */
|
/* chip id register */
|
||||||
uint32_t cidr;
|
uint32_t cidr;
|
||||||
const char * target_name;
|
const char *target_name;
|
||||||
uint32_t cclk;
|
uint32_t cclk;
|
||||||
|
|
||||||
uint32_t sector_size_break;
|
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;
|
uint32_t status;
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
timeout--;
|
timeout--;
|
||||||
target_read_u32(target, F_STAT, &status);
|
target_read_u32(target, F_STAT, &status);
|
||||||
} while (((status & FS_DONE) == 0) && timeout);
|
} while (((status & FS_DONE) == 0) && timeout);
|
||||||
|
|
||||||
if (timeout == 0)
|
if (timeout == 0) {
|
||||||
{
|
|
||||||
LOG_DEBUG("Timedout!");
|
LOG_DEBUG("Timedout!");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -132,14 +131,14 @@ static int lpc288x_read_part_info(struct flash_bank *bank)
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
|
|
||||||
if (lpc288x_info->cidr == 0x0102100A)
|
if (lpc288x_info->cidr == 0x0102100A)
|
||||||
return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
|
return ERROR_OK;/* already probed, multiple probes may cause memory leak, not
|
||||||
|
*allowed */
|
||||||
|
|
||||||
/* Read and parse chip identification register */
|
/* Read and parse chip identification register */
|
||||||
target_read_u32(target, DBGU_CIDR, &cidr);
|
target_read_u32(target, DBGU_CIDR, &cidr);
|
||||||
|
|
||||||
if (cidr != 0x0102100A)
|
if (cidr != 0x0102100A) {
|
||||||
{
|
LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr);
|
||||||
LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")",cidr);
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,16 +151,14 @@ static int lpc288x_read_part_info(struct flash_bank *bank)
|
||||||
bank->num_sectors = 23;
|
bank->num_sectors = 23;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * 23);
|
bank->sectors = malloc(sizeof(struct flash_sector) * 23);
|
||||||
|
|
||||||
for (i = 0; i < 15; i++)
|
for (i = 0; i < 15; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 64 * 1024;
|
bank->sectors[i].size = 64 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
for (i = 15; i < 23; i++)
|
for (i = 15; i < 23; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 8 * 1024;
|
bank->sectors[i].size = 8 * 1024;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -183,9 +180,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command)
|
||||||
struct lpc288x_flash_bank *lpc288x_info;
|
struct lpc288x_flash_bank *lpc288x_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank));
|
lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank));
|
||||||
bank->driver_priv = lpc288x_info;
|
bank->driver_priv = lpc288x_info;
|
||||||
|
@ -220,25 +215,18 @@ static void lpc288x_set_flash_clk(struct flash_bank *bank)
|
||||||
static void lpc288x_load_timer(int erase, struct target *target)
|
static void lpc288x_load_timer(int erase, struct target *target)
|
||||||
{
|
{
|
||||||
if (erase == LOAD_TIMER_ERASE)
|
if (erase == LOAD_TIMER_ERASE)
|
||||||
{
|
|
||||||
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
|
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
|
target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t lpc288x_system_ready(struct flash_bank *bank)
|
static uint32_t lpc288x_system_ready(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
|
struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
|
||||||
if (lpc288x_info->cidr == 0)
|
if (lpc288x_info->cidr == 0)
|
||||||
{
|
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -248,8 +236,7 @@ static uint32_t lpc288x_system_ready(struct flash_bank *bank)
|
||||||
static int lpc288x_erase_check(struct flash_bank *bank)
|
static int lpc288x_erase_check(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
|
uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
|
||||||
if (status != ERROR_OK)
|
if (status != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_INFO("Processor not halted/not probed");
|
LOG_INFO("Processor not halted/not probed");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -265,12 +252,9 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
status = lpc288x_system_ready(bank); /* probed? halted? */
|
status = lpc288x_system_ready(bank); /* probed? halted? */
|
||||||
if (status != ERROR_OK)
|
if (status != ERROR_OK)
|
||||||
{
|
|
||||||
return status;
|
return status;
|
||||||
}
|
|
||||||
|
|
||||||
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
|
||||||
{
|
|
||||||
LOG_INFO("Bad sector range");
|
LOG_INFO("Bad sector range");
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -278,30 +262,25 @@ static int lpc288x_erase(struct flash_bank *bank, int first, int last)
|
||||||
/* Configure the flash controller timing */
|
/* Configure the flash controller timing */
|
||||||
lpc288x_set_flash_clk(bank);
|
lpc288x_set_flash_clk(bank);
|
||||||
|
|
||||||
for (sector = first; sector <= last; sector++)
|
for (sector = first; sector <= last; sector++) {
|
||||||
{
|
|
||||||
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
|
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
lpc288x_load_timer(LOAD_TIMER_ERASE,target);
|
lpc288x_load_timer(LOAD_TIMER_ERASE, target);
|
||||||
|
|
||||||
target_write_u32(target, bank->sectors[sector].offset, 0x00);
|
target_write_u32(target, bank->sectors[sector].offset, 0x00);
|
||||||
|
|
||||||
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
|
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
|
||||||
}
|
}
|
||||||
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
|
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||||
{
|
{
|
||||||
uint8_t page_buffer[FLASH_PAGE_SIZE];
|
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;
|
struct target *target = bank->target;
|
||||||
uint32_t bytes_remaining = count;
|
uint32_t bytes_remaining = count;
|
||||||
uint32_t first_sector, last_sector, sector, page;
|
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? */
|
/* probed? halted? */
|
||||||
status = lpc288x_system_ready(bank);
|
status = lpc288x_system_ready(bank);
|
||||||
if (status != ERROR_OK)
|
if (status != ERROR_OK)
|
||||||
{
|
|
||||||
return status;
|
return status;
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise search indices */
|
/* Initialise search indices */
|
||||||
first_sector = last_sector = 0xffffffff;
|
first_sector = last_sector = 0xffffffff;
|
||||||
|
|
||||||
/* validate the write range... */
|
/* validate the write range... */
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
if ((offset >= bank->sectors[i].offset) &&
|
if ((offset >= bank->sectors[i].offset) &&
|
||||||
(offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
|
(offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
|
||||||
(first_sector == 0xffffffff))
|
(first_sector == 0xffffffff)) {
|
||||||
{
|
|
||||||
first_sector = i;
|
first_sector = i;
|
||||||
/* all writes must start on a sector boundary... */
|
/* all writes must start on a sector boundary... */
|
||||||
if (offset % bank->sectors[i].size)
|
if (offset % bank->sectors[i].size) {
|
||||||
{
|
LOG_INFO(
|
||||||
LOG_INFO("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, bank->sectors[i].size);
|
"offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
|
||||||
|
offset,
|
||||||
|
bank->sectors[i].size);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (((offset + count) > bank->sectors[i].offset) &&
|
if (((offset + count) > bank->sectors[i].offset) &&
|
||||||
((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
|
((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
|
||||||
(last_sector == 0xffffffff))
|
(last_sector == 0xffffffff))
|
||||||
{
|
|
||||||
last_sector = i;
|
last_sector = i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Range check... */
|
/* Range check... */
|
||||||
if (first_sector == 0xffffffff || last_sector == 0xffffffff)
|
if (first_sector == 0xffffffff || last_sector == 0xffffffff) {
|
||||||
{
|
|
||||||
LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
|
LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
|
||||||
return ERROR_FLASH_DST_OUT_OF_BANK;
|
return ERROR_FLASH_DST_OUT_OF_BANK;
|
||||||
}
|
}
|
||||||
|
@ -354,32 +328,23 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
source_offset = 0;
|
source_offset = 0;
|
||||||
dest_offset = 0;
|
dest_offset = 0;
|
||||||
|
|
||||||
for (sector = first_sector; sector <= last_sector; sector++)
|
for (sector = first_sector; sector <= last_sector; sector++) {
|
||||||
{
|
for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) {
|
||||||
for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++)
|
if (bytes_remaining == 0) {
|
||||||
{
|
|
||||||
if (bytes_remaining == 0)
|
|
||||||
{
|
|
||||||
count = 0;
|
count = 0;
|
||||||
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
|
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
|
||||||
}
|
} else if (bytes_remaining < FLASH_PAGE_SIZE) {
|
||||||
else if (bytes_remaining < FLASH_PAGE_SIZE)
|
|
||||||
{
|
|
||||||
count = bytes_remaining;
|
count = bytes_remaining;
|
||||||
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
|
memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
|
||||||
memcpy(page_buffer, &buffer[source_offset], count);
|
memcpy(page_buffer, &buffer[source_offset], count);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
count = FLASH_PAGE_SIZE;
|
count = FLASH_PAGE_SIZE;
|
||||||
memcpy(page_buffer, &buffer[source_offset], count);
|
memcpy(page_buffer, &buffer[source_offset], count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for flash to become ready */
|
/* Wait for flash to become ready */
|
||||||
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
|
if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* fill flash data latches with 1's */
|
/* fill flash data latches with 1's */
|
||||||
target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
|
target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
|
||||||
|
@ -389,14 +354,14 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
* it seems not to be a LOT slower....
|
* it seems not to be a LOT slower....
|
||||||
* bulk_write_memory() is no quicker :(*/
|
* bulk_write_memory() is no quicker :(*/
|
||||||
#if 1
|
#if 1
|
||||||
if (target_write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK)
|
if (target_write_memory(target, offset + dest_offset, 4, 128,
|
||||||
{
|
page_buffer) != ERROR_OK) {
|
||||||
LOG_ERROR("Write failed s %" PRIx32 " p %" PRIx32 "", sector, page);
|
LOG_ERROR("Write failed s %" PRIx32 " p %" PRIx32 "", sector, page);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK)
|
if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE,
|
||||||
{
|
page_buffer) != ERROR_OK) {
|
||||||
LOG_INFO("Write to flash buffer failed");
|
LOG_INFO("Write to flash buffer failed");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +372,8 @@ static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
|
|
||||||
lpc288x_load_timer(LOAD_TIMER_WRITE, target);
|
lpc288x_load_timer(LOAD_TIMER_WRITE, target);
|
||||||
|
|
||||||
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | FC_CS);
|
target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC |
|
||||||
|
FC_CS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,12 +387,9 @@ static int lpc288x_probe(struct flash_bank *bank)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (lpc288x_info->cidr != 0)
|
if (lpc288x_info->cidr != 0)
|
||||||
{
|
return ERROR_OK;/* already probed */
|
||||||
return ERROR_OK; /* already probed */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -452,32 +415,25 @@ static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last
|
||||||
/* probed? halted? */
|
/* probed? halted? */
|
||||||
status = lpc288x_system_ready(bank);
|
status = lpc288x_system_ready(bank);
|
||||||
if (status != ERROR_OK)
|
if (status != ERROR_OK)
|
||||||
{
|
|
||||||
return status;
|
return status;
|
||||||
}
|
|
||||||
|
|
||||||
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
||||||
{
|
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure the flash controller timing */
|
/* Configure the flash controller timing */
|
||||||
lpc288x_set_flash_clk(bank);
|
lpc288x_set_flash_clk(bank);
|
||||||
|
|
||||||
for (lockregion = first; lockregion <= last; lockregion++)
|
for (lockregion = first; lockregion <= last; lockregion++) {
|
||||||
{
|
if (set) {
|
||||||
if (set)
|
|
||||||
{
|
|
||||||
/* write an odd value to base addy to protect... */
|
/* write an odd value to base addy to protect... */
|
||||||
value = 0x01;
|
value = 0x01;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* write an even value to base addy to unprotect... */
|
/* write an even value to base addy to unprotect... */
|
||||||
value = 0x00;
|
value = 0x00;
|
||||||
}
|
}
|
||||||
target_write_u32(target, bank->sectors[lockregion].offset, value);
|
target_write_u32(target, bank->sectors[lockregion].offset, value);
|
||||||
target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | FC_CS);
|
target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC |
|
||||||
|
FC_CS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,7 +28,6 @@
|
||||||
#include "cfi.h"
|
#include "cfi.h"
|
||||||
#include "non_cfi.h"
|
#include "non_cfi.h"
|
||||||
|
|
||||||
|
|
||||||
#define KB 1024
|
#define KB 1024
|
||||||
#define MB (1024*1024)
|
#define MB (1024*1024)
|
||||||
#define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
|
#define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
|
||||||
|
@ -43,8 +43,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(16, 4*KB)
|
ERASE_REGION(16, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -57,8 +56,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(32, 4*KB)
|
ERASE_REGION(32, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -71,8 +69,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(64, 4*KB)
|
ERASE_REGION(64, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -85,8 +82,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(128, 4*KB)
|
ERASE_REGION(128, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -99,8 +95,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(8, 64*KB)
|
ERASE_REGION(8, 64*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -113,8 +108,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(128, 4*KB)
|
ERASE_REGION(128, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -127,8 +121,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -144,8 +137,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(7, 64*KB),
|
ERASE_REGION(7, 64*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
|
@ -168,8 +160,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(512, 4*KB)
|
ERASE_REGION(512, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -182,8 +173,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1024, 4*KB)
|
ERASE_REGION(1024, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -196,8 +186,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(512, 4*KB)
|
ERASE_REGION(512, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -210,8 +199,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(512, 4*KB)
|
ERASE_REGION(512, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -224,8 +212,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(512, 4*KB)
|
ERASE_REGION(512, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -238,8 +225,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1024, 4*KB)
|
ERASE_REGION(1024, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -252,8 +238,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1024, 4*KB)
|
ERASE_REGION(1024, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -266,8 +251,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
.num_erase_regions = 1,
|
.num_erase_regions = 1,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(2048, 4*KB)
|
ERASE_REGION(2048, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -280,8 +264,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -297,8 +280,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(7, 64*KB),
|
ERASE_REGION(7, 64*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
|
@ -314,8 +296,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -331,8 +312,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(15, 64*KB),
|
ERASE_REGION(15, 64*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
|
@ -348,8 +328,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x00,
|
.max_buf_write_size = 0x00,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -365,8 +344,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -382,8 +360,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -400,8 +377,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -417,8 +393,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(31, 64*KB),
|
ERASE_REGION(31, 64*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
|
@ -434,8 +409,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -451,8 +425,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 3,
|
.num_erase_regions = 3,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(8, 8*KB),
|
ERASE_REGION(8, 8*KB),
|
||||||
ERASE_REGION(2, 32*KB),
|
ERASE_REGION(2, 32*KB),
|
||||||
ERASE_REGION(30, 64*KB)
|
ERASE_REGION(30, 64*KB)
|
||||||
|
@ -467,8 +440,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 3,
|
.num_erase_regions = 3,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(30, 64*KB),
|
ERASE_REGION(30, 64*KB),
|
||||||
ERASE_REGION(2, 32*KB),
|
ERASE_REGION(2, 32*KB),
|
||||||
ERASE_REGION(8, 8*KB)
|
ERASE_REGION(8, 8*KB)
|
||||||
|
@ -483,8 +455,7 @@ static struct non_cfi non_cfi_flashes[] = {
|
||||||
.max_buf_write_size = 0x0,
|
.max_buf_write_size = 0x0,
|
||||||
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
.num_erase_regions = 4,
|
.num_erase_regions = 4,
|
||||||
.erase_region_info =
|
.erase_region_info = {
|
||||||
{
|
|
||||||
ERASE_REGION(1, 16*KB),
|
ERASE_REGION(1, 16*KB),
|
||||||
ERASE_REGION(2, 8*KB),
|
ERASE_REGION(2, 8*KB),
|
||||||
ERASE_REGION(1, 32*KB),
|
ERASE_REGION(1, 32*KB),
|
||||||
|
@ -503,19 +474,16 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
|
||||||
struct cfi_flash_bank *cfi_info = bank->driver_priv;
|
struct cfi_flash_bank *cfi_info = bank->driver_priv;
|
||||||
struct non_cfi *non_cfi = non_cfi_flashes;
|
struct non_cfi *non_cfi = non_cfi_flashes;
|
||||||
|
|
||||||
if(cfi_info->x16_as_x8)
|
if (cfi_info->x16_as_x8)
|
||||||
mask = 0xFF;
|
mask = 0xFF;
|
||||||
else
|
else
|
||||||
mask = 0xFFFF;
|
mask = 0xFFFF;
|
||||||
|
|
||||||
for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++)
|
for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++) {
|
||||||
{
|
|
||||||
if ((cfi_info->manufacturer == non_cfi->mfr)
|
if ((cfi_info->manufacturer == non_cfi->mfr)
|
||||||
&& (cfi_info->device_id == (non_cfi->id & mask)))
|
&& (cfi_info->device_id == (non_cfi->id & mask)))
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* only fixup jedec flashs found in table */
|
/* only fixup jedec flashs found in table */
|
||||||
if (!non_cfi->mfr)
|
if (!non_cfi->mfr)
|
||||||
|
@ -560,8 +528,7 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
|
||||||
non_cfi->erase_region_info, erase_region_info_size);
|
non_cfi->erase_region_info, erase_region_info_size);
|
||||||
cfi_info->dev_size = non_cfi->dev_size;
|
cfi_info->dev_size = non_cfi->dev_size;
|
||||||
|
|
||||||
if (cfi_info->pri_id == 0x2)
|
if (cfi_info->pri_id == 0x2) {
|
||||||
{
|
|
||||||
struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
|
struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
|
||||||
|
|
||||||
pri_ext->pri[0] = 'P';
|
pri_ext->pri[0] = 'P';
|
||||||
|
@ -589,8 +556,7 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
|
||||||
pri_ext->_reversed_geometry = 0;
|
pri_ext->_reversed_geometry = 0;
|
||||||
|
|
||||||
cfi_info->pri_ext = pri_ext;
|
cfi_info->pri_ext = pri_ext;
|
||||||
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3))
|
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3)) {
|
||||||
{
|
|
||||||
LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
|
LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef NON_CFI_H
|
#ifndef NON_CFI_H
|
||||||
#define NON_CFI_H
|
#define NON_CFI_H
|
||||||
|
|
||||||
struct non_cfi
|
struct non_cfi {
|
||||||
{
|
|
||||||
uint16_t mfr;
|
uint16_t mfr;
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
uint16_t pri_id;
|
uint16_t pri_id;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,9 +26,7 @@
|
||||||
#include "ocl.h"
|
#include "ocl.h"
|
||||||
#include <target/embeddedice.h>
|
#include <target/embeddedice.h>
|
||||||
|
|
||||||
|
struct ocl_priv {
|
||||||
struct ocl_priv
|
|
||||||
{
|
|
||||||
struct arm_jtag *jtag_info;
|
struct arm_jtag *jtag_info;
|
||||||
unsigned int buflen;
|
unsigned int buflen;
|
||||||
unsigned int bufalign;
|
unsigned int bufalign;
|
||||||
|
@ -50,9 +49,7 @@ FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
|
||||||
struct ocl_priv *ocl;
|
struct ocl_priv *ocl;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
arm7_9 = target_to_arm7_9(bank->target);
|
arm7_9 = target_to_arm7_9(bank->target);
|
||||||
if (!is_arm7_9(arm7_9))
|
if (!is_arm7_9(arm7_9))
|
||||||
|
@ -76,39 +73,36 @@ static int ocl_erase(struct flash_bank *bank, int first, int last)
|
||||||
if (bank->num_sectors == 0)
|
if (bank->num_sectors == 0)
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_RUNNING)
|
if (bank->target->state != TARGET_RUNNING) {
|
||||||
{
|
|
||||||
LOG_ERROR("target has to be running to communicate with the loader");
|
LOG_ERROR("target has to be running to communicate with the loader");
|
||||||
return ERROR_TARGET_NOT_RUNNING;
|
return ERROR_TARGET_NOT_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first == 0) && (last == bank->num_sectors - 1))
|
if ((first == 0) && (last == bank->num_sectors - 1)) {
|
||||||
{
|
|
||||||
dcc_buffer[0] = OCL_ERASE_ALL;
|
dcc_buffer[0] = OCL_ERASE_ALL;
|
||||||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
dcc_buffer[0] = OCL_ERASE_BLOCK;
|
dcc_buffer[0] = OCL_ERASE_BLOCK;
|
||||||
dcc_buffer[1] = first;
|
dcc_buffer[1] = first;
|
||||||
dcc_buffer[2] = last;
|
dcc_buffer[2] = last;
|
||||||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK))
|
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for response, fixed timeout of 1 s */
|
/* wait for response, fixed timeout of 1 s */
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* receive response */
|
/* receive response */
|
||||||
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1) != ERROR_OK))
|
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (dcc_buffer[1] != OCL_CMD_DONE)
|
if (dcc_buffer[1] != OCL_CMD_DONE) {
|
||||||
{
|
|
||||||
if (dcc_buffer[0] == OCL_ERASE_ALL)
|
if (dcc_buffer[0] == OCL_ERASE_ALL)
|
||||||
LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
|
LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
|
||||||
else
|
else
|
||||||
|
@ -140,8 +134,7 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
if (ocl->buflen == 0 || ocl->bufalign == 0)
|
if (ocl->buflen == 0 || ocl->bufalign == 0)
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_RUNNING)
|
if (bank->target->state != TARGET_RUNNING) {
|
||||||
{
|
|
||||||
LOG_ERROR("target has to be running to communicate with the loader");
|
LOG_ERROR("target has to be running to communicate with the loader");
|
||||||
return ERROR_TARGET_NOT_RUNNING;
|
return ERROR_TARGET_NOT_RUNNING;
|
||||||
}
|
}
|
||||||
|
@ -149,8 +142,7 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
/* allocate buffer for max. ocl buffer + overhead */
|
/* allocate buffer for max. ocl buffer + overhead */
|
||||||
dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
|
dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
|
||||||
|
|
||||||
while (count)
|
while (count) {
|
||||||
{
|
|
||||||
if (count + (offset % ocl->bufalign) > ocl->buflen)
|
if (count + (offset % ocl->bufalign) > ocl->buflen)
|
||||||
runlen = ocl->buflen - (offset % ocl->bufalign);
|
runlen = ocl->buflen - (offset % ocl->bufalign);
|
||||||
else
|
else
|
||||||
|
@ -165,10 +157,8 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
chksum = OCL_CHKS_INIT;
|
chksum = OCL_CHKS_INIT;
|
||||||
|
|
||||||
/* copy data to DCC buffer in proper byte order and properly aligned */
|
/* copy data to DCC buffer in proper byte order and properly aligned */
|
||||||
for (i = 0; i < runlen; i++)
|
for (i = 0; i < runlen; i++) {
|
||||||
{
|
switch (byteofs++) {
|
||||||
switch (byteofs++)
|
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
*dcc_bufptr &= *(buffer++) | 0xffffff00;
|
*dcc_bufptr &= *(buffer++) | 0xffffff00;
|
||||||
break;
|
break;
|
||||||
|
@ -194,28 +184,27 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
||||||
*(dcc_bufptr++) = chksum;
|
*(dcc_bufptr++) = chksum;
|
||||||
|
|
||||||
/* send the data */
|
/* send the data */
|
||||||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK)
|
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
free(dcc_buffer);
|
free(dcc_buffer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for response, fixed timeout of 1 s */
|
/* wait for response, fixed timeout of 1 s */
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
free(dcc_buffer);
|
free(dcc_buffer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive response */
|
/* receive response */
|
||||||
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
free(dcc_buffer);
|
free(dcc_buffer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dcc_buffer[0] != OCL_CMD_DONE)
|
if (dcc_buffer[0] != OCL_CMD_DONE) {
|
||||||
{
|
|
||||||
LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
|
LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
|
||||||
free(dcc_buffer);
|
free(dcc_buffer);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
@ -241,50 +230,61 @@ static int ocl_probe(struct flash_bank *bank)
|
||||||
embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
|
||||||
dcc_buffer[0] = OCL_PROBE;
|
dcc_buffer[0] = OCL_PROBE;
|
||||||
if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* wait for response, fixed timeout of 1 s */
|
/* wait for response, fixed timeout of 1 s */
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* receive response */
|
/* receive response */
|
||||||
if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (dcc_buffer[0] != OCL_CMD_DONE)
|
if (dcc_buffer[0] != OCL_CMD_DONE) {
|
||||||
{
|
|
||||||
LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
|
LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive and fill in parameters, detection of loader is important, receive it one by one */
|
/* receive and fill in parameters, detection of loader is important, receive it one by one */
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|
||||||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
bank->base = dcc_buffer[0];
|
bank->base = dcc_buffer[0];
|
||||||
|
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|
||||||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
bank->size = dcc_buffer[0];
|
bank->size = dcc_buffer[0];
|
||||||
|
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|
||||||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
bank->num_sectors = dcc_buffer[0];
|
bank->num_sectors = dcc_buffer[0];
|
||||||
|
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
|
retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
|
||||||
|| (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
ocl->buflen = dcc_buffer[0] & 0xffff;
|
ocl->buflen = dcc_buffer[0] & 0xffff;
|
||||||
ocl->bufalign = dcc_buffer[0] >> 16;
|
ocl->bufalign = dcc_buffer[0] >> 16;
|
||||||
|
|
||||||
bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
|
bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
|
||||||
if (bank->num_sectors == 0)
|
if (bank->num_sectors == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("number of sectors shall be non zero value");
|
LOG_ERROR("number of sectors shall be non zero value");
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -293,8 +293,7 @@ static int ocl_probe(struct flash_bank *bank)
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
sectsize = bank->size / bank->num_sectors;
|
sectsize = bank->size / bank->num_sectors;
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = i * sectsize;
|
bank->sectors[i].offset = i * sectsize;
|
||||||
bank->sectors[i].size = sectsize;
|
bank->sectors[i].size = sectsize;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
|
@ -304,20 +303,17 @@ static int ocl_probe(struct flash_bank *bank)
|
||||||
if (ocl->bufalign == 0)
|
if (ocl->bufalign == 0)
|
||||||
ocl->bufalign = 1;
|
ocl->bufalign = 1;
|
||||||
|
|
||||||
if (ocl->buflen == 0)
|
if (ocl->buflen == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("buflen shall be non zero value");
|
LOG_ERROR("buflen shall be non zero value");
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign))
|
if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) {
|
||||||
{
|
|
||||||
LOG_ERROR("buflen is not multiple of bufalign");
|
LOG_ERROR("buflen is not multiple of bufalign");
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ocl->buflen % 4)
|
if (ocl->buflen % 4) {
|
||||||
{
|
|
||||||
LOG_ERROR("buflen shall be divisible by 4");
|
LOG_ERROR("buflen shall be divisible by 4");
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef OCL_H
|
#ifndef OCL_H
|
||||||
#define OCL_H
|
#define OCL_H
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -90,8 +91,7 @@
|
||||||
#define NVMKEY1 0xAA996655
|
#define NVMKEY1 0xAA996655
|
||||||
#define NVMKEY2 0x556699AA
|
#define NVMKEY2 0x556699AA
|
||||||
|
|
||||||
struct pic32mx_flash_bank
|
struct pic32mx_flash_bank {
|
||||||
{
|
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
int probed;
|
int probed;
|
||||||
};
|
};
|
||||||
|
@ -171,9 +171,7 @@ FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
|
||||||
struct pic32mx_flash_bank *pic32mx_info;
|
struct pic32mx_flash_bank *pic32mx_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
|
pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
|
||||||
bank->driver_priv = pic32mx_info;
|
bank->driver_priv = pic32mx_info;
|
||||||
|
@ -199,8 +197,7 @@ static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout)
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
/* wait for busy to clear */
|
/* wait for busy to clear */
|
||||||
while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0))
|
while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("status: 0x%" PRIx32, status);
|
LOG_DEBUG("status: 0x%" PRIx32, status);
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
|
@ -240,8 +237,7 @@ static int pic32mx_protect_check(struct flash_bank *bank)
|
||||||
int s;
|
int s;
|
||||||
int num_pages;
|
int num_pages;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -250,14 +246,12 @@ static int pic32mx_protect_check(struct flash_bank *bank)
|
||||||
|
|
||||||
if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
|
if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
|
||||||
num_pages = 0xffff; /* All pages protected */
|
num_pages = 0xffff; /* All pages protected */
|
||||||
else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH)
|
else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
|
||||||
{
|
|
||||||
if (devcfg0 & (1 << 24))
|
if (devcfg0 & (1 << 24))
|
||||||
num_pages = 0; /* All pages unprotected */
|
num_pages = 0; /* All pages unprotected */
|
||||||
else
|
else
|
||||||
num_pages = 0xffff; /* All pages protected */
|
num_pages = 0xffff; /* All pages protected */
|
||||||
}
|
} else /* pgm flash */
|
||||||
else /* pgm flash */
|
|
||||||
num_pages = (~devcfg0 >> 12) & 0xff;
|
num_pages = (~devcfg0 >> 12) & 0xff;
|
||||||
|
|
||||||
for (s = 0; s < bank->num_sectors && s < num_pages; s++)
|
for (s = 0; s < bank->num_sectors && s < num_pages; s++)
|
||||||
|
@ -274,15 +268,13 @@ static int pic32mx_erase(struct flash_bank *bank, int first, int last)
|
||||||
int i;
|
int i;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first == 0) && (last == (bank->num_sectors - 1))
|
if ((first == 0) && (last == (bank->num_sectors - 1))
|
||||||
&& (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH))
|
&& (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) {
|
||||||
{
|
|
||||||
/* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
|
/* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
|
||||||
* we need to use the MTAP to perform a full erase */
|
* we need to use the MTAP to perform a full erase */
|
||||||
LOG_DEBUG("Erasing entire program flash");
|
LOG_DEBUG("Erasing entire program flash");
|
||||||
|
@ -294,8 +286,7 @@ static int pic32mx_erase(struct flash_bank *bank, int first, int last)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset));
|
target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset));
|
||||||
|
|
||||||
status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
|
status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
|
||||||
|
@ -314,8 +305,7 @@ static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -407,24 +397,20 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
/* flash write code */
|
/* flash write code */
|
||||||
if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code),
|
if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code),
|
||||||
&pic32mx_info->write_algorithm) != ERROR_OK)
|
&pic32mx_info->write_algorithm) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("no working area available, can't do block memory writes");
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((retval = target_write_buffer(target,
|
retval = target_write_buffer(target, pic32mx_info->write_algorithm->address,
|
||||||
pic32mx_info->write_algorithm->address,
|
sizeof(pic32mx_flash_write_code), (uint8_t *)pic32mx_flash_write_code);
|
||||||
sizeof(pic32mx_flash_write_code),
|
if (retval != ERROR_OK)
|
||||||
(uint8_t*)pic32mx_flash_write_code)) != ERROR_OK)
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
|
||||||
/* if we already allocated the writing code, but failed to get a
|
/* if we already allocated the writing code, but failed to get a
|
||||||
* buffer, free the algorithm */
|
* buffer, free the algorithm */
|
||||||
if (pic32mx_info->write_algorithm)
|
if (pic32mx_info->write_algorithm)
|
||||||
|
@ -442,25 +428,24 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
init_reg_param(®_params[1], "a1", 32, PARAM_OUT);
|
init_reg_param(®_params[1], "a1", 32, PARAM_OUT);
|
||||||
init_reg_param(®_params[2], "a2", 32, PARAM_OUT);
|
init_reg_param(®_params[2], "a2", 32, PARAM_OUT);
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
uint32_t thisrun_count = (count > (buffer_size / 4)) ?
|
uint32_t thisrun_count = (count > (buffer_size / 4)) ?
|
||||||
(buffer_size / 4) : count;
|
(buffer_size / 4) : count;
|
||||||
|
|
||||||
if ((retval = target_write_buffer(target, source->address,
|
retval = target_write_buffer(target, source->address,
|
||||||
thisrun_count * 4, buffer)) != ERROR_OK)
|
thisrun_count * 4, buffer);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address));
|
buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address));
|
||||||
buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address));
|
buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address));
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||||
pic32mx_info->write_algorithm->address,
|
pic32mx_info->write_algorithm->address,
|
||||||
0,
|
0, 10000, &mips32_info);
|
||||||
10000, &mips32_info)) != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("error executing pic32mx flash write algorithm");
|
LOG_ERROR("error executing pic32mx flash write algorithm");
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
|
@ -468,15 +453,13 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
status = buf_get_u32(reg_params[0].value, 0, 32);
|
status = buf_get_u32(reg_params[0].value, 0, 32);
|
||||||
|
|
||||||
if (status & NVMCON_NVMERR)
|
if (status & NVMCON_NVMERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
|
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & NVMCON_LVDERR)
|
if (status & NVMCON_LVDERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
|
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
|
@ -516,8 +499,7 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -525,53 +507,43 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32
|
LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32
|
||||||
" count: 0x%8.8" PRIx32 "", bank->base, offset, count);
|
" count: 0x%8.8" PRIx32 "", bank->base, offset, count);
|
||||||
|
|
||||||
if (offset & 0x3)
|
if (offset & 0x3) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
|
LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* multiple words (4-byte) to be programmed? */
|
/* multiple words (4-byte) to be programmed? */
|
||||||
if (words_remaining > 0)
|
if (words_remaining > 0) {
|
||||||
{
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
|
retval = pic32mx_write_block(bank, buffer, offset, words_remaining);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
{
|
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
* we use normal (slow) single dword accesses */
|
* we use normal (slow) single dword accesses */
|
||||||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
||||||
}
|
} else if (retval == ERROR_FLASH_OPERATION_FAILED) {
|
||||||
else if (retval == ERROR_FLASH_OPERATION_FAILED)
|
|
||||||
{
|
|
||||||
LOG_ERROR("flash writing failed");
|
LOG_ERROR("flash writing failed");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer += words_remaining * 4;
|
buffer += words_remaining * 4;
|
||||||
address += words_remaining * 4;
|
address += words_remaining * 4;
|
||||||
words_remaining = 0;
|
words_remaining = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (words_remaining > 0)
|
while (words_remaining > 0) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
|
memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
|
||||||
|
|
||||||
status = pic32mx_write_word(bank, address, value);
|
status = pic32mx_write_word(bank, address, value);
|
||||||
|
|
||||||
if (status & NVMCON_NVMERR)
|
if (status & NVMCON_NVMERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
|
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & NVMCON_LVDERR)
|
if (status & NVMCON_LVDERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
|
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -581,21 +553,18 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
||||||
address += 4;
|
address += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint32_t value = 0xffffffff;
|
uint32_t value = 0xffffffff;
|
||||||
memcpy(&value, buffer + bytes_written, bytes_remaining);
|
memcpy(&value, buffer + bytes_written, bytes_remaining);
|
||||||
|
|
||||||
status = pic32mx_write_word(bank, address, value);
|
status = pic32mx_write_word(bank, address, value);
|
||||||
|
|
||||||
if (status & NVMCON_NVMERR)
|
if (status & NVMCON_NVMERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
|
LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & NVMCON_LVDERR)
|
if (status & NVMCON_LVDERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
|
LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -631,8 +600,7 @@ static int pic32mx_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
page_size = 4096;
|
page_size = 4096;
|
||||||
|
|
||||||
if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH)
|
if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
|
||||||
{
|
|
||||||
/* 0x1FC00000: Boot flash size */
|
/* 0x1FC00000: Boot flash size */
|
||||||
#if 0
|
#if 0
|
||||||
/* for some reason this register returns 8k for the boot bank size
|
/* for some reason this register returns 8k for the boot bank size
|
||||||
|
@ -646,9 +614,7 @@ static int pic32mx_probe(struct flash_bank *bank)
|
||||||
/* fixed 12k boot bank - see comments above */
|
/* fixed 12k boot bank - see comments above */
|
||||||
num_pages = (12 * 1024);
|
num_pages = (12 * 1024);
|
||||||
#endif
|
#endif
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* read the flash size from the device */
|
/* read the flash size from the device */
|
||||||
if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
|
if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
|
||||||
LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
|
LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
|
||||||
|
@ -658,8 +624,7 @@ static int pic32mx_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024);
|
LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024);
|
||||||
|
|
||||||
if (bank->sectors)
|
if (bank->sectors) {
|
||||||
{
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
}
|
}
|
||||||
|
@ -670,8 +635,7 @@ static int pic32mx_probe(struct flash_bank *bank)
|
||||||
bank->num_sectors = num_pages;
|
bank->num_sectors = num_pages;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
||||||
|
|
||||||
for (i = 0; i < (int)num_pages; i++)
|
for (i = 0; i < (int)num_pages; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = i * page_size;
|
bank->sectors[i].offset = i * page_size;
|
||||||
bank->sectors[i].size = page_size;
|
bank->sectors[i].size = page_size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
|
@ -709,17 +673,15 @@ static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; pic32mx_devs[i].name != NULL; i++)
|
for (i = 0; pic32mx_devs[i].name != NULL; i++) {
|
||||||
{
|
|
||||||
if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
|
if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
|
||||||
printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
|
printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pic32mx_devs[i].name == NULL) {
|
if (pic32mx_devs[i].name == NULL)
|
||||||
printed = snprintf(buf, buf_size, "Unknown");
|
printed = snprintf(buf, buf_size, "Unknown");
|
||||||
}
|
|
||||||
|
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
@ -735,9 +697,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
|
||||||
int status, res;
|
int status, res;
|
||||||
|
|
||||||
if (CMD_ARGC != 3)
|
if (CMD_ARGC != 3)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||||
|
@ -747,8 +707,7 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (address < bank->base || address >= (bank->base + bank->size))
|
if (address < bank->base || address >= (bank->base + bank->size)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
|
command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -776,8 +735,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
|
||||||
struct mips_ejtag *ejtag_info;
|
struct mips_ejtag *ejtag_info;
|
||||||
int timeout = 10;
|
int timeout = 10;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "pic32mx unlock <bank>");
|
command_print(CMD_CTX, "pic32mx unlock <bank>");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -798,8 +756,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
|
||||||
/* first check status of device */
|
/* first check status of device */
|
||||||
mchip_cmd = MCHP_STATUS;
|
mchip_cmd = MCHP_STATUS;
|
||||||
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
|
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
|
||||||
if (mchip_cmd & (1 << 7))
|
if (mchip_cmd & (1 << 7)) {
|
||||||
{
|
|
||||||
/* device is not locked */
|
/* device is not locked */
|
||||||
command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway");
|
command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway");
|
||||||
}
|
}
|
||||||
|
@ -812,8 +769,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
|
||||||
do {
|
do {
|
||||||
mchip_cmd = MCHP_STATUS;
|
mchip_cmd = MCHP_STATUS;
|
||||||
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
|
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
|
||||||
if (timeout-- == 0)
|
if (timeout-- == 0) {
|
||||||
{
|
|
||||||
LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd);
|
LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,15 +91,14 @@
|
||||||
static void stellaris_read_clock_info(struct flash_bank *bank);
|
static void stellaris_read_clock_info(struct flash_bank *bank);
|
||||||
static int stellaris_mass_erase(struct flash_bank *bank);
|
static int stellaris_mass_erase(struct flash_bank *bank);
|
||||||
|
|
||||||
struct stellaris_flash_bank
|
struct stellaris_flash_bank {
|
||||||
{
|
|
||||||
/* chip id register */
|
/* chip id register */
|
||||||
uint32_t did0;
|
uint32_t did0;
|
||||||
uint32_t did1;
|
uint32_t did1;
|
||||||
uint32_t dc0;
|
uint32_t dc0;
|
||||||
uint32_t dc1;
|
uint32_t dc1;
|
||||||
|
|
||||||
const char * target_name;
|
const char *target_name;
|
||||||
uint8_t target_class;
|
uint8_t target_class;
|
||||||
|
|
||||||
uint32_t sramsiz;
|
uint32_t sramsiz;
|
||||||
|
@ -123,8 +122,8 @@ struct stellaris_flash_bank
|
||||||
const char *mck_desc;
|
const char *mck_desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Autogenerated by contrib/gen-stellaris-part-header.pl
|
/* Autogenerated by contrib/gen-stellaris-part-header.pl */
|
||||||
// From Stellaris Firmware Development Package revision 8049
|
/* From Stellaris Firmware Development Package revision 8049 */
|
||||||
static struct {
|
static struct {
|
||||||
uint8_t class;
|
uint8_t class;
|
||||||
uint8_t partno;
|
uint8_t partno;
|
||||||
|
@ -415,8 +414,7 @@ static struct {
|
||||||
{0xFF, 0x00, "Unknown Part"}
|
{0xFF, 0x00, "Unknown Part"}
|
||||||
};
|
};
|
||||||
|
|
||||||
static char * StellarisClassname[7] =
|
static char *StellarisClassname[7] = {
|
||||||
{
|
|
||||||
"Sandstorm",
|
"Sandstorm",
|
||||||
"Fury",
|
"Fury",
|
||||||
"Unknown",
|
"Unknown",
|
||||||
|
@ -437,9 +435,7 @@ FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
|
||||||
struct stellaris_flash_bank *stellaris_info;
|
struct stellaris_flash_bank *stellaris_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
|
stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
|
||||||
bank->base = 0x0;
|
bank->base = 0x0;
|
||||||
|
@ -503,8 +499,7 @@ static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
if (stellaris_info->num_lockbits > 0)
|
if (stellaris_info->num_lockbits > 0) {
|
||||||
{
|
|
||||||
snprintf(buf,
|
snprintf(buf,
|
||||||
buf_size,
|
buf_size,
|
||||||
"pagesize: %" PRIi32 ", pages: %d, "
|
"pagesize: %" PRIi32 ", pages: %d, "
|
||||||
|
@ -532,7 +527,7 @@ static void stellaris_set_flash_timing(struct flash_bank *bank)
|
||||||
if (stellaris_info->target_class > 1)
|
if (stellaris_info->target_class > 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOG_DEBUG("usecrl = %i",(int)(usecrl));
|
LOG_DEBUG("usecrl = %i", (int)(usecrl));
|
||||||
target_write_u32(target, SCB_BASE | USECRL, 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 = "";
|
stellaris_info->mck_desc = "";
|
||||||
|
|
||||||
switch (oscsrc)
|
switch (oscsrc) {
|
||||||
{
|
|
||||||
case 0: /* MOSC */
|
case 0: /* MOSC */
|
||||||
mainfreq = rcc_xtal[xtal];
|
mainfreq = rcc_xtal[xtal];
|
||||||
break;
|
break;
|
||||||
|
@ -670,22 +664,19 @@ static int stellaris_read_part_info(struct flash_bank *bank)
|
||||||
did0, did1, stellaris_info->dc0, stellaris_info->dc1);
|
did0, did1, stellaris_info->dc0, stellaris_info->dc1);
|
||||||
|
|
||||||
ver = did0 >> 28;
|
ver = did0 >> 28;
|
||||||
if ((ver != 0) && (ver != 1))
|
if ((ver != 0) && (ver != 1)) {
|
||||||
{
|
|
||||||
LOG_WARNING("Unknown did0 version, cannot identify target");
|
LOG_WARNING("Unknown did0 version, cannot identify target");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (did1 == 0)
|
if (did1 == 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("Cannot identify target as a Stellaris");
|
LOG_WARNING("Cannot identify target as a Stellaris");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ver = did1 >> 28;
|
ver = did1 >> 28;
|
||||||
fam = (did1 >> 24) & 0xF;
|
fam = (did1 >> 24) & 0xF;
|
||||||
if (((ver != 0) && (ver != 1)) || (fam != 0))
|
if (((ver != 0) && (ver != 1)) || (fam != 0)) {
|
||||||
{
|
|
||||||
LOG_WARNING("Unknown did1 version/family.");
|
LOG_WARNING("Unknown did1 version/family.");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -754,7 +745,7 @@ static int stellaris_read_part_info(struct flash_bank *bank)
|
||||||
stellaris_info->did1 = did1;
|
stellaris_info->did1 = did1;
|
||||||
|
|
||||||
stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
|
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->pagesize = 1024;
|
||||||
stellaris_info->pages_in_lockregion = 2;
|
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 stellaris_flash_bank *stellaris_info = bank->driver_priv;
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -833,14 +823,10 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last)
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
|
|
||||||
if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
|
if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
|
||||||
{
|
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
|
||||||
|
|
||||||
if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
|
if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
|
||||||
{
|
|
||||||
return stellaris_mass_erase(bank);
|
return stellaris_mass_erase(bank);
|
||||||
}
|
|
||||||
|
|
||||||
/* Refresh flash controller timing */
|
/* Refresh flash controller timing */
|
||||||
stellaris_read_clock_info(bank);
|
stellaris_read_clock_info(bank);
|
||||||
|
@ -854,24 +840,21 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last)
|
||||||
* it might want to process those IRQs.
|
* it might want to process those IRQs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (banknr = first; banknr <= last; banknr++)
|
for (banknr = first; banknr <= last; banknr++) {
|
||||||
{
|
|
||||||
/* Address is first word in page */
|
/* Address is first word in page */
|
||||||
target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
|
target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
|
||||||
/* Write erase command */
|
/* Write erase command */
|
||||||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
|
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
|
||||||
/* Wait until erase complete */
|
/* Wait until erase complete */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
||||||
}
|
} while (flash_fmc & FMC_ERASE);
|
||||||
while (flash_fmc & FMC_ERASE);
|
|
||||||
|
|
||||||
/* Check acess violations */
|
/* Check acess violations */
|
||||||
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
||||||
if (flash_cris & (AMASK))
|
if (flash_cris & (AMASK)) {
|
||||||
{
|
LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "",
|
||||||
LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
|
banknr, flash_cris);
|
||||||
target_write_u32(target, FLASH_CRIS, 0);
|
target_write_u32(target, FLASH_CRIS, 0);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -890,14 +873,12 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
|
||||||
struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
|
struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!set)
|
if (!set) {
|
||||||
{
|
|
||||||
LOG_ERROR("Hardware doesn't support page-level unprotect. "
|
LOG_ERROR("Hardware doesn't support page-level unprotect. "
|
||||||
"Try the 'recover' command.");
|
"Try the 'recover' command.");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
@ -909,8 +890,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
|
||||||
/* lockregions are 2 pages ... must protect [even..odd] */
|
/* lockregions are 2 pages ... must protect [even..odd] */
|
||||||
if ((first < 0) || (first & 1)
|
if ((first < 0) || (first & 1)
|
||||||
|| (last < first) || !(last & 1)
|
|| (last < first) || !(last & 1)
|
||||||
|| (last >= 2 * stellaris_info->num_lockbits))
|
|| (last >= 2 * stellaris_info->num_lockbits)) {
|
||||||
{
|
|
||||||
LOG_ERROR("Can't protect unaligned or out-of-range pages.");
|
LOG_ERROR("Can't protect unaligned or out-of-range pages.");
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* 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);
|
target_write_u32(target, SCB_BASE | FMPPE, fmppe);
|
||||||
|
|
||||||
/* Commit 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); */
|
/* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
|
||||||
|
|
||||||
/* Wait until erase complete */
|
/* Wait until erase complete */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
||||||
}
|
} while (flash_fmc & FMC_COMT);
|
||||||
while (flash_fmc & FMC_COMT);
|
|
||||||
|
|
||||||
/* Check acess violations */
|
/* Check acess violations */
|
||||||
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
||||||
if (flash_cris & (AMASK))
|
if (flash_cris & (AMASK)) {
|
||||||
{
|
|
||||||
LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
|
LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
|
||||||
target_write_u32(target, FLASH_CRIS, 0);
|
target_write_u32(target, FLASH_CRIS, 0);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
@ -980,8 +957,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
|
||||||
|
|
||||||
/* see contib/loaders/flash/stellaris.s for src */
|
/* see contib/loaders/flash/stellaris.s for src */
|
||||||
|
|
||||||
static const uint8_t stellaris_write_code[] =
|
static const uint8_t stellaris_write_code[] = {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
Call with :
|
Call with :
|
||||||
r0 = buffer address
|
r0 = buffer address
|
||||||
|
@ -995,28 +971,28 @@ static const uint8_t stellaris_write_code[] =
|
||||||
r6 = bytes written
|
r6 = bytes written
|
||||||
r7 = temp reg
|
r7 = temp reg
|
||||||
*/
|
*/
|
||||||
0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
|
0x07, 0x4B, /* ldr r3,pFLASH_CTRL_BASE */
|
||||||
0x08,0x4C, /* ldr r4,FLASHWRITECMD */
|
0x08, 0x4C, /* ldr r4,FLASHWRITECMD */
|
||||||
0x01,0x25, /* movs r5, 1 */
|
0x01, 0x25, /* movs r5, 1 */
|
||||||
0x00,0x26, /* movs r6, #0 */
|
0x00, 0x26, /* movs r6, #0 */
|
||||||
/* mainloop: */
|
/* mainloop: */
|
||||||
0x19,0x60, /* str r1, [r3, #0] */
|
0x19, 0x60, /* str r1, [r3, #0] */
|
||||||
0x87,0x59, /* ldr r7, [r0, r6] */
|
0x87, 0x59, /* ldr r7, [r0, r6] */
|
||||||
0x5F,0x60, /* str r7, [r3, #4] */
|
0x5F, 0x60, /* str r7, [r3, #4] */
|
||||||
0x9C,0x60, /* str r4, [r3, #8] */
|
0x9C, 0x60, /* str r4, [r3, #8] */
|
||||||
/* waitloop: */
|
/* waitloop: */
|
||||||
0x9F,0x68, /* ldr r7, [r3, #8] */
|
0x9F, 0x68, /* ldr r7, [r3, #8] */
|
||||||
0x2F,0x42, /* tst r7, r5 */
|
0x2F, 0x42, /* tst r7, r5 */
|
||||||
0xFC,0xD1, /* bne waitloop */
|
0xFC, 0xD1, /* bne waitloop */
|
||||||
0x04,0x31, /* adds r1, r1, #4 */
|
0x04, 0x31, /* adds r1, r1, #4 */
|
||||||
0x04,0x36, /* adds r6, r6, #4 */
|
0x04, 0x36, /* adds r6, r6, #4 */
|
||||||
0x96,0x42, /* cmp r6, r2 */
|
0x96, 0x42, /* cmp r6, r2 */
|
||||||
0xF4,0xD1, /* bne mainloop */
|
0xF4, 0xD1, /* bne mainloop */
|
||||||
0x00,0xBE, /* bkpt #0 */
|
0x00, 0xBE, /* bkpt #0 */
|
||||||
/* pFLASH_CTRL_BASE: */
|
/* pFLASH_CTRL_BASE: */
|
||||||
0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
|
0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
|
||||||
/* FLASHWRITECMD: */
|
/* FLASHWRITECMD: */
|
||||||
0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
|
0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int stellaris_write_block(struct flash_bank *bank,
|
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);
|
bank, buffer, offset, wcount);
|
||||||
|
|
||||||
/* flash write code */
|
/* flash write code */
|
||||||
if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
|
if (target_alloc_working_area(target, sizeof(stellaris_write_code),
|
||||||
{
|
&write_algorithm) != ERROR_OK) {
|
||||||
LOG_DEBUG("no working area for block memory writes");
|
LOG_DEBUG("no working area for block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
};
|
||||||
|
@ -1053,11 +1029,9 @@ static int stellaris_write_block(struct flash_bank *bank,
|
||||||
buffer_size = wcount * 4;
|
buffer_size = wcount * 4;
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= buf_min)
|
if (buffer_size <= buf_min) {
|
||||||
{
|
|
||||||
target_free_working_area(target, write_algorithm);
|
target_free_working_area(target, write_algorithm);
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
@ -1076,8 +1050,7 @@ static int stellaris_write_block(struct flash_bank *bank,
|
||||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
||||||
init_reg_param(®_params[2], "r2", 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;
|
uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
|
||||||
|
|
||||||
target_write_buffer(target, source->address, thisrun_count * 4, buffer);
|
target_write_buffer(target, source->address, thisrun_count * 4, buffer);
|
||||||
|
@ -1093,8 +1066,7 @@ static int stellaris_write_block(struct flash_bank *bank,
|
||||||
write_algorithm->address,
|
write_algorithm->address,
|
||||||
0,
|
0,
|
||||||
10000, &armv7m_info);
|
10000, &armv7m_info);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("error %d executing stellaris "
|
LOG_ERROR("error %d executing stellaris "
|
||||||
"flash write algorithm",
|
"flash write algorithm",
|
||||||
retval);
|
retval);
|
||||||
|
@ -1121,7 +1093,8 @@ static int stellaris_write_block(struct flash_bank *bank,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
static int stellaris_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
uint32_t offset, uint32_t count)
|
||||||
{
|
{
|
||||||
struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
|
struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
@ -1132,8 +1105,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
|
||||||
uint32_t bytes_written = 0;
|
uint32_t bytes_written = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1144,8 +1116,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
|
||||||
if (stellaris_info->did1 == 0)
|
if (stellaris_info->did1 == 0)
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
|
|
||||||
if (offset & 0x3)
|
if (offset & 0x3) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset size must be word aligned");
|
LOG_WARNING("offset size must be word aligned");
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
@ -1166,36 +1137,28 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* multiple words to be programmed? */
|
/* multiple words to be programmed? */
|
||||||
if (words_remaining > 0)
|
if (words_remaining > 0) {
|
||||||
{
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
retval = stellaris_write_block(bank, buffer, offset,
|
retval = stellaris_write_block(bank, buffer, offset,
|
||||||
words_remaining);
|
words_remaining);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("writing flash word-at-a-time");
|
LOG_DEBUG("writing flash word-at-a-time");
|
||||||
}
|
} else if (retval == ERROR_FLASH_OPERATION_FAILED) {
|
||||||
else if (retval == ERROR_FLASH_OPERATION_FAILED)
|
|
||||||
{
|
|
||||||
/* if an error occured, we examine the reason, and quit */
|
/* if an error occured, we examine the reason, and quit */
|
||||||
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
||||||
|
|
||||||
LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
|
LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer += words_remaining * 4;
|
buffer += words_remaining * 4;
|
||||||
address += words_remaining * 4;
|
address += words_remaining * 4;
|
||||||
words_remaining = 0;
|
words_remaining = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (words_remaining > 0)
|
while (words_remaining > 0) {
|
||||||
{
|
|
||||||
if (!(address & 0xff))
|
if (!(address & 0xff))
|
||||||
LOG_DEBUG("0x%" PRIx32 "", address);
|
LOG_DEBUG("0x%" PRIx32 "", address);
|
||||||
|
|
||||||
|
@ -1205,8 +1168,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
|
||||||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
|
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
|
||||||
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
|
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
|
||||||
/* Wait until write complete */
|
/* Wait until write complete */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
||||||
} while (flash_fmc & FMC_WRITE);
|
} while (flash_fmc & FMC_WRITE);
|
||||||
|
|
||||||
|
@ -1215,8 +1177,7 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
|
||||||
words_remaining--;
|
words_remaining--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
|
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
/* copy the last remaining bytes into the write buffer */
|
/* copy the last remaining bytes into the write buffer */
|
||||||
|
@ -1231,16 +1192,14 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of
|
||||||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
|
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
|
||||||
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
|
/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
|
||||||
/* Wait until write complete */
|
/* Wait until write complete */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
||||||
} while (flash_fmc & FMC_WRITE);
|
} while (flash_fmc & FMC_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check access violations */
|
/* Check access violations */
|
||||||
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
target_read_u32(target, FLASH_CRIS, &flash_cris);
|
||||||
if (flash_cris & (AMASK))
|
if (flash_cris & (AMASK)) {
|
||||||
{
|
|
||||||
LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
|
LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -1266,8 +1225,7 @@ static int stellaris_probe(struct flash_bank *bank)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (bank->sectors)
|
if (bank->sectors) {
|
||||||
{
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1276,8 +1234,7 @@ static int stellaris_probe(struct flash_bank *bank)
|
||||||
bank->size = 1024 * stellaris_info->num_pages;
|
bank->size = 1024 * stellaris_info->num_pages;
|
||||||
bank->num_sectors = stellaris_info->num_pages;
|
bank->num_sectors = stellaris_info->num_pages;
|
||||||
bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
|
bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
|
||||||
for (int i = 0; i < bank->num_sectors; i++)
|
for (int i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = i * stellaris_info->pagesize;
|
bank->sectors[i].offset = i * stellaris_info->pagesize;
|
||||||
bank->sectors[i].size = stellaris_info->pagesize;
|
bank->sectors[i].size = stellaris_info->pagesize;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
|
@ -1296,8 +1253,7 @@ static int stellaris_mass_erase(struct flash_bank *bank)
|
||||||
stellaris_info = bank->driver_priv;
|
stellaris_info = bank->driver_priv;
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1320,24 +1276,19 @@ static int stellaris_mass_erase(struct flash_bank *bank)
|
||||||
target_write_u32(target, FLASH_FMA, 0);
|
target_write_u32(target, FLASH_FMA, 0);
|
||||||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
|
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
|
||||||
/* Wait until erase complete */
|
/* Wait until erase complete */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
||||||
}
|
} while (flash_fmc & FMC_MERASE);
|
||||||
while (flash_fmc & FMC_MERASE);
|
|
||||||
|
|
||||||
/* if device has > 128k, then second erase cycle is needed
|
/* if device has > 128k, then second erase cycle is needed
|
||||||
* this is only valid for older devices, but will not hurt */
|
* this is only valid for older devices, but will not hurt */
|
||||||
if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
|
if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) {
|
||||||
{
|
|
||||||
target_write_u32(target, FLASH_FMA, 0x20000);
|
target_write_u32(target, FLASH_FMA, 0x20000);
|
||||||
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
|
target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
|
||||||
/* Wait until erase complete */
|
/* Wait until erase complete */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
target_read_u32(target, FLASH_FMC, &flash_fmc);
|
||||||
}
|
} while (flash_fmc & FMC_MERASE);
|
||||||
while (flash_fmc & FMC_MERASE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -1348,29 +1299,21 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (stellaris_mass_erase(bank) == ERROR_OK)
|
if (stellaris_mass_erase(bank) == ERROR_OK) {
|
||||||
{
|
|
||||||
/* set all sectors as erased */
|
/* set all sectors as erased */
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++)
|
||||||
{
|
|
||||||
bank->sectors[i].is_erased = 1;
|
bank->sectors[i].is_erased = 1;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "stellaris mass erase complete");
|
command_print(CMD_CTX, "stellaris mass erase complete");
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stellaris mass erase failed");
|
command_print(CMD_CTX, "stellaris mass erase failed");
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,15 +102,13 @@
|
||||||
#define KEY1 0x45670123
|
#define KEY1 0x45670123
|
||||||
#define KEY2 0xCDEF89AB
|
#define KEY2 0xCDEF89AB
|
||||||
|
|
||||||
struct stm32x_options
|
struct stm32x_options {
|
||||||
{
|
|
||||||
uint16_t RDP;
|
uint16_t RDP;
|
||||||
uint16_t user_options;
|
uint16_t user_options;
|
||||||
uint16_t protection[4];
|
uint16_t protection[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32x_flash_bank
|
struct stm32x_flash_bank {
|
||||||
{
|
|
||||||
struct stm32x_options option_bytes;
|
struct stm32x_options option_bytes;
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
int ppage_size;
|
int ppage_size;
|
||||||
|
@ -129,9 +128,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
|
||||||
struct stm32x_flash_bank *stm32x_info;
|
struct stm32x_flash_bank *stm32x_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
|
stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
|
||||||
bank->driver_priv = stm32x_info;
|
bank->driver_priv = stm32x_info;
|
||||||
|
@ -163,37 +160,32 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
/* wait for busy to clear */
|
/* wait for busy to clear */
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
retval = stm32x_get_flash_status(bank, &status);
|
retval = stm32x_get_flash_status(bank, &status);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||||
if ((status & FLASH_BSY) == 0)
|
if ((status & FLASH_BSY) == 0)
|
||||||
break;
|
break;
|
||||||
if (timeout-- <= 0)
|
if (timeout-- <= 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("timed out waiting for flash");
|
LOG_ERROR("timed out waiting for flash");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & FLASH_WRPRTERR)
|
if (status & FLASH_WRPRTERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("stm32x device protected");
|
LOG_ERROR("stm32x device protected");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & FLASH_PGERR)
|
if (status & FLASH_PGERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("stm32x device programming failed");
|
LOG_ERROR("stm32x device programming failed");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
if (status & (FLASH_WRPRTERR | FLASH_PGERR))
|
if (status & (FLASH_WRPRTERR | FLASH_PGERR)) {
|
||||||
{
|
|
||||||
/* If this operation fails, we ignore it and report the original
|
/* If this operation fails, we ignore it and report the original
|
||||||
* retval
|
* retval
|
||||||
*/
|
*/
|
||||||
|
@ -209,8 +201,7 @@ int stm32x_check_operation_supported(struct flash_bank *bank)
|
||||||
|
|
||||||
/* if we have a dual flash bank device then
|
/* if we have a dual flash bank device then
|
||||||
* we need to perform option byte stuff on bank0 only */
|
* we need to perform option byte stuff on bank0 only */
|
||||||
if (stm32x_info->register_base != FLASH_REG_BASE_B0)
|
if (stm32x_info->register_base != FLASH_REG_BASE_B0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Option Byte Operation's must use bank0");
|
LOG_ERROR("Option Byte Operation's must use bank0");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -395,8 +386,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
|
||||||
int num_bits;
|
int num_bits;
|
||||||
int set;
|
int set;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -415,8 +405,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
|
||||||
* high density - each protection bit is for 2 * 2K pages */
|
* high density - each protection bit is for 2 * 2K pages */
|
||||||
num_bits = (bank->num_sectors / stm32x_info->ppage_size);
|
num_bits = (bank->num_sectors / stm32x_info->ppage_size);
|
||||||
|
|
||||||
if (stm32x_info->ppage_size == 2)
|
if (stm32x_info->ppage_size == 2) {
|
||||||
{
|
|
||||||
/* high density flash/connectivity line protection */
|
/* high density flash/connectivity line protection */
|
||||||
|
|
||||||
set = 1;
|
set = 1;
|
||||||
|
@ -427,15 +416,12 @@ static int stm32x_protect_check(struct flash_bank *bank)
|
||||||
/* bit 31 controls sector 62 - 255 protection for high density
|
/* bit 31 controls sector 62 - 255 protection for high density
|
||||||
* bit 31 controls sector 62 - 127 protection for connectivity line */
|
* bit 31 controls sector 62 - 127 protection for connectivity line */
|
||||||
for (s = 62; s < bank->num_sectors; s++)
|
for (s = 62; s < bank->num_sectors; s++)
|
||||||
{
|
|
||||||
bank->sectors[s].is_protected = set;
|
bank->sectors[s].is_protected = set;
|
||||||
}
|
|
||||||
|
|
||||||
if (bank->num_sectors > 61)
|
if (bank->num_sectors > 61)
|
||||||
num_bits = 31;
|
num_bits = 31;
|
||||||
|
|
||||||
for (i = 0; i < num_bits; i++)
|
for (i = 0; i < num_bits; i++) {
|
||||||
{
|
|
||||||
set = 1;
|
set = 1;
|
||||||
|
|
||||||
if (protection & (1 << i))
|
if (protection & (1 << i))
|
||||||
|
@ -444,12 +430,9 @@ static int stm32x_protect_check(struct flash_bank *bank)
|
||||||
for (s = 0; s < stm32x_info->ppage_size; s++)
|
for (s = 0; s < stm32x_info->ppage_size; s++)
|
||||||
bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
|
bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* low/medium density flash protection */
|
/* low/medium density flash protection */
|
||||||
for (i = 0; i < num_bits; i++)
|
for (i = 0; i < num_bits; i++) {
|
||||||
{
|
|
||||||
set = 1;
|
set = 1;
|
||||||
|
|
||||||
if (protection & (1 << i))
|
if (protection & (1 << i))
|
||||||
|
@ -468,16 +451,13 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first == 0) && (last == (bank->num_sectors - 1)))
|
if ((first == 0) && (last == (bank->num_sectors - 1)))
|
||||||
{
|
|
||||||
return stm32x_mass_erase(bank);
|
return stm32x_mass_erase(bank);
|
||||||
}
|
|
||||||
|
|
||||||
/* unlock flash registers */
|
/* unlock flash registers */
|
||||||
int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
|
int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
|
||||||
|
@ -487,8 +467,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
|
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -526,8 +505,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
|
|
||||||
stm32x_info = bank->driver_priv;
|
stm32x_info = bank->driver_priv;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -536,14 +514,12 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if ((first % stm32x_info->ppage_size) != 0)
|
if ((first % stm32x_info->ppage_size) != 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("aligned start protect sector to a %d sector boundary",
|
LOG_WARNING("aligned start protect sector to a %d sector boundary",
|
||||||
stm32x_info->ppage_size);
|
stm32x_info->ppage_size);
|
||||||
first = first - (first % stm32x_info->ppage_size);
|
first = first - (first % stm32x_info->ppage_size);
|
||||||
}
|
}
|
||||||
if (((last + 1) % stm32x_info->ppage_size) != 0)
|
if (((last + 1) % stm32x_info->ppage_size) != 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("aligned end protect sector to a %d sector boundary",
|
LOG_WARNING("aligned end protect sector to a %d sector boundary",
|
||||||
stm32x_info->ppage_size);
|
stm32x_info->ppage_size);
|
||||||
last++;
|
last++;
|
||||||
|
@ -562,13 +538,11 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
prot_reg[2] = (uint16_t)(protection >> 16);
|
prot_reg[2] = (uint16_t)(protection >> 16);
|
||||||
prot_reg[3] = (uint16_t)(protection >> 24);
|
prot_reg[3] = (uint16_t)(protection >> 24);
|
||||||
|
|
||||||
if (stm32x_info->ppage_size == 2)
|
if (stm32x_info->ppage_size == 2) {
|
||||||
{
|
|
||||||
/* high density flash */
|
/* high density flash */
|
||||||
|
|
||||||
/* bit 7 controls sector 62 - 255 protection */
|
/* bit 7 controls sector 62 - 255 protection */
|
||||||
if (last > 61)
|
if (last > 61) {
|
||||||
{
|
|
||||||
if (set)
|
if (set)
|
||||||
prot_reg[3] &= ~(1 << 7);
|
prot_reg[3] &= ~(1 << 7);
|
||||||
else
|
else
|
||||||
|
@ -580,8 +554,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
if (last > 61)
|
if (last > 61)
|
||||||
last = 61;
|
last = 61;
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
reg = (i / stm32x_info->ppage_size) / 8;
|
reg = (i / stm32x_info->ppage_size) / 8;
|
||||||
bit = (i / stm32x_info->ppage_size) - (reg * 8);
|
bit = (i / stm32x_info->ppage_size) - (reg * 8);
|
||||||
|
|
||||||
|
@ -590,12 +563,9 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
else
|
else
|
||||||
prot_reg[reg] |= (1 << bit);
|
prot_reg[reg] |= (1 << bit);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* medium density flash */
|
/* medium density flash */
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
reg = (i / stm32x_info->ppage_size) / 8;
|
reg = (i / stm32x_info->ppage_size) / 8;
|
||||||
bit = (i / stm32x_info->ppage_size) - (reg * 8);
|
bit = (i / stm32x_info->ppage_size) - (reg * 8);
|
||||||
|
|
||||||
|
@ -606,7 +576,8 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status = stm32x_erase_options(bank)) != ERROR_OK)
|
status = stm32x_erase_options(bank);
|
||||||
|
if (status != ERROR_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
stm32x_info->option_bytes.protection[0] = prot_reg[0];
|
stm32x_info->option_bytes.protection[0] = prot_reg[0];
|
||||||
|
@ -675,24 +646,21 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
/* flash write code */
|
/* flash write code */
|
||||||
if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
|
if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
|
||||||
&stm32x_info->write_algorithm) != ERROR_OK)
|
&stm32x_info->write_algorithm) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("no working area available, can't do block memory writes");
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
|
retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
|
||||||
sizeof(stm32x_flash_write_code),
|
sizeof(stm32x_flash_write_code), (uint8_t *)stm32x_flash_write_code);
|
||||||
(uint8_t*)stm32x_flash_write_code)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
buffer_size &= ~3UL; // Make sure it's 4 byte aligned
|
buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
|
||||||
/* if we already allocated the writing code, but failed to get a
|
/* if we already allocated the writing code, but failed to get a
|
||||||
* buffer, free the algorithm */
|
* buffer, free the algorithm */
|
||||||
if (stm32x_info->write_algorithm)
|
if (stm32x_info->write_algorithm)
|
||||||
|
@ -736,35 +704,31 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
||||||
|
|
||||||
/* Start up algorithm on target and let it idle while writing the first chunk */
|
/* Start up algorithm on target and let it idle while writing the first chunk */
|
||||||
if ((retval = target_start_algorithm(target, 0, NULL, 5, reg_params,
|
retval = target_start_algorithm(target, 0, NULL, 5, reg_params,
|
||||||
stm32x_info->write_algorithm->address,
|
stm32x_info->write_algorithm->address,
|
||||||
0,
|
0,
|
||||||
&armv7m_info)) != ERROR_OK)
|
&armv7m_info);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("error starting stm32x flash write algorithm");
|
LOG_ERROR("error starting stm32x flash write algorithm");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
retval = target_read_u32(target, rp_addr, &rp);
|
retval = target_read_u32(target, rp_addr, &rp);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("failed to get read pointer");
|
LOG_ERROR("failed to get read pointer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("count 0x%"PRIx32" wp 0x%"PRIx32" rp 0x%"PRIx32, count, wp, rp);
|
LOG_DEBUG("count 0x%"PRIx32" wp 0x%"PRIx32" rp 0x%"PRIx32, count, wp, rp);
|
||||||
|
|
||||||
if (rp == 0)
|
if (rp == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("flash write algorithm aborted by target");
|
LOG_ERROR("flash write algorithm aborted by target");
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rp & 1) || rp < fifo_start_addr || rp >= fifo_end_addr)
|
if ((rp & 1) || rp < fifo_start_addr || rp >= fifo_end_addr) {
|
||||||
{
|
|
||||||
LOG_ERROR("corrupted fifo read pointer 0x%"PRIx32, rp);
|
LOG_ERROR("corrupted fifo read pointer 0x%"PRIx32, rp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -780,8 +744,7 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
else
|
else
|
||||||
thisrun_bytes = fifo_end_addr - wp - 2;
|
thisrun_bytes = fifo_end_addr - wp - 2;
|
||||||
|
|
||||||
if (thisrun_bytes == 0)
|
if (thisrun_bytes == 0) {
|
||||||
{
|
|
||||||
/* Throttle polling a bit if transfer is (much) faster than flash
|
/* Throttle polling a bit if transfer is (much) faster than flash
|
||||||
* programming. The exact delay shouldn't matter as long as it's
|
* programming. The exact delay shouldn't matter as long as it's
|
||||||
* less than buffer size / flash speed. This is very unlikely to
|
* less than buffer size / flash speed. This is very unlikely to
|
||||||
|
@ -812,36 +775,29 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
/* abort flash write algorithm on target */
|
/* abort flash write algorithm on target */
|
||||||
target_write_u32(target, wp_addr, 0);
|
target_write_u32(target, wp_addr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int retval2;
|
int retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params,
|
||||||
if ((retval2 = target_wait_algorithm(target, 0, NULL, 5, reg_params,
|
0, 10000, &armv7m_info);
|
||||||
0,
|
if (retval2 != ERROR_OK) {
|
||||||
10000,
|
|
||||||
&armv7m_info)) != ERROR_OK)
|
|
||||||
{
|
|
||||||
LOG_ERROR("error waiting for stm32x flash write algorithm");
|
LOG_ERROR("error waiting for stm32x flash write algorithm");
|
||||||
retval = retval2;
|
retval = retval2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval == ERROR_FLASH_OPERATION_FAILED)
|
if (retval == ERROR_FLASH_OPERATION_FAILED) {
|
||||||
{
|
|
||||||
LOG_ERROR("flash write failed at address 0x%"PRIx32,
|
LOG_ERROR("flash write failed at address 0x%"PRIx32,
|
||||||
buf_get_u32(reg_params[4].value, 0, 32));
|
buf_get_u32(reg_params[4].value, 0, 32));
|
||||||
|
|
||||||
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR)
|
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("flash memory not erased before writing");
|
LOG_ERROR("flash memory not erased before writing");
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_PGERR);
|
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_PGERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR)
|
if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("flash memory write protected");
|
LOG_ERROR("flash memory write protected");
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_WRPRTERR);
|
target_write_u32(target, STM32_FLASH_SR_B0, FLASH_WRPRTERR);
|
||||||
|
@ -871,14 +827,12 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
uint32_t bytes_written = 0;
|
uint32_t bytes_written = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset & 0x1)
|
if (offset & 0x1) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
@ -892,20 +846,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* multiple half words (2-byte) to be programmed? */
|
/* multiple half words (2-byte) to be programmed? */
|
||||||
if (words_remaining > 0)
|
if (words_remaining > 0) {
|
||||||
{
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
|
retval = stm32x_write_block(bank, buffer, offset, words_remaining);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
{
|
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
* we use normal (slow) single dword accesses */
|
* we use normal (slow) single dword accesses */
|
||||||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer += words_remaining * 2;
|
buffer += words_remaining * 2;
|
||||||
address += words_remaining * 2;
|
address += words_remaining * 2;
|
||||||
words_remaining = 0;
|
words_remaining = 0;
|
||||||
|
@ -915,8 +865,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
|
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
while (words_remaining > 0)
|
while (words_remaining > 0) {
|
||||||
{
|
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
|
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
|
||||||
|
|
||||||
|
@ -936,8 +885,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
address += 2;
|
address += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint16_t value = 0xffff;
|
uint16_t value = 0xffff;
|
||||||
memcpy(&value, buffer + bytes_written, bytes_remaining);
|
memcpy(&value, buffer + bytes_written, bytes_remaining);
|
||||||
|
|
||||||
|
@ -977,8 +925,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
/* get flash size from target. */
|
/* get flash size from target. */
|
||||||
retval = target_read_u16(target, 0x1FFFF7E0, &flash_size_in_kb);
|
retval = target_read_u16(target, 0x1FFFF7E0, &flash_size_in_kb);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("failed reading flash size, default to max target family");
|
LOG_WARNING("failed reading flash size, default to max target family");
|
||||||
/* failed reading flash size, default to max target family */
|
/* failed reading flash size, default to max target family */
|
||||||
flash_size_in_kb = 0xffff;
|
flash_size_in_kb = 0xffff;
|
||||||
|
@ -991,8 +938,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->ppage_size = 4;
|
stm32x_info->ppage_size = 4;
|
||||||
|
|
||||||
/* check for early silicon */
|
/* check for early silicon */
|
||||||
if (flash_size_in_kb == 0xffff)
|
if (flash_size_in_kb == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors incorrect on revA */
|
/* number of sectors incorrect on revA */
|
||||||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
|
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
|
||||||
flash_size_in_kb = 128;
|
flash_size_in_kb = 128;
|
||||||
|
@ -1004,8 +950,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->ppage_size = 4;
|
stm32x_info->ppage_size = 4;
|
||||||
|
|
||||||
/* check for early silicon */
|
/* check for early silicon */
|
||||||
if (flash_size_in_kb == 0xffff)
|
if (flash_size_in_kb == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors incorrect on revA */
|
/* number of sectors incorrect on revA */
|
||||||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash");
|
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash");
|
||||||
flash_size_in_kb = 32;
|
flash_size_in_kb = 32;
|
||||||
|
@ -1017,8 +962,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->ppage_size = 2;
|
stm32x_info->ppage_size = 2;
|
||||||
|
|
||||||
/* check for early silicon */
|
/* check for early silicon */
|
||||||
if (flash_size_in_kb == 0xffff)
|
if (flash_size_in_kb == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors incorrect on revZ */
|
/* number of sectors incorrect on revZ */
|
||||||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash");
|
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash");
|
||||||
flash_size_in_kb = 512;
|
flash_size_in_kb = 512;
|
||||||
|
@ -1030,8 +974,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->ppage_size = 2;
|
stm32x_info->ppage_size = 2;
|
||||||
|
|
||||||
/* check for early silicon */
|
/* check for early silicon */
|
||||||
if (flash_size_in_kb == 0xffff)
|
if (flash_size_in_kb == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors incorrect on revZ */
|
/* number of sectors incorrect on revZ */
|
||||||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash");
|
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash");
|
||||||
flash_size_in_kb = 256;
|
flash_size_in_kb = 256;
|
||||||
|
@ -1043,8 +986,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->ppage_size = 4;
|
stm32x_info->ppage_size = 4;
|
||||||
|
|
||||||
/* check for early silicon */
|
/* check for early silicon */
|
||||||
if (flash_size_in_kb == 0xffff)
|
if (flash_size_in_kb == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors may be incorrrect on early silicon */
|
/* number of sectors may be incorrrect on early silicon */
|
||||||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
|
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
|
||||||
flash_size_in_kb = 128;
|
flash_size_in_kb = 128;
|
||||||
|
@ -1056,8 +998,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->ppage_size = 4;
|
stm32x_info->ppage_size = 4;
|
||||||
|
|
||||||
/* check for early silicon */
|
/* check for early silicon */
|
||||||
if (flash_size_in_kb == 0xffff)
|
if (flash_size_in_kb == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors may be incorrrect on early silicon */
|
/* number of sectors may be incorrrect on early silicon */
|
||||||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
|
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
|
||||||
flash_size_in_kb = 128;
|
flash_size_in_kb = 128;
|
||||||
|
@ -1070,29 +1011,23 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->has_dual_banks = true;
|
stm32x_info->has_dual_banks = true;
|
||||||
|
|
||||||
/* check for early silicon */
|
/* check for early silicon */
|
||||||
if (flash_size_in_kb == 0xffff)
|
if (flash_size_in_kb == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors may be incorrrect on early silicon */
|
/* number of sectors may be incorrrect on early silicon */
|
||||||
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 1024k flash");
|
LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 1024k flash");
|
||||||
flash_size_in_kb = 1024;
|
flash_size_in_kb = 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* split reported size into matching bank */
|
/* split reported size into matching bank */
|
||||||
if (bank->base != 0x08080000)
|
if (bank->base != 0x08080000) {
|
||||||
{
|
|
||||||
/* bank 0 will be fixed 512k */
|
/* bank 0 will be fixed 512k */
|
||||||
flash_size_in_kb = 512;
|
flash_size_in_kb = 512;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
flash_size_in_kb -= 512;
|
flash_size_in_kb -= 512;
|
||||||
/* bank1 also uses a register offset */
|
/* bank1 also uses a register offset */
|
||||||
stm32x_info->register_base = FLASH_REG_BASE_B1;
|
stm32x_info->register_base = FLASH_REG_BASE_B1;
|
||||||
base_address = 0x08080000;
|
base_address = 0x08080000;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_WARNING("Cannot identify target as a STM32 family.");
|
LOG_WARNING("Cannot identify target as a STM32 family.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -1108,8 +1043,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
/* check that calculation result makes sense */
|
/* check that calculation result makes sense */
|
||||||
assert(num_pages > 0);
|
assert(num_pages > 0);
|
||||||
|
|
||||||
if (bank->sectors)
|
if (bank->sectors) {
|
||||||
{
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1119,8 +1053,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
bank->num_sectors = num_pages;
|
bank->num_sectors = num_pages;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
||||||
|
|
||||||
for (i = 0; i < num_pages; i++)
|
for (i = 0; i < num_pages; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = i * page_size;
|
bank->sectors[i].offset = i * page_size;
|
||||||
bank->sectors[i].size = page_size;
|
bank->sectors[i].size = page_size;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
|
@ -1163,8 +1096,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x0000:
|
case 0x0000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -1190,8 +1122,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x1000:
|
case 0x1000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -1205,8 +1136,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x1000:
|
case 0x1000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -1224,8 +1154,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x1000:
|
case 0x1000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -1243,8 +1172,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x1000:
|
case 0x1000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -1262,8 +1190,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x1000:
|
case 0x1000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -1281,8 +1208,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x1000:
|
case 0x1000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -1291,9 +1217,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
snprintf(buf, buf_size, "unknown");
|
snprintf(buf, buf_size, "unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(buf, buf_size, "Cannot identify target as a stm32x\n");
|
snprintf(buf, buf_size, "Cannot identify target as a stm32x\n");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -1307,9 +1231,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
|
||||||
struct stm32x_flash_bank *stm32x_info = NULL;
|
struct stm32x_flash_bank *stm32x_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1320,8 +1242,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1330,8 +1251,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (stm32x_erase_options(bank) != ERROR_OK)
|
if (stm32x_erase_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stm32x failed to erase options");
|
command_print(CMD_CTX, "stm32x failed to erase options");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1339,8 +1259,7 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
|
||||||
/* set readout protection */
|
/* set readout protection */
|
||||||
stm32x_info->option_bytes.RDP = 0;
|
stm32x_info->option_bytes.RDP = 0;
|
||||||
|
|
||||||
if (stm32x_write_options(bank) != ERROR_OK)
|
if (stm32x_write_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stm32x failed to lock device");
|
command_print(CMD_CTX, "stm32x failed to lock device");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1355,9 +1274,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
||||||
struct target *target = NULL;
|
struct target *target = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1366,8 +1283,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1376,14 +1292,12 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (stm32x_erase_options(bank) != ERROR_OK)
|
if (stm32x_erase_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stm32x failed to unlock device");
|
command_print(CMD_CTX, "stm32x failed to unlock device");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm32x_write_options(bank) != ERROR_OK)
|
if (stm32x_write_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stm32x failed to lock device");
|
command_print(CMD_CTX, "stm32x failed to lock device");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1402,9 +1316,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
|
||||||
struct stm32x_flash_bank *stm32x_info = NULL;
|
struct stm32x_flash_bank *stm32x_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1415,8 +1327,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1430,32 +1341,31 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
|
||||||
return retval;
|
return retval;
|
||||||
command_print(CMD_CTX, "Option Byte: 0x%" PRIx32 "", optionbyte);
|
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");
|
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");
|
command_print(CMD_CTX, "Readout Protection On");
|
||||||
else
|
else
|
||||||
command_print(CMD_CTX, "Readout Protection Off");
|
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");
|
command_print(CMD_CTX, "Software Watchdog");
|
||||||
else
|
else
|
||||||
command_print(CMD_CTX, "Hardware Watchdog");
|
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");
|
command_print(CMD_CTX, "Stop: No reset generated");
|
||||||
else
|
else
|
||||||
command_print(CMD_CTX, "Stop: Reset generated");
|
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");
|
command_print(CMD_CTX, "Standby: No reset generated");
|
||||||
else
|
else
|
||||||
command_print(CMD_CTX, "Standby: Reset generated");
|
command_print(CMD_CTX, "Standby: Reset generated");
|
||||||
|
|
||||||
if (stm32x_info->has_dual_banks)
|
if (stm32x_info->has_dual_banks) {
|
||||||
{
|
if (buf_get_u32((uint8_t *)&optionbyte, OPT_BFB2, 1))
|
||||||
if (buf_get_u32((uint8_t*)&optionbyte, OPT_BFB2, 1))
|
|
||||||
command_print(CMD_CTX, "Boot: Bank 0");
|
command_print(CMD_CTX, "Boot: Bank 0");
|
||||||
else
|
else
|
||||||
command_print(CMD_CTX, "Boot: Bank 1");
|
command_print(CMD_CTX, "Boot: Bank 1");
|
||||||
|
@ -1471,9 +1381,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
|
||||||
uint16_t optionbyte = 0xF8;
|
uint16_t optionbyte = 0xF8;
|
||||||
|
|
||||||
if (CMD_ARGC < 4)
|
if (CMD_ARGC < 4)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1484,8 +1392,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1500,57 +1407,38 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
|
||||||
|
|
||||||
/* OPT_RDWDGSW */
|
/* OPT_RDWDGSW */
|
||||||
if (strcmp(CMD_ARGV[1], "SWWDG") == 0)
|
if (strcmp(CMD_ARGV[1], "SWWDG") == 0)
|
||||||
{
|
|
||||||
optionbyte |= (1 << 0);
|
optionbyte |= (1 << 0);
|
||||||
}
|
|
||||||
else /* REVISIT must be "HWWDG" then ... */
|
else /* REVISIT must be "HWWDG" then ... */
|
||||||
{
|
|
||||||
optionbyte &= ~(1 << 0);
|
optionbyte &= ~(1 << 0);
|
||||||
}
|
|
||||||
|
|
||||||
/* OPT_RDRSTSTOP */
|
/* OPT_RDRSTSTOP */
|
||||||
if (strcmp(CMD_ARGV[2], "NORSTSTOP") == 0)
|
if (strcmp(CMD_ARGV[2], "NORSTSTOP") == 0)
|
||||||
{
|
|
||||||
optionbyte |= (1 << 1);
|
optionbyte |= (1 << 1);
|
||||||
}
|
|
||||||
else /* REVISIT must be "RSTSTNDBY" then ... */
|
else /* REVISIT must be "RSTSTNDBY" then ... */
|
||||||
{
|
|
||||||
optionbyte &= ~(1 << 1);
|
optionbyte &= ~(1 << 1);
|
||||||
}
|
|
||||||
|
|
||||||
/* OPT_RDRSTSTDBY */
|
/* OPT_RDRSTSTDBY */
|
||||||
if (strcmp(CMD_ARGV[3], "NORSTSTNDBY") == 0)
|
if (strcmp(CMD_ARGV[3], "NORSTSTNDBY") == 0)
|
||||||
{
|
|
||||||
optionbyte |= (1 << 2);
|
optionbyte |= (1 << 2);
|
||||||
}
|
|
||||||
else /* REVISIT must be "RSTSTOP" then ... */
|
else /* REVISIT must be "RSTSTOP" then ... */
|
||||||
{
|
|
||||||
optionbyte &= ~(1 << 2);
|
optionbyte &= ~(1 << 2);
|
||||||
}
|
|
||||||
|
|
||||||
if (CMD_ARGC > 4 && stm32x_info->has_dual_banks)
|
if (CMD_ARGC > 4 && stm32x_info->has_dual_banks) {
|
||||||
{
|
|
||||||
/* OPT_BFB2 */
|
/* OPT_BFB2 */
|
||||||
if (strcmp(CMD_ARGV[4], "BOOT0") == 0)
|
if (strcmp(CMD_ARGV[4], "BOOT0") == 0)
|
||||||
{
|
|
||||||
optionbyte |= (1 << 3);
|
optionbyte |= (1 << 3);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
optionbyte &= ~(1 << 3);
|
optionbyte &= ~(1 << 3);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (stm32x_erase_options(bank) != ERROR_OK)
|
if (stm32x_erase_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stm32x failed to erase options");
|
command_print(CMD_CTX, "stm32x failed to erase options");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32x_info->option_bytes.user_options = optionbyte;
|
stm32x_info->option_bytes.user_options = optionbyte;
|
||||||
|
|
||||||
if (stm32x_write_options(bank) != ERROR_OK)
|
if (stm32x_write_options(bank) != ERROR_OK) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stm32x failed to write options");
|
command_print(CMD_CTX, "stm32x failed to write options");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1566,8 +1454,7 @@ static int stm32x_mass_erase(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1584,7 +1471,8 @@ static int stm32x_mass_erase(struct flash_bank *bank)
|
||||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER);
|
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER | FLASH_STRT);
|
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
|
||||||
|
FLASH_MER | FLASH_STRT);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
@ -1604,9 +1492,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1614,20 +1500,14 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = stm32x_mass_erase(bank);
|
retval = stm32x_mass_erase(bank);
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK) {
|
||||||
{
|
|
||||||
/* set all sectors as erased */
|
/* set all sectors as erased */
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++)
|
||||||
{
|
|
||||||
bank->sectors[i].is_erased = 1;
|
bank->sectors[i].is_erased = 1;
|
||||||
}
|
|
||||||
|
|
||||||
command_print(CMD_CTX, "stm32x mass erase complete");
|
command_print(CMD_CTX, "stm32x mass erase complete");
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "stm32x mass erase failed");
|
command_print(CMD_CTX, "stm32x mass erase failed");
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,7 +71,8 @@
|
||||||
* http://www.st.com/internet/mcu/product/250192.jsp
|
* http://www.st.com/internet/mcu/product/250192.jsp
|
||||||
*
|
*
|
||||||
* PM0059
|
* PM0059
|
||||||
* www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/PROGRAMMING_MANUAL/CD00233952.pdf
|
* www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/
|
||||||
|
* PROGRAMMING_MANUAL/CD00233952.pdf
|
||||||
*
|
*
|
||||||
* STM32F1x series - notice that this code was copy, pasted and knocked
|
* STM32F1x series - notice that this code was copy, pasted and knocked
|
||||||
* into a stm32f2x driver, so in case something has been converted or
|
* into a stm32f2x driver, so in case something has been converted or
|
||||||
|
@ -85,11 +87,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Erase time can be as high as 1000ms, 10x this and it's toast...
|
/* Erase time can be as high as 1000ms, 10x this and it's toast... */
|
||||||
#define FLASH_ERASE_TIMEOUT 10000
|
#define FLASH_ERASE_TIMEOUT 10000
|
||||||
#define FLASH_WRITE_TIMEOUT 5
|
#define FLASH_WRITE_TIMEOUT 5
|
||||||
|
|
||||||
|
|
||||||
#define STM32_FLASH_BASE 0x40023c00
|
#define STM32_FLASH_BASE 0x40023c00
|
||||||
#define STM32_FLASH_ACR 0x40023c00
|
#define STM32_FLASH_ACR 0x40023c00
|
||||||
#define STM32_FLASH_KEYR 0x40023c04
|
#define STM32_FLASH_KEYR 0x40023c04
|
||||||
|
@ -99,8 +100,6 @@
|
||||||
#define STM32_FLASH_OPTCR 0x40023c14
|
#define STM32_FLASH_OPTCR 0x40023c14
|
||||||
#define STM32_FLASH_OBR 0x40023c1C
|
#define STM32_FLASH_OBR 0x40023c1C
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* option byte location */
|
/* option byte location */
|
||||||
|
|
||||||
#define STM32_OB_RDP 0x1FFFF800
|
#define STM32_OB_RDP 0x1FFFF800
|
||||||
|
@ -128,13 +127,13 @@
|
||||||
/* FLASH_SR register bits */
|
/* FLASH_SR register bits */
|
||||||
|
|
||||||
#define FLASH_BSY (1 << 16)
|
#define FLASH_BSY (1 << 16)
|
||||||
#define FLASH_PGSERR (1 << 7) // Programming sequence error
|
#define FLASH_PGSERR (1 << 7) /* Programming sequence error */
|
||||||
#define FLASH_PGPERR (1 << 6) // Programming parallelism error
|
#define FLASH_PGPERR (1 << 6) /* Programming parallelism error */
|
||||||
#define FLASH_PGAERR (1 << 5) // Programming alignment error
|
#define FLASH_PGAERR (1 << 5) /* Programming alignment error */
|
||||||
#define FLASH_WRPERR (1 << 4) // Write protection error
|
#define FLASH_WRPERR (1 << 4) /* Write protection error */
|
||||||
#define FLASH_OPERR (1 << 1) // Operation error
|
#define FLASH_OPERR (1 << 1) /* Operation error */
|
||||||
|
|
||||||
#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR| FLASH_WRPERR| FLASH_OPERR)
|
#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR)
|
||||||
|
|
||||||
/* STM32_FLASH_OBR bit definitions (reading) */
|
/* STM32_FLASH_OBR bit definitions (reading) */
|
||||||
|
|
||||||
|
@ -150,8 +149,7 @@
|
||||||
#define KEY1 0x45670123
|
#define KEY1 0x45670123
|
||||||
#define KEY2 0xCDEF89AB
|
#define KEY2 0xCDEF89AB
|
||||||
|
|
||||||
struct stm32x_flash_bank
|
struct stm32x_flash_bank {
|
||||||
{
|
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
int probed;
|
int probed;
|
||||||
};
|
};
|
||||||
|
@ -164,9 +162,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
|
||||||
struct stm32x_flash_bank *stm32x_info;
|
struct stm32x_flash_bank *stm32x_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
|
stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
|
||||||
bank->driver_priv = stm32x_info;
|
bank->driver_priv = stm32x_info;
|
||||||
|
@ -195,16 +191,14 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
/* wait for busy to clear */
|
/* wait for busy to clear */
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
retval = stm32x_get_flash_status(bank, &status);
|
retval = stm32x_get_flash_status(bank, &status);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||||
if ((status & FLASH_BSY) == 0)
|
if ((status & FLASH_BSY) == 0)
|
||||||
break;
|
break;
|
||||||
if (timeout-- <= 0)
|
if (timeout-- <= 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("timed out waiting for flash");
|
LOG_ERROR("timed out waiting for flash");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -212,15 +206,13 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (status & FLASH_WRPERR)
|
if (status & FLASH_WRPERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("stm32x device protected");
|
LOG_ERROR("stm32x device protected");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
if (status & FLASH_ERROR)
|
if (status & FLASH_ERROR) {
|
||||||
{
|
|
||||||
/* If this operation fails, we ignore it and report the original
|
/* If this operation fails, we ignore it and report the original
|
||||||
* retval
|
* retval
|
||||||
*/
|
*/
|
||||||
|
@ -275,8 +267,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -297,8 +288,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
|
||||||
4. Wait for the BSY bit to be cleared
|
4. Wait for the BSY bit to be cleared
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
retval = target_write_u32(target,
|
retval = target_write_u32(target,
|
||||||
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT);
|
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -361,30 +351,27 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
/* Flip endian */
|
/* Flip endian */
|
||||||
uint8_t stm32x_flash_write_code[sizeof(stm32x_flash_write_code_16)*2];
|
uint8_t stm32x_flash_write_code[sizeof(stm32x_flash_write_code_16)*2];
|
||||||
for (unsigned i = 0; i < sizeof(stm32x_flash_write_code_16) / 2; i++)
|
for (unsigned i = 0; i < sizeof(stm32x_flash_write_code_16) / 2; i++) {
|
||||||
{
|
|
||||||
stm32x_flash_write_code[i*2 + 0] = stm32x_flash_write_code_16[i] & 0xff;
|
stm32x_flash_write_code[i*2 + 0] = stm32x_flash_write_code_16[i] & 0xff;
|
||||||
stm32x_flash_write_code[i*2 + 1] = (stm32x_flash_write_code_16[i] >> 8) & 0xff;
|
stm32x_flash_write_code[i*2 + 1] = (stm32x_flash_write_code_16[i] >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
|
if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
|
||||||
&stm32x_info->write_algorithm) != ERROR_OK)
|
&stm32x_info->write_algorithm) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("no working area available, can't do block memory writes");
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
|
retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
|
||||||
sizeof(stm32x_flash_write_code),
|
sizeof(stm32x_flash_write_code),
|
||||||
(uint8_t*)stm32x_flash_write_code)) != ERROR_OK)
|
(uint8_t *)stm32x_flash_write_code);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
|
||||||
/* if we already allocated the writing code, but failed to get a
|
/* if we already allocated the writing code, but failed to get a
|
||||||
* buffer, free the algorithm */
|
* buffer, free the algorithm */
|
||||||
if (stm32x_info->write_algorithm)
|
if (stm32x_info->write_algorithm)
|
||||||
|
@ -404,28 +391,27 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT);
|
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT);
|
||||||
init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
|
init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
uint32_t thisrun_count = (count > (buffer_size / 2)) ?
|
uint32_t thisrun_count = (count > (buffer_size / 2)) ?
|
||||||
(buffer_size / 2) : count;
|
(buffer_size / 2) : count;
|
||||||
|
|
||||||
if ((retval = target_write_buffer(target, source->address,
|
retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
|
||||||
thisrun_count * 2, buffer)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
||||||
buf_set_u32(reg_params[1].value, 0, 32, address);
|
buf_set_u32(reg_params[1].value, 0, 32, address);
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
||||||
// R3 is a return value only
|
/* R3 is a return value only */
|
||||||
buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE);
|
buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE);
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL,
|
retval = target_run_algorithm(target, 0, NULL,
|
||||||
sizeof(reg_params) / sizeof(*reg_params),
|
sizeof(reg_params) / sizeof(*reg_params),
|
||||||
reg_params,
|
reg_params,
|
||||||
stm32x_info->write_algorithm->address,
|
stm32x_info->write_algorithm->address,
|
||||||
0,
|
0,
|
||||||
10000, &armv7m_info)) != ERROR_OK)
|
10000, &armv7m_info);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("error executing stm32x flash write algorithm");
|
LOG_ERROR("error executing stm32x flash write algorithm");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -433,12 +419,9 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
uint32_t error = buf_get_u32(reg_params[3].value, 0, 32) & FLASH_ERROR;
|
uint32_t error = buf_get_u32(reg_params[3].value, 0, 32) & FLASH_ERROR;
|
||||||
|
|
||||||
if (error & FLASH_WRPERR)
|
if (error & FLASH_WRPERR)
|
||||||
{
|
|
||||||
LOG_ERROR("flash memory write protected");
|
LOG_ERROR("flash memory write protected");
|
||||||
}
|
|
||||||
|
|
||||||
if (error != 0)
|
if (error != 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("flash write failed = %08x", error);
|
LOG_ERROR("flash write failed = %08x", error);
|
||||||
/* Clear but report errors */
|
/* Clear but report errors */
|
||||||
target_write_u32(target, STM32_FLASH_SR, error);
|
target_write_u32(target, STM32_FLASH_SR, error);
|
||||||
|
@ -473,14 +456,12 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
uint32_t bytes_written = 0;
|
uint32_t bytes_written = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset & 0x1)
|
if (offset & 0x1) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
@ -490,20 +471,16 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* multiple half words (2-byte) to be programmed? */
|
/* multiple half words (2-byte) to be programmed? */
|
||||||
if (words_remaining > 0)
|
if (words_remaining > 0) {
|
||||||
{
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
|
retval = stm32x_write_block(bank, buffer, offset, words_remaining);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
{
|
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
* we use normal (slow) single dword accesses */
|
* we use normal (slow) single dword accesses */
|
||||||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer += words_remaining * 2;
|
buffer += words_remaining * 2;
|
||||||
address += words_remaining * 2;
|
address += words_remaining * 2;
|
||||||
words_remaining = 0;
|
words_remaining = 0;
|
||||||
|
@ -529,8 +506,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
Double word access in case of x64 parallelism
|
Double word access in case of x64 parallelism
|
||||||
Wait for the BSY bit to be cleared
|
Wait for the BSY bit to be cleared
|
||||||
*/
|
*/
|
||||||
while (words_remaining > 0)
|
while (words_remaining > 0) {
|
||||||
{
|
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
|
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
|
||||||
|
|
||||||
|
@ -552,8 +528,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
address += 2;
|
address += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
|
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
|
||||||
FLASH_PG | FLASH_PSIZE_8);
|
FLASH_PG | FLASH_PSIZE_8);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -572,8 +547,7 @@ static int stm32x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
static void setup_sector(struct flash_bank *bank, int start, int num, int size)
|
static void setup_sector(struct flash_bank *bank, int start, int num, int size)
|
||||||
{
|
{
|
||||||
for (int i = start; i < (start + num) ; i++)
|
for (int i = start; i < (start + num) ; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = bank->size;
|
bank->sectors[i].offset = bank->size;
|
||||||
bank->sectors[i].size = size;
|
bank->sectors[i].size = size;
|
||||||
bank->size += bank->sectors[i].size;
|
bank->size += bank->sectors[i].size;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -117,8 +118,7 @@ static int stm32lx_enable_write_half_page(struct flash_bank *bank);
|
||||||
static int stm32lx_erase_sector(struct flash_bank *bank, int sector);
|
static int stm32lx_erase_sector(struct flash_bank *bank, int sector);
|
||||||
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank);
|
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank);
|
||||||
|
|
||||||
struct stm32lx_flash_bank
|
struct stm32lx_flash_bank {
|
||||||
{
|
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
int probed;
|
int probed;
|
||||||
};
|
};
|
||||||
|
@ -129,16 +129,13 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
|
||||||
{
|
{
|
||||||
struct stm32lx_flash_bank *stm32lx_info;
|
struct stm32lx_flash_bank *stm32lx_info;
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
// Create the bank structure
|
/* Create the bank structure */
|
||||||
stm32lx_info = malloc(sizeof(struct stm32lx_flash_bank));
|
stm32lx_info = malloc(sizeof(struct stm32lx_flash_bank));
|
||||||
|
|
||||||
// Check allocation
|
/* Check allocation */
|
||||||
if (stm32lx_info == NULL)
|
if (stm32lx_info == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("failed to allocate bank structure");
|
LOG_ERROR("failed to allocate bank structure");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -158,8 +155,7 @@ static int stm32lx_protect_check(struct flash_bank *bank)
|
||||||
|
|
||||||
uint32_t wrpr;
|
uint32_t wrpr;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -172,17 +168,12 @@ static int stm32lx_protect_check(struct flash_bank *bank)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++) {
|
||||||
{
|
|
||||||
if (wrpr & (1 << i))
|
if (wrpr & (1 << i))
|
||||||
{
|
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
bank->sectors[i].is_protected = 0;
|
bank->sectors[i].is_protected = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,8 +186,7 @@ static int stm32lx_erase(struct flash_bank *bank, int first, int last)
|
||||||
* erased, but it is not implemented yet.
|
* erased, but it is not implemented yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -204,8 +194,7 @@ static int stm32lx_erase(struct flash_bank *bank, int first, int last)
|
||||||
/*
|
/*
|
||||||
* Loop over the selected sectors and erase them
|
* Loop over the selected sectors and erase them
|
||||||
*/
|
*/
|
||||||
for (int i = first; i <= last; i++)
|
for (int i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
retval = stm32lx_erase_sector(bank, i);
|
retval = stm32lx_erase_sector(bank, i);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -238,72 +227,66 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
/* see contib/loaders/flash/stm32lx.s for src */
|
/* see contib/loaders/flash/stm32lx.s for src */
|
||||||
|
|
||||||
static const uint16_t stm32lx_flash_write_code_16[] =
|
static const uint16_t stm32lx_flash_write_code_16[] = {
|
||||||
{
|
/* 00000000 <write_word-0x4>: */
|
||||||
// 00000000 <write_word-0x4>:
|
0x2300, /* 0: 2300 movs r3, #0 */
|
||||||
0x2300, // 0: 2300 movs r3, #0
|
0xe004, /* 2: e004 b.n e <test_done> */
|
||||||
0xe004, // 2: e004 b.n e <test_done>
|
|
||||||
|
|
||||||
// 00000004 <write_word>:
|
/* 00000004 <write_word>: */
|
||||||
0xf851, 0xcb04, // 4: f851 cb04 ldr.w ip, [r1], #4
|
0xf851, 0xcb04, /* 4: f851 cb04 ldr.w ip, [r1], #4 */
|
||||||
0xf840, 0xcb04, // 8: f840 cb04 str.w ip, [r0], #4
|
0xf840, 0xcb04, /* 8: f840 cb04 str.w ip, [r0], #4 */
|
||||||
0x3301, // c: 3301 adds r3, #1
|
0x3301, /* c: 3301 adds r3, #1 */
|
||||||
|
|
||||||
// 0000000e <test_done>:
|
/* 0000000e <test_done>: */
|
||||||
0x4293, // e: 4293 cmp r3, r2
|
0x4293, /* e: 4293 cmp r3, r2 */
|
||||||
0xd3f8, // 10: d3f8 bcc.n 4 <write_word>
|
0xd3f8, /* 10: d3f8 bcc.n 4 <write_word> */
|
||||||
0xbe00, // 12: be00 bkpt 0x0000
|
0xbe00, /* 12: be00 bkpt 0x0000 */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flip endian
|
/* Flip endian */
|
||||||
uint8_t stm32lx_flash_write_code[sizeof(stm32lx_flash_write_code_16)];
|
uint8_t stm32lx_flash_write_code[sizeof(stm32lx_flash_write_code_16)];
|
||||||
for (unsigned int i = 0; i < sizeof(stm32lx_flash_write_code_16) / 2; i++)
|
for (unsigned int i = 0; i < sizeof(stm32lx_flash_write_code_16) / 2; i++) {
|
||||||
{
|
|
||||||
stm32lx_flash_write_code[i * 2 + 0] = stm32lx_flash_write_code_16[i]
|
stm32lx_flash_write_code[i * 2 + 0] = stm32lx_flash_write_code_16[i]
|
||||||
& 0xff;
|
& 0xff;
|
||||||
stm32lx_flash_write_code[i * 2 + 1] = (stm32lx_flash_write_code_16[i]
|
stm32lx_flash_write_code[i * 2 + 1] = (stm32lx_flash_write_code_16[i]
|
||||||
>> 8) & 0xff;
|
>> 8) & 0xff;
|
||||||
}
|
}
|
||||||
// Check if there is an even number of half pages (128bytes)
|
/* Check if there is an even number of half pages (128bytes) */
|
||||||
if (count % 128)
|
if (count % 128) {
|
||||||
{
|
|
||||||
LOG_ERROR("there should be an even number "
|
LOG_ERROR("there should be an even number "
|
||||||
"of half pages = 128 bytes (count = %" PRIi32 " bytes)", count);
|
"of half pages = 128 bytes (count = %" PRIi32 " bytes)", count);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate working area
|
/* Allocate working area */
|
||||||
reg32 = sizeof(stm32lx_flash_write_code);
|
reg32 = sizeof(stm32lx_flash_write_code);
|
||||||
// Add bytes to make 4byte aligned
|
/* Add bytes to make 4byte aligned */
|
||||||
reg32 += (4 - (reg32 % 4)) % 4;
|
reg32 += (4 - (reg32 % 4)) % 4;
|
||||||
retval = target_alloc_working_area(target, reg32,
|
retval = target_alloc_working_area(target, reg32,
|
||||||
&stm32lx_info->write_algorithm);
|
&stm32lx_info->write_algorithm);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
// Write the flashing code
|
/* Write the flashing code */
|
||||||
retval = target_write_buffer(target,
|
retval = target_write_buffer(target,
|
||||||
stm32lx_info->write_algorithm->address,
|
stm32lx_info->write_algorithm->address,
|
||||||
sizeof(stm32lx_flash_write_code),
|
sizeof(stm32lx_flash_write_code),
|
||||||
(uint8_t*) stm32lx_flash_write_code);
|
(uint8_t *)stm32lx_flash_write_code);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
target_free_working_area(target, stm32lx_info->write_algorithm);
|
target_free_working_area(target, stm32lx_info->write_algorithm);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate half pages memory
|
/* Allocate half pages memory */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source)
|
while (target_alloc_working_area_try(target, buffer_size, &source)
|
||||||
!= ERROR_OK)
|
!= ERROR_OK) {
|
||||||
{
|
|
||||||
if (buffer_size > 1024)
|
if (buffer_size > 1024)
|
||||||
buffer_size -= 1024;
|
buffer_size -= 1024;
|
||||||
else
|
else
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
|
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
|
||||||
/* if we already allocated the writing code, but failed to get a
|
/* if we already allocated the writing code, but failed to get a
|
||||||
* buffer, free the algorithm */
|
* buffer, free the algorithm */
|
||||||
if (stm32lx_info->write_algorithm)
|
if (stm32lx_info->write_algorithm)
|
||||||
|
@ -323,11 +306,9 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer,
|
||||||
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT);
|
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT);
|
||||||
init_reg_param(®_params[4], "r4", 32, PARAM_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);
|
retval = stm32lx_enable_write_half_page(bank);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
|
|
||||||
target_free_working_area(target, source);
|
target_free_working_area(target, source);
|
||||||
target_free_working_area(target, stm32lx_info->write_algorithm);
|
target_free_working_area(target, stm32lx_info->write_algorithm);
|
||||||
|
|
||||||
|
@ -335,38 +316,36 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer,
|
||||||
destroy_reg_param(®_params[1]);
|
destroy_reg_param(®_params[1]);
|
||||||
destroy_reg_param(®_params[2]);
|
destroy_reg_param(®_params[2]);
|
||||||
destroy_reg_param(®_params[3]);
|
destroy_reg_param(®_params[3]);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop while there are bytes to write
|
/* Loop while there are bytes to write */
|
||||||
while (count > 0)
|
while (count > 0) {
|
||||||
{
|
|
||||||
uint32_t this_count;
|
uint32_t this_count;
|
||||||
this_count = (count > buffer_size) ? buffer_size : count;
|
this_count = (count > buffer_size) ? buffer_size : count;
|
||||||
|
|
||||||
// Write the next half pages
|
/* Write the next half pages */
|
||||||
retval = target_write_buffer(target, source->address, this_count,
|
retval = target_write_buffer(target, source->address, this_count,
|
||||||
buffer);
|
buffer);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 4: Store useful information in the registers
|
/* 4: Store useful information in the registers */
|
||||||
// the destination address of the copy (R0)
|
/* the destination address of the copy (R0) */
|
||||||
buf_set_u32(reg_params[0].value, 0, 32, address);
|
buf_set_u32(reg_params[0].value, 0, 32, address);
|
||||||
// The source address of the copy (R1)
|
/* The source address of the copy (R1) */
|
||||||
buf_set_u32(reg_params[1].value, 0, 32, source->address);
|
buf_set_u32(reg_params[1].value, 0, 32, source->address);
|
||||||
// The length of the copy (R2)
|
/* The length of the copy (R2) */
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, this_count / 4);
|
buf_set_u32(reg_params[2].value, 0, 32, this_count / 4);
|
||||||
|
|
||||||
// 5: Execute the bunch of code
|
/* 5: Execute the bunch of code */
|
||||||
retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params)
|
retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params)
|
||||||
/ sizeof(*reg_params), reg_params,
|
/ sizeof(*reg_params), reg_params,
|
||||||
stm32lx_info->write_algorithm->address, 0, 20000, &armv7m_info);
|
stm32lx_info->write_algorithm->address, 0, 20000, &armv7m_info);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 6: Wait while busy
|
/* 6: Wait while busy */
|
||||||
retval = stm32lx_wait_until_bsy_clear(bank);
|
retval = stm32lx_wait_until_bsy_clear(bank);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
@ -401,34 +380,28 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
uint32_t bytes_written = 0;
|
uint32_t bytes_written = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset & 0x1)
|
if (offset & 0x1) {
|
||||||
{
|
|
||||||
LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there are some full half pages
|
/* Check if there are some full half pages */
|
||||||
if (((offset % 128) == 0) && (count >= 128))
|
if (((offset % 128) == 0) && (count >= 128)) {
|
||||||
{
|
|
||||||
halfpages_number = count / 128;
|
halfpages_number = count / 128;
|
||||||
words_remaining = (count - 128 * halfpages_number) / 4;
|
words_remaining = (count - 128 * halfpages_number) / 4;
|
||||||
bytes_remaining = (count & 0x3);
|
bytes_remaining = (count & 0x3);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
halfpages_number = 0;
|
halfpages_number = 0;
|
||||||
words_remaining = (count / 4);
|
words_remaining = (count / 4);
|
||||||
bytes_remaining = (count & 0x3);
|
bytes_remaining = (count & 0x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (halfpages_number)
|
if (halfpages_number) {
|
||||||
{
|
|
||||||
retval = stm32lx_write_half_pages(bank, buffer, offset, 128
|
retval = stm32lx_write_half_pages(bank, buffer, offset, 128
|
||||||
* halfpages_number);
|
* halfpages_number);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -441,12 +414,11 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
while (words_remaining > 0)
|
while (words_remaining > 0) {
|
||||||
{
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint8_t* p = buffer + bytes_written;
|
uint8_t *p = buffer + bytes_written;
|
||||||
|
|
||||||
// Prepare the word, Little endian conversion
|
/* Prepare the word, Little endian conversion */
|
||||||
value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
||||||
|
|
||||||
retval = target_write_u32(target, address, value);
|
retval = target_write_u32(target, address, value);
|
||||||
|
@ -462,8 +434,7 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
|
uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
/* copy the last remaining bytes into the write buffer */
|
/* copy the last remaining bytes into the write buffer */
|
||||||
|
@ -508,14 +479,13 @@ static int stm32lx_probe(struct flash_bank *bank)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the RDP byte and check if it is 0xAA
|
/* Read the RDP byte and check if it is 0xAA */
|
||||||
uint8_t rdp;
|
uint8_t rdp;
|
||||||
retval = target_read_u32(target, FLASH_OBR, ®32);
|
retval = target_read_u32(target, FLASH_OBR, ®32);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
rdp = reg32 & 0xFF;
|
rdp = reg32 & 0xFF;
|
||||||
if (rdp != 0xAA)
|
if (rdp != 0xAA) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* Unlocking the option byte is done by unlocking the PECR, then
|
* Unlocking the option byte is done by unlocking the PECR, then
|
||||||
* by writing the 2 option byte keys to OPTKEYR
|
* by writing the 2 option byte keys to OPTKEYR
|
||||||
|
@ -549,19 +519,18 @@ static int stm32lx_probe(struct flash_bank *bank)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (reg32 & FLASH_PECR__OPTLOCK)
|
if (reg32 & FLASH_PECR__OPTLOCK) {
|
||||||
{
|
|
||||||
LOG_ERROR("OPTLOCK is not cleared");
|
LOG_ERROR("OPTLOCK is not cleared");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, write RDP to 0x00 to set level 1
|
/* Then, write RDP to 0x00 to set level 1 */
|
||||||
reg32 = ((~0xAA) << 16) | (0xAA);
|
reg32 = ((~0xAA) << 16) | (0xAA);
|
||||||
retval = target_write_u32(target, OB_RDP, reg32);
|
retval = target_write_u32(target, OB_RDP, reg32);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
// Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR
|
/* Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR */
|
||||||
reg32 = FLASH_PECR__OBL_LAUNCH;
|
reg32 = FLASH_PECR__OBL_LAUNCH;
|
||||||
retval = target_write_u32(target, FLASH_PECR, reg32);
|
retval = target_write_u32(target, FLASH_PECR, reg32);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -574,8 +543,7 @@ static int stm32lx_probe(struct flash_bank *bank)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* check for valid flash size */
|
/* check for valid flash size */
|
||||||
if (flash_size == 0xffff)
|
if (flash_size == 0xffff) {
|
||||||
{
|
|
||||||
/* number of sectors incorrect on revA */
|
/* number of sectors incorrect on revA */
|
||||||
LOG_ERROR("STM32 flash size failed, probe inaccurate");
|
LOG_ERROR("STM32 flash size failed, probe inaccurate");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -588,8 +556,7 @@ static int stm32lx_probe(struct flash_bank *bank)
|
||||||
int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE;
|
int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE;
|
||||||
LOG_INFO("flash size = %dkbytes", flash_size);
|
LOG_INFO("flash size = %dkbytes", flash_size);
|
||||||
|
|
||||||
if (bank->sectors)
|
if (bank->sectors) {
|
||||||
{
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
}
|
}
|
||||||
|
@ -598,14 +565,12 @@ static int stm32lx_probe(struct flash_bank *bank)
|
||||||
bank->size = flash_size * 1024;
|
bank->size = flash_size * 1024;
|
||||||
bank->num_sectors = num_sectors;
|
bank->num_sectors = num_sectors;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
|
bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
|
||||||
if (bank->sectors == NULL)
|
if (bank->sectors == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("failed to allocate bank sectors");
|
LOG_ERROR("failed to allocate bank sectors");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_sectors; i++)
|
for (i = 0; i < num_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
|
bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
|
||||||
bank->sectors[i].size = FLASH_SECTOR_SIZE;
|
bank->sectors[i].size = FLASH_SECTOR_SIZE;
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
|
@ -622,9 +587,7 @@ static int stm32lx_auto_probe(struct flash_bank *bank)
|
||||||
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
|
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
|
||||||
|
|
||||||
if (stm32lx_info->probed)
|
if (stm32lx_info->probed)
|
||||||
{
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
|
||||||
|
|
||||||
return stm32lx_probe(bank);
|
return stm32lx_probe(bank);
|
||||||
}
|
}
|
||||||
|
@ -637,60 +600,51 @@ static int stm32lx_erase_check(struct flash_bank *bank)
|
||||||
uint32_t nBytes;
|
uint32_t nBytes;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *buffer = malloc(buffer_size);
|
uint8_t *buffer = malloc(buffer_size);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("failed to allocate read buffer");
|
LOG_ERROR("failed to allocate read buffer");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
uint32_t j;
|
uint32_t j;
|
||||||
bank->sectors[i].is_erased = 1;
|
bank->sectors[i].is_erased = 1;
|
||||||
|
|
||||||
// Loop chunk by chunk over the sector
|
/* Loop chunk by chunk over the sector */
|
||||||
for (j = 0; j < bank->sectors[i].size; j += buffer_size)
|
for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
|
||||||
{
|
|
||||||
uint32_t chunk;
|
uint32_t chunk;
|
||||||
chunk = buffer_size;
|
chunk = buffer_size;
|
||||||
if (chunk > (j - bank->sectors[i].size))
|
if (chunk > (j - bank->sectors[i].size))
|
||||||
{
|
|
||||||
chunk = (j - bank->sectors[i].size);
|
chunk = (j - bank->sectors[i].size);
|
||||||
}
|
|
||||||
|
|
||||||
retval = target_read_memory(target, bank->base
|
retval = target_read_memory(target, bank->base
|
||||||
+ bank->sectors[i].offset + j, 4, chunk / 4, buffer);
|
+ bank->sectors[i].offset + j, 4, chunk / 4, buffer);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (nBytes = 0; nBytes < chunk; nBytes++)
|
for (nBytes = 0; nBytes < chunk; nBytes++) {
|
||||||
{
|
if (buffer[nBytes] != 0x00) {
|
||||||
if (buffer[nBytes] != 0x00)
|
|
||||||
{
|
|
||||||
bank->sectors[i].is_erased = 0;
|
bank->sectors[i].is_erased = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
|
static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
// This method must return a string displaying information about the bank
|
/* This method must return a string displaying information about the bank */
|
||||||
|
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
uint32_t device_id;
|
uint32_t device_id;
|
||||||
|
@ -706,8 +660,7 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
buf += printed;
|
buf += printed;
|
||||||
buf_size -= printed;
|
buf_size -= printed;
|
||||||
|
|
||||||
switch (device_id >> 16)
|
switch (device_id >> 16) {
|
||||||
{
|
|
||||||
case 0x1000:
|
case 0x1000:
|
||||||
snprintf(buf, buf_size, "A");
|
snprintf(buf, buf_size, "A");
|
||||||
break;
|
break;
|
||||||
|
@ -719,9 +672,7 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
snprintf(buf, buf_size, "unknown");
|
snprintf(buf, buf_size, "unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(buf, buf_size, "Cannot identify target as a stm32lx");
|
snprintf(buf, buf_size, "Cannot identify target as a stm32lx");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -729,13 +680,11 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct command_registration stm32lx_exec_command_handlers[] =
|
static const struct command_registration stm32lx_exec_command_handlers[] = {
|
||||||
{
|
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct command_registration stm32lx_command_handlers[] =
|
static const struct command_registration stm32lx_command_handlers[] = {
|
||||||
{
|
|
||||||
{
|
{
|
||||||
.name = "stm32lx",
|
.name = "stm32lx",
|
||||||
.mode = COMMAND_ANY,
|
.mode = COMMAND_ANY,
|
||||||
|
@ -746,8 +695,7 @@ static const struct command_registration stm32lx_command_handlers[] =
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct flash_driver stm32lx_flash =
|
struct flash_driver stm32lx_flash = {
|
||||||
{
|
|
||||||
.name = "stm32lx",
|
.name = "stm32lx",
|
||||||
.commands = stm32lx_command_handlers,
|
.commands = stm32lx_command_handlers,
|
||||||
.flash_bank_command = stm32lx_flash_bank_command,
|
.flash_bank_command = stm32lx_flash_bank_command,
|
||||||
|
@ -762,8 +710,7 @@ struct flash_driver stm32lx_flash =
|
||||||
.info = stm32lx_get_info,
|
.info = stm32lx_get_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static methods implementation
|
/* Static methods implementation */
|
||||||
|
|
||||||
static int stm32lx_unlock_program_memory(struct flash_bank *bank)
|
static int stm32lx_unlock_program_memory(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
|
@ -789,8 +736,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (reg32 & FLASH_PECR__PELOCK)
|
if (reg32 & FLASH_PECR__PELOCK) {
|
||||||
{
|
|
||||||
LOG_ERROR("PELOCK is not cleared :(");
|
LOG_ERROR("PELOCK is not cleared :(");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -807,8 +753,7 @@ static int stm32lx_unlock_program_memory(struct flash_bank *bank)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (reg32 & FLASH_PECR__PRGLOCK)
|
if (reg32 & FLASH_PECR__PRGLOCK) {
|
||||||
{
|
|
||||||
LOG_ERROR("PRGLOCK is not cleared :(");
|
LOG_ERROR("PRGLOCK is not cleared :(");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -892,8 +837,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (int page = 0; page < FLASH_PAGES_PER_SECTOR; page++)
|
for (int page = 0; page < FLASH_PAGES_PER_SECTOR; page++) {
|
||||||
{
|
|
||||||
reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
|
reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
|
||||||
retval = target_write_u32(target, FLASH_PECR, reg32);
|
retval = target_write_u32(target, FLASH_PECR, reg32);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -929,32 +873,26 @@ static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank)
|
||||||
int timeout = 100;
|
int timeout = 100;
|
||||||
|
|
||||||
/* wait for busy to clear */
|
/* wait for busy to clear */
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
retval = target_read_u32(target, FLASH_SR, &status);
|
retval = target_read_u32(target, FLASH_SR, &status);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if ((status & FLASH_SR__BSY) == 0)
|
if ((status & FLASH_SR__BSY) == 0)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
if (timeout-- <= 0) {
|
||||||
if (timeout-- <= 0)
|
|
||||||
{
|
|
||||||
LOG_ERROR("timed out waiting for flash");
|
LOG_ERROR("timed out waiting for flash");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & FLASH_SR__WRPERR)
|
if (status & FLASH_SR__WRPERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("access denied / write protected");
|
LOG_ERROR("access denied / write protected");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & FLASH_SR__PGAERR)
|
if (status & FLASH_SR__PGAERR) {
|
||||||
{
|
|
||||||
LOG_ERROR("invalid program address");
|
LOG_ERROR("invalid program address");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
__v; \
|
__v; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SMI_WRITE_REG(a,v) \
|
#define SMI_WRITE_REG(a, v) \
|
||||||
{ \
|
{ \
|
||||||
int __r; \
|
int __r; \
|
||||||
\
|
\
|
||||||
|
@ -117,8 +117,7 @@
|
||||||
#define SMI_PROBE_TIMEOUT (100)
|
#define SMI_PROBE_TIMEOUT (100)
|
||||||
#define SMI_MAX_TIMEOUT (3000)
|
#define SMI_MAX_TIMEOUT (3000)
|
||||||
|
|
||||||
struct stmsmi_flash_bank
|
struct stmsmi_flash_bank {
|
||||||
{
|
|
||||||
int probed;
|
int probed;
|
||||||
uint32_t io_base;
|
uint32_t io_base;
|
||||||
uint32_t bank_num;
|
uint32_t bank_num;
|
||||||
|
@ -202,16 +201,13 @@ FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command)
|
||||||
{
|
{
|
||||||
struct stmsmi_flash_bank *stmsmi_info;
|
struct stmsmi_flash_bank *stmsmi_info;
|
||||||
|
|
||||||
LOG_DEBUG("%s", __FUNCTION__);
|
LOG_DEBUG("%s", __func__);
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank));
|
stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank));
|
||||||
if (stmsmi_info == NULL)
|
if (stmsmi_info == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("not enough memory");
|
LOG_ERROR("not enough memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -324,8 +320,7 @@ static int smi_write_enable(struct flash_bank *bank)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Check write enabled */
|
/* Check write enabled */
|
||||||
if ((status & SMI_WEL_BIT) == 0)
|
if ((status & SMI_WEL_BIT) == 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
|
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -391,37 +386,31 @@ static int stmsmi_erase(struct flash_bank *bank, int first, int last)
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
int sector;
|
int sector;
|
||||||
|
|
||||||
LOG_DEBUG("%s: from sector %d to sector %d", __FUNCTION__, first, last);
|
LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((first < 0) || (last < first) || (last >= bank->num_sectors))
|
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash sector invalid");
|
LOG_ERROR("Flash sector invalid");
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(stmsmi_info->probed))
|
if (!(stmsmi_info->probed)) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash bank not probed");
|
LOG_ERROR("Flash bank not probed");
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (sector = first; sector <= last; sector++)
|
for (sector = first; sector <= last; sector++) {
|
||||||
{
|
if (bank->sectors[sector].is_protected) {
|
||||||
if (bank->sectors[sector].is_protected)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Flash sector %d protected", sector);
|
LOG_ERROR("Flash sector %d protected", sector);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (sector = first; sector <= last; sector++)
|
for (sector = first; sector <= last; sector++) {
|
||||||
{
|
|
||||||
retval = smi_erase_sector(bank, sector);
|
retval = smi_erase_sector(bank, sector);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
|
@ -452,7 +441,7 @@ static int smi_write_buffer(struct flash_bank *bank, uint8_t *buffer,
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
|
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
|
||||||
__FUNCTION__, address, len);
|
__func__, address, len);
|
||||||
|
|
||||||
retval = smi_write_enable(bank);
|
retval = smi_write_enable(bank);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -479,30 +468,26 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
|
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
|
||||||
__FUNCTION__, offset, count);
|
__func__, offset, count);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset + count > stmsmi_info->dev->size_in_bytes)
|
if (offset + count > stmsmi_info->dev->size_in_bytes) {
|
||||||
{
|
|
||||||
LOG_WARNING("Write pasts end of flash. Extra data discarded.");
|
LOG_WARNING("Write pasts end of flash. Extra data discarded.");
|
||||||
count = stmsmi_info->dev->size_in_bytes - offset;
|
count = stmsmi_info->dev->size_in_bytes - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check sector protection */
|
/* Check sector protection */
|
||||||
for (sector = 0; sector < bank->num_sectors; sector++)
|
for (sector = 0; sector < bank->num_sectors; sector++) {
|
||||||
{
|
|
||||||
/* Start offset in or before this sector? */
|
/* Start offset in or before this sector? */
|
||||||
/* End offset in or behind this sector? */
|
/* End offset in or behind this sector? */
|
||||||
if ( (offset <
|
if ((offset <
|
||||||
(bank->sectors[sector].offset + bank->sectors[sector].size))
|
(bank->sectors[sector].offset + bank->sectors[sector].size))
|
||||||
&& ((offset + count - 1) >= bank->sectors[sector].offset)
|
&& ((offset + count - 1) >= bank->sectors[sector].offset)
|
||||||
&& bank->sectors[sector].is_protected )
|
&& bank->sectors[sector].is_protected) {
|
||||||
{
|
|
||||||
LOG_ERROR("Flash sector %d protected", sector);
|
LOG_ERROR("Flash sector %d protected", sector);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -511,8 +496,7 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
page_size = stmsmi_info->dev->pagesize;
|
page_size = stmsmi_info->dev->pagesize;
|
||||||
|
|
||||||
/* unaligned buffer head */
|
/* unaligned buffer head */
|
||||||
if (count > 0 && (offset & 3) != 0)
|
if (count > 0 && (offset & 3) != 0) {
|
||||||
{
|
|
||||||
cur_count = 4 - (offset & 3);
|
cur_count = 4 - (offset & 3);
|
||||||
if (cur_count > count)
|
if (cur_count > count)
|
||||||
cur_count = count;
|
cur_count = count;
|
||||||
|
@ -527,8 +511,7 @@ static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
page_offset = offset % page_size;
|
page_offset = offset % page_size;
|
||||||
/* central part, aligned words */
|
/* central part, aligned words */
|
||||||
while (count >= 4)
|
while (count >= 4) {
|
||||||
{
|
|
||||||
/* clip block at page boundary */
|
/* clip block at page boundary */
|
||||||
if (page_offset + count > page_size)
|
if (page_offset + count > page_size)
|
||||||
cur_count = page_size - page_offset;
|
cur_count = page_size - page_offset;
|
||||||
|
@ -567,8 +550,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id)
|
||||||
uint32_t io_base = stmsmi_info->io_base;
|
uint32_t io_base = stmsmi_info->io_base;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -614,18 +596,16 @@ static int stmsmi_probe(struct flash_bank *bank)
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
stmsmi_info->probed = 0;
|
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)
|
if (target_device->tap_idcode == target->tap->idcode)
|
||||||
break;
|
break;
|
||||||
if (!target_device->name)
|
if (!target_device->name) {
|
||||||
{
|
|
||||||
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable",
|
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable",
|
||||||
target->tap->idcode);
|
target->tap->idcode);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (bank->base - target_device->smi_base)
|
switch (bank->base - target_device->smi_base) {
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
stmsmi_info->bank_num = SMI_SEL_BANK0;
|
stmsmi_info->bank_num = SMI_SEL_BANK0;
|
||||||
break;
|
break;
|
||||||
|
@ -661,8 +641,7 @@ static int stmsmi_probe(struct flash_bank *bank)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stmsmi_info->dev)
|
if (!stmsmi_info->dev) {
|
||||||
{
|
|
||||||
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
|
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -677,14 +656,12 @@ static int stmsmi_probe(struct flash_bank *bank)
|
||||||
bank->num_sectors =
|
bank->num_sectors =
|
||||||
stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize;
|
stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize;
|
||||||
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
if (sectors == NULL)
|
if (sectors == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("not enough memory");
|
LOG_ERROR("not enough memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int sector = 0; sector < bank->num_sectors; sector++)
|
for (int sector = 0; sector < bank->num_sectors; sector++) {
|
||||||
{
|
|
||||||
sectors[sector].offset = sector * stmsmi_info->dev->sectorsize;
|
sectors[sector].offset = sector * stmsmi_info->dev->sectorsize;
|
||||||
sectors[sector].size = stmsmi_info->dev->sectorsize;
|
sectors[sector].size = stmsmi_info->dev->sectorsize;
|
||||||
sectors[sector].is_erased = -1;
|
sectors[sector].is_erased = -1;
|
||||||
|
@ -714,8 +691,7 @@ static int get_stmsmi_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
|
struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
|
||||||
|
|
||||||
if (!(stmsmi_info->probed))
|
if (!(stmsmi_info->probed)) {
|
||||||
{
|
|
||||||
snprintf(buf, buf_size,
|
snprintf(buf, buf_size,
|
||||||
"\nSMI flash bank not probed yet\n");
|
"\nSMI flash bank not probed yet\n");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,7 +33,6 @@
|
||||||
#include <helper/binarybuffer.h>
|
#include <helper/binarybuffer.h>
|
||||||
#include <target/algorithm.h>
|
#include <target/algorithm.h>
|
||||||
|
|
||||||
|
|
||||||
/* Flash registers */
|
/* Flash registers */
|
||||||
|
|
||||||
#define FLASH_CR0 0x00000000
|
#define FLASH_CR0 0x00000000
|
||||||
|
@ -85,8 +85,7 @@
|
||||||
#define FLASH_ERR 0x00000001
|
#define FLASH_ERR 0x00000001
|
||||||
|
|
||||||
|
|
||||||
struct str7x_flash_bank
|
struct str7x_flash_bank {
|
||||||
{
|
|
||||||
uint32_t *sector_bits;
|
uint32_t *sector_bits;
|
||||||
uint32_t disable_bit;
|
uint32_t disable_bit;
|
||||||
uint32_t busy_bits;
|
uint32_t busy_bits;
|
||||||
|
@ -100,8 +99,7 @@ struct str7x_mem_layout {
|
||||||
uint32_t sector_bit;
|
uint32_t sector_bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum str7x_status_codes
|
enum str7x_status_codes {
|
||||||
{
|
|
||||||
STR7X_CMD_SUCCESS = 0,
|
STR7X_CMD_SUCCESS = 0,
|
||||||
STR7X_INVALID_COMMAND = 1,
|
STR7X_INVALID_COMMAND = 1,
|
||||||
STR7X_SRC_ADDR_ERROR = 2,
|
STR7X_SRC_ADDR_ERROR = 2,
|
||||||
|
@ -135,7 +133,7 @@ static struct str7x_mem_layout mem_layout_str7bank1[] = {
|
||||||
static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
|
static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
|
||||||
{
|
{
|
||||||
struct str7x_flash_bank *str7x_info = bank->driver_priv;
|
struct str7x_flash_bank *str7x_info = bank->driver_priv;
|
||||||
return (str7x_info->register_base | reg);
|
return str7x_info->register_base | reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int str7x_build_block_list(struct flash_bank *bank)
|
static int str7x_build_block_list(struct flash_bank *bank)
|
||||||
|
@ -146,8 +144,7 @@ static int str7x_build_block_list(struct flash_bank *bank)
|
||||||
int num_sectors;
|
int num_sectors;
|
||||||
int b0_sectors = 0, b1_sectors = 0;
|
int b0_sectors = 0, b1_sectors = 0;
|
||||||
|
|
||||||
switch (bank->size)
|
switch (bank->size) {
|
||||||
{
|
|
||||||
case 16 * 1024:
|
case 16 * 1024:
|
||||||
b1_sectors = 2;
|
b1_sectors = 2;
|
||||||
break;
|
break;
|
||||||
|
@ -173,8 +170,7 @@ static int str7x_build_block_list(struct flash_bank *bank)
|
||||||
|
|
||||||
num_sectors = 0;
|
num_sectors = 0;
|
||||||
|
|
||||||
for (i = 0; i < b0_sectors; i++)
|
for (i = 0; i < b0_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
|
bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
|
||||||
bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
|
bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
|
||||||
bank->sectors[num_sectors].is_erased = -1;
|
bank->sectors[num_sectors].is_erased = -1;
|
||||||
|
@ -185,8 +181,7 @@ static int str7x_build_block_list(struct flash_bank *bank)
|
||||||
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
|
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < b1_sectors; i++)
|
for (i = 0; i < b1_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
|
bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
|
||||||
bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
|
bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
|
||||||
bank->sectors[num_sectors].is_erased = -1;
|
bank->sectors[num_sectors].is_erased = -1;
|
||||||
|
@ -207,9 +202,7 @@ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
|
||||||
struct str7x_flash_bank *str7x_info;
|
struct str7x_flash_bank *str7x_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 7)
|
if (CMD_ARGC < 7)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
str7x_info = malloc(sizeof(struct str7x_flash_bank));
|
str7x_info = malloc(sizeof(struct str7x_flash_bank));
|
||||||
bank->driver_priv = str7x_info;
|
bank->driver_priv = str7x_info;
|
||||||
|
@ -219,21 +212,14 @@ FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
|
||||||
str7x_info->disable_bit = (1 << 1);
|
str7x_info->disable_bit = (1 << 1);
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[6], "STR71x") == 0)
|
if (strcmp(CMD_ARGV[6], "STR71x") == 0)
|
||||||
{
|
|
||||||
str7x_info->register_base = 0x40100000;
|
str7x_info->register_base = 0x40100000;
|
||||||
}
|
else if (strcmp(CMD_ARGV[6], "STR73x") == 0) {
|
||||||
else if (strcmp(CMD_ARGV[6], "STR73x") == 0)
|
|
||||||
{
|
|
||||||
str7x_info->register_base = 0x80100000;
|
str7x_info->register_base = 0x80100000;
|
||||||
str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0);
|
str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0);
|
||||||
}
|
} else if (strcmp(CMD_ARGV[6], "STR75x") == 0) {
|
||||||
else if (strcmp(CMD_ARGV[6], "STR75x") == 0)
|
|
||||||
{
|
|
||||||
str7x_info->register_base = 0x20100000;
|
str7x_info->register_base = 0x20100000;
|
||||||
str7x_info->disable_bit = (1 << 0);
|
str7x_info->disable_bit = (1 << 0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]);
|
LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]);
|
||||||
free(str7x_info);
|
free(str7x_info);
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
|
@ -263,8 +249,7 @@ static int str7x_waitbusy(struct flash_bank *bank)
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
struct str7x_flash_bank *str7x_info = bank->driver_priv;
|
struct str7x_flash_bank *str7x_info = bank->driver_priv;
|
||||||
|
|
||||||
for (i = 0 ; i < 10000; i++)
|
for (i = 0 ; i < 10000; i++) {
|
||||||
{
|
|
||||||
uint32_t retval;
|
uint32_t retval;
|
||||||
err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
|
err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
|
||||||
if (err != ERROR_OK)
|
if (err != ERROR_OK)
|
||||||
|
@ -290,35 +275,28 @@ static int str7x_result(struct flash_bank *bank)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (flash_flags & FLASH_WPF)
|
if (flash_flags & FLASH_WPF) {
|
||||||
{
|
|
||||||
LOG_ERROR("str7x hw write protection set");
|
LOG_ERROR("str7x hw write protection set");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (flash_flags & FLASH_RESER)
|
if (flash_flags & FLASH_RESER) {
|
||||||
{
|
|
||||||
LOG_ERROR("str7x suspended program erase not resumed");
|
LOG_ERROR("str7x suspended program erase not resumed");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (flash_flags & FLASH_10ER)
|
if (flash_flags & FLASH_10ER) {
|
||||||
{
|
|
||||||
LOG_ERROR("str7x trying to set bit to 1 when it is already 0");
|
LOG_ERROR("str7x trying to set bit to 1 when it is already 0");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (flash_flags & FLASH_PGER)
|
if (flash_flags & FLASH_PGER) {
|
||||||
{
|
|
||||||
LOG_ERROR("str7x program error");
|
LOG_ERROR("str7x program error");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (flash_flags & FLASH_ERER)
|
if (flash_flags & FLASH_ERER) {
|
||||||
{
|
|
||||||
LOG_ERROR("str7x erase error");
|
LOG_ERROR("str7x erase error");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK) {
|
||||||
{
|
if (flash_flags & FLASH_ERR) {
|
||||||
if (flash_flags & FLASH_ERR)
|
|
||||||
{
|
|
||||||
/* this should always be set if one of the others are set... */
|
/* this should always be set if one of the others are set... */
|
||||||
LOG_ERROR("str7x write operation failed / bad setup");
|
LOG_ERROR("str7x write operation failed / bad setup");
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
|
@ -336,8 +314,7 @@ static int str7x_protect_check(struct flash_bank *bank)
|
||||||
int i;
|
int i;
|
||||||
uint32_t flash_flags;
|
uint32_t flash_flags;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -347,8 +324,7 @@ static int str7x_protect_check(struct flash_bank *bank)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
if (flash_flags & str7x_info->sector_bits[i])
|
if (flash_flags & str7x_info->sector_bits[i])
|
||||||
bank->sectors[i].is_protected = 0;
|
bank->sectors[i].is_protected = 0;
|
||||||
else
|
else
|
||||||
|
@ -368,16 +344,13 @@ static int str7x_erase(struct flash_bank *bank, int first, int last)
|
||||||
uint32_t sectors = 0;
|
uint32_t sectors = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++)
|
||||||
{
|
|
||||||
sectors |= str7x_info->sector_bits[i];
|
sectors |= str7x_info->sector_bits[i];
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);
|
LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);
|
||||||
|
|
||||||
|
@ -423,16 +396,14 @@ static int str7x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
uint32_t protect_blocks;
|
uint32_t protect_blocks;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
protect_blocks = 0xFFFFFFFF;
|
protect_blocks = 0xFFFFFFFF;
|
||||||
|
|
||||||
if (set)
|
if (set) {
|
||||||
{
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++)
|
||||||
protect_blocks &= ~(str7x_info->sector_bits[i]);
|
protect_blocks &= ~(str7x_info->sector_bits[i]);
|
||||||
}
|
}
|
||||||
|
@ -516,21 +487,18 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
/* flash write code */
|
/* flash write code */
|
||||||
if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code),
|
if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code),
|
||||||
&str7x_info->write_algorithm) != ERROR_OK)
|
&str7x_info->write_algorithm) != ERROR_OK) {
|
||||||
{
|
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
target_write_buffer(target, str7x_info->write_algorithm->address,
|
target_write_buffer(target, str7x_info->write_algorithm->address,
|
||||||
sizeof(str7x_flash_write_code),
|
sizeof(str7x_flash_write_code),
|
||||||
(uint8_t*)str7x_flash_write_code);
|
(uint8_t *)str7x_flash_write_code);
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
|
||||||
/* if we already allocated the writing code, but failed to get a
|
/* if we already allocated the writing code, but failed to get a
|
||||||
* buffer, free the algorithm */
|
* buffer, free the algorithm */
|
||||||
if (str7x_info->write_algorithm)
|
if (str7x_info->write_algorithm)
|
||||||
|
@ -552,8 +520,7 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
init_reg_param(®_params[4], "r4", 32, PARAM_IN);
|
init_reg_param(®_params[4], "r4", 32, PARAM_IN);
|
||||||
init_reg_param(®_params[5], "r5", 32, PARAM_OUT);
|
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;
|
uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;
|
||||||
|
|
||||||
target_write_buffer(target, source->address, thisrun_count * 8, buffer);
|
target_write_buffer(target, source->address, thisrun_count * 8, buffer);
|
||||||
|
@ -564,16 +531,14 @@ static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
|
buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
|
||||||
buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);
|
buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
|
||||||
str7x_info->write_algorithm->address,
|
str7x_info->write_algorithm->address,
|
||||||
str7x_info->write_algorithm->address + (sizeof(str7x_flash_write_code) - 4),
|
str7x_info->write_algorithm->address + (sizeof(str7x_flash_write_code) - 4),
|
||||||
10000, &armv4_5_info)) != ERROR_OK)
|
10000, &armv4_5_info);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
|
if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00) {
|
||||||
{
|
|
||||||
retval = str7x_result(bank);
|
retval = str7x_result(bank);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -609,26 +574,22 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
uint32_t check_address = offset;
|
uint32_t check_address = offset;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset & 0x7)
|
if (offset & 0x7) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
uint32_t sec_start = bank->sectors[i].offset;
|
uint32_t sec_start = bank->sectors[i].offset;
|
||||||
uint32_t sec_end = sec_start + bank->sectors[i].size;
|
uint32_t sec_end = sec_start + bank->sectors[i].size;
|
||||||
|
|
||||||
/* check if destination falls within the current sector */
|
/* check if destination falls within the current sector */
|
||||||
if ((check_address >= sec_start) && (check_address < sec_end))
|
if ((check_address >= sec_start) && (check_address < sec_end)) {
|
||||||
{
|
|
||||||
/* check if destination ends in the current sector */
|
/* check if destination ends in the current sector */
|
||||||
if (offset + count < sec_end)
|
if (offset + count < sec_end)
|
||||||
check_address = offset + count;
|
check_address = offset + count;
|
||||||
|
@ -644,32 +605,25 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
|
||||||
|
|
||||||
/* multiple dwords (8-byte) to be programmed? */
|
/* multiple dwords (8-byte) to be programmed? */
|
||||||
if (dwords_remaining > 0)
|
if (dwords_remaining > 0) {
|
||||||
{
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
if ((retval = str7x_write_block(bank, buffer, offset,
|
retval = str7x_write_block(bank, buffer, offset, dwords_remaining);
|
||||||
dwords_remaining)) != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
|
||||||
{
|
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
* we use normal (slow) single dword accesses */
|
* we use normal (slow) single dword accesses */
|
||||||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer += dwords_remaining * 8;
|
buffer += dwords_remaining * 8;
|
||||||
address += dwords_remaining * 8;
|
address += dwords_remaining * 8;
|
||||||
dwords_remaining = 0;
|
dwords_remaining = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (dwords_remaining > 0)
|
while (dwords_remaining > 0) {
|
||||||
{
|
|
||||||
/* command */
|
/* command */
|
||||||
cmd = FLASH_DWPG;
|
cmd = FLASH_DWPG;
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
|
||||||
|
@ -704,8 +658,7 @@ static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
address += 8;
|
address += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
/* copy the last remaining bytes into the write buffer */
|
/* copy the last remaining bytes into the write buffer */
|
||||||
|
@ -777,9 +730,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
|
||||||
uint16_t ProtectionRegs;
|
uint16_t ProtectionRegs;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -790,8 +741,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -801,30 +751,24 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
|
||||||
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), ®);
|
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), ®);
|
||||||
|
|
||||||
if (!(reg & str7x_info->disable_bit))
|
if (!(reg & str7x_info->disable_bit))
|
||||||
{
|
|
||||||
ProtectionLevel = 1;
|
ProtectionLevel = 1;
|
||||||
}
|
|
||||||
|
|
||||||
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), ®);
|
target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), ®);
|
||||||
ProtectionRegs = ~(reg >> 16);
|
ProtectionRegs = ~(reg >> 16);
|
||||||
|
|
||||||
while (((ProtectionRegs) != 0) && (ProtectionLevel < 16))
|
while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) {
|
||||||
{
|
|
||||||
ProtectionRegs >>= 1;
|
ProtectionRegs >>= 1;
|
||||||
ProtectionLevel++;
|
ProtectionLevel++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProtectionLevel == 0)
|
if (ProtectionLevel == 0) {
|
||||||
{
|
|
||||||
flash_cmd = FLASH_SPR;
|
flash_cmd = FLASH_SPR;
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
|
||||||
flash_cmd = FLASH_SPR | FLASH_WMS;
|
flash_cmd = FLASH_SPR | FLASH_WMS;
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
flash_cmd = FLASH_SPR;
|
flash_cmd = FLASH_SPR;
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
|
||||||
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);
|
target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,7 +32,6 @@
|
||||||
#include <target/arm966e.h>
|
#include <target/arm966e.h>
|
||||||
#include <target/algorithm.h>
|
#include <target/algorithm.h>
|
||||||
|
|
||||||
|
|
||||||
/* Flash registers */
|
/* Flash registers */
|
||||||
|
|
||||||
#define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */
|
#define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */
|
||||||
|
@ -42,17 +42,14 @@
|
||||||
#define FLASH_SR 0x5400001C /* Status Register */
|
#define FLASH_SR 0x5400001C /* Status Register */
|
||||||
#define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */
|
#define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */
|
||||||
|
|
||||||
|
struct str9x_flash_bank {
|
||||||
struct str9x_flash_bank
|
|
||||||
{
|
|
||||||
uint32_t *sector_bits;
|
uint32_t *sector_bits;
|
||||||
int variant;
|
int variant;
|
||||||
int bank1;
|
int bank1;
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum str9x_status_codes
|
enum str9x_status_codes {
|
||||||
{
|
|
||||||
STR9X_CMD_SUCCESS = 0,
|
STR9X_CMD_SUCCESS = 0,
|
||||||
STR9X_INVALID_COMMAND = 1,
|
STR9X_INVALID_COMMAND = 1,
|
||||||
STR9X_SRC_ADDR_ERROR = 2,
|
STR9X_SRC_ADDR_ERROR = 2,
|
||||||
|
@ -82,8 +79,7 @@ static int str9x_build_block_list(struct flash_bank *bank)
|
||||||
str9x_info->variant = 0;
|
str9x_info->variant = 0;
|
||||||
str9x_info->bank1 = 0;
|
str9x_info->bank1 = 0;
|
||||||
|
|
||||||
switch (bank->size)
|
switch (bank->size) {
|
||||||
{
|
|
||||||
case (256 * 1024):
|
case (256 * 1024):
|
||||||
b0_sectors = 4;
|
b0_sectors = 4;
|
||||||
break;
|
break;
|
||||||
|
@ -124,8 +120,7 @@ static int str9x_build_block_list(struct flash_bank *bank)
|
||||||
|
|
||||||
num_sectors = 0;
|
num_sectors = 0;
|
||||||
|
|
||||||
for (i = 0; i < b0_sectors; i++)
|
for (i = 0; i < b0_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[num_sectors].offset = offset;
|
bank->sectors[num_sectors].offset = offset;
|
||||||
bank->sectors[num_sectors].size = 0x10000;
|
bank->sectors[num_sectors].size = 0x10000;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -134,8 +129,7 @@ static int str9x_build_block_list(struct flash_bank *bank)
|
||||||
str9x_info->sector_bits[num_sectors++] = (1 << i);
|
str9x_info->sector_bits[num_sectors++] = (1 << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < b1_sectors; i++)
|
for (i = 0; i < b1_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[num_sectors].offset = offset;
|
bank->sectors[num_sectors].offset = offset;
|
||||||
bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
|
bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -157,9 +151,7 @@ FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command)
|
||||||
struct str9x_flash_bank *str9x_info;
|
struct str9x_flash_bank *str9x_info;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
str9x_info = malloc(sizeof(struct str9x_flash_bank));
|
str9x_info = malloc(sizeof(struct str9x_flash_bank));
|
||||||
bank->driver_priv = str9x_info;
|
bank->driver_priv = str9x_info;
|
||||||
|
@ -182,64 +174,49 @@ static int str9x_protect_check(struct flash_bank *bank)
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
uint16_t hstatus = 0;
|
uint16_t hstatus = 0;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read level one protection */
|
/* read level one protection */
|
||||||
|
|
||||||
if (str9x_info->variant)
|
if (str9x_info->variant) {
|
||||||
{
|
if (str9x_info->bank1) {
|
||||||
if (str9x_info->bank1)
|
|
||||||
{
|
|
||||||
adr = bank1start + 0x18;
|
adr = bank1start + 0x18;
|
||||||
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
|
retval = target_write_u16(target, adr, 0x90);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
retval = target_read_u16(target, adr, &hstatus);
|
||||||
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
status = hstatus;
|
status = hstatus;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
adr = bank1start + 0x14;
|
adr = bank1start + 0x14;
|
||||||
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
|
retval = target_write_u16(target, adr, 0x90);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_read_u32(target, adr, &status);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
if ((retval = target_read_u32(target, adr, &status)) != ERROR_OK)
|
} else {
|
||||||
{
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
adr = bank1start + 0x10;
|
adr = bank1start + 0x10;
|
||||||
if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
|
retval = target_write_u16(target, adr, 0x90);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
retval = target_read_u16(target, adr, &hstatus);
|
||||||
if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
status = hstatus;
|
status = hstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read array command */
|
/* read array command */
|
||||||
if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
|
retval = target_write_u16(target, adr, 0xFF);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
if (status & str9x_info->sector_bits[i])
|
if (status & str9x_info->sector_bits[i])
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
else
|
else
|
||||||
|
@ -258,22 +235,18 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
|
||||||
uint8_t erase_cmd;
|
uint8_t erase_cmd;
|
||||||
int total_timeout;
|
int total_timeout;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we can erase whole bank */
|
/* Check if we can erase whole bank */
|
||||||
if ((first == 0) && (last == (bank->num_sectors - 1)))
|
if ((first == 0) && (last == (bank->num_sectors - 1))) {
|
||||||
{
|
|
||||||
/* Optimize to run erase bank command instead of sector */
|
/* Optimize to run erase bank command instead of sector */
|
||||||
erase_cmd = 0x80;
|
erase_cmd = 0x80;
|
||||||
/* Add timeout duration since erase bank takes more time */
|
/* Add timeout duration since erase bank takes more time */
|
||||||
total_timeout = 1000 * bank->num_sectors;
|
total_timeout = 1000 * bank->num_sectors;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Erase sector command */
|
/* Erase sector command */
|
||||||
erase_cmd = 0x20;
|
erase_cmd = 0x20;
|
||||||
total_timeout = 1000;
|
total_timeout = 1000;
|
||||||
|
@ -282,58 +255,48 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
|
||||||
/* this is so the compiler can *know* */
|
/* this is so the compiler can *know* */
|
||||||
assert(total_timeout > 0);
|
assert(total_timeout > 0);
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
int retval;
|
int retval;
|
||||||
adr = bank->base + bank->sectors[i].offset;
|
adr = bank->base + bank->sectors[i].offset;
|
||||||
|
|
||||||
/* erase sectors or block */
|
/* erase sectors or block */
|
||||||
if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK)
|
retval = target_write_u16(target, adr, erase_cmd);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
retval = target_write_u16(target, adr, 0xD0);
|
||||||
if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* get status */
|
/* get status */
|
||||||
if ((retval = target_write_u16(target, adr, 0x70)) != ERROR_OK)
|
retval = target_write_u16(target, adr, 0x70);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
int timeout;
|
int timeout;
|
||||||
for (timeout = 0; timeout < total_timeout; timeout++)
|
for (timeout = 0; timeout < total_timeout; timeout++) {
|
||||||
{
|
retval = target_read_u8(target, adr, &status);
|
||||||
if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
if (status & 0x80)
|
if (status & 0x80)
|
||||||
break;
|
break;
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
if (timeout == total_timeout)
|
if (timeout == total_timeout) {
|
||||||
{
|
|
||||||
LOG_ERROR("erase timed out");
|
LOG_ERROR("erase timed out");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear status, also clear read array */
|
/* clear status, also clear read array */
|
||||||
if ((retval = target_write_u16(target, adr, 0x50)) != ERROR_OK)
|
retval = target_write_u16(target, adr, 0x50);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/* read array command */
|
/* read array command */
|
||||||
if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
|
retval = target_write_u16(target, adr, 0xFF);
|
||||||
{
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
if (status & 0x22)
|
if (status & 0x22) {
|
||||||
{
|
|
||||||
LOG_ERROR("error erasing flash bank, status: 0x%x", status);
|
LOG_ERROR("error erasing flash bank, status: 0x%x", status);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -357,14 +320,12 @@ static int str9x_protect(struct flash_bank *bank,
|
||||||
uint32_t adr;
|
uint32_t adr;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
/* Level One Protection */
|
/* Level One Protection */
|
||||||
|
|
||||||
adr = bank->base + bank->sectors[i].offset;
|
adr = bank->base + bank->sectors[i].offset;
|
||||||
|
@ -429,22 +390,19 @@ static int str9x_write_block(struct flash_bank *bank,
|
||||||
|
|
||||||
/* flash write code */
|
/* flash write code */
|
||||||
if (target_alloc_working_area(target, sizeof(str9x_flash_write_code),
|
if (target_alloc_working_area(target, sizeof(str9x_flash_write_code),
|
||||||
&str9x_info->write_algorithm) != ERROR_OK)
|
&str9x_info->write_algorithm) != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_WARNING("no working area available, can't do block memory writes");
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
target_write_buffer(target, str9x_info->write_algorithm->address,
|
target_write_buffer(target, str9x_info->write_algorithm->address,
|
||||||
sizeof(str9x_flash_write_code),
|
sizeof(str9x_flash_write_code),
|
||||||
(uint8_t*)str9x_flash_write_code);
|
(uint8_t *)str9x_flash_write_code);
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
|
||||||
{
|
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256) {
|
||||||
{
|
|
||||||
/* if we already allocated the writing code, but failed to get a
|
/* if we already allocated the writing code, but failed to get a
|
||||||
* buffer, free the algorithm */
|
* buffer, free the algorithm */
|
||||||
if (str9x_info->write_algorithm)
|
if (str9x_info->write_algorithm)
|
||||||
|
@ -464,8 +422,7 @@ static int str9x_write_block(struct flash_bank *bank,
|
||||||
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
|
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
|
||||||
init_reg_param(®_params[3], "r3", 32, PARAM_IN);
|
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;
|
uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
|
||||||
|
|
||||||
target_write_buffer(target, source->address, thisrun_count * 2, buffer);
|
target_write_buffer(target, source->address, thisrun_count * 2, buffer);
|
||||||
|
@ -474,17 +431,16 @@ static int str9x_write_block(struct flash_bank *bank,
|
||||||
buf_set_u32(reg_params[1].value, 0, 32, address);
|
buf_set_u32(reg_params[1].value, 0, 32, address);
|
||||||
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
||||||
|
|
||||||
if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
|
||||||
str9x_info->write_algorithm->address,
|
str9x_info->write_algorithm->address,
|
||||||
0, 10000, &armv4_5_info)) != ERROR_OK)
|
0, 10000, &armv4_5_info);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("error executing str9x flash write algorithm");
|
LOG_ERROR("error executing str9x flash write algorithm");
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
|
if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80) {
|
||||||
{
|
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -519,26 +475,22 @@ static int str9x_write(struct flash_bank *bank,
|
||||||
uint32_t bank_adr;
|
uint32_t bank_adr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset & 0x1)
|
if (offset & 0x1) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
uint32_t sec_start = bank->sectors[i].offset;
|
uint32_t sec_start = bank->sectors[i].offset;
|
||||||
uint32_t sec_end = sec_start + bank->sectors[i].size;
|
uint32_t sec_end = sec_start + bank->sectors[i].size;
|
||||||
|
|
||||||
/* check if destination falls within the current sector */
|
/* check if destination falls within the current sector */
|
||||||
if ((check_address >= sec_start) && (check_address < sec_end))
|
if ((check_address >= sec_start) && (check_address < sec_end)) {
|
||||||
{
|
|
||||||
/* check if destination ends in the current sector */
|
/* check if destination ends in the current sector */
|
||||||
if (offset + count < sec_end)
|
if (offset + count < sec_end)
|
||||||
check_address = offset + count;
|
check_address = offset + count;
|
||||||
|
@ -551,33 +503,26 @@ static int str9x_write(struct flash_bank *bank,
|
||||||
return ERROR_FLASH_DST_OUT_OF_BANK;
|
return ERROR_FLASH_DST_OUT_OF_BANK;
|
||||||
|
|
||||||
/* multiple half words (2-byte) to be programmed? */
|
/* multiple half words (2-byte) to be programmed? */
|
||||||
if (words_remaining > 0)
|
if (words_remaining > 0) {
|
||||||
{
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
|
retval = str9x_write_block(bank, buffer, offset, words_remaining);
|
||||||
{
|
if (retval != ERROR_OK) {
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
{
|
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
* we use normal (slow) single dword accesses */
|
* we use normal (slow) single dword accesses */
|
||||||
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
||||||
}
|
} else if (retval == ERROR_FLASH_OPERATION_FAILED) {
|
||||||
else if (retval == ERROR_FLASH_OPERATION_FAILED)
|
|
||||||
{
|
|
||||||
LOG_ERROR("flash writing failed");
|
LOG_ERROR("flash writing failed");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer += words_remaining * 2;
|
buffer += words_remaining * 2;
|
||||||
address += words_remaining * 2;
|
address += words_remaining * 2;
|
||||||
words_remaining = 0;
|
words_remaining = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (words_remaining > 0)
|
while (words_remaining > 0) {
|
||||||
{
|
|
||||||
bank_adr = address & ~0x03;
|
bank_adr = address & ~0x03;
|
||||||
|
|
||||||
/* write data command */
|
/* write data command */
|
||||||
|
@ -588,15 +533,13 @@ static int str9x_write(struct flash_bank *bank,
|
||||||
target_write_u16(target, bank_adr, 0x70);
|
target_write_u16(target, bank_adr, 0x70);
|
||||||
|
|
||||||
int timeout;
|
int timeout;
|
||||||
for (timeout = 0; timeout < 1000; timeout++)
|
for (timeout = 0; timeout < 1000; timeout++) {
|
||||||
{
|
|
||||||
target_read_u8(target, bank_adr, &status);
|
target_read_u8(target, bank_adr, &status);
|
||||||
if (status & 0x80)
|
if (status & 0x80)
|
||||||
break;
|
break;
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
if (timeout == 1000)
|
if (timeout == 1000) {
|
||||||
{
|
|
||||||
LOG_ERROR("write timed out");
|
LOG_ERROR("write timed out");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -615,8 +558,7 @@ static int str9x_write(struct flash_bank *bank,
|
||||||
address += 2;
|
address += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint8_t last_halfword[2] = {0xff, 0xff};
|
uint8_t last_halfword[2] = {0xff, 0xff};
|
||||||
|
|
||||||
/* copy the last remaining bytes into the write buffer */
|
/* copy the last remaining bytes into the write buffer */
|
||||||
|
@ -632,15 +574,13 @@ static int str9x_write(struct flash_bank *bank,
|
||||||
target_write_u16(target, bank_adr, 0x70);
|
target_write_u16(target, bank_adr, 0x70);
|
||||||
|
|
||||||
int timeout;
|
int timeout;
|
||||||
for (timeout = 0; timeout < 1000; timeout++)
|
for (timeout = 0; timeout < 1000; timeout++) {
|
||||||
{
|
|
||||||
target_read_u8(target, bank_adr, &status);
|
target_read_u8(target, bank_adr, &status);
|
||||||
if (status & 0x80)
|
if (status & 0x80)
|
||||||
break;
|
break;
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
if (timeout == 1000)
|
if (timeout == 1000) {
|
||||||
{
|
|
||||||
LOG_ERROR("write timed out");
|
LOG_ERROR("write timed out");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -681,9 +621,7 @@ COMMAND_HANDLER(str9x_handle_flash_config_command)
|
||||||
struct target *target = NULL;
|
struct target *target = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 5)
|
if (CMD_ARGC < 5)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -698,8 +636,7 @@ COMMAND_HANDLER(str9x_handle_flash_config_command)
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,7 +28,6 @@
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include <target/arm7_9_common.h>
|
#include <target/arm7_9_common.h>
|
||||||
|
|
||||||
|
|
||||||
/* ISC commands */
|
/* ISC commands */
|
||||||
|
|
||||||
#define ISC_IDCODE 0xFE
|
#define ISC_IDCODE 0xFE
|
||||||
|
@ -61,16 +61,14 @@
|
||||||
#define STR9XPEC_OPT_LVDWARNBIT 51
|
#define STR9XPEC_OPT_LVDWARNBIT 51
|
||||||
#define STR9XPEC_OPT_OTPBIT 63
|
#define STR9XPEC_OPT_OTPBIT 63
|
||||||
|
|
||||||
enum str9xpec_status_codes
|
enum str9xpec_status_codes {
|
||||||
{
|
|
||||||
STR9XPEC_INVALID_COMMAND = 1,
|
STR9XPEC_INVALID_COMMAND = 1,
|
||||||
STR9XPEC_ISC_SUCCESS = 2,
|
STR9XPEC_ISC_SUCCESS = 2,
|
||||||
STR9XPEC_ISC_DISABLED = 3,
|
STR9XPEC_ISC_DISABLED = 3,
|
||||||
STR9XPEC_ISC_INTFAIL = 32,
|
STR9XPEC_ISC_INTFAIL = 32,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct str9xpec_flash_controller
|
struct str9xpec_flash_controller {
|
||||||
{
|
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
uint32_t *sector_bits;
|
uint32_t *sector_bits;
|
||||||
int chain_pos;
|
int chain_pos;
|
||||||
|
@ -84,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)
|
static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state)
|
||||||
{
|
{
|
||||||
if (tap == NULL) {
|
if (tap == NULL)
|
||||||
return ERROR_TARGET_INVALID;
|
return ERROR_TARGET_INVALID;
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
|
||||||
{
|
|
||||||
struct scan_field field;
|
struct scan_field field;
|
||||||
|
|
||||||
field.num_bits = tap->ir_length;
|
field.num_bits = tap->ir_length;
|
||||||
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;
|
field.out_value = t;
|
||||||
buf_set_u32(t, 0, field.num_bits, new_instr);
|
buf_set_u32(t, 0, field.num_bits, new_instr);
|
||||||
field.in_value = NULL;
|
field.in_value = NULL;
|
||||||
|
@ -147,8 +143,7 @@ static int str9xpec_isc_enable(struct flash_bank *bank)
|
||||||
|
|
||||||
/* check ISC status */
|
/* check ISC status */
|
||||||
status = str9xpec_isc_status(tap);
|
status = str9xpec_isc_status(tap);
|
||||||
if (status & ISC_STATUS_MODE)
|
if (status & ISC_STATUS_MODE) {
|
||||||
{
|
|
||||||
/* we have entered isc mode */
|
/* we have entered isc mode */
|
||||||
str9xpec_info->isc_enable = 1;
|
str9xpec_info->isc_enable = 1;
|
||||||
LOG_DEBUG("ISC_MODE Enabled");
|
LOG_DEBUG("ISC_MODE Enabled");
|
||||||
|
@ -176,8 +171,7 @@ static int str9xpec_isc_disable(struct flash_bank *bank)
|
||||||
|
|
||||||
/* check ISC status */
|
/* check ISC status */
|
||||||
status = str9xpec_isc_status(tap);
|
status = str9xpec_isc_status(tap);
|
||||||
if (!(status & ISC_STATUS_MODE))
|
if (!(status & ISC_STATUS_MODE)) {
|
||||||
{
|
|
||||||
/* we have left isc mode */
|
/* we have left isc mode */
|
||||||
str9xpec_info->isc_enable = 0;
|
str9xpec_info->isc_enable = 0;
|
||||||
LOG_DEBUG("ISC_MODE Disabled");
|
LOG_DEBUG("ISC_MODE Disabled");
|
||||||
|
@ -224,8 +218,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
int b1_size = 0x2000;
|
int b1_size = 0x2000;
|
||||||
|
|
||||||
switch (bank->size)
|
switch (bank->size) {
|
||||||
{
|
|
||||||
case (256 * 1024):
|
case (256 * 1024):
|
||||||
b0_sectors = 4;
|
b0_sectors = 4;
|
||||||
break;
|
break;
|
||||||
|
@ -258,8 +251,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
|
||||||
|
|
||||||
num_sectors = 0;
|
num_sectors = 0;
|
||||||
|
|
||||||
for (i = 0; i < b0_sectors; i++)
|
for (i = 0; i < b0_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[num_sectors].offset = offset;
|
bank->sectors[num_sectors].offset = offset;
|
||||||
bank->sectors[num_sectors].size = 0x10000;
|
bank->sectors[num_sectors].size = 0x10000;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -268,8 +260,7 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
|
||||||
str9xpec_info->sector_bits[num_sectors++] = i;
|
str9xpec_info->sector_bits[num_sectors++] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < b1_sectors; i++)
|
for (i = 0; i < b1_sectors; i++) {
|
||||||
{
|
|
||||||
bank->sectors[num_sectors].offset = offset;
|
bank->sectors[num_sectors].offset = offset;
|
||||||
bank->sectors[num_sectors].size = b1_size;
|
bank->sectors[num_sectors].size = b1_size;
|
||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
|
@ -291,9 +282,7 @@ FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command)
|
||||||
struct arm_jtag *jtag_info = NULL;
|
struct arm_jtag *jtag_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller));
|
str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller));
|
||||||
bank->driver_priv = str9xpec_info;
|
bank->driver_priv = str9xpec_info;
|
||||||
|
@ -329,21 +318,18 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
tap = str9xpec_info->tap;
|
tap = str9xpec_info->tap;
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
str9xpec_isc_enable(bank);
|
str9xpec_isc_enable(bank);
|
||||||
}
|
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
buffer = calloc(DIV_ROUND_UP(64, 8), 1);
|
buffer = calloc(DIV_ROUND_UP(64, 8), 1);
|
||||||
|
|
||||||
LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
|
LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
|
||||||
|
|
||||||
for (i = first; i <= last; i++) {
|
for (i = first; i <= last; i++)
|
||||||
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
|
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
|
||||||
}
|
|
||||||
|
|
||||||
/* execute ISC_BLANK_CHECK command */
|
/* execute ISC_BLANK_CHECK command */
|
||||||
str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE);
|
str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE);
|
||||||
|
@ -365,8 +351,7 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
status = str9xpec_isc_status(tap);
|
status = str9xpec_isc_status(tap);
|
||||||
|
|
||||||
for (i = first; i <= last; i++)
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
|
if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
|
||||||
bank->sectors[i].is_erased = 0;
|
bank->sectors[i].is_erased = 0;
|
||||||
else
|
else
|
||||||
|
@ -391,8 +376,7 @@ static int str9xpec_protect_check(struct flash_bank *bank)
|
||||||
|
|
||||||
status = str9xpec_read_config(bank);
|
status = str9xpec_read_config(bank);
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
|
if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
else
|
else
|
||||||
|
@ -416,13 +400,11 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
tap = str9xpec_info->tap;
|
tap = str9xpec_info->tap;
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
str9xpec_isc_enable(bank);
|
str9xpec_isc_enable(bank);
|
||||||
}
|
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
return ISC_STATUS_ERROR;
|
return ISC_STATUS_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
buffer = calloc(DIV_ROUND_UP(64, 8), 1);
|
buffer = calloc(DIV_ROUND_UP(64, 8), 1);
|
||||||
|
|
||||||
|
@ -430,22 +412,15 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
|
||||||
|
|
||||||
/* last bank: 0xFF signals a full erase (unlock complete device) */
|
/* last bank: 0xFF signals a full erase (unlock complete device) */
|
||||||
/* last bank: 0xFE signals a option byte erase */
|
/* last bank: 0xFE signals a option byte erase */
|
||||||
if (last == 0xFF)
|
if (last == 0xFF) {
|
||||||
{
|
for (i = 0; i < 64; i++)
|
||||||
for (i = 0; i < 64; i++) {
|
|
||||||
buf_set_u32(buffer, i, 1, 1);
|
buf_set_u32(buffer, i, 1, 1);
|
||||||
}
|
} else if (last == 0xFE)
|
||||||
}
|
|
||||||
else if (last == 0xFE)
|
|
||||||
{
|
|
||||||
buf_set_u32(buffer, 49, 1, 1);
|
buf_set_u32(buffer, 49, 1, 1);
|
||||||
}
|
else {
|
||||||
else
|
for (i = first; i <= last; i++)
|
||||||
{
|
|
||||||
for (i = first; i <= last; i++) {
|
|
||||||
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
|
buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("ISC_ERASE");
|
LOG_DEBUG("ISC_ERASE");
|
||||||
|
|
||||||
|
@ -462,9 +437,8 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
|
||||||
jtag_add_sleep(10);
|
jtag_add_sleep(10);
|
||||||
|
|
||||||
/* wait for erase completion */
|
/* wait for erase completion */
|
||||||
while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) {
|
while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY))
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
|
@ -495,13 +469,11 @@ static int str9xpec_lock_device(struct flash_bank *bank)
|
||||||
str9xpec_info = bank->driver_priv;
|
str9xpec_info = bank->driver_priv;
|
||||||
tap = str9xpec_info->tap;
|
tap = str9xpec_info->tap;
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
str9xpec_isc_enable(bank);
|
str9xpec_isc_enable(bank);
|
||||||
}
|
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
return ISC_STATUS_ERROR;
|
return ISC_STATUS_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/* set security address */
|
/* set security address */
|
||||||
str9xpec_set_address(bank, 0x80);
|
str9xpec_set_address(bank, 0x80);
|
||||||
|
@ -550,22 +522,15 @@ static int str9xpec_protect(struct flash_bank *bank, int set, int first, int las
|
||||||
LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
|
LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
|
||||||
|
|
||||||
/* last bank: 0xFF signals a full device protect */
|
/* last bank: 0xFF signals a full device protect */
|
||||||
if (last == 0xFF)
|
if (last == 0xFF) {
|
||||||
{
|
|
||||||
if (set)
|
if (set)
|
||||||
{
|
|
||||||
status = str9xpec_lock_device(bank);
|
status = str9xpec_lock_device(bank);
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* perform full erase to unlock device */
|
/* perform full erase to unlock device */
|
||||||
status = str9xpec_unlock_device(bank);
|
status = str9xpec_unlock_device(bank);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
for (i = first; i <= last; i++) {
|
||||||
{
|
|
||||||
for (i = first; i <= last; i++)
|
|
||||||
{
|
|
||||||
if (set)
|
if (set)
|
||||||
buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
|
buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
|
||||||
else
|
else
|
||||||
|
@ -619,28 +584,23 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
tap = str9xpec_info->tap;
|
tap = str9xpec_info->tap;
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
str9xpec_isc_enable(bank);
|
str9xpec_isc_enable(bank);
|
||||||
}
|
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
if (offset & 0x7)
|
if (offset & 0x7) {
|
||||||
{
|
|
||||||
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++) {
|
||||||
{
|
|
||||||
uint32_t sec_start = bank->sectors[i].offset;
|
uint32_t sec_start = bank->sectors[i].offset;
|
||||||
uint32_t sec_end = sec_start + bank->sectors[i].size;
|
uint32_t sec_end = sec_start + bank->sectors[i].size;
|
||||||
|
|
||||||
/* check if destination falls within the current sector */
|
/* check if destination falls within the current sector */
|
||||||
if ((check_address >= sec_start) && (check_address < sec_end))
|
if ((check_address >= sec_start) && (check_address < sec_end)) {
|
||||||
{
|
|
||||||
/* check if destination ends in the current sector */
|
/* check if destination ends in the current sector */
|
||||||
if (offset + count < sec_end)
|
if (offset + count < sec_end)
|
||||||
check_address = offset + count;
|
check_address = offset + count;
|
||||||
|
@ -648,14 +608,12 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
check_address = sec_end;
|
check_address = sec_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((offset >= sec_start) && (offset < sec_end)) {
|
if ((offset >= sec_start) && (offset < sec_end))
|
||||||
first_sector = i;
|
first_sector = i;
|
||||||
}
|
|
||||||
|
|
||||||
if ((offset + count >= sec_start) && (offset + count < sec_end)) {
|
if ((offset + count >= sec_start) && (offset + count < sec_end))
|
||||||
last_sector = i;
|
last_sector = i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (check_address != offset + count)
|
if (check_address != offset + count)
|
||||||
return ERROR_FLASH_DST_OUT_OF_BANK;
|
return ERROR_FLASH_DST_OUT_OF_BANK;
|
||||||
|
@ -666,15 +624,13 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
|
||||||
LOG_DEBUG("ISC_PROGRAM");
|
LOG_DEBUG("ISC_PROGRAM");
|
||||||
|
|
||||||
for (i = first_sector; i <= last_sector; i++)
|
for (i = first_sector; i <= last_sector; i++) {
|
||||||
{
|
|
||||||
str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
|
str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
|
||||||
|
|
||||||
dwords_remaining = dwords_remaining < (bank->sectors[i].size/8)
|
dwords_remaining = dwords_remaining < (bank->sectors[i].size/8)
|
||||||
? dwords_remaining : (bank->sectors[i].size/8);
|
? dwords_remaining : (bank->sectors[i].size/8);
|
||||||
|
|
||||||
while (dwords_remaining > 0)
|
while (dwords_remaining > 0) {
|
||||||
{
|
|
||||||
str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
|
str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
|
||||||
|
|
||||||
field.num_bits = 64;
|
field.num_bits = 64;
|
||||||
|
@ -711,8 +667,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_remaining)
|
if (bytes_remaining) {
|
||||||
{
|
|
||||||
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
/* copy the last remaining bytes into the write buffer */
|
/* copy the last remaining bytes into the write buffer */
|
||||||
|
@ -818,9 +773,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_read_command)
|
||||||
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -883,13 +836,11 @@ static int str9xpec_write_options(struct flash_bank *bank)
|
||||||
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
|
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
str9xpec_isc_enable(bank);
|
str9xpec_isc_enable(bank);
|
||||||
}
|
|
||||||
|
|
||||||
if (!str9xpec_info->isc_enable) {
|
if (!str9xpec_info->isc_enable)
|
||||||
return ISC_STATUS_ERROR;
|
return ISC_STATUS_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/* according to data 64th bit has to be set */
|
/* according to data 64th bit has to be set */
|
||||||
buf_set_u32(str9xpec_info->options, 63, 1, 1);
|
buf_set_u32(str9xpec_info->options, 63, 1, 1);
|
||||||
|
@ -931,9 +882,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -957,9 +906,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
|
||||||
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -969,13 +916,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
|
||||||
str9xpec_info = bank->driver_priv;
|
str9xpec_info = bank->driver_priv;
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[1], "bank1") == 0)
|
if (strcmp(CMD_ARGV[1], "bank1") == 0)
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -985,9 +928,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
|
||||||
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -997,13 +938,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
|
||||||
str9xpec_info = bank->driver_priv;
|
str9xpec_info = bank->driver_priv;
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[1], "2.7v") == 0)
|
if (strcmp(CMD_ARGV[1], "2.7v") == 0)
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1013,9 +950,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
|
||||||
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1025,13 +960,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
|
||||||
str9xpec_info = bank->driver_priv;
|
str9xpec_info = bank->driver_priv;
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
|
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1041,9 +972,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
|
||||||
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1053,13 +982,9 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
|
||||||
str9xpec_info = bank->driver_priv;
|
str9xpec_info = bank->driver_priv;
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
|
if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
|
buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1069,9 +994,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_lock_command)
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1091,9 +1014,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1120,9 +1041,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
|
||||||
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1135,23 +1054,22 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
|
||||||
|
|
||||||
/* remove arm core from chain - enter turbo mode */
|
/* remove arm core from chain - enter turbo mode */
|
||||||
tap1 = tap0->next_tap;
|
tap1 = tap0->next_tap;
|
||||||
if (tap1 == NULL)
|
if (tap1 == NULL) {
|
||||||
{
|
|
||||||
/* things are *WRONG* */
|
/* things are *WRONG* */
|
||||||
command_print(CMD_CTX,"**STR9FLASH** (tap1) invalid chain?");
|
command_print(CMD_CTX, "**STR9FLASH** (tap1) invalid chain?");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
tap2 = tap1->next_tap;
|
tap2 = tap1->next_tap;
|
||||||
if (tap2 == NULL)
|
if (tap2 == NULL) {
|
||||||
{
|
|
||||||
/* things are *WRONG* */
|
/* things are *WRONG* */
|
||||||
command_print(CMD_CTX,"**STR9FLASH** (tap2) invalid chain?");
|
command_print(CMD_CTX, "**STR9FLASH** (tap2) invalid chain?");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable turbo mode - TURBO-PROG-ENABLE */
|
/* enable turbo mode - TURBO-PROG-ENABLE */
|
||||||
str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
|
str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
|
||||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* modify scan chain - str9 core has been removed */
|
/* modify scan chain - str9 core has been removed */
|
||||||
|
@ -1166,9 +1084,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
|
||||||
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
struct str9xpec_flash_controller *str9xpec_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
@ -1187,9 +1103,8 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
|
||||||
jtag_execute_queue();
|
jtag_execute_queue();
|
||||||
|
|
||||||
/* restore previous scan chain */
|
/* restore previous scan chain */
|
||||||
if (tap->next_tap) {
|
if (tap->next_tap)
|
||||||
tap->next_tap->enabled = 1;
|
tap->next_tap->enabled = 1;
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
|
||||||
return get_flash_bank_by_num(bank_num, bank);
|
return get_flash_bank_by_num(bank_num, bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_flash_info_command)
|
COMMAND_HANDLER(handle_flash_info_command)
|
||||||
{
|
{
|
||||||
struct flash_bank *p;
|
struct flash_bank *p;
|
||||||
|
@ -61,12 +60,12 @@ COMMAND_HANDLER(handle_flash_info_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (p != NULL)
|
if (p != NULL) {
|
||||||
{
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
/* attempt auto probe */
|
/* attempt auto probe */
|
||||||
if ((retval = p->driver->auto_probe(p)) != ERROR_OK)
|
retval = p->driver->auto_probe(p);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* We must query the hardware to avoid printing stale information! */
|
/* We must query the hardware to avoid printing stale information! */
|
||||||
|
@ -75,15 +74,15 @@ COMMAND_HANDLER(handle_flash_info_command)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
command_print(CMD_CTX,
|
command_print(CMD_CTX,
|
||||||
"#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", buswidth %i, chipwidth %i",
|
"#%" PRIu32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32
|
||||||
|
", buswidth %i, chipwidth %i",
|
||||||
p->bank_number,
|
p->bank_number,
|
||||||
p->driver->name,
|
p->driver->name,
|
||||||
p->base,
|
p->base,
|
||||||
p->size,
|
p->size,
|
||||||
p->bus_width,
|
p->bus_width,
|
||||||
p->chip_width);
|
p->chip_width);
|
||||||
for (j = 0; j < p->num_sectors; j++)
|
for (j = 0; j < p->num_sectors; j++) {
|
||||||
{
|
|
||||||
char *protect_state;
|
char *protect_state;
|
||||||
|
|
||||||
if (p->sectors[j].is_protected == 0)
|
if (p->sectors[j].is_protected == 0)
|
||||||
|
@ -102,7 +101,8 @@ COMMAND_HANDLER(handle_flash_info_command)
|
||||||
protect_state);
|
protect_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
*buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
|
*buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver
|
||||||
|
*function fails */
|
||||||
retval = p->driver->info(p, buf, sizeof(buf));
|
retval = p->driver->info(p, buf, sizeof(buf));
|
||||||
command_print(CMD_CTX, "%s", buf);
|
command_print(CMD_CTX, "%s", buf);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -118,23 +118,20 @@ COMMAND_HANDLER(handle_flash_probe_command)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
|
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (p)
|
if (p) {
|
||||||
{
|
retval = p->driver->probe(p);
|
||||||
if ((retval = p->driver->probe(p)) == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
{
|
command_print(CMD_CTX,
|
||||||
command_print(CMD_CTX, "flash '%s' found at 0x%8.8" PRIx32, p->driver->name, p->base);
|
"flash '%s' found at 0x%8.8" PRIx32,
|
||||||
}
|
p->driver->name,
|
||||||
}
|
p->base);
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
|
command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -145,9 +142,7 @@ COMMAND_HANDLER(handle_flash_probe_command)
|
||||||
COMMAND_HANDLER(handle_flash_erase_check_command)
|
COMMAND_HANDLER(handle_flash_erase_check_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
struct flash_bank *p;
|
struct flash_bank *p;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
|
||||||
|
@ -155,18 +150,17 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
int j;
|
int j;
|
||||||
if ((retval = p->driver->erase_check(p)) == ERROR_OK)
|
retval = p->driver->erase_check(p);
|
||||||
{
|
if (retval == ERROR_OK)
|
||||||
command_print(CMD_CTX, "successfully checked erase state");
|
command_print(CMD_CTX, "successfully checked erase state");
|
||||||
}
|
else {
|
||||||
else
|
command_print(CMD_CTX,
|
||||||
{
|
"unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
|
||||||
command_print(CMD_CTX, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
|
CMD_ARGV[0],
|
||||||
CMD_ARGV[0], p->base);
|
p->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < p->num_sectors; j++)
|
for (j = 0; j < p->num_sectors; j++) {
|
||||||
{
|
|
||||||
char *erase_state;
|
char *erase_state;
|
||||||
|
|
||||||
if (p->sectors[j].is_erased == 0)
|
if (p->sectors[j].is_erased == 0)
|
||||||
|
@ -198,35 +192,27 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
|
||||||
bool do_unlock = false;
|
bool do_unlock = false;
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
|
|
||||||
while (CMD_ARGC >= 3)
|
while (CMD_ARGC >= 3) {
|
||||||
{
|
|
||||||
/* Optionally pad out the address range to block/sector
|
/* Optionally pad out the address range to block/sector
|
||||||
* boundaries. We can't know if there's data in that part
|
* boundaries. We can't know if there's data in that part
|
||||||
* of the flash; only do padding if we're told to.
|
* of the flash; only do padding if we're told to.
|
||||||
*/
|
*/
|
||||||
if (strcmp("pad", CMD_ARGV[0]) == 0)
|
if (strcmp("pad", CMD_ARGV[0]) == 0)
|
||||||
{
|
|
||||||
do_pad = true;
|
do_pad = true;
|
||||||
} else if (strcmp("unlock", CMD_ARGV[0]) == 0)
|
else if (strcmp("unlock", CMD_ARGV[0]) == 0)
|
||||||
{
|
|
||||||
do_unlock = true;
|
do_unlock = true;
|
||||||
} else
|
else
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
CMD_ARGC--;
|
CMD_ARGC--;
|
||||||
CMD_ARGV++;
|
CMD_ARGV++;
|
||||||
}
|
}
|
||||||
if (CMD_ARGC != 2)
|
if (CMD_ARGC != 2)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "Length must be >0");
|
command_print(CMD_CTX, "Length must be >0");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -235,24 +221,20 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* We can't know if we did a resume + halt, in which case we no longer know the erased state */
|
/* We can't know if we did a resume + halt, in which case we no longer know the erased state
|
||||||
|
**/
|
||||||
flash_set_dirty();
|
flash_set_dirty();
|
||||||
|
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
duration_start(&bench);
|
duration_start(&bench);
|
||||||
|
|
||||||
if (do_unlock)
|
if (do_unlock)
|
||||||
{
|
|
||||||
retval = flash_unlock_address_range(target, address, length);
|
retval = flash_unlock_address_range(target, address, length);
|
||||||
}
|
|
||||||
|
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
{
|
|
||||||
retval = flash_erase_address_range(target, do_pad, address, length);
|
retval = flash_erase_address_range(target, do_pad, address, length);
|
||||||
}
|
|
||||||
|
|
||||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "erased address 0x%8.8x (length %i)"
|
command_print(CMD_CTX, "erased address 0x%8.8x (length %i)"
|
||||||
" in %fs (%0.3f KiB/s)", address, length,
|
" in %fs (%0.3f KiB/s)", address, length,
|
||||||
duration_elapsed(&bench), duration_kbps(&bench, length));
|
duration_elapsed(&bench), duration_kbps(&bench, length));
|
||||||
|
@ -300,8 +282,8 @@ COMMAND_HANDLER(handle_flash_erase_command)
|
||||||
else
|
else
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
|
||||||
|
|
||||||
if ((retval = flash_check_sector_parameters(CMD_CTX,
|
retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
|
||||||
first, last, p->num_sectors)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
|
@ -309,10 +291,9 @@ COMMAND_HANDLER(handle_flash_erase_command)
|
||||||
|
|
||||||
retval = flash_driver_erase(p, first, last);
|
retval = flash_driver_erase(p, first, last);
|
||||||
|
|
||||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "erased sectors %" PRIu32 " "
|
command_print(CMD_CTX, "erased sectors %" PRIu32 " "
|
||||||
"through %" PRIu32" on flash bank %" PRIu32 " "
|
"through %" PRIu32 " on flash bank %" PRIu32 " "
|
||||||
"in %fs", first, last, p->bank_number, duration_elapsed(&bench));
|
"in %fs", first, last, p->bank_number, duration_elapsed(&bench));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,8 +324,8 @@ COMMAND_HANDLER(handle_flash_protect_command)
|
||||||
bool set;
|
bool set;
|
||||||
COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
|
COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
|
||||||
|
|
||||||
if ((retval = flash_check_sector_parameters(CMD_CTX,
|
retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
|
||||||
first, last, p->num_sectors)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = flash_driver_protect(p, set, first, last);
|
retval = flash_driver_protect(p, set, first, last);
|
||||||
|
@ -368,41 +349,31 @@ COMMAND_HANDLER(handle_flash_write_image_command)
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/* flash auto-erase is disabled by default*/
|
/* flash auto-erase is disabled by default*/
|
||||||
int auto_erase = 0;
|
int auto_erase = 0;
|
||||||
bool auto_unlock = false;
|
bool auto_unlock = false;
|
||||||
|
|
||||||
for (;;)
|
for (;; ) {
|
||||||
{
|
if (strcmp(CMD_ARGV[0], "erase") == 0) {
|
||||||
if (strcmp(CMD_ARGV[0], "erase") == 0)
|
|
||||||
{
|
|
||||||
auto_erase = 1;
|
auto_erase = 1;
|
||||||
CMD_ARGV++;
|
CMD_ARGV++;
|
||||||
CMD_ARGC--;
|
CMD_ARGC--;
|
||||||
command_print(CMD_CTX, "auto erase enabled");
|
command_print(CMD_CTX, "auto erase enabled");
|
||||||
} else if (strcmp(CMD_ARGV[0], "unlock") == 0)
|
} else if (strcmp(CMD_ARGV[0], "unlock") == 0) {
|
||||||
{
|
|
||||||
auto_unlock = true;
|
auto_unlock = true;
|
||||||
CMD_ARGV++;
|
CMD_ARGV++;
|
||||||
CMD_ARGC--;
|
CMD_ARGC--;
|
||||||
command_print(CMD_CTX, "auto unlock enabled");
|
command_print(CMD_CTX, "auto unlock enabled");
|
||||||
} else
|
} else
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
if (!target)
|
if (!target) {
|
||||||
{
|
|
||||||
LOG_ERROR("no target selected");
|
LOG_ERROR("no target selected");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -410,13 +381,10 @@ COMMAND_HANDLER(handle_flash_write_image_command)
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
duration_start(&bench);
|
duration_start(&bench);
|
||||||
|
|
||||||
if (CMD_ARGC >= 2)
|
if (CMD_ARGC >= 2) {
|
||||||
{
|
|
||||||
image.base_address_set = 1;
|
image.base_address_set = 1;
|
||||||
COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
|
COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
image.base_address_set = 0;
|
image.base_address_set = 0;
|
||||||
image.base_address = 0x0;
|
image.base_address = 0x0;
|
||||||
}
|
}
|
||||||
|
@ -425,19 +393,15 @@ COMMAND_HANDLER(handle_flash_write_image_command)
|
||||||
|
|
||||||
retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
|
retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
|
retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
image_close(&image);
|
image_close(&image);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
|
command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
|
||||||
"in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
|
"in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
|
||||||
duration_elapsed(&bench), duration_kbps(&bench, written));
|
duration_elapsed(&bench), duration_kbps(&bench, written));
|
||||||
|
@ -468,20 +432,17 @@ COMMAND_HANDLER(handle_flash_fill_command)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
uint8_t *readback = malloc(chunksize);
|
uint8_t *readback = malloc(chunksize);
|
||||||
if (readback == NULL)
|
if (readback == NULL) {
|
||||||
{
|
|
||||||
free(chunk);
|
free(chunk);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (CMD_ARGC != 3)
|
if (CMD_ARGC != 3) {
|
||||||
{
|
|
||||||
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
|
||||||
|
@ -489,8 +450,7 @@ COMMAND_HANDLER(handle_flash_fill_command)
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
switch (CMD_NAME[4])
|
switch (CMD_NAME[4]) {
|
||||||
{
|
|
||||||
case 'w':
|
case 'w':
|
||||||
wordsize = 4;
|
wordsize = 4;
|
||||||
break;
|
break;
|
||||||
|
@ -506,19 +466,14 @@ COMMAND_HANDLER(handle_flash_fill_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_count = MIN(count, (chunksize / wordsize));
|
chunk_count = MIN(count, (chunksize / wordsize));
|
||||||
switch (wordsize)
|
switch (wordsize) {
|
||||||
{
|
|
||||||
case 4:
|
case 4:
|
||||||
for (i = 0; i < chunk_count; i++)
|
for (i = 0; i < chunk_count; i++)
|
||||||
{
|
|
||||||
target_buffer_set_u32(target, chunk + i * wordsize, pattern);
|
target_buffer_set_u32(target, chunk + i * wordsize, pattern);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for (i = 0; i < chunk_count; i++)
|
for (i = 0; i < chunk_count; i++)
|
||||||
{
|
|
||||||
target_buffer_set_u16(target, chunk + i * wordsize, pattern);
|
target_buffer_set_u16(target, chunk + i * wordsize, pattern);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
memset(chunk, pattern, chunk_count);
|
memset(chunk, pattern, chunk_count);
|
||||||
|
@ -531,43 +486,40 @@ COMMAND_HANDLER(handle_flash_fill_command)
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
duration_start(&bench);
|
duration_start(&bench);
|
||||||
|
|
||||||
for (wrote = 0; wrote < (count*wordsize); wrote += cur_size)
|
for (wrote = 0; wrote < (count*wordsize); wrote += cur_size) {
|
||||||
{
|
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
|
|
||||||
retval = get_flash_bank_by_addr(target, address, true, &bank );
|
retval = get_flash_bank_by_addr(target, address, true, &bank);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
cur_size = MIN((count * wordsize - wrote), chunksize);
|
cur_size = MIN((count * wordsize - wrote), chunksize);
|
||||||
err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size);
|
err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size);
|
||||||
if (err != ERROR_OK)
|
if (err != ERROR_OK) {
|
||||||
{
|
|
||||||
retval = err;
|
retval = err;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size);
|
err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size);
|
||||||
if (err != ERROR_OK)
|
if (err != ERROR_OK) {
|
||||||
{
|
|
||||||
retval = err;
|
retval = err;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < cur_size; i++)
|
for (i = 0; i < cur_size; i++) {
|
||||||
{
|
if (readback[i] != chunk[i]) {
|
||||||
if (readback[i]!=chunk[i])
|
LOG_ERROR(
|
||||||
{
|
"Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
|
||||||
LOG_ERROR("Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
|
address + wrote + i,
|
||||||
address + wrote + i, readback[i], chunk[i]);
|
readback[i],
|
||||||
|
chunk[i]);
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK))
|
if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32
|
command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32
|
||||||
" in %fs (%0.3f KiB/s)", wrote, address,
|
" in %fs (%0.3f KiB/s)", wrote, address,
|
||||||
duration_elapsed(&bench), duration_kbps(&bench, wrote));
|
duration_elapsed(&bench), duration_kbps(&bench, wrote));
|
||||||
|
@ -600,28 +552,23 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
|
||||||
|
|
||||||
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
|
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
|
||||||
{
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
|
||||||
|
|
||||||
int filesize;
|
int filesize;
|
||||||
retval = fileio_size(&fileio, &filesize);
|
retval = fileio_size(&fileio, &filesize);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
fileio_close(&fileio);
|
fileio_close(&fileio);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = malloc(filesize);
|
buffer = malloc(filesize);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL) {
|
||||||
{
|
|
||||||
fileio_close(&fileio);
|
fileio_close(&fileio);
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
size_t buf_cnt;
|
size_t buf_cnt;
|
||||||
if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK)
|
if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) {
|
||||||
{
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
fileio_close(&fileio);
|
fileio_close(&fileio);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -632,8 +579,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
|
|
||||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u"
|
command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u"
|
||||||
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
||||||
(long)filesize, CMD_ARGV[1], p->bank_number, offset,
|
(long)filesize, CMD_ARGV[1], p->bank_number, offset,
|
||||||
|
@ -651,13 +597,10 @@ void flash_set_dirty(void)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* set all flash to require erasing */
|
/* set all flash to require erasing */
|
||||||
for (c = flash_bank_list(); c; c = c->next)
|
for (c = flash_bank_list(); c; c = c->next) {
|
||||||
{
|
|
||||||
for (i = 0; i < c->num_sectors; i++)
|
for (i = 0; i < c->num_sectors; i++)
|
||||||
{
|
|
||||||
c->sectors[i].is_erased = 0;
|
c->sectors[i].is_erased = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct command_registration flash_exec_command_handlers[] = {
|
static const struct command_registration flash_exec_command_handlers[] = {
|
||||||
|
@ -770,47 +713,41 @@ static int flash_init_drivers(struct command_context *cmd_ctx)
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_flash_bank_command)
|
COMMAND_HANDLER(handle_flash_bank_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC < 7)
|
if (CMD_ARGC < 7) {
|
||||||
{
|
|
||||||
LOG_ERROR("usage: flash bank <name> <driver> "
|
LOG_ERROR("usage: flash bank <name> <driver> "
|
||||||
"<base> <size> <chip_width> <bus_width> <target>");
|
"<base> <size> <chip_width> <bus_width> <target>");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
// save bank name and advance arguments for compatibility
|
/* save bank name and advance arguments for compatibility */
|
||||||
const char *bank_name = *CMD_ARGV++;
|
const char *bank_name = *CMD_ARGV++;
|
||||||
CMD_ARGC--;
|
CMD_ARGC--;
|
||||||
|
|
||||||
struct target *target;
|
struct target *target = get_target(CMD_ARGV[5]);
|
||||||
if ((target = get_target(CMD_ARGV[5])) == NULL)
|
if (target == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
|
LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *driver_name = CMD_ARGV[0];
|
const char *driver_name = CMD_ARGV[0];
|
||||||
struct flash_driver *driver = flash_driver_find_by_name(driver_name);
|
struct flash_driver *driver = flash_driver_find_by_name(driver_name);
|
||||||
if (NULL == driver)
|
if (NULL == driver) {
|
||||||
{
|
|
||||||
/* no matching flash driver found */
|
/* no matching flash driver found */
|
||||||
LOG_ERROR("flash driver '%s' not found", driver_name);
|
LOG_ERROR("flash driver '%s' not found", driver_name);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check the flash bank name is unique */
|
/* check the flash bank name is unique */
|
||||||
if (get_flash_bank_by_name_noprobe(bank_name) != NULL)
|
if (get_flash_bank_by_name_noprobe(bank_name) != NULL) {
|
||||||
{
|
|
||||||
/* flash bank name already exists */
|
/* flash bank name already exists */
|
||||||
LOG_ERROR("flash bank name '%s' already exists", bank_name);
|
LOG_ERROR("flash bank name '%s' already exists", bank_name);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register flash specific commands */
|
/* register flash specific commands */
|
||||||
if (NULL != driver->commands)
|
if (NULL != driver->commands) {
|
||||||
{
|
|
||||||
int retval = register_commands(CMD_CTX, NULL,
|
int retval = register_commands(CMD_CTX, NULL,
|
||||||
driver->commands);
|
driver->commands);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval) {
|
||||||
{
|
|
||||||
LOG_ERROR("couldn't register '%s' commands",
|
LOG_ERROR("couldn't register '%s' commands",
|
||||||
driver_name);
|
driver_name);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -832,8 +769,7 @@ COMMAND_HANDLER(handle_flash_bank_command)
|
||||||
|
|
||||||
int retval;
|
int retval;
|
||||||
retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
|
retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval) {
|
||||||
{
|
|
||||||
LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "Usage %s",
|
LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "Usage %s",
|
||||||
driver_name, c->base, driver->usage);
|
driver_name, c->base, driver->usage);
|
||||||
free(c);
|
free(c);
|
||||||
|
@ -854,8 +790,7 @@ COMMAND_HANDLER(handle_flash_banks_command)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++)
|
for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) {
|
||||||
{
|
|
||||||
LOG_USER("#%" PRIu32 " : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
|
LOG_USER("#%" PRIu32 " : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
|
||||||
"buswidth %u, chipwidth %u", p->bank_number,
|
"buswidth %u, chipwidth %u", p->bank_number,
|
||||||
p->name, p->driver->name, p->base, p->size,
|
p->name, p->driver->name, p->base, p->size,
|
||||||
|
@ -864,10 +799,9 @@ COMMAND_HANDLER(handle_flash_banks_command)
|
||||||
return ERROR_OK;
|
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,
|
Jim_WrongNumArgs(interp, 1, argv,
|
||||||
"no arguments to 'flash list' command");
|
"no arguments to 'flash list' command");
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
|
@ -875,8 +809,7 @@ static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
|
|
||||||
Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
|
Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
|
||||||
|
|
||||||
for (struct flash_bank *p = flash_bank_list(); p; p = p->next)
|
for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
|
||||||
{
|
|
||||||
Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
|
Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
|
||||||
|
|
||||||
Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
|
Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
|
||||||
|
@ -898,15 +831,13 @@ static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
return JIM_OK;
|
return JIM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_flash_init_command)
|
COMMAND_HANDLER(handle_flash_init_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 0)
|
if (CMD_ARGC != 0)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
static bool flash_initialized = false;
|
static bool flash_initialized;
|
||||||
if (flash_initialized)
|
if (flash_initialized) {
|
||||||
{
|
|
||||||
LOG_INFO("'flash init' has already been called");
|
LOG_INFO("'flash init' has already been called");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,18 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
Internal Support, Helpers
|
* Internal Support, Helpers
|
||||||
---------------------------------------------------------------------- */
|
* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
struct tms470_flash_bank
|
struct tms470_flash_bank {
|
||||||
{
|
|
||||||
unsigned ordinal;
|
unsigned ordinal;
|
||||||
|
|
||||||
/* device identification register */
|
/* device identification register */
|
||||||
|
@ -38,7 +37,7 @@ struct tms470_flash_bank
|
||||||
uint32_t technology_family;
|
uint32_t technology_family;
|
||||||
uint32_t rom_flash;
|
uint32_t rom_flash;
|
||||||
uint32_t part_number;
|
uint32_t part_number;
|
||||||
const char * part_name;
|
const char *part_name;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,8 +140,7 @@ static int tms470_read_part_info(struct flash_bank *bank)
|
||||||
|
|
||||||
LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg);
|
LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg);
|
||||||
|
|
||||||
if ((device_ident_reg & 7) == 0)
|
if ((device_ident_reg & 7) == 0) {
|
||||||
{
|
|
||||||
LOG_WARNING("Cannot identify target as a TMS470 family.");
|
LOG_WARNING("Cannot identify target as a TMS470 family.");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -152,8 +150,7 @@ static int tms470_read_part_info(struct flash_bank *bank)
|
||||||
rom_flash = (device_ident_reg >> 10) & 1;
|
rom_flash = (device_ident_reg >> 10) & 1;
|
||||||
part_number = (device_ident_reg >> 3) & 0x7f;
|
part_number = (device_ident_reg >> 3) & 0x7f;
|
||||||
|
|
||||||
if (bank->sectors)
|
if (bank->sectors) {
|
||||||
{
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
}
|
}
|
||||||
|
@ -164,14 +161,14 @@ static int tms470_read_part_info(struct flash_bank *bank)
|
||||||
* ranges. Then fixup/complete the remaining fields of the flash
|
* ranges. Then fixup/complete the remaining fields of the flash
|
||||||
* bank structure.
|
* bank structure.
|
||||||
*/
|
*/
|
||||||
switch (part_number)
|
switch (part_number) {
|
||||||
{
|
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
part_name = "TMS470R1A256";
|
part_name = "TMS470R1A256";
|
||||||
|
|
||||||
if (bank->base >= 0x00040000)
|
if (bank->base >= 0x00040000) {
|
||||||
{
|
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
|
||||||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
|
part_name,
|
||||||
|
bank->base);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
tms470_info->ordinal = 0;
|
tms470_info->ordinal = 0;
|
||||||
|
@ -180,44 +177,36 @@ static int tms470_read_part_info(struct flash_bank *bank)
|
||||||
bank->num_sectors = TMS470R1A256_NUM_SECTORS;
|
bank->num_sectors = TMS470R1A256_NUM_SECTORS;
|
||||||
bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
|
bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
|
||||||
if (!bank->sectors)
|
if (!bank->sectors)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
|
(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2b:
|
case 0x2b:
|
||||||
part_name = "TMS470R1A288";
|
part_name = "TMS470R1A288";
|
||||||
|
|
||||||
if (bank->base < 0x00008000)
|
if (bank->base < 0x00008000) {
|
||||||
{
|
|
||||||
tms470_info->ordinal = 0;
|
tms470_info->ordinal = 0;
|
||||||
bank->base = 0x00000000;
|
bank->base = 0x00000000;
|
||||||
bank->size = 32 * 1024;
|
bank->size = 32 * 1024;
|
||||||
bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
|
bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
|
||||||
bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
|
bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
|
||||||
if (!bank->sectors)
|
if (!bank->sectors)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS,
|
||||||
(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS, sizeof(TMS470R1A288_BANK0_SECTORS));
|
sizeof(TMS470R1A288_BANK0_SECTORS));
|
||||||
}
|
} else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
|
||||||
else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000))
|
|
||||||
{
|
|
||||||
tms470_info->ordinal = 1;
|
tms470_info->ordinal = 1;
|
||||||
bank->base = 0x00040000;
|
bank->base = 0x00040000;
|
||||||
bank->size = 256 * 1024;
|
bank->size = 256 * 1024;
|
||||||
bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
|
bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
|
||||||
bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
|
bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
|
||||||
if (!bank->sectors)
|
if (!bank->sectors)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS,
|
||||||
(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, sizeof(TMS470R1A288_BANK1_SECTORS));
|
sizeof(TMS470R1A288_BANK1_SECTORS));
|
||||||
}
|
} else {
|
||||||
else
|
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
|
||||||
{
|
part_name, bank->base);
|
||||||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -225,54 +214,46 @@ static int tms470_read_part_info(struct flash_bank *bank)
|
||||||
case 0x2d:
|
case 0x2d:
|
||||||
part_name = "TMS470R1A384";
|
part_name = "TMS470R1A384";
|
||||||
|
|
||||||
if (bank->base < 0x00020000)
|
if (bank->base < 0x00020000) {
|
||||||
{
|
|
||||||
tms470_info->ordinal = 0;
|
tms470_info->ordinal = 0;
|
||||||
bank->base = 0x00000000;
|
bank->base = 0x00000000;
|
||||||
bank->size = 128 * 1024;
|
bank->size = 128 * 1024;
|
||||||
bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
|
bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
|
||||||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
|
bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
|
||||||
if (!bank->sectors)
|
if (!bank->sectors)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS,
|
||||||
(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS, sizeof(TMS470R1A384_BANK0_SECTORS));
|
sizeof(TMS470R1A384_BANK0_SECTORS));
|
||||||
}
|
} else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
|
||||||
else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000))
|
|
||||||
{
|
|
||||||
tms470_info->ordinal = 1;
|
tms470_info->ordinal = 1;
|
||||||
bank->base = 0x00020000;
|
bank->base = 0x00020000;
|
||||||
bank->size = 128 * 1024;
|
bank->size = 128 * 1024;
|
||||||
bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
|
bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
|
||||||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
|
bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
|
||||||
if (!bank->sectors)
|
if (!bank->sectors)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS,
|
||||||
(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS, sizeof(TMS470R1A384_BANK1_SECTORS));
|
sizeof(TMS470R1A384_BANK1_SECTORS));
|
||||||
}
|
} else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
|
||||||
else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000))
|
|
||||||
{
|
|
||||||
tms470_info->ordinal = 2;
|
tms470_info->ordinal = 2;
|
||||||
bank->base = 0x00040000;
|
bank->base = 0x00040000;
|
||||||
bank->size = 128 * 1024;
|
bank->size = 128 * 1024;
|
||||||
bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
|
bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
|
||||||
bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
|
bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
|
||||||
if (!bank->sectors)
|
if (!bank->sectors)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS,
|
||||||
(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, sizeof(TMS470R1A384_BANK2_SECTORS));
|
sizeof(TMS470R1A384_BANK2_SECTORS));
|
||||||
}
|
} else {
|
||||||
else
|
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
|
||||||
{
|
part_name, bank->base);
|
||||||
LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", (unsigned)part_number);
|
LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.",
|
||||||
|
(unsigned)part_number);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,67 +287,57 @@ static int tms470_read_part_info(struct flash_bank *bank)
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
static uint32_t keysSet = 0;
|
static uint32_t keysSet;
|
||||||
static uint32_t flashKeys[4];
|
static uint32_t flashKeys[4];
|
||||||
|
|
||||||
COMMAND_HANDLER(tms470_handle_flash_keyset_command)
|
COMMAND_HANDLER(tms470_handle_flash_keyset_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC > 4)
|
if (CMD_ARGC > 4)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
else if (CMD_ARGC == 4) {
|
||||||
else if (CMD_ARGC == 4)
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
{
|
|
||||||
int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;
|
int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;
|
||||||
|
|
||||||
if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i]))
|
if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) {
|
||||||
{
|
command_print(CMD_CTX, "could not process flash key %s",
|
||||||
command_print(CMD_CTX, "could not process flash key %s", CMD_ARGV[i]);
|
CMD_ARGV[i]);
|
||||||
LOG_ERROR("could not process flash key %s", CMD_ARGV[i]);
|
LOG_ERROR("could not process flash key %s", CMD_ARGV[i]);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keysSet = 1;
|
keysSet = 1;
|
||||||
}
|
} else if (CMD_ARGC != 0) {
|
||||||
else if (CMD_ARGC != 0)
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
|
command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keysSet)
|
if (keysSet) {
|
||||||
{
|
command_print(CMD_CTX,
|
||||||
command_print(CMD_CTX, "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
|
"using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
|
||||||
flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3]);
|
flashKeys[0],
|
||||||
}
|
flashKeys[1],
|
||||||
else
|
flashKeys[2],
|
||||||
{
|
flashKeys[3]);
|
||||||
|
} else
|
||||||
command_print(CMD_CTX, "flash keys not set");
|
command_print(CMD_CTX, "flash keys not set");
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
|
static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
0xFFFFFFFF, 0xFFFFFFFF,
|
0xFFFFFFFF, 0xFFFFFFFF,};
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
|
static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
|
||||||
0x00000000, 0x00000000,
|
0x00000000, 0x00000000,};
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
|
static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
|
||||||
0xf0fff0ff, 0xf0fff0ff
|
0xf0fff0ff, 0xf0fff0ff};
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
|
static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
|
||||||
0x0000ffff, 0x0000ffff
|
0x0000ffff, 0x0000ffff};
|
||||||
};
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -375,16 +346,11 @@ static int oscMHz = 12;
|
||||||
COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
|
COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC > 1)
|
if (CMD_ARGC > 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
else if (CMD_ARGC == 1)
|
else if (CMD_ARGC == 1)
|
||||||
{
|
|
||||||
sscanf(CMD_ARGV[0], "%d", &oscMHz);
|
sscanf(CMD_ARGV[0], "%d", &oscMHz);
|
||||||
}
|
|
||||||
|
|
||||||
if (oscMHz <= 0)
|
if (oscMHz <= 0) {
|
||||||
{
|
|
||||||
LOG_ERROR("osc_megahertz must be positive and non-zero!");
|
LOG_ERROR("osc_megahertz must be positive and non-zero!");
|
||||||
command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!");
|
command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!");
|
||||||
oscMHz = 12;
|
oscMHz = 12;
|
||||||
|
@ -398,16 +364,13 @@ COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int plldis = 0;
|
static int plldis;
|
||||||
|
|
||||||
COMMAND_HANDLER(tms470_handle_plldis_command)
|
COMMAND_HANDLER(tms470_handle_plldis_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC > 1)
|
if (CMD_ARGC > 1)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
else if (CMD_ARGC == 1) {
|
||||||
else if (CMD_ARGC == 1)
|
|
||||||
{
|
|
||||||
sscanf(CMD_ARGV[0], "%d", &plldis);
|
sscanf(CMD_ARGV[0], "%d", &plldis);
|
||||||
plldis = plldis ? 1 : 0;
|
plldis = plldis ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
uint32_t fmbbusy;
|
||||||
|
|
||||||
target_read_u32(target, 0xFFE89C08, &fmbbusy);
|
target_read_u32(target, 0xFFE89C08, &fmbbusy);
|
||||||
LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s", fmbbusy, fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
|
LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s",
|
||||||
|
fmbbusy,
|
||||||
|
fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
|
||||||
return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
|
return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
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;
|
uint32_t glbctrl, fmmstat;
|
||||||
int retval = ERROR_FLASH_OPERATION_FAILED;
|
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 */
|
/* only perform the key match when 3VSTAT is clear */
|
||||||
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
||||||
if (!(fmmstat & 0x08))
|
if (!(fmmstat & 0x08)) {
|
||||||
{
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
uint32_t fmbptr, fmbac2, orig_fmregopt;
|
uint32_t fmbptr, fmbac2, orig_fmregopt;
|
||||||
|
|
||||||
target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);
|
target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);
|
||||||
|
|
||||||
/* wait for pump ready */
|
/* wait for pump ready */
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, 0xFFE8A814, &fmbptr);
|
target_read_u32(target, 0xFFE8A814, &fmbptr);
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
} while (!(fmbptr & 0x0200));
|
||||||
while (!(fmbptr & 0x0200));
|
|
||||||
|
|
||||||
/* force max wait states */
|
/* force max wait states */
|
||||||
target_read_u32(target, 0xFFE88004, &fmbac2);
|
target_read_u32(target, 0xFFE88004, &fmbac2);
|
||||||
|
@ -464,8 +426,7 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se
|
||||||
target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
|
target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
|
||||||
target_write_u32(target, 0xFFE89C00, 0x00);
|
target_write_u32(target, 0xFFE89C00, 0x00);
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
{
|
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
/* There is no point displaying the value of tmp, it is
|
/* There is no point displaying the value of tmp, it is
|
||||||
|
@ -478,15 +439,13 @@ static int tms470_try_flash_keys(struct target * target, const uint32_t * key_se
|
||||||
target_write_u32(target, 0xFFE89C0C, key_set[i]);
|
target_write_u32(target, 0xFFE89C0C, key_set[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ERROR_OK == tms470_check_flash_unlocked(target))
|
if (ERROR_OK == tms470_check_flash_unlocked(target)) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* There seems to be a side-effect of reading the FMPKEY
|
* There seems to be a side-effect of reading the FMPKEY
|
||||||
* register in that it re-enables the protection. So we
|
* register in that it re-enables the protection. So we
|
||||||
* re-enable it.
|
* re-enable it.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
{
|
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
|
target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
|
||||||
|
@ -514,17 +473,14 @@ static int tms470_unlock_flash(struct flash_bank *bank)
|
||||||
const uint32_t *p_key_sets[5];
|
const uint32_t *p_key_sets[5];
|
||||||
unsigned i, key_set_count;
|
unsigned i, key_set_count;
|
||||||
|
|
||||||
if (keysSet)
|
if (keysSet) {
|
||||||
{
|
|
||||||
key_set_count = 5;
|
key_set_count = 5;
|
||||||
p_key_sets[0] = flashKeys;
|
p_key_sets[0] = flashKeys;
|
||||||
p_key_sets[1] = FLASH_KEYS_ALL_ONES;
|
p_key_sets[1] = FLASH_KEYS_ALL_ONES;
|
||||||
p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
|
p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
|
||||||
p_key_sets[3] = FLASH_KEYS_MIX1;
|
p_key_sets[3] = FLASH_KEYS_MIX1;
|
||||||
p_key_sets[4] = FLASH_KEYS_MIX2;
|
p_key_sets[4] = FLASH_KEYS_MIX2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
key_set_count = 4;
|
key_set_count = 4;
|
||||||
p_key_sets[0] = FLASH_KEYS_ALL_ONES;
|
p_key_sets[0] = FLASH_KEYS_ALL_ONES;
|
||||||
p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
|
p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
|
||||||
|
@ -532,10 +488,8 @@ static int tms470_unlock_flash(struct flash_bank *bank)
|
||||||
p_key_sets[3] = FLASH_KEYS_MIX2;
|
p_key_sets[3] = FLASH_KEYS_MIX2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < key_set_count; i++)
|
for (i = 0; i < key_set_count; i++) {
|
||||||
{
|
if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) {
|
||||||
if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK)
|
|
||||||
{
|
|
||||||
LOG_INFO("tms470 flash is unlocked");
|
LOG_INFO("tms470 flash is unlocked");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -594,14 +548,11 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban
|
||||||
* configure VHV
|
* configure VHV
|
||||||
*/
|
*/
|
||||||
target_read_u32(target, 0xFFE8A080, &fmmaxep);
|
target_read_u32(target, 0xFFE8A080, &fmmaxep);
|
||||||
if (fmmaxep == 0xf000)
|
if (fmmaxep == 0xf000) {
|
||||||
{
|
|
||||||
fmmaxep = 0xf000 + 4095;
|
fmmaxep = 0xf000 + 4095;
|
||||||
target_write_u32(target, 0xFFE8A80C, 0x9964);
|
target_write_u32(target, 0xFFE8A80C, 0x9964);
|
||||||
LOG_DEBUG("set fmptr3 = 0x9964");
|
LOG_DEBUG("set fmptr3 = 0x9964");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fmmaxep = 0xa000 + 4095;
|
fmmaxep = 0xa000 + 4095;
|
||||||
target_write_u32(target, 0xFFE8A80C, 0x9b64);
|
target_write_u32(target, 0xFFE8A80C, 0x9b64);
|
||||||
LOG_DEBUG("set fmptr3 = 0x9b64");
|
LOG_DEBUG("set fmptr3 = 0x9b64");
|
||||||
|
@ -692,44 +643,37 @@ static int tms470_flash_status(struct flash_bank *bank)
|
||||||
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
||||||
LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);
|
LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);
|
||||||
|
|
||||||
if (fmmstat & 0x0080)
|
if (fmmstat & 0x0080) {
|
||||||
{
|
|
||||||
LOG_WARNING("tms470 flash command: erase still active after busy clear.");
|
LOG_WARNING("tms470 flash command: erase still active after busy clear.");
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmmstat & 0x0040)
|
if (fmmstat & 0x0040) {
|
||||||
{
|
|
||||||
LOG_WARNING("tms470 flash command: program still active after busy clear.");
|
LOG_WARNING("tms470 flash command: program still active after busy clear.");
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmmstat & 0x0020)
|
if (fmmstat & 0x0020) {
|
||||||
{
|
|
||||||
LOG_WARNING("tms470 flash command: invalid data command.");
|
LOG_WARNING("tms470 flash command: invalid data command.");
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmmstat & 0x0010)
|
if (fmmstat & 0x0010) {
|
||||||
{
|
|
||||||
LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
|
LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmmstat & 0x0008)
|
if (fmmstat & 0x0008) {
|
||||||
{
|
|
||||||
LOG_WARNING("tms470 flash command: voltage instability detected.");
|
LOG_WARNING("tms470 flash command: voltage instability detected.");
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmmstat & 0x0006)
|
if (fmmstat & 0x0006) {
|
||||||
{
|
|
||||||
LOG_WARNING("tms470 flash command: command suspend detected.");
|
LOG_WARNING("tms470 flash command: command suspend detected.");
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmmstat & 0x0001)
|
if (fmmstat & 0x0001) {
|
||||||
{
|
|
||||||
LOG_WARNING("tms470 flash command: sector was locked.");
|
LOG_WARNING("tms470 flash command: sector was locked.");
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -765,14 +709,11 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
|
||||||
* Select one or more bits in FMBSEA or FMBSEB to disable Level 1
|
* Select one or more bits in FMBSEA or FMBSEB to disable Level 1
|
||||||
* protection for the particular sector to be erased/written.
|
* protection for the particular sector to be erased/written.
|
||||||
*/
|
*/
|
||||||
if (sector < 16)
|
if (sector < 16) {
|
||||||
{
|
|
||||||
target_read_u32(target, 0xFFE88008, &fmbsea);
|
target_read_u32(target, 0xFFE88008, &fmbsea);
|
||||||
target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
|
target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
|
||||||
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
|
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
target_read_u32(target, 0xFFE8800C, &fmbseb);
|
target_read_u32(target, 0xFFE8800C, &fmbseb);
|
||||||
target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
|
target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
|
||||||
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
|
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
|
||||||
|
@ -793,26 +734,19 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
|
||||||
* Monitor FMMSTAT, busy until clear, then check and other flags for
|
* Monitor FMMSTAT, busy until clear, then check and other flags for
|
||||||
* ultimate result of the operation.
|
* ultimate result of the operation.
|
||||||
*/
|
*/
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
||||||
if (fmmstat & 0x0100)
|
if (fmmstat & 0x0100)
|
||||||
{
|
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
} while (fmmstat & 0x0100);
|
||||||
}
|
|
||||||
while (fmmstat & 0x0100);
|
|
||||||
|
|
||||||
result = tms470_flash_status(bank);
|
result = tms470_flash_status(bank);
|
||||||
|
|
||||||
if (sector < 16)
|
if (sector < 16) {
|
||||||
{
|
|
||||||
target_write_u32(target, 0xFFE88008, fmbsea);
|
target_write_u32(target, 0xFFE88008, fmbsea);
|
||||||
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
|
LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
|
||||||
bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
|
bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
target_write_u32(target, 0xFFE8800C, fmbseb);
|
target_write_u32(target, 0xFFE8800C, fmbseb);
|
||||||
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
|
LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
|
||||||
bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
|
bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
|
||||||
|
@ -823,16 +757,14 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
|
||||||
LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
|
LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
|
||||||
|
|
||||||
if (result == ERROR_OK)
|
if (result == ERROR_OK)
|
||||||
{
|
|
||||||
bank->sectors[sector].is_erased = 1;
|
bank->sectors[sector].is_erased = 1;
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
Implementation of Flash Driver Interfaces
|
* Implementation of Flash Driver Interfaces
|
||||||
---------------------------------------------------------------------- */
|
*---------------------------------------------------------------------- */
|
||||||
|
|
||||||
static const struct command_registration tms470_any_command_handlers[] = {
|
static const struct command_registration tms470_any_command_handlers[] = {
|
||||||
{
|
{
|
||||||
|
@ -876,42 +808,34 @@ static int tms470_erase(struct flash_bank *bank, int first, int last)
|
||||||
struct tms470_flash_bank *tms470_info = bank->driver_priv;
|
struct tms470_flash_bank *tms470_info = bank->driver_priv;
|
||||||
int sector, result = ERROR_OK;
|
int sector, result = ERROR_OK;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
tms470_read_part_info(bank);
|
tms470_read_part_info(bank);
|
||||||
|
|
||||||
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last))
|
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
|
||||||
{
|
(last >= bank->num_sectors) || (first > last)) {
|
||||||
LOG_ERROR("Sector range %d to %d invalid.", first, last);
|
LOG_ERROR("Sector range %d to %d invalid.", first, last);
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = tms470_unlock_flash(bank);
|
result = tms470_unlock_flash(bank);
|
||||||
if (result != ERROR_OK)
|
if (result != ERROR_OK)
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
for (sector = first; sector <= last; sector++)
|
for (sector = first; sector <= last; sector++) {
|
||||||
{
|
|
||||||
LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector);
|
LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector);
|
||||||
|
|
||||||
result = tms470_erase_sector(bank, sector);
|
result = tms470_erase_sector(bank, sector);
|
||||||
|
|
||||||
if (result != ERROR_OK)
|
if (result != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_ERROR("tms470 could not erase flash sector.");
|
LOG_ERROR("tms470 could not erase flash sector.");
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_INFO("sector erased successfully.");
|
LOG_INFO("sector erased successfully.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -925,16 +849,15 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
uint32_t fmmac2, fmbsea, fmbseb;
|
uint32_t fmmac2, fmbsea, fmbseb;
|
||||||
int sector;
|
int sector;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
tms470_read_part_info(bank);
|
tms470_read_part_info(bank);
|
||||||
|
|
||||||
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last))
|
if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
|
||||||
{
|
(last >= bank->num_sectors) || (first > last)) {
|
||||||
LOG_ERROR("Sector range %d to %d invalid.", first, last);
|
LOG_ERROR("Sector range %d to %d invalid.", first, last);
|
||||||
return ERROR_FLASH_SECTOR_INVALID;
|
return ERROR_FLASH_SECTOR_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -947,16 +870,13 @@ static int tms470_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
target_read_u32(target, 0xFFE88008, &fmbsea);
|
target_read_u32(target, 0xFFE88008, &fmbsea);
|
||||||
target_read_u32(target, 0xFFE8800C, &fmbseb);
|
target_read_u32(target, 0xFFE8800C, &fmbseb);
|
||||||
|
|
||||||
for (sector = 0; sector < bank->num_sectors; sector++)
|
for (sector = 0; sector < bank->num_sectors; sector++) {
|
||||||
{
|
if (sector < 16) {
|
||||||
if (sector < 16)
|
|
||||||
{
|
|
||||||
fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
|
fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
|
||||||
bank->sectors[sector].is_protected = set ? 1 : 0;
|
bank->sectors[sector].is_protected = set ? 1 : 0;
|
||||||
}
|
} else {
|
||||||
else
|
fmbseb = set ? fmbseb &
|
||||||
{
|
~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
|
||||||
fmbseb = set ? fmbseb & ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
|
|
||||||
bank->sectors[sector].is_protected = set ? 1 : 0;
|
bank->sectors[sector].is_protected = set ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
struct target *target = bank->target;
|
||||||
uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
|
uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
|
||||||
int result = ERROR_OK;
|
int result = ERROR_OK;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
tms470_read_part_info(bank);
|
tms470_read_part_info(bank);
|
||||||
|
|
||||||
LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base + offset);
|
LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base +
|
||||||
|
offset);
|
||||||
|
|
||||||
/* set GLBCTRL.4 */
|
/* set GLBCTRL.4 */
|
||||||
target_read_u32(target, 0xFFFFFFDC, &glbctrl);
|
target_read_u32(target, 0xFFFFFFDC, &glbctrl);
|
||||||
|
@ -1012,13 +932,11 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs
|
||||||
/* read MAXPP */
|
/* read MAXPP */
|
||||||
target_read_u32(target, 0xFFE8A07C, &fmmaxpp);
|
target_read_u32(target, 0xFFE8A07C, &fmmaxpp);
|
||||||
|
|
||||||
for (i = 0; i < count; i += 2)
|
for (i = 0; i < count; i += 2) {
|
||||||
{
|
|
||||||
uint32_t addr = bank->base + offset + i;
|
uint32_t addr = bank->base + offset + i;
|
||||||
uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];
|
uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];
|
||||||
|
|
||||||
if (word != 0xffff)
|
if (word != 0xffff) {
|
||||||
{
|
|
||||||
LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);
|
LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);
|
||||||
|
|
||||||
/* clear status register */
|
/* clear status register */
|
||||||
|
@ -1032,29 +950,24 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs
|
||||||
* Monitor FMMSTAT, busy until clear, then check and other flags
|
* Monitor FMMSTAT, busy until clear, then check and other flags
|
||||||
* for ultimate result of the operation.
|
* for ultimate result of the operation.
|
||||||
*/
|
*/
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
|
||||||
if (fmmstat & 0x0100)
|
if (fmmstat & 0x0100)
|
||||||
{
|
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
} while (fmmstat & 0x0100);
|
||||||
}
|
|
||||||
while (fmmstat & 0x0100);
|
|
||||||
|
|
||||||
if (fmmstat & 0x3ff)
|
if (fmmstat & 0x3ff) {
|
||||||
{
|
|
||||||
LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat);
|
LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat);
|
||||||
LOG_ERROR("Could not program word 0x%04x at address 0x%08" PRIx32 ".", word, addr);
|
LOG_ERROR(
|
||||||
|
"Could not program word 0x%04x at address 0x%08" PRIx32 ".",
|
||||||
|
word,
|
||||||
|
addr);
|
||||||
result = ERROR_FLASH_OPERATION_FAILED;
|
result = ERROR_FLASH_OPERATION_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
|
LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* restore */
|
/* restore */
|
||||||
target_write_u32(target, 0xFFE88008, fmbsea);
|
target_write_u32(target, 0xFFE88008, fmbsea);
|
||||||
|
@ -1070,8 +983,7 @@ static int tms470_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offs
|
||||||
|
|
||||||
static int tms470_probe(struct flash_bank *bank)
|
static int tms470_probe(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
if (bank->target->state != TARGET_HALTED)
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_WARNING("Cannot communicate... target not halted.");
|
LOG_WARNING("Cannot communicate... target not halted.");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -1098,16 +1010,13 @@ static int tms470_erase_check(struct flash_bank *bank)
|
||||||
uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt;
|
uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt;
|
||||||
static uint8_t buffer[64 * 1024];
|
static uint8_t buffer[64 * 1024];
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tms470_info->device_ident_reg)
|
if (!tms470_info->device_ident_reg)
|
||||||
{
|
|
||||||
tms470_read_part_info(bank);
|
tms470_read_part_info(bank);
|
||||||
}
|
|
||||||
|
|
||||||
/* set GLBCTRL.4 */
|
/* set GLBCTRL.4 */
|
||||||
target_read_u32(target, 0xFFFFFFDC, &glbctrl);
|
target_read_u32(target, 0xFFFFFFDC, &glbctrl);
|
||||||
|
@ -1136,10 +1045,8 @@ static int tms470_erase_check(struct flash_bank *bank)
|
||||||
* word at a time. Here we read an entire sector and inspect it in
|
* word at a time. Here we read an entire sector and inspect it in
|
||||||
* an attempt to reduce the JTAG overhead.
|
* an attempt to reduce the JTAG overhead.
|
||||||
*/
|
*/
|
||||||
for (sector = 0; sector < bank->num_sectors; sector++)
|
for (sector = 0; sector < bank->num_sectors; sector++) {
|
||||||
{
|
if (bank->sectors[sector].is_erased != 1) {
|
||||||
if (bank->sectors[sector].is_erased != 1)
|
|
||||||
{
|
|
||||||
uint32_t i, addr = bank->base + bank->sectors[sector].offset;
|
uint32_t i, addr = bank->base + bank->sectors[sector].offset;
|
||||||
|
|
||||||
LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector);
|
LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector);
|
||||||
|
@ -1147,28 +1054,27 @@ static int tms470_erase_check(struct flash_bank *bank)
|
||||||
target_read_buffer(target, addr, bank->sectors[sector].size, buffer);
|
target_read_buffer(target, addr, bank->sectors[sector].size, buffer);
|
||||||
|
|
||||||
bank->sectors[sector].is_erased = 1;
|
bank->sectors[sector].is_erased = 1;
|
||||||
for (i = 0; i < bank->sectors[sector].size; i++)
|
for (i = 0; i < bank->sectors[sector].size; i++) {
|
||||||
{
|
if (buffer[i] != 0xff) {
|
||||||
if (buffer[i] != 0xff)
|
LOG_WARNING("tms470 bank %d, sector %d, not erased.",
|
||||||
{
|
tms470_info->ordinal,
|
||||||
LOG_WARNING("tms470 bank %d, sector %d, not erased.", tms470_info->ordinal, sector);
|
sector);
|
||||||
LOG_WARNING("at location 0x%08" PRIx32 ": flash data is 0x%02x.", addr + i, buffer[i]);
|
LOG_WARNING(
|
||||||
|
"at location 0x%08" PRIx32 ": flash data is 0x%02x.",
|
||||||
|
addr + i,
|
||||||
|
buffer[i]);
|
||||||
|
|
||||||
bank->sectors[sector].is_erased = 0;
|
bank->sectors[sector].is_erased = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bank->sectors[sector].is_erased != 1)
|
if (bank->sectors[sector].is_erased != 1) {
|
||||||
{
|
|
||||||
result = ERROR_FLASH_SECTOR_NOT_ERASED;
|
result = ERROR_FLASH_SECTOR_NOT_ERASED;
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_INFO("sector erased");
|
LOG_INFO("sector erased");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* reset TEZ, wait states, read mode, GLBCTRL.4 */
|
/* reset TEZ, wait states, read mode, GLBCTRL.4 */
|
||||||
target_write_u32(target, 0xFFE88010, 0x0f);
|
target_write_u32(target, 0xFFE88010, 0x0f);
|
||||||
|
@ -1188,16 +1094,13 @@ static int tms470_protect_check(struct flash_bank *bank)
|
||||||
int sector, result = ERROR_OK;
|
int sector, result = ERROR_OK;
|
||||||
uint32_t fmmac2, fmbsea, fmbseb;
|
uint32_t fmmac2, fmbsea, fmbseb;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED) {
|
||||||
{
|
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tms470_info->device_ident_reg)
|
if (!tms470_info->device_ident_reg)
|
||||||
{
|
|
||||||
tms470_read_part_info(bank);
|
tms470_read_part_info(bank);
|
||||||
}
|
|
||||||
|
|
||||||
/* enable the appropriate bank */
|
/* enable the appropriate bank */
|
||||||
target_read_u32(target, 0xFFE8BC04, &fmmac2);
|
target_read_u32(target, 0xFFE8BC04, &fmmac2);
|
||||||
|
@ -1206,22 +1109,21 @@ static int tms470_protect_check(struct flash_bank *bank)
|
||||||
target_read_u32(target, 0xFFE88008, &fmbsea);
|
target_read_u32(target, 0xFFE88008, &fmbsea);
|
||||||
target_read_u32(target, 0xFFE8800C, &fmbseb);
|
target_read_u32(target, 0xFFE8800C, &fmbseb);
|
||||||
|
|
||||||
for (sector = 0; sector < bank->num_sectors; sector++)
|
for (sector = 0; sector < bank->num_sectors; sector++) {
|
||||||
{
|
|
||||||
int protected;
|
int protected;
|
||||||
|
|
||||||
if (sector < 16)
|
if (sector < 16) {
|
||||||
{
|
|
||||||
protected = fmbsea & (1 << sector) ? 0 : 1;
|
protected = fmbsea & (1 << sector) ? 0 : 1;
|
||||||
bank->sectors[sector].is_protected = protected;
|
bank->sectors[sector].is_protected = protected;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
|
protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
|
||||||
bank->sectors[sector].is_protected = protected;
|
bank->sectors[sector].is_protected = protected;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("bank %d sector %d is %s", tms470_info->ordinal, sector, protected ? "protected" : "not protected");
|
LOG_DEBUG("bank %d sector %d is %s",
|
||||||
|
tms470_info->ordinal,
|
||||||
|
sector,
|
||||||
|
protected ? "protected" : "not protected");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1235,21 +1137,21 @@ static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
struct tms470_flash_bank *tms470_info = bank->driver_priv;
|
struct tms470_flash_bank *tms470_info = bank->driver_priv;
|
||||||
|
|
||||||
if (!tms470_info->device_ident_reg)
|
if (!tms470_info->device_ident_reg)
|
||||||
{
|
|
||||||
tms470_read_part_info(bank);
|
tms470_read_part_info(bank);
|
||||||
}
|
|
||||||
|
|
||||||
if (!tms470_info->device_ident_reg)
|
if (!tms470_info->device_ident_reg) {
|
||||||
{
|
|
||||||
(void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
|
(void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
used = snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n", tms470_info->part_name);
|
used =
|
||||||
|
snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n",
|
||||||
|
tms470_info->part_name);
|
||||||
buf += used;
|
buf += used;
|
||||||
buf_size -= used;
|
buf_size -= used;
|
||||||
|
|
||||||
snprintf(buf, buf_size, "Flash protection level 2 is %s\n", tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");
|
snprintf(buf, buf_size, "Flash protection level 2 is %s\n",
|
||||||
|
tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1266,9 +1168,7 @@ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
|
||||||
bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
|
bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
|
||||||
|
|
||||||
if (!bank->driver_priv)
|
if (!bank->driver_priv)
|
||||||
{
|
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
(void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));
|
(void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));
|
||||||
|
|
||||||
|
|
|
@ -17,20 +17,20 @@
|
||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
|
|
||||||
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);
|
master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv);
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
LOG_ERROR("master flash bank '%s' does not exist", (char*)bank->driver_priv);
|
LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv);
|
||||||
}
|
|
||||||
|
|
||||||
return master_bank;
|
return master_bank;
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,8 @@ static void virtual_update_bank_info(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* update the info we do not have */
|
/* update the info we do not have */
|
||||||
bank->size = master_bank->size;
|
bank->size = master_bank->size;
|
||||||
|
@ -54,16 +53,13 @@ static void virtual_update_bank_info(struct flash_bank *bank)
|
||||||
FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
|
FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC < 7)
|
if (CMD_ARGC < 7)
|
||||||
{
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/* get the master flash bank */
|
/* get the master flash bank */
|
||||||
const char *bank_name = CMD_ARGV[6];
|
const char *bank_name = CMD_ARGV[6];
|
||||||
struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name);
|
struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name);
|
||||||
|
|
||||||
if (master_bank == NULL)
|
if (master_bank == NULL) {
|
||||||
{
|
|
||||||
LOG_ERROR("master flash bank '%s' does not exist", bank_name);
|
LOG_ERROR("master flash bank '%s' does not exist", bank_name);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -79,13 +75,12 @@ static int virtual_protect(struct flash_bank *bank, int set, int first, int last
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->protect(master_bank, set,
|
retval = master_bank->driver->protect(master_bank, set, first, last);
|
||||||
first, last)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -96,12 +91,12 @@ static int virtual_protect_check(struct flash_bank *bank)
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->protect_check(master_bank)) != ERROR_OK)
|
retval = master_bank->driver->protect_check(master_bank);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -112,13 +107,12 @@ static int virtual_erase(struct flash_bank *bank, int first, int last)
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->erase(master_bank,
|
retval = master_bank->driver->erase(master_bank, first, last);
|
||||||
first, last)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -130,13 +124,12 @@ static int virtual_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->write(master_bank, buffer,
|
retval = master_bank->driver->write(master_bank, buffer, offset, count);
|
||||||
offset, count)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -147,12 +140,12 @@ static int virtual_probe(struct flash_bank *bank)
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->probe(master_bank)) != ERROR_OK)
|
retval = master_bank->driver->probe(master_bank);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* update the info we do not have */
|
/* update the info we do not have */
|
||||||
|
@ -166,12 +159,12 @@ static int virtual_auto_probe(struct flash_bank *bank)
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->auto_probe(master_bank)) != ERROR_OK)
|
retval = master_bank->driver->auto_probe(master_bank);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* update the info we do not have */
|
/* update the info we do not have */
|
||||||
|
@ -184,9 +177,8 @@ static int virtual_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
|
snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
|
||||||
bank->driver->name, master_bank->name, master_bank->base);
|
bank->driver->name, master_bank->name, master_bank->base);
|
||||||
|
@ -199,12 +191,12 @@ static int virtual_blank_check(struct flash_bank *bank)
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->erase_check(master_bank)) != ERROR_OK)
|
retval = master_bank->driver->erase_check(master_bank);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -216,13 +208,12 @@ static int virtual_flash_read(struct flash_bank *bank,
|
||||||
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
struct flash_bank *master_bank = virtual_get_master_bank(bank);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (master_bank == NULL) {
|
if (master_bank == NULL)
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
/* call master handler */
|
/* call master handler */
|
||||||
if ((retval = master_bank->driver->read(master_bank, buffer,
|
retval = master_bank->driver->read(master_bank, buffer, offset, count);
|
||||||
offset, count)) != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
Loading…
Reference in New Issue