Question about OTP of LPC54605J512

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

Question about OTP of LPC54605J512

1,325 Views
noboba
Contributor I

Hi,

I am using LPC54605J512 and trying to read/write OTP. I can read/write Banks 0 and 3 with no problems. However, I cannot write Banks 1 and 2. When I execute OTP_ProgramRegister() to Bank 1 or 2, it returns the error code of “illegal bank.” Do I have to use different API to write Banks 1 and 2? Or, simply the LPC54605J512 has Banks 0 and 3 only?

Regards,

Ohba

Labels (1)
0 Kudos
9 Replies

1,020 Views
noboba
Contributor I

I am waiting for another three weeks. Did you confirm Banks 1 and 2 of OTP do not work?

Regards,

Ohba

0 Kudos

1,020 Views
soledad
NXP Employee
NXP Employee

Sorry for the delay, I am trying to reproduce the issue using a NXPboard. I will update you as soon as possible. 

Regards 

Sol 

0 Kudos

1,021 Views
soledad
NXP Employee
NXP Employee

Hi, 

otpEnableBankWriteLock API must be called to enable the appropriate register before calling otpProgramReg API function.

Please check you are not disabling the banks,  for example: 

Example 1: “otpEnableBankReadLock(0x3, 0x3, 0xC, 0x00)” will enable read access to BANK3-REG0, REG1 and disables access to BANK3-REG2, REG3. These access values can be changed by a subsequent call to “otpEnableBankReadLock”.

Example 2: “otpEnableBankReadLock (0x3, 0x6, 0x9, 0x01)” will enable read access to BANK3-REG1, REG2 and disable read access to BANK3-REG3, REG0 and since the write lock mask is also set, these permissions will be set and cannot be changed until reset. Note: The disable mask takes priority if both enable and disable masks are set.

Regards 

Sol 

0 Kudos

1,021 Views
noboba
Contributor I

Hi,

Thanks for your reply. I still cannot get my program to work for Banks 1 and 2. Again, it works good for Banks 0 and 3. What I have tried so far are:

  1. I reconfirmed I was able to write data to the registers in Banks 0 and 3. However, I noticed I must make the target register not only writeable but also readable using OTP_EnableBankReadLock() in order to write data. If I make the register not readable, OTP_ProgramRegister() returns the kStatus_OTP_ReadAccessLocked error code. This seems odd, but am I correct?
  2. For registers in Banks 0 and 3, I intentionally skipped OTP_EnableBankWriteLock() to leave the register write-locked (not writeable), and then ran OTP_ProgramRegister(). It returned the kStatus_OTP_WriteAccessLocked error code. That is very reasonable. However, for registers in Banks 1 and 2, it returned kStatus_OTP_IllegalBank. It seems to me that Banks 1 and 2 behave differently.

I would appreciate your help.

Regards,

Ohba

0 Kudos

1,021 Views
soledad
NXP Employee
NXP Employee

Hello Nobuyuki San,

The procedure for all the Banks it is the same, if you have working Bank 0 and Bank 3,  follow the same steps, for the Bank1 and Bank2. The API, it is the same for all the banks also. If you can put an small part of your code, we can try to review it, and see if there is something wrong.

0 Kudos

1,021 Views
noboba
Contributor I

Hi, soledad,

I fully agree with you. If I can write data to banks 0 and 3, I should be able to write data to banks 1 and 2, too. So, I am baffled. Here is my code. I hope it makes sense. I ran this code on LPCXpresso546xx Eval Board Rev. D, and got the same results (I could not write data to banks 1 and 2).

Thanks again for your help.

Ohba

/**********************/
#include <stdbool.h>
#include "board.h"
#include "pin_mux.h"
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "fsl_rng.h"
#include "fsl_otp.h"
#include "fsl_clock.h"
#include "fsl_reset.h"

/*******************************************************************************
* Definitions
******************************************************************************/
#define OPT_BASE_ADDRESS (0x40015000u)

/*******************************************************************************
* Prototypes
******************************************************************************/

/*******************************************************************************
* Code
******************************************************************************/
uint32_t readOtp( int bank, int reg_index ){ //Read OTP register at bank/reg_index, bank can be 0, 1, 2, or 3. reg_index can be 0, 1, 2, or 3.
int rc;
otp_word_t enable_mask = 0;
int reg_offset = 0;
uint32_t *offset;
switch( reg_index ){
case 0: enable_mask = 0x01; reg_offset = 0x00; break;
case 1: enable_mask = 0x02; reg_offset = 0x04; break;
case 2: enable_mask = 0x04; reg_offset = 0x08; break;
case 3: enable_mask = 0x08; reg_offset = 0x0C; break;
default: enable_mask = 0; break;
}
rc = OTP_EnableBankReadLock( bank, enable_mask, 0x00u, 0x00u );
if( rc != kStatus_Success ){
PRINTF( "OTP_EnableBankReadLock() failed and returned %x\r\n", rc );
return 0;
}
else{
//PRINTF( "OTP_EnableBankReadLock(%d) succeeded\r\n" );
}
offset = (uint32_t *)(OPT_BASE_ADDRESS+bank*0x10+reg_offset);
return *offset;
}

/*Write data to OTP bank's reg_index. Bank can be 0, 1, 2, or 3. reg_index can be 0, 1, 2 or 3*/
bool writeOtp( uint32_t bank_index, uint32_t reg_index, uint32_t data ){
if( reg_index != 2 && reg_index != 3 ){ //Registers 0 and 1 are reserved for system use.
PRINTF( "You can write data to register 2 or 3 only.\r\n" );
return false;
}
int rc, rc_prog;
uint32_t bank_mask = 0;
switch( bank_index ){
case 0: bank_mask = 0x01; break;
case 1: bank_mask = 0x02; break;
case 2: bank_mask = 0x04; break;
case 3: bank_mask = 0x08; break;
default: bank_mask = 0; break;
}
rc = OTP_EnableBankWriteMask( bank_mask ); //Enable write access of the specified bank
if( rc != kStatus_Success ){
PRINTF( "OTP_EnableBankWriteMask() failed and returned %d (0x%x)\r\n", rc, rc );
return false;
}
uint32_t enable_mask = 0;
uint32_t disable_mask = 0;
switch( reg_index ){
case 0: enable_mask = 0x01; break;
case 1: enable_mask = 0x02; break;
case 2: enable_mask = 0x04; break;
case 3: enable_mask = 0x08; break;
default: enable_mask = 0; break;
}
disable_mask = enable_mask;

rc = OTP_EnableBankWriteLock( bank_index, enable_mask, 0, 0 ); //Enable write access of the specified register
if( rc != kStatus_Success ){
PRINTF( "OTP_EnableBankWriteLock() failed and returned %d (0x%x)\r\n", rc, rc );
return false;
}

rc = OTP_EnableBankReadLock( bank_index, enable_mask, 0, 0 ); //Enable read access of the specified register, is this really needed?
if( rc != kStatus_Success ){
PRINTF( "OTP_EnableBankReadLock() failed and returned %d (0x%x)\r\n", rc, rc );
return false;
}

rc_prog = OTP_ProgramRegister( bank_index, reg_index, data ); //Write data to the OTP of bank_index & reg_index
if( rc_prog != kStatus_Success ){
PRINTF( "OTP_ProgramRegister() failed and returned %d (0x%x)\r\n", rc_prog, rc_prog );
}

rc = OTP_EnableBankReadLock( bank_index, 0, disable_mask, 0 ); //Disable read access of the specified register, is this really needed?
if( rc != kStatus_Success ){
PRINTF( "OTP_EnableBankReadLock() failed and returned %d (0x%x)\r\n", rc, rc );
return false;
}

rc = OTP_EnableBankWriteLock( bank_index, 0, disable_mask, 0 ); //Disable write access of the specified register
if( rc != kStatus_Success ){
PRINTF( "OTP_EnableBankWriteLock() failed and returned %d (0x%x)\r\n", rc, rc );
return false;
}

rc = OTP_DisableBankWriteMask( bank_mask ); //Disable write access of the specified bank
if( rc != kStatus_Success ){
PRINTF( "OTP_DisableBankWriteMask() failed and returned %d (0x%x)\r\n", rc, rc );
return false;
}

if( rc_prog != kStatus_Success )
return false;
else
return true;
}

void dumpOtp(){
int bank, reg_index;
uint32_t d32;
for( bank = 0; bank < 4; bank++ ){
PRINTF( "OTP bank %d:\t", bank );
for( reg_index = 0; reg_index < 4; reg_index++ ){
d32 = readOtp( bank, reg_index );
PRINTF( "reg%d=%08X\t", reg_index, d32 );
}
PRINTF( "\r\n" );
}
}

int main(void)
{
uint32_t version;
/* Init hardware*/
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
/* enable clock to OTP and reset it */
CLOCK_EnableClock(kCLOCK_Otp);
RESET_PeripheralReset(kOTP_RST_SHIFT_RSTn);
BOARD_InitPins();
/* main clock needs to be set to 12 MHz in order to use OTP */
BOARD_BootClockFRO12M();
BOARD_InitDebugConsole();

/* Get version of driver in ROM */
version = OTP_GetDriverVersion();
PRINTF("OTP ROM API driver version: 0x%X\r\n\r\n", version);

int bank, reg;
uint32_t data;

for( bank = 0; bank < 4; bank++ ){
for( reg = 2; reg < 4; reg++ ){
data = 0x00000000u;
PRINTF( "Writing 0x%08X to bank%d register%d... ", data, bank, reg );
if( writeOtp( bank, reg, data ) ){
PRINTF( " Succeeded.\r\n" );
}
else{
//PRINTF( "Failed.\r\n" );
}
}
}

dumpOtp();

PRINTF( "Program finished.\r\n" );
while(true){}
}

0 Kudos

1,021 Views
soledad
NXP Employee
NXP Employee

Hello Nobuyuki San,

Here is an example, I am trying with the same Banks 0 and 1 but it is prepared for bank any bank, can you please try?

The example programs 4 words of data each into OTP bank 1 and OTP bank 2. The example uses LPC54018 SDK drivers. The complete SDK for LPC54018 can be downloaded from Welcome | MCUXpresso SDK Builder .

0 Kudos

1,021 Views
noboba
Contributor I

Hi, Soledad,

Many thanks for your sample code. Since I do not have LPC54018 here, I tried your code on LPC54608J512 (LPCXpresso546xx development board) with the LPC54608 SDK. The code failed at 

status = OTP_ProgramRegister(BANK1_IDX, 0x0, bank1_word0);

at Line 129. The returned status code is 6109 decimal, which I believe indicates "illegal bank."

I also ran your code on LPC54605J512 (my original board), and got the exactly same result.

Have you successfully run your code on LPC54018?

Regards,

Ohba

0 Kudos

1,021 Views
noboba
Contributor I

It has been three weeks since I posted the last question. I would appreciate any feedback.

Thanks,

Ohba

0 Kudos