Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lpc21isp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,13 @@ static void ReadArguments(ISP_ENVIRONMENT *IspEnvironment, unsigned int argc, ch
continue;
}

if (stricmp(argv[i], "-reset") == 0)
{
IspEnvironment->DoReset = 1;
DebugPrintf(3, "Reset the MCU core after programming.\n");
continue;
}

if(strnicmp(argv[i],"-try", 4) == 0)
{
int
Expand Down Expand Up @@ -1598,6 +1605,7 @@ static void ReadArguments(ISP_ENVIRONMENT *IspEnvironment, unsigned int argc, ch
" -debug3 for progress info only\n"
" -debug5 for full debug\n"
" -donotstart do not start MCU after download\n"
" -reset reset the MCU after download\n"
" -try<n> try n times to synchronise\n"
" -wipe Erase entire device before upload\n"
" -control for controlling RS232 lines for easier booting\n"
Expand Down
1 change: 1 addition & 0 deletions lpc21isp.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ typedef struct
FILE_LIST *f_list; // List of files to read in.
int nQuestionMarks; // how many times to try to synchronise
int DoNotStart;
int DoReset;
int BootHold;
char *serial_port; // Name of the serial port to use to
// communicate with the microcontroller.
Expand Down
116 changes: 115 additions & 1 deletion lpcprog.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,64 @@ Portions Copyright (c) by Aeolus Development 2004 http://www.aeolusdevelopment.c
#ifdef LPC_SUPPORT
#include "lpcprog.h"

/*
* Reset an ARM Cortex-M core using the AIRCR system reset request bit in the
* SCB. This code is then downloaded into RAM and executed after programming.
*
* See ARMv6-M Architecture Reference Manual (f.eks. DDI0419C, sections B1.5.16
* and B3.2.6).
*
* #include <stdint.h>
* #include <core_cm0.h>
*
* static volatile uint32_t *scb = (volatile uint32_t *)0xe000ed00;
* static const uint32_t AIRCR_VECTKEY = 0x05fa0000;
* static const uint32_t AIRCR_SYSRESETREQ = 0x00000004;
*
* void doreset(void) __attribute__((naked));
* void doreset(void)
* {
* __DSB();
* scb[3] = AIRCR_VECTKEY | AIRCR_SYSRESETREQ;
* __DSB();
* while(1)
* ;
* }
*
* Compile : $ arm-none-eabi-gcc -Wall -O2 -mthumb -mcpu=cortex-m0 -std=c99 -c -o doreset.o doreset.c
* Dump code : $ arm-none-eabi-objdump -d doreset.o
* Binary code: $ arm-none-eabi-objcopy -O binary doreset.o doreset.bin
* Checksum : $ s=0 && for i in $(hexdump -e '/1 "0x%02x" "\n"' doreset.bin); do s=$(($s+$i)); done && echo $s
* Uuencode : $ uuencode doreset.bin doreset.bin | head -2 | tail -1
* Bytecount : $ wc -c doreset.bin | cut -d' ' -f1
*
* Note: Above uuencode command assumes there are less than 45 bytes in the
* code. Change head and tail counts accordingly when more lines are
* to be sent.
*
* .text segment code dump:
* 00000000 <doreset>:
* 0: f3bf 8f4f dsb sy
* 4: 4a02 ldr r2, [pc, #8] ; (10 <doreset+0x10>)
* 6: 4b03 ldr r3, [pc, #12] ; (14 <doreset+0x14>)
* 8: 60da str r2, [r3, #12]
* a: f3bf 8f4f dsb sy
* e: e7fe b.n e <doreset+0xe>
* 10: 05fa0004 .word 0x05fa0004
* 14: e000ed00 .word 0xe000ed00
*
* As little-endian bytes in an array:
* static const unsigned char reset_code_m0_le[] = {
* 0xbf, 0xf3, 0x4f, 0x8f, 0x02, 0x4a, 0x03, 0x4b,
* 0xda, 0x60, 0xbf, 0xf3, 0x4f, 0x8f, 0xfe, 0xe7,
* 0x04, 0x00, 0xfa, 0x05, 0x00, 0xed, 0x00, 0xe0
* };
*/

static const char reset_code_m0_le_uu[] = "8O_-/CP)*`TO:8+_S3X_^YP0`^@4`[0#@";
static const unsigned reset_code_m0_le_length = 24;
static const unsigned reset_code_m0_le_checksum = 2985;

static const unsigned int SectorTable_210x[] =
{
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
Expand Down Expand Up @@ -90,6 +148,14 @@ static const unsigned int SectorTable_11xx[] =
4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096
};

static const unsigned int SectorTable_11x6x[] =
{
4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
32768, 32768, 32768, 32768, 32768
};

// Used for LPC17xx devices
static const unsigned int SectorTable_17xx[] =
{
Expand Down Expand Up @@ -210,6 +276,16 @@ static LPC_DEVICE_TYPE LPCtypes[] =
{ 0x00007C44, 0x00000000, 0, "11U37HFBD64/401", 128, 10, 32, 4096, SectorTable_11xx, CHIP_VARIANT_LPC11XX }, /* From UM10462 Rev. 5 -- 20 Nov 2013 */
{ 0x00007C40, 0x00000000, 0, "11U37FBD64/501", 128, 12, 32, 4096, SectorTable_11xx, CHIP_VARIANT_LPC11XX }, /* From UM10462 Rev. 5 -- 20 Nov 2013 */

/* LPC11[UE]6x see UM10732 */
{ 0x0000DCC8, 0x00000000, 0, "11U66", 64, 8, 16, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },
{ 0x0000BC88, 0x00000000, 0, "11U67", 128, 16, 25, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },
{ 0x0000BC80, 0x00000000, 0, "11U67JBD100", 128, 16, 25, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },
{ 0x00007C08, 0x00000000, 0, "11U68", 256, 32, 29, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },
{ 0x00007C00, 0x00000000, 0, "11U68JBD100", 256, 32, 29, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },
{ 0x0000DCC1, 0x00000000, 0, "11E66", 64, 8, 16, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },
{ 0x0000BC81, 0x00000000, 0, "11E67", 128, 16, 25, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },
{ 0x00007C01, 0x00000000, 0, "11E68", 256, 32, 29, 4096, SectorTable_11x6x, CHIP_VARIANT_LPC11XX },

{ 0x3640C02B, 0x00000000, 0, "1224.../101", 32, 8, 4, 2048, SectorTable_17xx, CHIP_VARIANT_LPC11XX },
{ 0x3642C02B, 0x00000000, 0, "1224.../121", 48, 12, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },
{ 0x3650002B, 0x00000000, 0, "1225.../301", 64, 16, 32, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX },
Expand Down Expand Up @@ -1574,7 +1650,45 @@ int NxpDownload(ISP_ENVIRONMENT *IspEnvironment)
}
}

if(IspEnvironment->DoNotStart == 0)
if (IspEnvironment->DoReset)
{
const long ramaddr = 0x10000200;

DebugPrintf(2, "Resetting the core...\n");

/* Download reset code to ram-start + 0x200 */
sprintf(tmpString, "W %ld %u\r\n", ramaddr, reset_code_m0_le_length);
if (!SendAndVerify(IspEnvironment, tmpString, Answer, sizeof Answer))
{
DebugPrintf(1, "Wrong answer on Write-Command on reset code download\n");
return (WRONG_ANSWER_WRIT + GetAndReportErrorNumber(Answer));
}

/* Send reset code */
sprintf(tmpString, "%s\r\n", reset_code_m0_le_uu);
SendComPort(IspEnvironment, tmpString);
ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 1, 5000);

sprintf(tmpString, "%u\r\n", reset_code_m0_le_checksum);
SendComPort(IspEnvironment, tmpString);
ReceiveComPort(IspEnvironment, Answer, sizeof(Answer)-1, &realsize, 2,5000);
sprintf(tmpString, "%u\nOK\n", reset_code_m0_le_checksum);
FormatCommand(tmpString, tmpString);
FormatCommand(Answer, Answer);
if (strcmp(Answer, tmpString) != 0)
{
DebugPrintf(1, "Error on writing reset code CRC\n");
return (ERROR_WRITE_CRC);
}

sprintf(tmpString, "G %ld T\r\n", ramaddr);
SendComPort(IspEnvironment, tmpString);
/*
* We probably never see what happens next... The chip is reset and
* anything may happen. Therefore, we just quit assuming all went well.
*/
}
else if (IspEnvironment->DoNotStart == 0)
{
DebugPrintf(2, "Now launching the brand new code\n");
fflush(stdout);
Expand Down