Use a single static program buffer rather than allocating several on the stack.
This commit is contained in:
parent
00651032ad
commit
af45139767
@ -8,19 +8,21 @@
|
|||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "nxp_tgt.h"
|
#include "nxp_tgt.h"
|
||||||
|
|
||||||
|
#define IAP_PGM_CHUNKSIZE 256 /* should fit in RAM on any device */
|
||||||
|
|
||||||
struct flash_param {
|
struct flash_param {
|
||||||
uint16_t opcodes[2]; /* two opcodes to return to after calling the ROM */
|
uint16_t opcodes[2]; /* two opcodes to return to after calling the ROM */
|
||||||
uint32_t command[5]; /* command operands */
|
uint32_t command[5]; /* command operands */
|
||||||
uint32_t result[4]; /* result data */
|
uint32_t result[4]; /* result data */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IAP_PGM_CHUNKSIZE 256 /* should fit in RAM on any device */
|
|
||||||
|
|
||||||
struct flash_program {
|
struct flash_program {
|
||||||
struct flash_param p;
|
struct flash_param p;
|
||||||
uint8_t data[IAP_PGM_CHUNKSIZE];
|
uint8_t data[IAP_PGM_CHUNKSIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct flash_program flash_pgm;
|
||||||
|
|
||||||
#define IAP_ENTRYPOINT 0x1fff1ff1
|
#define IAP_ENTRYPOINT 0x1fff1ff1
|
||||||
#define IAP_RAM_BASE 0x10000000
|
#define IAP_RAM_BASE 0x10000000
|
||||||
|
|
||||||
@ -140,16 +142,14 @@ lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned par
|
|||||||
static int
|
static int
|
||||||
lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len)
|
lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len)
|
||||||
{
|
{
|
||||||
struct flash_param p;
|
|
||||||
|
|
||||||
/* prepare the sector(s) to be erased */
|
/* prepare the sector(s) to be erased */
|
||||||
memset(&p, 0, sizeof(p));
|
memset(&flash_pgm.p, 0, sizeof(flash_pgm.p));
|
||||||
p.command[0] = IAP_CMD_PREPARE;
|
flash_pgm.p.command[0] = IAP_CMD_PREPARE;
|
||||||
p.command[1] = addr / 4096;
|
flash_pgm.p.command[1] = addr / 4096;
|
||||||
p.command[2] = p.command[1] + ((len + 4095) / 4096) - 1;
|
flash_pgm.p.command[2] = flash_pgm.p.command[1] + ((len + 4095) / 4096) - 1;
|
||||||
|
|
||||||
lpc11x_iap_call(target, &p, sizeof(p));
|
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
|
||||||
if (p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +159,6 @@ lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len)
|
|||||||
static int
|
static int
|
||||||
lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len)
|
lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len)
|
||||||
{
|
{
|
||||||
struct flash_param p;
|
|
||||||
|
|
||||||
if (addr % 4096)
|
if (addr % 4096)
|
||||||
return -1;
|
return -1;
|
||||||
@ -169,17 +168,17 @@ lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* and now erase them */
|
/* and now erase them */
|
||||||
p.command[0] = IAP_CMD_ERASE;
|
flash_pgm.p.command[0] = IAP_CMD_ERASE;
|
||||||
p.command[1] = addr / 4096;
|
flash_pgm.p.command[1] = addr / 4096;
|
||||||
p.command[2] = p.command[1] + ((len + 4095) / 4096) - 1;
|
flash_pgm.p.command[2] = flash_pgm.p.command[1] + ((len + 4095) / 4096) - 1;
|
||||||
p.command[3] = 12000; /* XXX safe to assume this? */
|
flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */
|
||||||
lpc11x_iap_call(target, &p, sizeof(p));
|
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
|
||||||
if (p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p.command[0] = IAP_CMD_BLANKCHECK;
|
flash_pgm.p.command[0] = IAP_CMD_BLANKCHECK;
|
||||||
lpc11x_iap_call(target, &p, sizeof(p));
|
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
|
||||||
if (p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +188,6 @@ lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len)
|
|||||||
static int
|
static int
|
||||||
lpc11xx_flash_write_words(struct target_s *target, uint32_t dest, const uint32_t *src, int len)
|
lpc11xx_flash_write_words(struct target_s *target, uint32_t dest, const uint32_t *src, int len)
|
||||||
{
|
{
|
||||||
struct flash_program pgm;
|
|
||||||
const uint8_t *s = (const uint8_t *)src;
|
const uint8_t *s = (const uint8_t *)src;
|
||||||
unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE;
|
unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE;
|
||||||
unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE;
|
unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE;
|
||||||
@ -203,13 +201,13 @@ lpc11xx_flash_write_words(struct target_s *target, uint32_t dest, const uint32_t
|
|||||||
if ((chunk == first_chunk) || (chunk == last_chunk)) {
|
if ((chunk == first_chunk) || (chunk == last_chunk)) {
|
||||||
|
|
||||||
/* fill with all ff to avoid sector rewrite corrupting other writes */
|
/* fill with all ff to avoid sector rewrite corrupting other writes */
|
||||||
memset(pgm.data, 0xff, sizeof(pgm.data));
|
memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data));
|
||||||
|
|
||||||
/* copy as much as fits */
|
/* copy as much as fits */
|
||||||
int copylen = IAP_PGM_CHUNKSIZE - chunk_offset;
|
int copylen = IAP_PGM_CHUNKSIZE - chunk_offset;
|
||||||
if (copylen > len)
|
if (copylen > len)
|
||||||
copylen = len;
|
copylen = len;
|
||||||
memcpy(&pgm.data[chunk_offset], s, copylen);
|
memcpy(&flash_pgm.data[chunk_offset], s, copylen);
|
||||||
|
|
||||||
/* update to suit */
|
/* update to suit */
|
||||||
len -= copylen;
|
len -= copylen;
|
||||||
@ -218,7 +216,7 @@ lpc11xx_flash_write_words(struct target_s *target, uint32_t dest, const uint32_t
|
|||||||
|
|
||||||
/* if we are programming the vectors, calculate the magic number */
|
/* if we are programming the vectors, calculate the magic number */
|
||||||
if (chunk == 0) {
|
if (chunk == 0) {
|
||||||
uint32_t *w = (uint32_t *)(&pgm.data[0]);
|
uint32_t *w = (uint32_t *)(&flash_pgm.data[0]);
|
||||||
uint32_t sum = 0;
|
uint32_t sum = 0;
|
||||||
|
|
||||||
for (unsigned i = 0; i < 7; i++)
|
for (unsigned i = 0; i < 7; i++)
|
||||||
@ -229,7 +227,7 @@ lpc11xx_flash_write_words(struct target_s *target, uint32_t dest, const uint32_t
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* interior chunk, must be aligned and full-sized */
|
/* interior chunk, must be aligned and full-sized */
|
||||||
memcpy(pgm.data, s, IAP_PGM_CHUNKSIZE);
|
memcpy(flash_pgm.data, s, IAP_PGM_CHUNKSIZE);
|
||||||
len -= IAP_PGM_CHUNKSIZE;
|
len -= IAP_PGM_CHUNKSIZE;
|
||||||
s += IAP_PGM_CHUNKSIZE;
|
s += IAP_PGM_CHUNKSIZE;
|
||||||
}
|
}
|
||||||
@ -239,13 +237,13 @@ lpc11xx_flash_write_words(struct target_s *target, uint32_t dest, const uint32_t
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* set the destination address and program */
|
/* set the destination address and program */
|
||||||
pgm.p.command[0] = IAP_CMD_PROGRAM;
|
flash_pgm.p.command[0] = IAP_CMD_PROGRAM;
|
||||||
pgm.p.command[1] = chunk * IAP_PGM_CHUNKSIZE;
|
flash_pgm.p.command[1] = chunk * IAP_PGM_CHUNKSIZE;
|
||||||
pgm.p.command[2] = IAP_RAM_BASE + offsetof(struct flash_program, data);
|
flash_pgm.p.command[2] = IAP_RAM_BASE + offsetof(struct flash_program, data);
|
||||||
pgm.p.command[3] = IAP_PGM_CHUNKSIZE;
|
flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE;
|
||||||
pgm.p.command[4] = 12000; /* XXX safe to presume this? */
|
flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */
|
||||||
lpc11x_iap_call(target, &pgm.p, sizeof(pgm));
|
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm));
|
||||||
if (pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user