AnsweredAssumed Answered

LPC1549 How to calculate flash signature by original code?

Question asked by Fukuda Takuya on Jan 22, 2018
Latest reply on Jan 30, 2018 by jeremyzhou

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;
}

Outcomes