Merge commit 'cfaa5ea9633fb8719da9455f6c04908810395abe' into sam-update
This commit is contained in:
commit
aece87bf3e
@ -40,6 +40,7 @@ SRC = \
|
|||||||
lmi.c \
|
lmi.c \
|
||||||
lpc_common.c \
|
lpc_common.c \
|
||||||
lpc11xx.c \
|
lpc11xx.c \
|
||||||
|
lpc17xx.c \
|
||||||
lpc15xx.c \
|
lpc15xx.c \
|
||||||
lpc43xx.c \
|
lpc43xx.c \
|
||||||
kinetis.c \
|
kinetis.c \
|
||||||
|
@ -125,7 +125,10 @@ static const char tdesc_cortex_m[] =
|
|||||||
" <reg name=\"xpsr\" bitsize=\"32\"/>"
|
" <reg name=\"xpsr\" bitsize=\"32\"/>"
|
||||||
" <reg name=\"msp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
" <reg name=\"msp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
||||||
" <reg name=\"psp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
" <reg name=\"psp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
||||||
" <reg name=\"special\" bitsize=\"32\" save-restore=\"no\"/>"
|
" <reg name=\"primask\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
|
" <reg name=\"basepri\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
|
" <reg name=\"faultmask\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
|
" <reg name=\"control\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
" </feature>"
|
" </feature>"
|
||||||
"</target>";
|
"</target>";
|
||||||
|
|
||||||
@ -154,7 +157,10 @@ static const char tdesc_cortex_mf[] =
|
|||||||
" <reg name=\"xpsr\" bitsize=\"32\"/>"
|
" <reg name=\"xpsr\" bitsize=\"32\"/>"
|
||||||
" <reg name=\"msp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
" <reg name=\"msp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
||||||
" <reg name=\"psp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
" <reg name=\"psp\" bitsize=\"32\" save-restore=\"no\" type=\"data_ptr\"/>"
|
||||||
" <reg name=\"special\" bitsize=\"32\" save-restore=\"no\"/>"
|
" <reg name=\"primask\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
|
" <reg name=\"basepri\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
|
" <reg name=\"faultmask\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
|
" <reg name=\"control\" bitsize=\"8\" save-restore=\"no\"/>"
|
||||||
" </feature>"
|
" </feature>"
|
||||||
" <feature name=\"org.gnu.gdb.arm.vfp\">"
|
" <feature name=\"org.gnu.gdb.arm.vfp\">"
|
||||||
" <reg name=\"fpscr\" bitsize=\"32\"/>"
|
" <reg name=\"fpscr\" bitsize=\"32\"/>"
|
||||||
@ -299,6 +305,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
|
|||||||
PROBE(stm32l4_probe);
|
PROBE(stm32l4_probe);
|
||||||
PROBE(lpc11xx_probe);
|
PROBE(lpc11xx_probe);
|
||||||
PROBE(lpc15xx_probe);
|
PROBE(lpc15xx_probe);
|
||||||
|
PROBE(lpc17xx_probe);
|
||||||
PROBE(lpc43xx_probe);
|
PROBE(lpc43xx_probe);
|
||||||
PROBE(sam3x_probe);
|
PROBE(sam3x_probe);
|
||||||
PROBE(sam4l_probe);
|
PROBE(sam4l_probe);
|
||||||
|
@ -61,6 +61,8 @@ static const struct jtag_dev_descr_s {
|
|||||||
.descr = "ST Microelectronics: STM32F4xx."},
|
.descr = "ST Microelectronics: STM32F4xx."},
|
||||||
{.idcode = 0x0BB11477 , .idmask = 0xFFFFFFFF,
|
{.idcode = 0x0BB11477 , .idmask = 0xFFFFFFFF,
|
||||||
.descr = "NPX: LPC11C24."},
|
.descr = "NPX: LPC11C24."},
|
||||||
|
{.idcode = 0x4BA00477 , .idmask = 0xFFFFFFFF,
|
||||||
|
.descr = "NXP: LPC17xx family."},
|
||||||
/* Just for fun, unsupported */
|
/* Just for fun, unsupported */
|
||||||
{.idcode = 0x8940303F, .idmask = 0xFFFFFFFF, .descr = "ATMEL: ATMega16."},
|
{.idcode = 0x8940303F, .idmask = 0xFFFFFFFF, .descr = "ATMEL: ATMega16."},
|
||||||
{.idcode = 0x0792603F, .idmask = 0xFFFFFFFF, .descr = "ATMEL: AT91SAM9261."},
|
{.idcode = 0x0792603F, .idmask = 0xFFFFFFFF, .descr = "ATMEL: AT91SAM9261."},
|
||||||
|
@ -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,31 @@ 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 = "KL27x128"; // MKL27 >=128kb
|
||||||
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;
|
||||||
|
case 0x271:
|
||||||
|
switch((sdid>>16)&0x0f){
|
||||||
|
case 4:
|
||||||
|
t->driver = "KL27x32";
|
||||||
|
target_add_ram(t, 0x1ffff800, 0x0800);
|
||||||
|
target_add_ram(t, 0x20000000, 0x1800);
|
||||||
|
kl_gen_add_flash(t, 0x00000000, 0x8000, 0x400, KL_WRITE_LEN);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
t->driver = "KL27x64";
|
||||||
|
target_add_ram(t, 0x1ffff000, 0x1000);
|
||||||
|
target_add_ram(t, 0x20000000, 0x3000);
|
||||||
|
kl_gen_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x021: /* KL02 family */
|
case 0x021: /* KL02 family */
|
||||||
switch((sdid>>16) & 0x0f){
|
switch((sdid>>16) & 0x0f){
|
||||||
@ -121,19 +150,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 +172,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 +240,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 +264,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 +294,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;
|
||||||
}
|
}
|
||||||
|
201
src/target/lpc17xx.c
Normal file
201
src/target/lpc17xx.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "target.h"
|
||||||
|
#include "target_internal.h"
|
||||||
|
#include "cortexm.h"
|
||||||
|
#include "lpc_common.h"
|
||||||
|
#include "adiv5.h"
|
||||||
|
|
||||||
|
#define IAP_PGM_CHUNKSIZE 4096
|
||||||
|
|
||||||
|
#define MIN_RAM_SIZE 8192 // LPC1751
|
||||||
|
#define RAM_USAGE_FOR_IAP_ROUTINES 32 // IAP routines use 32 bytes at top of ram
|
||||||
|
|
||||||
|
#define IAP_ENTRYPOINT 0x1FFF1FF1
|
||||||
|
#define IAP_RAM_BASE 0x10000000
|
||||||
|
|
||||||
|
#define ARM_CPUID 0xE000ED00
|
||||||
|
#define CORTEX_M3_CPUID 0x412FC230 // Cortex-M3 r2p0
|
||||||
|
#define CORTEX_M3_CPUID_MASK 0xFF00FFF0
|
||||||
|
#define MEMMAP 0x400FC040
|
||||||
|
#define LPC17xx_JTAG_IDCODE 0x4BA00477
|
||||||
|
#define LPC17xx_SWDP_IDCODE 0x2BA01477
|
||||||
|
#define FLASH_NUM_SECTOR 30
|
||||||
|
|
||||||
|
struct flash_param {
|
||||||
|
uint16_t opcode;
|
||||||
|
uint16_t pad0;
|
||||||
|
uint32_t command;
|
||||||
|
uint32_t words[4];
|
||||||
|
uint32_t result[5]; // return code and maximum of 4 result parameters
|
||||||
|
} __attribute__((aligned(4)));
|
||||||
|
|
||||||
|
static void lpc17xx_extended_reset(target *t);
|
||||||
|
static bool lpc17xx_cmd_erase(target *t, int argc, const char *argv[]);
|
||||||
|
enum iap_status lpc17xx_iap_call(target *t, struct flash_param *param, enum iap_cmd cmd, ...);
|
||||||
|
|
||||||
|
const struct command_s lpc17xx_cmd_list[] = {
|
||||||
|
{"erase_mass", lpc17xx_cmd_erase, "Erase entire flash memory"},
|
||||||
|
{NULL, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
void lpc17xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize, unsigned int base_sector)
|
||||||
|
{
|
||||||
|
struct lpc_flash *lf = lpc_add_flash(t, addr, len);
|
||||||
|
lf->f.blocksize = erasesize;
|
||||||
|
lf->base_sector = base_sector;
|
||||||
|
lf->f.buf_size = IAP_PGM_CHUNKSIZE;
|
||||||
|
lf->f.write_buf = lpc_flash_write_magic_vect;
|
||||||
|
lf->iap_entry = IAP_ENTRYPOINT;
|
||||||
|
lf->iap_ram = IAP_RAM_BASE;
|
||||||
|
lf->iap_msp = IAP_RAM_BASE + MIN_RAM_SIZE - RAM_USAGE_FOR_IAP_ROUTINES;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
lpc17xx_probe(target *t)
|
||||||
|
{
|
||||||
|
/* Read the IDCODE register from the SW-DP */
|
||||||
|
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||||
|
uint32_t ap_idcode = ap->dp->idcode;
|
||||||
|
|
||||||
|
if (ap_idcode == LPC17xx_JTAG_IDCODE || ap_idcode == LPC17xx_SWDP_IDCODE) {
|
||||||
|
/* LPC176x/5x family. See UM10360.pdf 33.7 JTAG TAP Identification*/
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cpuid = target_mem_read32(t, ARM_CPUID);
|
||||||
|
if (((cpuid & CORTEX_M3_CPUID_MASK) == (CORTEX_M3_CPUID & CORTEX_M3_CPUID_MASK))) {
|
||||||
|
/*
|
||||||
|
* Now that we're sure it's a Cortex-M3, we need to halt the
|
||||||
|
* target and make an IAP call to get the part number.
|
||||||
|
* There appears to have no other method of reading the part number.
|
||||||
|
*/
|
||||||
|
target_halt_request(t);
|
||||||
|
|
||||||
|
/* Read the Part ID */
|
||||||
|
struct flash_param param;
|
||||||
|
lpc17xx_iap_call(t, ¶m, IAP_CMD_PARTID);
|
||||||
|
target_halt_resume(t, 0);
|
||||||
|
|
||||||
|
if (param.result[0]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (param.result[1]) {
|
||||||
|
case 0x26113F37: /* LPC1769 */
|
||||||
|
case 0x26013F37: /* LPC1768 */
|
||||||
|
case 0x26012837: /* LPC1767 */
|
||||||
|
case 0x26013F33: /* LPC1766 */
|
||||||
|
case 0x26013733: /* LPC1765 */
|
||||||
|
case 0x26011922: /* LPC1764 */
|
||||||
|
case 0x25113737: /* LPC1759 */
|
||||||
|
case 0x25013F37: /* LPC1758 */
|
||||||
|
case 0x25011723: /* LPC1756 */
|
||||||
|
case 0x25011722: /* LPC1754 */
|
||||||
|
case 0x25001121: /* LPC1752 */
|
||||||
|
case 0x25001118: /* LPC1751 */
|
||||||
|
case 0x25001110: /* LPC1751 (No CRP) */
|
||||||
|
|
||||||
|
t->driver = "LPC17xx";
|
||||||
|
t->extended_reset = lpc17xx_extended_reset;
|
||||||
|
target_add_ram(t, 0x10000000, 0x8000);
|
||||||
|
target_add_ram(t, 0x2007C000, 0x4000);
|
||||||
|
target_add_ram(t, 0x20080000, 0x4000);
|
||||||
|
lpc17xx_add_flash(t, 0x00000000, 0x10000, 0x1000, 0);
|
||||||
|
lpc17xx_add_flash(t, 0x00010000, 0x70000, 0x8000, 16);
|
||||||
|
target_add_commands(t, lpc17xx_cmd_list, "LPC17xx");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
lpc17xx_cmd_erase(target *t, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
struct flash_param param;
|
||||||
|
|
||||||
|
if (lpc17xx_iap_call(t, ¶m, IAP_CMD_PREPARE, 0, FLASH_NUM_SECTOR-1)) {
|
||||||
|
DEBUG("lpc17xx_cmd_erase: prepare failed %d\n", (unsigned int)param.result[0]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpc17xx_iap_call(t, ¶m, IAP_CMD_ERASE, 0, FLASH_NUM_SECTOR-1, CPU_CLK_KHZ)) {
|
||||||
|
DEBUG("lpc17xx_cmd_erase: erase failed %d\n", (unsigned int)param.result[0]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpc17xx_iap_call(t, ¶m, IAP_CMD_BLANKCHECK, 0, FLASH_NUM_SECTOR-1)) {
|
||||||
|
DEBUG("lpc17xx_cmd_erase: blankcheck failed %d\n", (unsigned int)param.result[0]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tc_printf(t, "Erase OK.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Target has been reset, make sure to remap the boot ROM
|
||||||
|
* from 0x00000000 leaving the user flash visible
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
lpc17xx_extended_reset(target *t)
|
||||||
|
{
|
||||||
|
/* From §33.6 Debug memory re-mapping (Page 643) UM10360.pdf (Rev 2) */
|
||||||
|
target_mem_write32(t, MEMMAP, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum iap_status
|
||||||
|
lpc17xx_iap_call(target *t, struct flash_param *param, enum iap_cmd cmd, ...) {
|
||||||
|
param->opcode = ARM_THUMB_BREAKPOINT;
|
||||||
|
param->command = cmd;
|
||||||
|
|
||||||
|
/* fill out the remainder of the parameters */
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, cmd);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
param->words[i] = va_arg(ap, uint32_t);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
/* copy the structure to RAM */
|
||||||
|
target_mem_write(t, IAP_RAM_BASE, param, sizeof(struct flash_param));
|
||||||
|
|
||||||
|
/* set up for the call to the IAP ROM */
|
||||||
|
uint32_t regs[t->regs_size / sizeof(uint32_t)];
|
||||||
|
target_regs_read(t, regs);
|
||||||
|
regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command);
|
||||||
|
regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result);
|
||||||
|
regs[REG_MSP] = IAP_RAM_BASE + MIN_RAM_SIZE - RAM_USAGE_FOR_IAP_ROUTINES;
|
||||||
|
regs[REG_LR] = IAP_RAM_BASE | 1;
|
||||||
|
regs[REG_PC] = IAP_ENTRYPOINT;
|
||||||
|
target_regs_write(t, regs);
|
||||||
|
|
||||||
|
/* start the target and wait for it to halt again */
|
||||||
|
target_halt_resume(t, false);
|
||||||
|
while (!target_halt_poll(t, NULL));
|
||||||
|
|
||||||
|
/* copy back just the parameters structure */
|
||||||
|
target_mem_read(t, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param));
|
||||||
|
return param->result[0];
|
||||||
|
}
|
@ -26,6 +26,7 @@ enum iap_cmd {
|
|||||||
IAP_CMD_PROGRAM = 51,
|
IAP_CMD_PROGRAM = 51,
|
||||||
IAP_CMD_ERASE = 52,
|
IAP_CMD_ERASE = 52,
|
||||||
IAP_CMD_BLANKCHECK = 53,
|
IAP_CMD_BLANKCHECK = 53,
|
||||||
|
IAP_CMD_PARTID = 54,
|
||||||
IAP_CMD_SET_ACTIVE_BANK = 60,
|
IAP_CMD_SET_ACTIVE_BANK = 60,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -165,6 +165,7 @@ bool nrf51_probe(target *t)
|
|||||||
return true;
|
return true;
|
||||||
case 0x00AC: /* nRF52832 Preview QFAA BA0 */
|
case 0x00AC: /* nRF52832 Preview QFAA BA0 */
|
||||||
case 0x00C7: /* nRF52832 Revision 1 QFAA B00 */
|
case 0x00C7: /* nRF52832 Revision 1 QFAA B00 */
|
||||||
|
case 0x00E3: /* nRF52832-CIAA CSP */
|
||||||
t->driver = "Nordic nRF52";
|
t->driver = "Nordic nRF52";
|
||||||
target_add_ram(t, 0x20000000, 64*1024);
|
target_add_ram(t, 0x20000000, 64*1024);
|
||||||
nrf51_add_flash(t, 0x00000000, 512*1024, NRF52_PAGE_SIZE);
|
nrf51_add_flash(t, 0x00000000, 512*1024, NRF52_PAGE_SIZE);
|
||||||
|
@ -175,6 +175,7 @@ bool stm32l4_probe(target *t);
|
|||||||
bool lmi_probe(target *t);
|
bool lmi_probe(target *t);
|
||||||
bool lpc11xx_probe(target *t);
|
bool lpc11xx_probe(target *t);
|
||||||
bool lpc15xx_probe(target *t);
|
bool lpc15xx_probe(target *t);
|
||||||
|
bool lpc17xx_probe(target *t);
|
||||||
bool lpc43xx_probe(target *t);
|
bool lpc43xx_probe(target *t);
|
||||||
bool sam3x_probe(target *t);
|
bool sam3x_probe(target *t);
|
||||||
bool sam4l_probe(target *t);
|
bool sam4l_probe(target *t);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user