- Added support for native MinGW builds (thanks to Spencer Oliver and Michael Fischer) - you still need to install GiveIO (not part of OpenOCD)
- Added state-move support to ftd2xx and bitbang JTAG drivers (required for XScale, possibly useful for other targets, too) - various fixes git-svn-id: svn://svn.berlios.de/openocd/trunk@78 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
@@ -33,6 +33,11 @@ There are some things to notice
|
||||
* Lock regions (sectors) are 32 or 64 pages
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "replacements.h"
|
||||
|
||||
#include "at91sam7.h"
|
||||
|
||||
@@ -59,7 +64,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size);
|
||||
u32 at91sam7_get_flash_status(flash_bank_t *bank);
|
||||
void at91sam7_set_flash_mode(flash_bank_t *bank,int mode);
|
||||
u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout);
|
||||
int at91sam7_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
|
||||
flash_driver_t at91sam7_flash =
|
||||
{
|
||||
@@ -115,6 +120,15 @@ long SRAMSIZ[16] = {
|
||||
0x80000, /* 512K */
|
||||
};
|
||||
|
||||
int at91sam7_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
command_t *at91sam7_cmd = register_command(cmd_ctx, NULL, "at91sam7", NULL, COMMAND_ANY, NULL);
|
||||
register_command(cmd_ctx, at91sam7_cmd, "gpnvm", at91sam7_handle_gpnvm_command, COMMAND_EXEC,
|
||||
"at91sam7 gpnvm <num> <bit> set|clear, set or clear at91sam7 gpnvm bit");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
u32 at91sam7_get_flash_status(flash_bank_t *bank)
|
||||
{
|
||||
at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
|
||||
@@ -126,6 +140,69 @@ u32 at91sam7_get_flash_status(flash_bank_t *bank)
|
||||
return fsr;
|
||||
}
|
||||
|
||||
/** Read clock configuration and set at91sam7_info->usec_clocks*/
|
||||
void at91sam7_read_clock_info(flash_bank_t *bank)
|
||||
{
|
||||
at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
|
||||
target_t *target = at91sam7_info->target;
|
||||
unsigned long mckr, mcfr, pllr, tmp, status, mainfreq;
|
||||
unsigned int css, pres, mul, div;
|
||||
|
||||
/* Read main clock freqency register */
|
||||
target->type->read_memory(target, CKGR_MCFR, 4, 1, (u8 *)&mcfr);
|
||||
/* Read master clock register */
|
||||
target->type->read_memory(target, PMC_MCKR, 4, 1, (u8 *)&mckr);
|
||||
/* Read Clock Generator PLL Register */
|
||||
target->type->read_memory(target, CKGR_PLLR, 4, 1, (u8 *)&pllr);
|
||||
|
||||
pres = (mckr>>2)&0x7;
|
||||
mul = (pllr>>16)&0x7FF;
|
||||
div = pllr&0xFF;
|
||||
|
||||
at91sam7_info->mck_valid = 0;
|
||||
switch (mckr & PMC_MCKR_CSS) {
|
||||
case 0: /* Slow Clock */
|
||||
at91sam7_info->mck_valid = 1;
|
||||
tmp = RC_FREQ;
|
||||
break;
|
||||
case 1: /* Main Clock */
|
||||
if (mcfr & CKGR_MCFR_MAINRDY)
|
||||
{
|
||||
at91sam7_info->mck_valid = 1;
|
||||
mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
|
||||
tmp = mainfreq;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* Reserved */
|
||||
break;
|
||||
case 3: /* PLL Clock */
|
||||
if (mcfr & CKGR_MCFR_MAINRDY)
|
||||
{
|
||||
target->type->read_memory(target, CKGR_PLLR, 4, 1,
|
||||
(u8 *)&pllr);
|
||||
if (!(pllr & CKGR_PLLR_DIV))
|
||||
break; /* 0 Hz */
|
||||
at91sam7_info->mck_valid = 1;
|
||||
mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
|
||||
/* Integer arithmetic should have sufficient precision
|
||||
as long as PLL is properly configured. */
|
||||
tmp = mainfreq / (pllr & CKGR_PLLR_DIV) *
|
||||
(((pllr & CKGR_PLLR_MUL) >> 16) + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Prescaler adjust */
|
||||
if (((mckr & PMC_MCKR_PRES) >> 2) == 7)
|
||||
at91sam7_info->mck_valid = 0;
|
||||
else
|
||||
at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
|
||||
|
||||
/* Forget old flash timing */
|
||||
at91sam7_set_flash_mode(bank,0);
|
||||
}
|
||||
|
||||
/* Setup the timimg registers for nvbits or normal flash */
|
||||
void at91sam7_set_flash_mode(flash_bank_t *bank,int mode)
|
||||
{
|
||||
@@ -133,19 +210,24 @@ void at91sam7_set_flash_mode(flash_bank_t *bank,int mode)
|
||||
at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
|
||||
target_t *target = at91sam7_info->target;
|
||||
|
||||
if (mode != at91sam7_info->flashmode) {
|
||||
/* mainf contains the number of main clocks in approx 500uS */
|
||||
if (mode && (mode != at91sam7_info->flashmode)) {
|
||||
/* Always round up (ceil) */
|
||||
if (mode==1)
|
||||
/* main clocks in 1uS */
|
||||
fmcn = (at91sam7_info->mainf>>9)+1;
|
||||
else
|
||||
fmcn = (at91sam7_info->mck_freq/1000000ul)+1;
|
||||
else if (mode==2)
|
||||
/* main clocks in 1.5uS */
|
||||
fmcn = (at91sam7_info->mainf>>9)+(at91sam7_info->mainf>>10)+1;
|
||||
fmcn = (at91sam7_info->mck_freq/666666ul)+1;
|
||||
|
||||
/* Only allow fmcn=0 if clock period is > 30 us. */
|
||||
if (at91sam7_info->mck_freq <= 33333)
|
||||
fmcn = 0;
|
||||
|
||||
DEBUG("fmcn: %i", fmcn);
|
||||
fmr = fmcn<<16;
|
||||
target->type->write_memory(target, MC_FSR, 4, 1, (u8 *)&fmr);
|
||||
at91sam7_info->flashmode = mode;
|
||||
}
|
||||
at91sam7_info->flashmode = mode;
|
||||
}
|
||||
|
||||
u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout)
|
||||
@@ -174,6 +256,7 @@ u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Send one command to the AT91SAM flash controller */
|
||||
int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen)
|
||||
{
|
||||
u32 fcr;
|
||||
@@ -222,23 +305,12 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
at91sam7_info->cidr_eproc = (cidr>>5)&0x0007;
|
||||
at91sam7_info->cidr_version = cidr&0x001F;
|
||||
bank->size = NVPSIZ[at91sam7_info->cidr_nvpsiz];
|
||||
at91sam7_info->target_name = "Unknown";
|
||||
|
||||
DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch );
|
||||
|
||||
/* Read main clock freqency register */
|
||||
target->type->read_memory(target, CKGR_MCFR, 4, 1, (u8 *)&mcfr);
|
||||
if (mcfr&0x10000)
|
||||
{
|
||||
at91sam7_info->mainrdy = 1;
|
||||
at91sam7_info->mainf = mcfr&0xFFFF;
|
||||
at91sam7_info->usec_clocks = mcfr>>9;
|
||||
}
|
||||
else
|
||||
{
|
||||
at91sam7_info->mainrdy = 0;
|
||||
at91sam7_info->mainf = 0;
|
||||
at91sam7_info->usec_clocks = 0;
|
||||
}
|
||||
/* Read main and master clock freqency register */
|
||||
at91sam7_read_clock_info(bank);
|
||||
|
||||
status = at91sam7_get_flash_status(bank);
|
||||
at91sam7_info->lockbits = status>>16;
|
||||
@@ -252,6 +324,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
bank->bus_width = 4;
|
||||
if (bank->size==0x40000) /* AT91SAM7S256 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7S256";
|
||||
at91sam7_info->num_lockbits = 16;
|
||||
at91sam7_info->pagesize = 256;
|
||||
at91sam7_info->pages_in_lockregion = 64;
|
||||
@@ -259,6 +332,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
}
|
||||
if (bank->size==0x20000) /* AT91SAM7S128 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7S128";
|
||||
at91sam7_info->num_lockbits = 8;
|
||||
at91sam7_info->pagesize = 256;
|
||||
at91sam7_info->pages_in_lockregion = 64;
|
||||
@@ -266,6 +340,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
}
|
||||
if (bank->size==0x10000) /* AT91SAM7S64 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7S64";
|
||||
at91sam7_info->num_lockbits = 16;
|
||||
at91sam7_info->pagesize = 128;
|
||||
at91sam7_info->pages_in_lockregion = 32;
|
||||
@@ -273,6 +348,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
}
|
||||
if (bank->size==0x08000) /* AT91SAM7S321/32 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7S321/32";
|
||||
at91sam7_info->num_lockbits = 8;
|
||||
at91sam7_info->pagesize = 128;
|
||||
at91sam7_info->pages_in_lockregion = 32;
|
||||
@@ -290,6 +366,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
bank->bus_width = 4;
|
||||
if (bank->size==0x40000) /* AT91SAM7XC256 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7XC256";
|
||||
at91sam7_info->num_lockbits = 16;
|
||||
at91sam7_info->pagesize = 256;
|
||||
at91sam7_info->pages_in_lockregion = 64;
|
||||
@@ -297,6 +374,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
}
|
||||
if (bank->size==0x20000) /* AT91SAM7XC128 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7XC128";
|
||||
at91sam7_info->num_lockbits = 8;
|
||||
at91sam7_info->pagesize = 256;
|
||||
at91sam7_info->pages_in_lockregion = 64;
|
||||
@@ -314,6 +392,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
bank->bus_width = 4;
|
||||
if (bank->size==0x40000) /* AT91SAM7X256 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7X256";
|
||||
at91sam7_info->num_lockbits = 16;
|
||||
at91sam7_info->pagesize = 256;
|
||||
at91sam7_info->pages_in_lockregion = 64;
|
||||
@@ -321,6 +400,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
}
|
||||
if (bank->size==0x20000) /* AT91SAM7X128 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7X128";
|
||||
at91sam7_info->num_lockbits = 8;
|
||||
at91sam7_info->pagesize = 256;
|
||||
at91sam7_info->pages_in_lockregion = 64;
|
||||
@@ -339,6 +419,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
|
||||
|
||||
if (bank->size == 0x40000) /* AT91SAM7A3 */
|
||||
{
|
||||
at91sam7_info->target_name = "AT91SAM7A3";
|
||||
at91sam7_info->num_lockbits = 16;
|
||||
at91sam7_info->pagesize = 256;
|
||||
at91sam7_info->pages_in_lockregion = 64;
|
||||
@@ -392,14 +473,6 @@ int at91sam7_protect_check(struct flash_bank_s *bank)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int at91sam7_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
command_t *at91sam7_cmd = register_command(cmd_ctx, NULL, "at91sam7", NULL, COMMAND_ANY, "at91sam7 specific commands");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
|
||||
{
|
||||
at91sam7_flash_bank_t *at91sam7_info;
|
||||
@@ -452,11 +525,15 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last)
|
||||
return ERROR_FLASH_SECTOR_INVALID;
|
||||
}
|
||||
|
||||
/* Configure the flash controller timing */
|
||||
at91sam7_read_clock_info(bank);
|
||||
at91sam7_set_flash_mode(bank,2);
|
||||
|
||||
if ((first == 0) && (last == (at91sam7_info->num_lockbits-1)))
|
||||
{
|
||||
return at91sam7_flash_command(bank, EA, 0);
|
||||
}
|
||||
|
||||
|
||||
WARNING("Can only erase the whole flash area, pages are autoerased on write");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
@@ -490,7 +567,8 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
/* Configure the flash controller timing */
|
||||
/* Configure the flash controller timing */
|
||||
at91sam7_read_clock_info(bank);
|
||||
at91sam7_set_flash_mode(bank,1);
|
||||
|
||||
for (lockregion=first;lockregion<=last;lockregion++)
|
||||
@@ -560,6 +638,7 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
|
||||
DEBUG("first_page: %i, last_page: %i, count %i", first_page, last_page, count);
|
||||
|
||||
/* Configure the flash controller timing */
|
||||
at91sam7_read_clock_info(bank);
|
||||
at91sam7_set_flash_mode(bank,2);
|
||||
|
||||
for (pagen=first_page; pagen<last_page; pagen++) {
|
||||
@@ -611,10 +690,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
int printed;
|
||||
at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
|
||||
|
||||
if (at91sam7_info->cidr == 0)
|
||||
{
|
||||
at91sam7_read_part_info(bank);
|
||||
}
|
||||
at91sam7_read_part_info(bank);
|
||||
|
||||
if (at91sam7_info->cidr == 0)
|
||||
{
|
||||
@@ -632,7 +708,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
buf += printed;
|
||||
buf_size -= printed;
|
||||
|
||||
printed = snprintf(buf, buf_size, "main clock(estimated): %ikHz \n", at91sam7_info->mainf*2);
|
||||
printed = snprintf(buf, buf_size, "master clock(estimated): %ikHz \n", at91sam7_info->mck_freq / 1000);
|
||||
buf += printed;
|
||||
buf_size -= printed;
|
||||
|
||||
@@ -648,3 +724,92 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* On AT91SAM7S: When the gpnmv bits are set with
|
||||
* > at91sam7 gpnvm 0 bitnr set
|
||||
* the changes are not visible in the flash controller status register MC_FSR
|
||||
* until the processor has been reset.
|
||||
* On the Olimex board this requires a power cycle.
|
||||
* Note that the AT91SAM7S has the following errata (doc6175.pdf sec 14.1.3):
|
||||
* The maximum number of write/erase cycles for Non Volatile Memory bits is 100. This includes
|
||||
* Lock Bits (LOCKx), General Purpose NVM bits (GPNVMx) and the Security Bit.
|
||||
*/
|
||||
int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
flash_bank_t *bank;
|
||||
int bit;
|
||||
u8 flashcmd;
|
||||
u32 status;
|
||||
char *value;
|
||||
at91sam7_flash_bank_t *at91sam7_info;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
command_print(cmd_ctx, "at91sam7 gpnvm <num> <bit> <set|clear>");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
|
||||
bit = atoi(args[1]);
|
||||
value = args[2];
|
||||
|
||||
if (!bank)
|
||||
{
|
||||
command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
at91sam7_info = bank->driver_priv;
|
||||
|
||||
if (at91sam7_info->target->state != TARGET_HALTED)
|
||||
{
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
if (at91sam7_info->cidr == 0)
|
||||
{
|
||||
at91sam7_read_part_info(bank);
|
||||
}
|
||||
|
||||
if (at91sam7_info->cidr == 0)
|
||||
{
|
||||
WARNING("Cannot identify target as an AT91SAM");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if ((bit<0) || (at91sam7_info->num_nvmbits <= bit))
|
||||
{
|
||||
command_print(cmd_ctx, "gpnvm bit '#%s' is out of bounds for target %s", args[1],at91sam7_info->target_name);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
if (strcmp(value, "set") == 0)
|
||||
{
|
||||
flashcmd = SGPB;
|
||||
}
|
||||
else if (strcmp(value, "clear") == 0)
|
||||
{
|
||||
flashcmd = CGPB;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_print(cmd_ctx, "usage: at91sam7 gpnvm <num> <bit> <set|clear>");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* Configure the flash controller timing */
|
||||
at91sam7_read_clock_info(bank);
|
||||
at91sam7_set_flash_mode(bank,1);
|
||||
|
||||
if (at91sam7_flash_command(bank, flashcmd, (u16)(bit)) != ERROR_OK)
|
||||
{
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
status = at91sam7_get_flash_status(bank);
|
||||
DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value 0x%x, status 0x%x \n",flashcmd,bit,status);
|
||||
at91sam7_info->nvmbits = (status>>8)&((1<<at91sam7_info->num_nvmbits)-1);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user