Added support for k64 (#301)
This commit is contained in:
parent
471ce2547c
commit
31965a5bbc
|
@ -25,6 +25,12 @@
|
||||||
* KL25 Sub-family Reference Manual
|
* KL25 Sub-family Reference Manual
|
||||||
*
|
*
|
||||||
* Extended with support for KL02 family
|
* Extended with support for KL02 family
|
||||||
|
*
|
||||||
|
* Extended with support for K64 family with info from K22P64M50SF4RM:
|
||||||
|
* K22 Sub-Family Reference Manual
|
||||||
|
*
|
||||||
|
* Extended with support for K64 family with info from K64P144M120SF5RM:
|
||||||
|
* K64 Sub-Family Reference Manual, Rev. 2,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
|
@ -51,7 +57,9 @@
|
||||||
#define FTFA_CMD_CHECK_ERASE 0x01
|
#define FTFA_CMD_CHECK_ERASE 0x01
|
||||||
#define FTFA_CMD_PROGRAM_CHECK 0x02
|
#define FTFA_CMD_PROGRAM_CHECK 0x02
|
||||||
#define FTFA_CMD_READ_RESOURCE 0x03
|
#define FTFA_CMD_READ_RESOURCE 0x03
|
||||||
#define FTFA_CMD_PROGRAM_LONGWORD 0x06
|
#define FTFA_CMD_PROGRAM_LONGWORD 0x06
|
||||||
|
/* Part of the FTFE module for K64 */
|
||||||
|
#define FTFE_CMD_PROGRAM_PHRASE 0x07
|
||||||
#define FTFA_CMD_ERASE_SECTOR 0x09
|
#define FTFA_CMD_ERASE_SECTOR 0x09
|
||||||
#define FTFA_CMD_CHECK_ERASE_ALL 0x40
|
#define FTFA_CMD_CHECK_ERASE_ALL 0x40
|
||||||
#define FTFA_CMD_READ_ONCE 0x41
|
#define FTFA_CMD_READ_ONCE 0x41
|
||||||
|
@ -59,7 +67,9 @@
|
||||||
#define FTFA_CMD_ERASE_ALL 0x44
|
#define FTFA_CMD_ERASE_ALL 0x44
|
||||||
#define FTFA_CMD_BACKDOOR_ACCESS 0x45
|
#define FTFA_CMD_BACKDOOR_ACCESS 0x45
|
||||||
|
|
||||||
#define KL_GEN_PAGESIZE 0x400
|
#define KL_WRITE_LEN 4
|
||||||
|
/* 8 byte phrases need to be written to the k64 flash */
|
||||||
|
#define K64_WRITE_LEN 8
|
||||||
|
|
||||||
static bool kinetis_cmd_unsafe(target *t, int argc, char *argv[]);
|
static bool kinetis_cmd_unsafe(target *t, int argc, char *argv[]);
|
||||||
static bool unsafe_enabled;
|
static bool unsafe_enabled;
|
||||||
|
@ -85,7 +95,8 @@ static int kl_gen_flash_write(struct target_flash *f,
|
||||||
static int kl_gen_flash_done(struct target_flash *f);
|
static int kl_gen_flash_done(struct target_flash *f);
|
||||||
|
|
||||||
static void kl_gen_add_flash(target *t,
|
static void kl_gen_add_flash(target *t,
|
||||||
uint32_t addr, size_t length, size_t erasesize)
|
uint32_t addr, size_t length, size_t erasesize,
|
||||||
|
size_t write_len)
|
||||||
{
|
{
|
||||||
struct target_flash *f = calloc(1, sizeof(*f));
|
struct target_flash *f = calloc(1, sizeof(*f));
|
||||||
f->start = addr;
|
f->start = addr;
|
||||||
|
@ -94,7 +105,7 @@ static void kl_gen_add_flash(target *t,
|
||||||
f->erase = kl_gen_flash_erase;
|
f->erase = kl_gen_flash_erase;
|
||||||
f->write = kl_gen_flash_write;
|
f->write = kl_gen_flash_write;
|
||||||
f->done = kl_gen_flash_done;
|
f->done = kl_gen_flash_done;
|
||||||
f->align = 4;
|
f->align = write_len;
|
||||||
f->erased = 0xff;
|
f->erased = 0xff;
|
||||||
target_add_flash(t, f);
|
target_add_flash(t, f);
|
||||||
}
|
}
|
||||||
|
@ -107,13 +118,13 @@ bool kinetis_probe(target *t)
|
||||||
t->driver = "KL25";
|
t->driver = "KL25";
|
||||||
target_add_ram(t, 0x1ffff000, 0x1000);
|
target_add_ram(t, 0x1ffff000, 0x1000);
|
||||||
target_add_ram(t, 0x20000000, 0x3000);
|
target_add_ram(t, 0x20000000, 0x3000);
|
||||||
kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400);
|
kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN);
|
||||||
break;
|
break;
|
||||||
case 0x231:
|
case 0x231:
|
||||||
t->driver = "KL27";
|
t->driver = "KL27";
|
||||||
target_add_ram(t, 0x1fffe000, 0x2000);
|
target_add_ram(t, 0x1fffe000, 0x2000);
|
||||||
target_add_ram(t, 0x20000000, 0x6000);
|
target_add_ram(t, 0x20000000, 0x6000);
|
||||||
kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400);
|
kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN);
|
||||||
break;
|
break;
|
||||||
case 0x021: /* KL02 family */
|
case 0x021: /* KL02 family */
|
||||||
switch((sdid>>16) & 0x0f){
|
switch((sdid>>16) & 0x0f){
|
||||||
|
@ -121,19 +132,19 @@ bool kinetis_probe(target *t)
|
||||||
t->driver = "KL02x32";
|
t->driver = "KL02x32";
|
||||||
target_add_ram(t, 0x1FFFFC00, 0x400);
|
target_add_ram(t, 0x1FFFFC00, 0x400);
|
||||||
target_add_ram(t, 0x20000000, 0xc00);
|
target_add_ram(t, 0x20000000, 0xc00);
|
||||||
kl_gen_add_flash(t, 0x00000000, 0x7FFF, 0x400);
|
kl_gen_add_flash(t, 0x00000000, 0x7FFF, 0x400, KL_WRITE_LEN);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
t->driver = "KL02x16";
|
t->driver = "KL02x16";
|
||||||
target_add_ram(t, 0x1FFFFE00, 0x200);
|
target_add_ram(t, 0x1FFFFE00, 0x200);
|
||||||
target_add_ram(t, 0x20000000, 0x600);
|
target_add_ram(t, 0x20000000, 0x600);
|
||||||
kl_gen_add_flash(t, 0x00000000, 0x3FFF, 0x400);
|
kl_gen_add_flash(t, 0x00000000, 0x3FFF, 0x400, KL_WRITE_LEN);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
t->driver = "KL02x8";
|
t->driver = "KL02x8";
|
||||||
target_add_ram(t, 0x1FFFFF00, 0x100);
|
target_add_ram(t, 0x1FFFFF00, 0x100);
|
||||||
target_add_ram(t, 0x20000000, 0x300);
|
target_add_ram(t, 0x20000000, 0x300);
|
||||||
kl_gen_add_flash(t, 0x00000000, 0x1FFF, 0x400);
|
kl_gen_add_flash(t, 0x00000000, 0x1FFF, 0x400, KL_WRITE_LEN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -143,14 +154,25 @@ bool kinetis_probe(target *t)
|
||||||
t->driver = "KL03";
|
t->driver = "KL03";
|
||||||
target_add_ram(t, 0x1ffffe00, 0x200);
|
target_add_ram(t, 0x1ffffe00, 0x200);
|
||||||
target_add_ram(t, 0x20000000, 0x600);
|
target_add_ram(t, 0x20000000, 0x600);
|
||||||
kl_gen_add_flash(t, 0, 0x8000, 0x400);
|
kl_gen_add_flash(t, 0, 0x8000, 0x400, KL_WRITE_LEN);
|
||||||
break;
|
break;
|
||||||
case 0x220: /* K22F family */
|
case 0x220: /* K22F family */
|
||||||
t->driver = "K22F";
|
t->driver = "K22F";
|
||||||
target_add_ram(t, 0x1c000000, 0x4000000);
|
target_add_ram(t, 0x1c000000, 0x4000000);
|
||||||
target_add_ram(t, 0x20000000, 0x100000);
|
target_add_ram(t, 0x20000000, 0x100000);
|
||||||
kl_gen_add_flash(t, 0, 0x40000, 0x800);
|
kl_gen_add_flash(t, 0, 0x40000, 0x800, KL_WRITE_LEN);
|
||||||
kl_gen_add_flash(t, 0x40000, 0x40000, 0x800);
|
kl_gen_add_flash(t, 0x40000, 0x40000, 0x800, KL_WRITE_LEN);
|
||||||
|
break;
|
||||||
|
case 0x620: /* K64F family. */
|
||||||
|
/* This should be 0x640, but according to the errata sheet
|
||||||
|
* (KINETIS_1N83J) K64 and K24's will show up with the
|
||||||
|
* subfamily nibble as 2
|
||||||
|
*/
|
||||||
|
t->driver = "K64";
|
||||||
|
target_add_ram(t, 0x1FFF0000, 0x10000);
|
||||||
|
target_add_ram(t, 0x20000000, 0x30000);
|
||||||
|
kl_gen_add_flash(t, 0, 0x80000, 0x1000, K64_WRITE_LEN);
|
||||||
|
kl_gen_add_flash(t, 0x80000, 0x80000, 0x1000, K64_WRITE_LEN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -200,8 +222,9 @@ static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t l
|
||||||
{
|
{
|
||||||
while (len) {
|
while (len) {
|
||||||
if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL)) {
|
if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL)) {
|
||||||
len -= KL_GEN_PAGESIZE;
|
/* Different targets have different flash erase sizes */
|
||||||
addr += KL_GEN_PAGESIZE;
|
len -= f->blocksize;
|
||||||
|
addr += f->blocksize;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -223,11 +246,19 @@ static int kl_gen_flash_write(struct target_flash *f,
|
||||||
FLASH_SECURITY_BYTE_UNSECURED;
|
FLASH_SECURITY_BYTE_UNSECURED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine write command based on the alignment. */
|
||||||
|
uint8_t write_cmd;
|
||||||
|
if (f->align == K64_WRITE_LEN) {
|
||||||
|
write_cmd = FTFE_CMD_PROGRAM_PHRASE;
|
||||||
|
} else {
|
||||||
|
write_cmd = FTFA_CMD_PROGRAM_LONGWORD;
|
||||||
|
}
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if (kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, dest, src)) {
|
if (kl_gen_command(f->t, write_cmd, dest, src)) {
|
||||||
len -= 4;
|
len -= f->align;
|
||||||
dest += 4;
|
dest += f->align;
|
||||||
src += 4;
|
src += f->align;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -245,10 +276,22 @@ static int kl_gen_flash_done(struct target_flash *f)
|
||||||
FLASH_SECURITY_BYTE_UNSECURED)
|
FLASH_SECURITY_BYTE_UNSECURED)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS);
|
/* Load the security byte based on the alignment (determine 8 byte phrases
|
||||||
val = (val & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED;
|
* vs 4 byte phrases).
|
||||||
kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD,
|
*/
|
||||||
FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&val);
|
if (f->align == 8) {
|
||||||
|
uint32_t vals[2];
|
||||||
|
vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS-4);
|
||||||
|
vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS);
|
||||||
|
vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED;
|
||||||
|
kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE,
|
||||||
|
FLASH_SECURITY_BYTE_ADDRESS - 4, (uint8_t*)vals);
|
||||||
|
} else {
|
||||||
|
uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS);
|
||||||
|
val = (val & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED;
|
||||||
|
kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD,
|
||||||
|
FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&val);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue