LPC1549 How to calculate flash signature by original code?

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

LPC1549 How to calculate flash signature by original code?

2,778 Views
fukudatakuya
Contributor I

Hello.

I want to know the algorithm about generating flash signature for LPC 15xx. I cannot understand it at all.

I use LPCXpresso1549 board with MCUXpresso IDE 10.1.0 and LPCOpen V2.20.

I read User Manual at https://www.nxp.com/docs/en/user-guide/UM10736.pdf.

At first, I tested example code "periph_flashiap" from LPCOpen archive, but it didn't work.

I found some bugs at fmc_15xx.h in lpc_chip_15xx folder, and modified as below (red characters).

---fmc_15xx.h

+++fmc_15xx.h

/**
* @brief FLASH Memory Controller Unit register block structure
*/
typedef struct { /*!< FMC Structure */

-__I  uint32_t  RESERVED1[7];
+__I uint32_t RESERVED1[8];
__IO uint32_t FMSSTART;
__IO uint32_t FMSSTOP;
__I uint32_t RESERVED2;
__I uint32_t FMSW[1];
} LPC_FMC_T;

/* Flash signature start and busy status bit */

-#define FMC_FLASHSIG_BUSY   (1UL << 17)

+#define FMC_FLASHSIG_BUSY (1UL << 31)
/**

And it worked example code.

The code told the flash signature of example data is "Hex:0x2d4d6544".

Next I made original calculate code from User Manual algo (page550).

But it didn't match the result, the calculated result was "Hex:0x4ef39cd5".

So I searched LPC forum and found this thread LPC11U6X Flash Signature .

I didn't know and not use LPC11u6X , but I read User Manual about LPC11U6X https://www.nxp.com/docs/en/user-guide/UM10732.pdf.

In Chapter 25(from page425), LPC11U6X has almost same peripherals for flash signature as LPC15xx.

In the thread, The user who original asked found that LPC11U6X have not 32bit generator only, but also 128bit generator in it.

And the result from 128bit mbed LPC signature generator code LPC Signature Generator | Mbed  was matched .

So I implemented and test the code, But the result was not matched.

 I'm very confused, I cannot understand the algo.

Please help.

Thank you.

I attached my modified code "flashiap.c".

/*
* @brief FLASH IAP programming & FLASH signature example using IAP commands
* to write to FLASH memory and a FLASH signature generator
*
* @note
* Copyright(C) NXP Semiconductors, 2013
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/

#include "board.h"
#include <stdio.h>

/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/

#define TICKRATE_HZ (10) /* 10 ticks per second */

/* Last sector address */
#define START_ADDR_LAST_SECTOR 0x0003F000

/* LAST SECTOR */
#define IAP_LAST_SECTOR 63

/* Number of bytes to be written to the last sector */
#define IAP_NUM_BYTES_TO_WRITE 1024

/* Size of each sector */
#define SECTOR_SIZE 4096

/* Number elements in array */
#define ARRAY_ELEMENTS (IAP_NUM_BYTES_TO_WRITE / sizeof(uint32_t))

/* Data array to write to flash */
static uint32_t src_iap_array_data[ARRAY_ELEMENTS];

typedef struct {
unsigned int word0; //Word 0 of 128-bit signature (bits 31 to 0).
unsigned int word1; //Word 1 of 128-bit signature (bits 63 to 32).
unsigned int word2; //Word 2 of 128-bit signature (bits 95 to 64).
unsigned int word3; //Word 3 of 128-bit signature (bits 127 to 96).
} FLASH_SIG_Type;

FLASH_SIG_Type software_sig;


/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/

/*****************************************************************************
* Private functions
****************************************************************************/

/*****************************************************************************
* Public functions
****************************************************************************/

/**
* @brief Handle interrupt from SysTick timer
* @return Nothing
*/
void SysTick_Handler(void)
{
Board_LED_Toggle(0);
}

/**
* @brief Main program body
* @return Always returns 0
*/
int main(void)
{
uint32_t i;
uint8_t ret_code;
uint32_t part_id;

/* Generic Initialization */
SystemCoreClockUpdate();
Board_Init();
Board_LED_Set(0, false);

/* Enable SysTick Timer */
SysTick_Config(SystemCoreClock / TICKRATE_HZ);

/* Initialize the array data to be written to FLASH */
for (i = 0; i < ARRAY_ELEMENTS; i++) {
src_iap_array_data[i] = 0x11223340 + i;
}

/* Read Part Identification Number*/
part_id = Chip_IAP_ReadPID();
DEBUGOUT("Part ID is: %x\r\n", part_id);

/* Disable interrupt mode so it doesn't fire during FLASH updates */
__disable_irq();

/* IAP Flash programming */
/* Prepare to write/erase the last sector */
ret_code = Chip_IAP_PreSectorForReadWrite(IAP_LAST_SECTOR, IAP_LAST_SECTOR);

/* Error checking */
if (ret_code != IAP_CMD_SUCCESS) {
DEBUGOUT("Command failed to execute, return code is: %x\r\n", ret_code);
}

/* Erase the last sector */
ret_code = Chip_IAP_EraseSector(IAP_LAST_SECTOR, IAP_LAST_SECTOR);

/* Error checking */
if (ret_code != IAP_CMD_SUCCESS) {
DEBUGOUT("Command failed to execute, return code is: %x\r\n", ret_code);
}

/* Prepare to write/erase the last sector */
ret_code = Chip_IAP_PreSectorForReadWrite(IAP_LAST_SECTOR, IAP_LAST_SECTOR);

/* Error checking */
if (ret_code != IAP_CMD_SUCCESS) {
DEBUGOUT("Command failed to execute, return code is: %x\r\n", ret_code);
}

/* Write to the last sector */
ret_code = Chip_IAP_CopyRamToFlash(START_ADDR_LAST_SECTOR, src_iap_array_data, IAP_NUM_BYTES_TO_WRITE);

/* Error checking */
if (ret_code != IAP_CMD_SUCCESS) {
DEBUGOUT("Command failed to execute, return code is: %x\r\n", ret_code);
}

/* Re-enable interrupt mode */
__enable_irq();

/* Start the signature generator for the last sector */
Chip_FMC_ComputeSignatureBlocks(START_ADDR_LAST_SECTOR, (SECTOR_SIZE / 16));

/* Check for signature geenration completion */
while (Chip_FMC_IsSignatureBusy()) {}

/* Get the generated FLASH signature value */
DEBUGOUT("Generated signature for the last sector is: %x \r\n", Chip_FMC_GetSignature(0));

/*
* my oroginal calc code
*/

uint32_t sign =0;
uint32_t next_sign =0;

uint32_t start_addr = START_ADDR_LAST_SECTOR;
uint32_t end_addr = (START_ADDR_LAST_SECTOR + SECTOR_SIZE);

for (uint32_t addr = start_addr; addr < end_addr ; addr+=sizeof(uint32_t))
{
for (i=0;i<31 ;i++)
{
next_sign |= (*(uint32_t *)(addr) & (1UL << i)) ^ ((sign & (1UL<<(i+1)) ) >> 1) ;
}
next_sign |= (*(uint32_t *)(addr) & (1UL << 31) ) ^ ((sign & (1UL << 0) ) << 31) ^ ((sign & (1UL<< 10) ) << 21) ^ ((sign & (1UL<<30)) << 1) ^ (sign & (1UL <<31));
sign = next_sign;
next_sign = 0;
}

/* Get the generated FLASH signature value */
DEBUGOUT("Generated signature for the last sector is: %x \r\n", sign);

/*
* Mbed LPC signature generator
*/

unsigned int startAddr = START_ADDR_LAST_SECTOR;
unsigned int length = SECTOR_SIZE;

FLASH_SIG_Type flashWord;
FLASH_SIG_Type refSignature = {0, 0, 0, 0};
FLASH_SIG_Type nextSign;
unsigned int* PageAddr = (unsigned int *)startAddr;

for (unsigned int i = 0; i < (length >> 4); i++) {
flashWord.word0 = *PageAddr;
PageAddr++;
flashWord.word1 = *PageAddr;
PageAddr++;
flashWord.word2 = *PageAddr;
PageAddr++;
flashWord.word3 = *PageAddr;
PageAddr++;

//Update 128 bit signature
nextSign.word0 = flashWord.word0 ^ refSignature.word0 >> 1 ^ refSignature.word1 << 31;
nextSign.word1 = flashWord.word1 ^ refSignature.word1 >> 1 ^ refSignature.word2 << 31;
nextSign.word2 = flashWord.word2 ^ refSignature.word2 >> 1 ^ refSignature.word3 << 31;
nextSign.word3 = flashWord.word3 ^ refSignature.word3 >> 1 ^
(refSignature.word0 & 1 << 29) << 2 ^
(refSignature.word0 & 1 << 27) << 4 ^
(refSignature.word0 & 1 << 2) << 29 ^
(refSignature.word0 & 1 << 0) << 31;

//Point to the calculated value
refSignature.word0 = nextSign.word0;
refSignature.word1 = nextSign.word1;
refSignature.word2 = nextSign.word2;
refSignature.word3 = nextSign.word3;
}

//Copy the reference signature to the result pointer
software_sig.word0 = refSignature.word0;
software_sig.word1 = refSignature.word1;
software_sig.word2 = refSignature.word2;
software_sig.word3 = refSignature.word3;

DEBUGOUT("Calculated signature for the last sector is: %x \r\n", software_sig.word0);

while (1) {
__WFI();
}

return 0;
}

Labels (4)
Tags (1)
0 Kudos
5 Replies

969 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Fukuda Takuya

Thank you for your interest in NXP Semiconductor products and 
the opportunity to serve you.
The flash signature generation algorithm which is illustrated in the LPC Signature Generator | Mbed  is correct.
I've tested it by myself.

This generator can produce a 128-bit signature from a range of flash memory.

After signature generation, a 32-bit signature can be read from the FMSW0 register. The
32-bit signature reflects the corrected data read from the flash and the flash parity bits and
check bit values and User doesn't necessary to get the 128-bit signature.

Have a great day,
TIC

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!

969 Views
fukudatakuya
Contributor I

Thank you, Jeremyzhou.

I made  some test codes, and could get signature match!

You are correct.

But it is very hard to find and very strange behaviour.

LPC1549 has 128-bit signature with algorithm as same as LPC Signature Generator | Mbed and LPC11U6X Flash Signature .

But specifiable start and end address are aligned 128 bytes boundaries for LPC1549.

If the specified start address is within the range from 0xXXXXXX00 to 0xXXXXXX7F, the address is changed to 0xXXXXXX00.

The start address range is within from 0xXXXXXX80 to 0xXXXXXXFF,  it is set to 0xXXXXXX80.

The end address is within the range from 0xXXXXXX00 to 0xXXXXXX7F, the address is changed to 0xXXXXXX7F.

The end address range is within from 0xXXXXXX80 to 0xXXXXXXFF,  it is set to 0xXXXXXXFF.

The signature is calculated within the changed address range (128 byte boundaries)

So we cannot calculate the exact target flash memory range.

This means that the result of below code is same.

    LPC_FMC->FMSSTART    = ((0x0003F000) >> 4);
    LPC_FMC->FMSSTOP     = ((0x0003F000) >> 4) | FMC_FLASHSIG_BUSY;
    while (Chip_FMC_IsSignatureBusy()) {}
    DEBUGOUT("Signature is: %x \r\n",     LPC_FMC->FMSW[0]);

    LPC_FMC->FMSSTART    = ((0x0003F000) >> 4);
    LPC_FMC->FMSSTOP     = ((0x0003F010) >> 4) | FMC_FLASHSIG_BUSY;
    while (Chip_FMC_IsSignatureBusy()) {}
    DEBUGOUT("Signature is: %x \r\n",     LPC_FMC->FMSW[0]);

    LPC_FMC->FMSSTART    = ((0x0003F000) >> 4);
    LPC_FMC->FMSSTOP     = ((0x0003F07F) >> 4) | FMC_FLASHSIG_BUSY;
    while (Chip_FMC_IsSignatureBusy()) {}
    DEBUGOUT("Signature is: %x \r\n",     LPC_FMC->FMSW[0]);

    LPC_FMC->FMSSTART    = ((0x0003F020) >> 4);
    LPC_FMC->FMSSTOP     = ((0x0003F07F) >> 4) | FMC_FLASHSIG_BUSY;
    while (Chip_FMC_IsSignatureBusy()) {}
    DEBUGOUT("Signature is: %x \r\n",     LPC_FMC->FMSW[0]);

Thank you for your answer, Jeremyzhou.

I can understand it.

0 Kudos

969 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Fukuda Takuya,

Thanks for your reply.

I think the start and end address are aligned on 16 bytes boundary , not aligned on 128 bytes.
Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

969 Views
fukudatakuya
Contributor I

Hi, jeremyzhou.

That is the point why I cannot match the result, exactly.

I attach MCUXpresso ide debug console pic.

At first, I write sample data from 0x0003F000.

memory.jpg

 Next, I set start address 0x0003F000.

1.jpg2.jpg

And I set end address 0x0003F000( It's same as start address.), but not set STRTBIST bit yet.

3.jpg

So the end address is set to 0x0003F07X , aligned on 128 bytes automatically.

I set STRTBIST bit, then the signature is generated.4.jpg

I set end address to 0x0003F010, but it set to 0x0003F07X automatically.

7.jpg

And the generated signature is same.

8.jpg

I set start address to 0x0003F020, but it set to 0x0003F000 automatically, and generated signature is same also.

11.jpg

At the last, start address to 0x0003F120, end address to 0x0003F230, but start is changed to 0x0003F100 and end is to 0x0003F27X automatically.

12.jpg13.jpg14.jpg

So I think the start and end address are aligned on 128 bytes boundary for LPC15XX.

Regards,

0 Kudos

969 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Fukuda Takuya,

Thanks for your clarification.
Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos