Programming the LPC1857 using another microcontroller via SWD

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Programming the LPC1857 using another microcontroller via SWD

9,229 Views
fabiano1
Contributor III

I need to program the LPC1857 via SWD using another microcontroller. I cannot use UART for this, it has to be via SWD.

I have no doubts about the SWD protocol, so much so that I can already reset JTAG-TO-SWD, read the LPC1857 IDCode and perform other transactions through the SWD.

Using the NXP LPC-link, I programed LPC1857. During programming, I perform the communication sniffer. For this program I use a known .hex.

Using the data obtained in the sniffer, I copied and saved everything that the NXP LPC-Link sent to the LPC1857 until the start of sending the .hex.

Using the documents: UM10430 (LPC1857 reference manual), Cortex: tm: -M3 - Technical Reference Manual and CoreSight: tm: Components - Technical Reference Manual (where you have the information about the SWD), I tried to understand the values obtained in the sniffer, but I couldn't find the following addresses in any of these documents:

- 0xE000ED88
- 0xE00FFFBC
- 0xE00FF000
- 0xE000EFBC
- 0xE0001FBC
- 0xE0002FBC
- 0xE0000FBC
- 0xE0040FBC
- 0xE0041FBC

I know that the values listed above are addresses, as they are written in the TAR register of the SWD.

Some of these values can be found in the documentation for Cotex-M4, Cotex-M7 and Cortex-M33, but as the LPC1857 is a Cortex-M3, I imagine that I cannot use this information found in these documents.

I need a document that explains how to record the LPC1857 via SWD, or at least a documentation that has an explanation of the addresses listed above.

Thank you.

Tags (2)
25 Replies

7,857 Views
converse
Senior Contributor V

You can find descriptions of these registers in the Cortex-M3 Technical reference manual

http://infocenter.arm.com/help/topic/com.arm.doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdf

the addresses you provide look like they are part of the NVIC and System Comtrol Block. chapter 8 in the above manual

0 Kudos
Reply

7,857 Views
fabiano1
Contributor III

Thank you for your support!

But I did not find these registers in the NVIC address range (chapter 8). Here are the considerations:

0xE000ED88:
- In chapter 8, it even has the description of register 0xE000ED70 (ISAR4), then skips to register 0xE000EF00 (Software Trigger Interrupt Register), skipping register 0xE000ED88.

0xE000EFBC:
- The register 0xE000EFBC is outside the address range shown in chapter 8, as the ranges are:
- 0xE000EF00 - 0xE000EF0F. Software Trigger Exception Register
- 0xE000EFD0 - 0xE000EFFF. ID space.

- 0xE0001FBC, 0xE0002FBC and 0xE0000FBC:
- These registers are before the address range of chapter 8, since the NVIC address map starts at address 0xE000E000.

- 0xE00FFFBC, 0xE00FF000, 0xE0040FBC and 0xE0041FBC:
- These registers are after the address range of chapter 8, since the NVIC address map ends at address 0xE000EFFF.

All the above information was obtained from the document sent.

In this way, I still don't know what these registers sent by NXP LPC-link mean during the recording of LPC1857.

Do you have another document that can explain what these registers are?

0 Kudos
Reply

7,857 Views
converse
Senior Contributor V

I think you are going about this the wrong way. You will be better to start from working debugger source, such as Arm’s DAPLink (formerly CMSIS-DAP).

get it from here

GitHub - ARMmbed/DAPLink 

0 Kudos
Reply

7,857 Views
fabiano1
Contributor III

Thank you very much for the reply.

I really liked this code and I am studying it as suggested.

- As I understand it, to add a new microcontroller in the code it is necessary to generate a BLOB according to the file "DAPLink / docs / PORT_TARGET_FAMILY.md". This file references the project "https://github.com/mbedmicro/FlashAlgo" to generate the BLOB.
Within this repository "FlashAlgo" has two python projects, "flash_algo.py and generate_blobs.py".
I have some doubts:
- How should I use these softwares, flash_algo and generate_blobs?
- In the generete_blobs software, I need to pass two arguments: elf_pach and blob_start. What should be the content of these arguments?
- In the flash_algo software, I need to pass two arguments: input and template. What should be the content of these arguments?

Remembering that I need to generate this BLOB for LPC1857.

0 Kudos
Reply

7,857 Views
converse
Senior Contributor V

There are already flash algorithms for NXP using IAP (which is the only way to program the flash) in the NXP directory.  It works generically and you just add a new entry in a table for your part. There is one for LPC4337 which is virtually identical to your part, so just modify that.

0 Kudos
Reply

7,857 Views
fabiano1
Contributor III

To be able to change what you told us, I need to understand the questions I asked in the previous question, because I need to generate the BLOB of LPC1857 and I cannot use the BLOB of LPC4337 and for that, I need to use the Flash Algo algorithm. Can you help me generate this BLOB for LPC1857, please?

Thanks in advance!

0 Kudos
Reply

7,857 Views
Carlos_Mendoza
NXP Employee
NXP Employee

Hello Fabiano,

  1. I would strongly suggest to use ARM' DAPLINK open source project as start point, reverse engineering is not an easy task.
  2. Generally, SWD host should do the following:

 

- Enable DP and read DPID.

- Reset the chip.

- Set CoreDebug bit.

- Set Halt on Reset bit in SCB and then reset the chip again, this is aim to halt target core.

- Do chip specific task, such as disable WDOG, disable MPU etc. to let SWD host fully and safely control target.

- Inject flash programming algo.

- Do flash programming.

Let us know if you run into any issue.

Regards,

Carlos Mendoza

7,857 Views
fabiano1
Contributor III

Hello Carlos Mendoza, how are you?

I am at a point in my project that needs a lot of help. I realized that you liked my answer, I would like to know if you are elaborating the answer. Do not understand it as a demand from me, but I really need that help.

Thank you!

7,857 Views
Carlos_Mendoza
NXP Employee
NXP Employee

Hello Fabiano,

 

Getting back to your questions:

About the generation of the BLOB: we should following ARM's porting guide (install Py2.7 and related 3th's packet). and using the command:

progen generate -t uvision

This will generate blob file.

 

For programming LPC1857:

 I believe that the NVIC should have the same address as the beginning of the firmware located in RAM and that the MSP should have the address assigned to NVIC + 4. Is this correct?

Yes, correct.

My main question is what would be the sequence of manipulations of the CORTEX registers for the firmware located in RAM to be executed. In other words, once my firmware is loaded in RAM, what should I do to make it run?


The answer is quite complex. after we load the algorithm into RAM, the SWD host will modify PC to RAM address and write some core register to let target MCU runing that code. The detail implementation can be found on ARM's DAPLINK source. A colleague wrote a AN about this long time ago, you can refer to it:

https://www.nxp.com/docs/en/application-note/AN5331.pdf

Let me know any question!

Regards,

Carlos Mendoza

7,845 Views
fabiano1
Contributor III

Hi Carlos, how are you?

Thank you very much for your support so far.

I managed to develop a lot with the DAP-Link project, I put it to work using some microcontrollers that it has. I really liked the project, very complete and organized.

However, I am now having trouble recording the LPC1857. I added the files flash_blob.c, target.c and in the compilation files (.yaml) of the project I put the microcontroller. So far everything is ok. I successfully built the project, I managed to put it in the BOARD that would record the LPC1857, however, when I drag and drop the firmware I would like to record, the following error message appears:

error: The firmware interface FAILED to reset / halt the target MCU

type: target

Could anyone help me with this problem? Could it be caused by the target.c file?

Thanks in advance!

0 Kudos
Reply

7,845 Views
Carlos_Mendoza
NXP Employee
NXP Employee

Hello Fabiano,

Good to hear the DAP-Link project was helpful. I have a few questions:

  • Are you using a custom board for the test?
  • Are you able to program the same MCU with another tool?
  • How are the MCUs interconnected in the Board?

Regards!

Carlos Mendoza

FAE

0 Kudos
Reply

7,842 Views
fabiano1
Contributor III

Hello Carlos, how are you?

First by answering your questions:

- I am using a STM32F103 to record the LPC1857.
- I have already performed tests using the STM32F103 to successfully record STM32F072.

I managed to fix the problem on reset, for that I had to make the following change to the file lpc1857expresso.c:

const board_info_t g_board_info = {
.info_version = kBoardInfoVersion,
.board_id = "7777",
.family_id = kStub_HWReset_FamilyID,
.target_cfg = & target_device,
};

For:

const board_info_t g_board_info = {
.info_version = kBoardInfoVersion,
.board_id = "7777",
.family_id = kStub_SWVectReset_FamilyID,
.target_cfg = & target_device,
};

That is, I changed from hardware reset to software reset. In addition, I had to make the following change to flash_blob.c, which I believe is generated wrong.

static const program_target_t flash = {
0x2000002f, // Init
0x20000081, // UnInit
0x20000085, // EraseChip
0x200000d7, // EraseSector
0x2000012d, // ProgramPage
0x12000001f, // Verify

For

static const program_target_t flash = {
0x2000002f, // Init
0x20000081, // UnInit
0x20000085, // EraseChip
0x200000d7, // EraseSector
0x2000012d, // ProgramPage
0x00000000, // Verify

It is noticed that Verify does not make any sense, I don’t know what impact this can generate, I tried to use verify as 0x2000001f, but it didn’t work either. As soon as I set it to 0x00, the recording worked! However, I need to write a firmware that uses the two LPC1857 flashes, 0x1A000000 and 0x1B000000. I made the following changes to flash_blob.c:

// Size of flash
static const uint32_t flash_size = 0x000FA000;

/ **
* List of start and size for each size of flash sector - even indexes are start, odd are size
* The size will apply to all sectors between the listed address and the next address
* in the list.
* The last pair in the list will have sectors starting at that address and ending
* at address flash_start + flash_size.
* /
static const sector_info_t sectors_info [] = {
{0x1a000000, 0x00002000},
{0x1a010000, 0x00010000},
{0x1b000000, 0x00002000},
{0x1b010000, 0x00010000}
};

At target.c I made the following changes:

target_cfg_t target_device = {
.sectors_info = sectors_info,
.sector_info_length = (sizeof (sectors_info)) / (sizeof (sector_info_t)),
.flash_regions [0] .start = 0x1a000000,
.flash_regions [0] .end = 0x1a000000 + KB (512),
.flash_regions [0] .flags = kRegionIsDefault,
.flash_regions [0] .flash_algo = (program_target_t *) & flash,

.flash_regions [1] .start = 0x1b000000,
.flash_regions [1] .end = 0x1b000000 + KB (512),
.flash_regions [1] .flash_algo = (program_target_t *) & flash,

.ram_regions [0] .start = 0x20000000,
.ram_regions [0] .end = 0x20000000 + KB (32)
};

It is worth remembering that when I delete any of the parts added to the flash I can perform the recording of the other flash, for example, when I delete all parameters of the flash 0x1A000000, I can write a firmware in the 0x1B000000. But when I try to record a firmware that uses both flashes, the following error appears:

Flash algorithm write command FAILURE

7,842 Views
Carlos_Mendoza
NXP Employee
NXP Employee

Hello Fabiano,

I have never developed DAPLINK which need support two flash bank, I'm not sure if DAPLINK can support multiple banks of flash.

For Verify, we need to check if Verify is implemented in the flash algorithm. Some flash algorithm does not implement this function, so 0x0000_0000 just like DAPLINK think Verify function address is illegal and pass this function.

Regards!

Carlos Mendoza

FAE

0 Kudos
Reply

7,844 Views
fabiano1
Contributor III

Hello Carlos, how are you?

I'm trying to make the DAPLink environment work. I'm following the tutorial: https://github.com/ARMmbed/DAPLink/blob/master/docs/DEVELOPERS-GUIDE.md

However, I am facing a problem in step 4.2, where I must execute the command:

$ tools / mbedcli_compile.py

The following error appears:

Building project DAPLink (k20dx_frdmkl02z_if, ARM)
Scan: DAPLink
Compile [1.3%]: frdmkl02z.c
[ERROR] Error: C9555E: Failed to check out a license.
The license file could not be found. Check that ARMLMD_LICENSE_FILE is set correctly.
ARMLMD_LICENSE_FILE is not set. You must set this to the path to your license.

Would you help me out of this? Do I really need this lisence? If so, how do I get it?

Thank you very much.

0 Kudos
Reply

7,842 Views
converse
Senior Contributor V

Looks like that is for ARM DS-5 (an expensive toolchain!). Is there no option to use gcc?

7,854 Views
fabiano1
Contributor III

Hello Carlos, thank you very much for the answer.

I am analyzing the DAP_Link code and I am enjoying what I am seeing. Thank you very much.

I'll send you more information soon.

7,854 Views
Carlos_Mendoza
NXP Employee
NXP Employee

Hello Fabiano,

I'm doing well thanks! Yes, I'm doing some research and I will get back to you as soon as possible.

Regards,

Carlos Mendoza

0 Kudos
Reply

7,854 Views
fabiano1
Contributor III

Hello Carlos.

First of all, I would like to thank you for your support.

About DAP-Link, I started an analysis and stopped at the point of generating the BLOB, where I checked the documentation that needed to use Flash_Algo (https://github.com/mbedmicro/FlashAlgo), but I couldn't understand how to use this software to generate the BLOB. This did not concern me, because I am at a very advanced level of my project. Today with my project I can program via SWD microcontrollers like: STM32F107 from ST, SAMD and SAM4E from Atmel.

The steps I am following today to attempt to program LPC1857 are:

- Reset JTAG-to-SWD
- Read IDCODE
- Set the CDBGPWRUPREQ and CSYSPWRUPREQ registers
- Reading the CTRL / STAT
- Select extra address for reading the IDR (SELECT = 0x000000F0)
- Read IDR
- Return to common address range (SELECT = 0x00)
- Configure 32-bit transactions (CSW = 0x23000042)
- Sending DBGKEY and setting C_HALT and C_DEBUGGEN (0xA05F0003) to DHCSR (0xE000EDF0)
- From that point on, I can load firmware into a RAM address and also manipulate (read / write) CORTEX registers (MSP, PC, R0…)

I believe that the NVIC should have the same address as the beginning of the firmware located in RAM and that the MSP should have the address assigned to NVIC + 4. Is this correct?

My main question is what would be the sequence of manipulations of the CORTEX registers for the firmware located in RAM to be executed. In other words, once my firmware is loaded in RAM, what should I do to make it run?

Thank you very much and I look forward to your reply.

7,854 Views
converse
Senior Contributor V

I'd suggest

setting a breakpoint at a known place in your code so that you know when it has finished its 'task'

having some sort of communication area at a known location so that messages can be sent between the host code and the target

to start executing your code, you should only need to set up a stack pointer and the PC and running

For some clues as to how NXP do this, take a look at the source code to the flash drivers that they provide, which can be found in the MCUXpresso IDE installation at ide/Examples/Flashdrivers/NXP

0 Kudos
Reply

7,854 Views
johnzhao
Contributor I

I used generate_blobs.py to generate the BLOB of LPC1857 .bankA  .the c_blob.c is

static const uint32_t LPC18xx43xx_512_BA_flash_prog_blob[] = {
0xE00ABE00, 0x062D780D, 0x24084068, 0xD3000040, 0x1E644058, 0x1C49D1FA, 0x2A001E52, 0x4770D1F2,
0x0e400300, 0xd3012807, 0x1dc008c0, 0xb5704770, 0x220d4956, 0x06524449, 0x42906048, 0x2001d001,
0x2000e000, 0x4a536088, 0x62d04851, 0x4c534852, 0x444c6008, 0x4e522031, 0x46216020, 0x68323118,
0x4620460d, 0x20004790, 0x203661a0, 0x68326020, 0x46204629, 0x69a04790, 0xd0002800, 0xbd702001,
0x47702000, 0x4c45b5f8, 0x444c2032, 0x270e2600, 0x4d3ec4c1, 0x444d4621, 0x602068a8, 0x310c4840,
0x483e6802, 0x44483c0c, 0x47909100, 0x280069a0, 0x2034d10f, 0x6828c4c1, 0x68a86020, 0x48386060,
0x68023c0c, 0x99004835, 0x47904448, 0x280069a0, 0x2001d000, 0xb5f8bdf8, 0xffa2f7ff, 0x46044d2f,
0x444d2032, 0x4e29c511, 0x444e602c, 0x606868b0, 0x46294f2b, 0x48293110, 0x4448683a, 0x91003d08,
0x69a84790, 0xd10f2800, 0xc5112034, 0x6830602c, 0x68b06068, 0x482160a8, 0x4448683a, 0x99003d08,
0x69a84790, 0xd0002800, 0xbdf82001, 0xb082b5f7, 0xf7ff4607, 0x4c19ff75, 0x444c2132, 0x60216060,
0x60a04d12, 0x68a8444d, 0x60e04e15, 0x31184621, 0x46206832, 0x47909100, 0x280069a0, 0x2033d113,
0x9804c481, 0x20016020, 0x60600280, 0x60a06828, 0x60e068a8, 0x68324809, 0x3c084448, 0x47909900,
0x280069a0, 0x2001d000, 0xbdf0b005, 0x00000004, 0x01000800, 0x40050040, 0x00002ee0, 0x00000010,
0x10400100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};

// Start address of flash
static const uint32_t flash_start = 0x1a000000;
// Size of flash
static const uint32_t flash_size = 0x00080000;

/**
* List of start and size for each size of flash sector - even indexes are start, odd are size
* The size will apply to all sectors between the listed address and the next address
* in the list.
* The last pair in the list will have sectors starting at that address and ending
* at address flash_start + flash_size.
*/
static const uint32_t sectors_info[] = {
0x1a000000, 0x00002000,
0x1a010000, 0x00010000,
};

static const program_target_t flash = {
0x2000002f, // Init
0x20000081, // UnInit
0x20000085, // EraseChip
0x200000d7, // EraseSector
0x2000012d, // ProgramPage
0x12000001f, // Verify

// BKPT : start of blob + 1
// RSB : blob start + header + rw data offset
// RSP : stack pointer
{
0x20000001,
0x200001a4,
0x20000400
},

0x20000000 + 0x00000A00, // mem buffer location
0x20000000, // location to write prog_blob in target RAM
sizeof(LPC18xx43xx_512_BA_flash_prog_blob), // prog_blob size
LPC18xx43xx_512_BA_flash_prog_blob, // address of prog_blob
0x00000400 // ram_to_flash_bytes_to_be_written
};