Writing to the EEPROM on the LPC11U37

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

Writing to the EEPROM on the LPC11U37

1,094 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by psatyshur on Thu Dec 26 13:06:55 MST 2013
I am attempting to write to the EEPROM on the LPC11U37 and have run into some difficulties. I first tried the IAP commands:

uint8_t EEPROM_Write(uint8_t AddressToWrite, uint8_t *DataArray, uint8_t BytesToWrite)
{
unsigned int IAP_Command[5];
unsigned int IAP_Result[5];

IAP_Result[0] = 0;

IAP_Command[0] = IAP_EEPROM_WRITE;//EEPROM write command (61)
IAP_Command[1] = (unsigned int)AddressToWrite;//EEPROM address
IAP_Command[2] = *DataArray;//RAM address
IAP_Command[3] = (unsigned int)BytesToWrite;        //Number of bytes to write
IAP_Command[4] = SystemCoreClock/1000;//System clock frequency in kHz

iap_entry(IAP_Command, IAP_Result);

return (uint8_t)IAP_Result[0];
}

uint8_t EEPROM_Read(uint8_t AddressToRead, uint8_t *DataArray, uint8_t BytesToRead)
{
unsigned int IAP_Command[5];
unsigned int IAP_Result[5];

IAP_Result[0] = 0;

IAP_Command[0] = IAP_EEPROM_READ;//EEPROM read command (62)
IAP_Command[1] = (unsigned int)AddressToRead;//EEPROM address
IAP_Command[2] = *DataArray;//RAM address
IAP_Command[3] = (unsigned int)BytesToRead;//Number of bytes to read
IAP_Command[4] = SystemCoreClock/1000;//System clock frequency in kHz

iap_entry(IAP_Command, IAP_Result);

return (uint8_t)IAP_Result[0];
}


I also reserved 32 bytes for the IAP functions following this guide. [s]Note: I did not disable interrupts during this function.[/s] EDIT: I tried disabling interrupts around the iap_entry() function. The same problem occurred.

The returned value is always 14, and nothing is written to the EEPROM. This does not seem to be a valid return value. What does this return value mean?

To remove the requirement to disable interrupts, I decided to use the LPC1100/LPC1300 EEPROM library. This required changes to the code

uint8_t EEPROM_Write(uint8_t AddressToWrite, uint8_t *DataArray, uint8_t BytesToWrite)
{
EELIB_Command IAP_Command;
EELIB_Result IAP_Result;

IAP_Result[0] = 0;

//TODO: check to make sure the address is valid

IAP_Command[0] = EELIB_IAP_COMMAND_EEPROM_WRITE;//EEPROM write command
IAP_Command[1] = (unsigned int)AddressToWrite;//EEPROM address
IAP_Command[2] = *DataArray;//RAM address
IAP_Command[3] = (unsigned int)BytesToWrite;//Number of bytes to write
IAP_Command[4] = SystemCoreClock/1000;//System clock frequency in kHz

EELIB_entry(IAP_Command, IAP_Result);

return (uint8_t)IAP_Result[0];
}

uint8_t EEPROM_Read(uint8_t AddressToRead, uint8_t *DataArray, uint8_t BytesToRead)
{
EELIB_Command IAP_Command;
EELIB_Result IAP_Result;

IAP_Result[0] = 0;

//TODO: check to make sure the address is valid

IAP_Command[0] = EELIB_IAP_COMMAND_EEPROM_READ;//EEPROM read command
IAP_Command[1] = (unsigned int)AddressToRead;//EEPROM address
IAP_Command[2] = *DataArray;//RAM address
IAP_Command[3] = (unsigned int)BytesToRead;//Number of bytes to read
IAP_Command[4] = SystemCoreClock/1000;//System clock frequency in kHz

EELIB_entry(IAP_Command, IAP_Result);

return (uint8_t)IAP_Result[0];
}


I added the library to the project and included the header file. When I run the EEPROM_Read() function, it hangs the controller. Am I missing something in my implementation of the library functions?
3 Replies

716 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by psatyshur on Sun Jan 12 09:49:09 MST 2014
Thanks for the link. Using that code, I was able to find the problem with my code. It was a problem with the pointer to the address to put the data. More specifically, it was this line

IAP_Command[2] = *DataArray;


Since DataArray is already a pointer, passing *DataArray is passing a pointer to a pointer (which is bad). I have fixed that and updated a few other things. In case anyone else is looking for another exmaple of working EEPROM functions, here is my final functions.

uint8_t EEPROM_Write(uint8_t AddressToWrite, void* DataArray, uint8_t BytesToWrite)
{
#ifdef USE_EEPROM_LIB
EELIB_Command IAP_Command;
EELIB_Result IAP_Result;
#else
uint32_t IAP_Command[5];
uint32_t IAP_Result[4];
#endif

IAP_Result[0] = 0;

#ifdef USE_EEPROM_LIB
IAP_Command[0] = EELIB_IAP_COMMAND_EEPROM_WRITE;//EEPROM library write command
#else
IAP_Command[0] = IAP_EEPROM_WRITE;//IAP EEPROM write command
#endif
IAP_Command[1] = (uint32_t)AddressToWrite;//EEPROM address to write to
IAP_Command[2] = (uint32_t)DataArray;//RAM address of the data to write
IAP_Command[3] = (uint32_t)BytesToWrite;//Number of bytes to write
IAP_Command[4] = SystemCoreClock/1000;//System clock frequency in kHz

#ifdef USE_EEPROM_LIB
EELIB_entry(IAP_Command, IAP_Result);
#else
vPortEnterCritical();
iap_entry(IAP_Command, IAP_Result);
vPortExitCritical();
#endif

return (uint8_t)IAP_Result[0];
}

uint8_t EEPROM_Read(uint8_t AddressToRead, void* DataArray, uint8_t BytesToRead)
{
#ifdef USE_EEPROM_LIB
EELIB_Command IAP_Command;
EELIB_Result IAP_Result;
#else
uint32_t IAP_Command[5];
uint32_t IAP_Result[4];
#endif

IAP_Result[0] = 0;

#ifdef USE_EEPROM_LIB
IAP_Command[0] = EELIB_IAP_COMMAND_EEPROM_READ;//EEPROM library read command
#else
IAP_Command[0] = IAP_EEPROM_READ;//IAP EEPROM read command
#endif
IAP_Command[1] = (uint32_t)AddressToRead;//EEPROM address to read from
IAP_Command[2] = (uint32_t)DataArray;//RAM address to copy the EEPROM data to
IAP_Command[3] = (uint32_t)BytesToRead;//Number of bytes to read
IAP_Command[4] = SystemCoreClock/1000;//System clock frequency in kHz

#ifdef USE_EEPROM_LIB
EELIB_entry(IAP_Command, IAP_Result);
#else
vPortEnterCritical();
iap_entry(IAP_Command, IAP_Result);
vPortExitCritical();
#endif

return (uint8_t)IAP_Result[0];
}


A few notes: This code works with either the EEPROM library or with the basic IAP commands. To use the EEPROM library, the compiler variable USE_EEPROM_LIB must be defined. When not using the EEPROM library, interrupts must be disabled when calling IAP_entry(). Since my project is using FreeRTOS, I use the vPortEnterCritical() and vPortExitCritical() functions.

I have tested this code by saving arrays and structs into EEPROM. To save an array, the call is pretty easy.

uint8_t val = 0;
uint8_t DataArray[4];

/* Put data into DataArray */

resp = EEPROM_Write(val, &DataArray, 4);


Writes four bytes to address 0 in EEPROM.

Writing structs is pretty similar, but the struct needs to be packed.
typedef struct __attribute__((packed)){
uint8_t EventType;
uint8_t EventTime[3];
uint8_t EventOutputState;
} TimerEvent;

uint8_t val = 0;
TimerEvent TestEvent;

/* put data in the TestEvent struct */

resp = EEPROM_Write(val, &TestEvent, sizeof(TestEvent));


Reading the data from EEPROM works pretty much the same way

resp = EEPROM_Read(val, &DataArray, 4);
resp = EEPROM_Read(0, &TestEvent, sizeof(TestEvent));


I hope this helps anyone else that gets stuck trying to access the EEPROM on these devices.

716 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CVAS on Sat Dec 28 04:30:40 MST 2013
Hello,

take a look in "eepromAPI" from :

http://www.lpcware.com/content/nxpfile/sample-code-bundle-lpc11uxx-peripherals-using-keils-mdk-arm-0

I tested the writeEEPROM(...) and readEEPROM(...) functions on Embedded Artists' Low-Power Application Kit (Oryx)  and both functions work properly.

CVAS

0 Kudos

716 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by psatyshur on Fri Dec 27 10:28:51 MST 2013
Anyone? I tried disabling interrupts around the IAP_ENTRY() call and it did not make a difference. I implemented several other IAP functions such as reading the UID and PID, and these seemed to work correctly. I am unsure what else I can do to fix the problem. It is probably something simple that I have overlooked, but I cannot (obviously) see what it is. Are there any working examples of reading and writing from EEPROM on the LPC11uXX devices that I can look at?
0 Kudos