diff --git a/src/cortexm.c b/src/cortexm.c index ae1c59d3..e7bed5b3 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -195,14 +195,6 @@ static const char tdesc_cortex_mf[] = " " ""; -#define REG_SP 13 -#define REG_LR 14 -#define REG_PC 15 -#define REG_XPSR 16 -#define REG_MSP 17 -#define REG_PSP 18 -#define REG_SPECIAL 19 - bool cortexm_probe(target *t) { t->driver = cortexm_driver_str; diff --git a/src/include/cortexm.h b/src/include/cortexm.h index f7396bf9..0a9c3aed 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -143,6 +143,16 @@ #define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0) #define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0) +#define REG_SP 13 +#define REG_LR 14 +#define REG_PC 15 +#define REG_XPSR 16 +#define REG_MSP 17 +#define REG_PSP 18 +#define REG_SPECIAL 19 + +#define ARM_THUMB_BREAKPOINT 0xBE00 + bool cortexm_attach(target *t); void cortexm_detach(target *t); void cortexm_halt_resume(target *t, bool step); diff --git a/src/include/lpc_common.h b/src/include/lpc_common.h new file mode 100644 index 00000000..45d2964e --- /dev/null +++ b/src/include/lpc_common.h @@ -0,0 +1,83 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Gareth McMullin + * + * 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 . + */ + +#ifndef __LPC_COMMON_H +#define __LPC_COMMON_H + +#define IAP_CMD_INIT 49 +#define IAP_CMD_PREPARE 50 +#define IAP_CMD_PROGRAM 51 +#define IAP_CMD_ERASE 52 +#define IAP_CMD_BLANKCHECK 53 +#define IAP_CMD_SET_ACTIVE_BANK 60 + +#define IAP_STATUS_CMD_SUCCESS 0 +#define IAP_STATUS_INVALID_COMMAND 1 +#define IAP_STATUS_SRC_ADDR_ERROR 2 +#define IAP_STATUS_DST_ADDR_ERROR 3 +#define IAP_STATUS_SRC_ADDR_NOT_MAPPED 4 +#define IAP_STATUS_DST_ADDR_NOT_MAPPED 5 +#define IAP_STATUS_COUNT_ERROR 6 +#define IAP_STATUS_INVALID_SECTOR 7 +#define IAP_STATUS_SECTOR_NOT_BLANK 8 +#define IAP_STATUS_SECTOR_NOT_PREPARED 9 +#define IAP_STATUS_COMPARE_ERROR 10 +#define IAP_STATUS_BUSY 11 + +/* CPU Frequency */ +#define CPU_CLK_KHZ 12000 + +struct flash_param { + uint16_t opcode;/* opcode to return to after calling the ROM */ + uint16_t pad0; + uint32_t command;/* IAP command */ + union { + uint32_t words[5];/* command parameters */ + struct { + uint32_t start_sector; + uint32_t end_sector; + uint32_t flash_bank; + } prepare; + struct { + uint32_t start_sector; + uint32_t end_sector; + uint32_t cpu_clk_khz; + uint32_t flash_bank; + } erase; + struct { + uint32_t dest; + uint32_t source; + uint32_t byte_count; + uint32_t cpu_clk_khz; + } program; + struct { + uint32_t start_sector; + uint32_t end_sector; + uint32_t flash_bank; + } blank_check; + struct { + uint32_t flash_bank; + uint32_t cpu_clk_khz; + } make_active; + }; + uint32_t result[5]; /* result data */ +} __attribute__((aligned(4))); + +#endif + diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 3a85ded9..7c6d7426 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -1,6 +1,9 @@ /* * This file is part of the Black Magic Debug project. * + * Copyright (C) 2011 Mike Smith + * Copyright (C) 2015 Gareth McMullin + * * 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 @@ -14,26 +17,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + #include "general.h" -#include "adiv5.h" #include "target.h" +#include "cortexm.h" +#include "lpc_common.h" #define IAP_PGM_CHUNKSIZE 256 /* should fit in RAM on any device */ -struct flash_param { - uint16_t opcodes[2]; /* two opcodes to return to after calling the ROM */ - uint32_t command[5]; /* command operands */ - uint32_t result[4]; /* result data */ -}; -struct flash_program { - struct flash_param p; - uint8_t data[IAP_PGM_CHUNKSIZE]; -}; - -static struct flash_program flash_pgm; - -#define MSP 17 /* Main stack pointer register number */ #define MIN_RAM_SIZE_FOR_LPC8xx 1024 #define MIN_RAM_SIZE_FOR_LPC1xxx 2048 #define RAM_USAGE_FOR_IAP_ROUTINES 32 /* IAP routines use 32 bytes at top of ram */ @@ -41,24 +33,6 @@ static struct flash_program flash_pgm; #define IAP_ENTRYPOINT 0x1fff1ff1 #define IAP_RAM_BASE 0x10000000 -#define IAP_CMD_PREPARE 50 -#define IAP_CMD_PROGRAM 51 -#define IAP_CMD_ERASE 52 -#define IAP_CMD_BLANKCHECK 53 - -#define IAP_STATUS_CMD_SUCCESS 0 -#define IAP_STATUS_INVALID_COMMAND 1 -#define IAP_STATUS_SRC_ADDR_ERROR 2 -#define IAP_STATUS_DST_ADDR_ERROR 3 -#define IAP_STATUS_SRC_ADDR_NOT_MAPPED 4 -#define IAP_STATUS_DST_ADDR_NOT_MAPPED 5 -#define IAP_STATUS_COUNT_ERROR 6 -#define IAP_STATUS_INVALID_SECTOR 7 -#define IAP_STATUS_SECTOR_NOT_BLANK 8 -#define IAP_STATUS_SECTOR_NOT_PREPARED 9 -#define IAP_STATUS_COMPARE_ERROR 10 -#define IAP_STATUS_BUSY 11 - static const char lpc8xx_driver[] = "lpc8xx"; static const char lpc11xx_driver[] = "lpc11xx"; static void lpc11x_iap_call(target *t, struct flash_param *param, unsigned param_len); @@ -67,6 +41,11 @@ static int lpc11xx_flash_erase(target *t, uint32_t addr, size_t len); static int lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); +struct flash_program { + struct flash_param p; + uint8_t data[IAP_PGM_CHUNKSIZE]; +}; + /* * Note that this memory map is actually for the largest of the lpc11xx devices; * There seems to be no good way to decode the part number to determine the RAM @@ -168,8 +147,8 @@ lpc11x_iap_call(target *t, struct flash_param *param, unsigned param_len) uint32_t regs[t->regs_size / sizeof(uint32_t)]; /* fill out the remainder of the parameters and copy the structure to RAM */ - param->opcodes[0] = 0xbe00; - param->opcodes[1] = 0x0000; + param->opcode = ARM_THUMB_BREAKPOINT; + param->pad0 = 0x0000; target_mem_write(t, IAP_RAM_BASE, param, param_len); /* set up for the call to the IAP ROM */ @@ -179,11 +158,11 @@ lpc11x_iap_call(target *t, struct flash_param *param, unsigned param_len) // stack pointer - top of the smallest ram less 32 for IAP usage if (t->driver == lpc8xx_driver) - regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC8xx - RAM_USAGE_FOR_IAP_ROUTINES; + regs[REG_MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC8xx - RAM_USAGE_FOR_IAP_ROUTINES; else - regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES; - regs[14] = IAP_RAM_BASE | 1; - regs[15] = IAP_ENTRYPOINT; + regs[REG_MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - 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 */ @@ -205,11 +184,12 @@ static int flash_page_size(target *t) static int lpc11xx_flash_prepare(target *t, uint32_t addr, int len) { + struct flash_program flash_pgm; /* prepare the sector(s) to be erased */ memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); - flash_pgm.p.command[0] = IAP_CMD_PREPARE; - flash_pgm.p.command[1] = addr / flash_page_size(t); - flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(t); + flash_pgm.p.command = IAP_CMD_PREPARE; + flash_pgm.p.prepare.start_sector = addr / flash_page_size(t); + flash_pgm.p.prepare.end_sector = (addr + len - 1) / flash_page_size(t); lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -222,6 +202,7 @@ lpc11xx_flash_prepare(target *t, uint32_t addr, int len) static int lpc11xx_flash_erase(target *t, uint32_t addr, size_t len) { + struct flash_program flash_pgm; if (addr % flash_page_size(t)) return -1; @@ -231,15 +212,18 @@ lpc11xx_flash_erase(target *t, uint32_t addr, size_t len) return -1; /* and now erase them */ - flash_pgm.p.command[0] = IAP_CMD_ERASE; - flash_pgm.p.command[1] = addr / flash_page_size(t); - flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(t); - flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */ + flash_pgm.p.command = IAP_CMD_ERASE; + flash_pgm.p.erase.start_sector = addr / flash_page_size(t); + flash_pgm.p.erase.end_sector = (addr + len - 1) / flash_page_size(t); + flash_pgm.p.erase.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } - flash_pgm.p.command[0] = IAP_CMD_BLANKCHECK; + + /* check erase ok */ + flash_pgm.p.command = IAP_CMD_BLANKCHECK; lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; @@ -255,6 +239,7 @@ lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE; unsigned chunk; + struct flash_program flash_pgm; for (chunk = first_chunk; chunk <= last_chunk; chunk++) { @@ -269,8 +254,8 @@ lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) size_t copylen = IAP_PGM_CHUNKSIZE - chunk_offset; if (copylen > len) copylen = len; - memcpy(&flash_pgm.data[chunk_offset], src, copylen); + memcpy(flash_pgm.data + chunk_offset, src, copylen); /* if we are programming the vectors, calculate the magic number */ if ((chunk == 0) && (chunk_offset == 0)) { if (copylen < 32) { @@ -290,9 +275,7 @@ lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) len -= copylen; src += copylen; chunk_offset = 0; - } else { - /* interior chunk, must be aligned and full-sized */ memcpy(flash_pgm.data, src, IAP_PGM_CHUNKSIZE); len -= IAP_PGM_CHUNKSIZE; @@ -304,12 +287,12 @@ lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) return -1; /* set the destination address and program */ - flash_pgm.p.command[0] = IAP_CMD_PROGRAM; - flash_pgm.p.command[1] = chunk * IAP_PGM_CHUNKSIZE; - flash_pgm.p.command[2] = IAP_RAM_BASE + offsetof(struct flash_program, data); - flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE; - /* assuming we are running off IRC - safe lower bound */ - flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */ + flash_pgm.p.command = IAP_CMD_PROGRAM; + flash_pgm.p.program.dest = chunk * IAP_PGM_CHUNKSIZE; + flash_pgm.p.program.source = IAP_RAM_BASE + offsetof(struct flash_program, data); + flash_pgm.p.program.byte_count = IAP_PGM_CHUNKSIZE; + flash_pgm.p.program.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 15193066..ad93c8d2 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -1,7 +1,8 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2012 Gareth McMullin + * Copyright (C) 2014 Allen Ibara + * Copyright (C) 2015 Gareth McMullin * * 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 @@ -19,17 +20,13 @@ #include "general.h" #include "command.h" -#include "adiv5.h" #include "target.h" #include "gdb_packet.h" +#include "cortexm.h" +#include "lpc_common.h" #define LPC43XX_CHIPID 0x40043200 #define ARM_CPUID 0xE000ED00 -#define ARM_THUMB_BREAKPOINT 0xBE00 - -#define R_MSP 17 // Main stack pointer register number -#define R_PC 15 // Program counter register number -#define R_LR 14 // Link register number #define IAP_ENTRYPOINT_LOCATION 0x10400100 @@ -47,25 +44,6 @@ #define IAP_PGM_CHUNKSIZE 4096 -#define IAP_CMD_INIT 49 -#define IAP_CMD_PREPARE 50 -#define IAP_CMD_PROGRAM 51 -#define IAP_CMD_ERASE 52 -#define IAP_CMD_BLANKCHECK 53 -#define IAP_CMD_SET_ACTIVE_BANK 60 - -#define IAP_STATUS_CMD_SUCCESS 0 -#define IAP_STATUS_INVALID_COMMAND 1 -#define IAP_STATUS_SRC_ADDR_ERROR 2 -#define IAP_STATUS_DST_ADDR_ERROR 3 -#define IAP_STATUS_SRC_ADDR_NOT_MAPPED 4 -#define IAP_STATUS_DST_ADDR_NOT_MAPPED 5 -#define IAP_STATUS_COUNT_ERROR 6 -#define IAP_STATUS_INVALID_SECTOR 7 -#define IAP_STATUS_SECTOR_NOT_BLANK 8 -#define IAP_STATUS_SECTOR_NOT_PREPARED 9 -#define IAP_STATUS_COMPARE_ERROR 10 -#define IAP_STATUS_BUSY 11 #define FLASH_BANK_A_BASE 0x1A000000 #define FLASH_BANK_A_SIZE 0x80000 @@ -75,45 +53,6 @@ #define FLASH_NUM_SECTOR 15 #define FLASH_LARGE_SECTOR_OFFSET 0x00010000 -/* CPU Frequency */ -#define CPU_CLK_KHZ 12000 - -struct flash_param { - uint16_t opcode; /* opcode to return to after calling the ROM */ - uint16_t pad0; - uint32_t command; /* IAP command */ - union { - uint32_t words[5]; /* command parameters */ - struct { - uint32_t start_sector; - uint32_t end_sector; - uint32_t flash_bank; - } prepare; - struct { - uint32_t start_sector; - uint32_t end_sector; - uint32_t cpu_clk_khz; - uint32_t flash_bank; - } erase; - struct { - uint32_t dest; - uint32_t source; - uint32_t byte_count; - uint32_t cpu_clk_khz; - } program; - struct { - uint32_t start_sector; - uint32_t end_sector; - uint32_t flash_bank; - } blank_check; - struct { - uint32_t flash_bank; - uint32_t cpu_clk_khz; - } make_active; - } params; - uint32_t result[5]; /* result data */ -} __attribute__((aligned(4))); - struct flash_program { struct flash_param p; uint8_t data[IAP_PGM_CHUNKSIZE]; @@ -242,9 +181,9 @@ static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]) for (bank = 0; bank < FLASH_NUM_BANK; bank++) { flash_pgm.p.command = IAP_CMD_PREPARE; - flash_pgm.p.params.prepare.start_sector = 0; - flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1; - flash_pgm.p.params.prepare.flash_bank = bank; + flash_pgm.p.prepare.start_sector = 0; + flash_pgm.p.prepare.end_sector = FLASH_NUM_SECTOR-1; + flash_pgm.p.prepare.flash_bank = bank; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -252,10 +191,10 @@ static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]) } flash_pgm.p.command = IAP_CMD_ERASE; - flash_pgm.p.params.erase.start_sector = 0; - flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1; - flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; - flash_pgm.p.params.erase.flash_bank = bank; + flash_pgm.p.erase.start_sector = 0; + flash_pgm.p.prepare.end_sector = FLASH_NUM_SECTOR-1; + flash_pgm.p.erase.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.erase.flash_bank = bank; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) @@ -343,8 +282,8 @@ static void lpc43xx_iap_call(target *t, struct flash_param *param, unsigned para target_mem_read(t, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); /* fill out the remainder of the parameters and copy the structure to RAM */ - param->opcode = ARM_THUMB_BREAKPOINT; /* breakpoint */ - param->pad0 = 0x0000; /* pad */ + param->opcode = ARM_THUMB_BREAKPOINT; + param->pad0 = 0x0000; target_mem_write(t, IAP_RAM_BASE, param, param_len); /* set up for the call to the IAP ROM */ @@ -352,9 +291,9 @@ static void lpc43xx_iap_call(target *t, struct flash_param *param, unsigned para regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); - regs[R_MSP] = IAP_RAM_BASE + IAP_RAM_SIZE; - regs[R_LR] = IAP_RAM_BASE | 1; - regs[R_PC] = iap_entry; + regs[REG_MSP] = IAP_RAM_BASE + IAP_RAM_SIZE; + regs[REG_LR] = IAP_RAM_BASE | 1; + regs[REG_PC] = iap_entry; target_regs_write(t, regs); /* start the target and wait for it to halt again */ @@ -370,11 +309,11 @@ static int lpc43xx_flash_prepare(target *t, uint32_t addr, int len) struct flash_program flash_pgm; /* prepare the sector(s) to be erased */ + memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); flash_pgm.p.command = IAP_CMD_PREPARE; - flash_pgm.p.params.prepare.start_sector = sector_number(addr); - flash_pgm.p.params.prepare.end_sector = sector_number(addr+len); - flash_pgm.p.params.prepare.flash_bank = flash_bank(addr); - flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + flash_pgm.p.prepare.start_sector = sector_number(addr); + flash_pgm.p.prepare.end_sector = sector_number(addr+len); + flash_pgm.p.prepare.flash_bank = flash_bank(addr); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -402,10 +341,10 @@ static int lpc43xx_flash_erase(target *t, uint32_t addr, size_t len) /* and now erase them */ flash_pgm.p.command = IAP_CMD_ERASE; - flash_pgm.p.params.erase.start_sector = sector_number(addr); - flash_pgm.p.params.erase.end_sector = sector_number(addr+len); - flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; - flash_pgm.p.params.erase.flash_bank = flash_bank(addr); + flash_pgm.p.erase.start_sector = sector_number(addr); + flash_pgm.p.erase.end_sector = sector_number(addr+len); + flash_pgm.p.erase.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.erase.flash_bank = flash_bank(addr); flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -414,9 +353,9 @@ static int lpc43xx_flash_erase(target *t, uint32_t addr, size_t len) /* check erase ok */ flash_pgm.p.command = IAP_CMD_BLANKCHECK; - flash_pgm.p.params.blank_check.start_sector = sector_number(addr); - flash_pgm.p.params.blank_check.end_sector = sector_number(addr+len); - flash_pgm.p.params.blank_check.flash_bank = flash_bank(addr); + flash_pgm.p.blank_check.start_sector = sector_number(addr); + flash_pgm.p.blank_check.end_sector = sector_number(addr+len); + flash_pgm.p.blank_check.flash_bank = flash_bank(addr); flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -437,17 +376,13 @@ static int lpc43xx_flash_write(target *t, { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; - unsigned chunk_offset; + unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE; unsigned chunk; struct flash_program flash_pgm; for (chunk = first_chunk; chunk <= last_chunk; chunk++) { - if (chunk == first_chunk) { - chunk_offset = dest % IAP_PGM_CHUNKSIZE; - } else { - chunk_offset = 0; - } + DEBUG("chunk %u len %zu\n", chunk, len); /* first and last chunk may require special handling */ if ((chunk == first_chunk) || (chunk == last_chunk)) { @@ -464,6 +399,7 @@ static int lpc43xx_flash_write(target *t, /* update to suit */ len -= copylen; src += copylen; + chunk_offset = 0; } else { /* interior chunk, must be aligned and full-sized */ memcpy(flash_pgm.data, src, IAP_PGM_CHUNKSIZE); @@ -472,21 +408,15 @@ static int lpc43xx_flash_write(target *t, } /* prepare... */ - if (lpc43xx_flash_prepare(t, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) { + if (lpc43xx_flash_prepare(t, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) return -1; - } - - /* copy buffer into target memory */ - target_mem_write(t, - IAP_RAM_BASE + offsetof(struct flash_program, data), - flash_pgm.data, sizeof(flash_pgm.data)); /* set the destination address and program */ flash_pgm.p.command = IAP_CMD_PROGRAM; - flash_pgm.p.params.program.dest = chunk * IAP_PGM_CHUNKSIZE; - flash_pgm.p.params.program.source = IAP_RAM_BASE + offsetof(struct flash_program, data); - flash_pgm.p.params.program.byte_count = IAP_PGM_CHUNKSIZE; - flash_pgm.p.params.program.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.program.dest = chunk * IAP_PGM_CHUNKSIZE; + flash_pgm.p.program.source = IAP_RAM_BASE + offsetof(struct flash_program, data); + flash_pgm.p.program.byte_count = IAP_PGM_CHUNKSIZE; + flash_pgm.p.program.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -524,8 +454,8 @@ static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]) /* special command to compute/write magic vector for signature */ flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK; - flash_pgm.p.params.make_active.flash_bank = bank; - flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.make_active.flash_bank = bank; + flash_pgm.p.make_active.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {