LPC812 IAP Copy Command not Affecting Destination

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

LPC812 IAP Copy Command not Affecting Destination

1,760 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rorrik on Wed Feb 18 13:18:48 MST 2015
I'm trying to copy from one part of flash memory to another on the LPC812. After running the code below, a compare between the two blocks of memory reveals that they are not the same, and by looking at the flash in disassembly, I can see the code in the source block is there, and that the destination block is still blank.
int eraseAddress = 0x1000;
int eraseEnd=0x2400;
int sectorSize = 0x400;
unsigned long PrepareCommand[4];
unsigned long results[3];
PrepareCommand[0]=50;
PrepareCommand[1]=eraseAddress/sectorSize;
PrepareCommand[2]=eraseEnd/sectorSize;
iap_entry (PrepareCommand,results);
unsigned long EraseCommand[4];
EraseCommand[0]=52;
EraseCommand[1]=eraseAddress/sectorSize;
EraseCommand[2]=eraseEnd/sectorSize;
EraseCommand[3]=12000;
iap_entry (EraseCommand,results);
iap_entry (PrepareCommand,results);
unsigned long CopyCommand[5];
CopyCommand[0]=51;
CopyCommand[4]=12000;
int startDestAddress=0x1000;
int startSrcAddress=0x2800;
int ProgramLength=0x1800;
int idx=0;
while(ProgramLength-idx*1024>0)
{
  CopyCommand[1]=startDestAddress+idx*1024;
  CopyCommand[2]=startSrcAddress+idx*1024;
  //Needs to be a power of 2 greater than 64, up to 1024
  if(ProgramLength-idx*1024>1024)
  {
  CopyCommand[3]=1024;
  }
  else
  {
  CopyCommand[3]=ProgramLength-idx*1024;
  }
  idx++;
  iap_entry (CopyCommand,results);
}

I suspect one of two things: 1) The system clock frequency for the copy is wrong, but I think the default clock is 12 MHz, is that wrong? 2) The copy command is specifically "Copy RAM to Flash" and I am trying to copy Flash to Flash. Could this be the problem?

Thanks
Labels (1)
0 Kudos
Reply
12 Replies

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rorrik on Wed Mar 18 08:44:12 MST 2015
Thanks for the help everybody. I was able to get the copy working by fixing the Prepares to only prepare valid addresses, I was trying to prepare up to sector 16, when they go 0 to 15. This is because I was using the end address of sector 15 to calculate the sector. I had a similar problem with my erase.

Again, thanks for all of the suggestions and the debugging tools.
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpc_bloke on Sat Feb 28 00:41:50 MST 2015
Flash page size is 64-bytes.  There is a strong chance you could get away with one buffer this size (assuming your boot loader is also running from flash).

The simple way to delclare a buffer if this size to be 32-bit aligned would be:
uint32_t flash_buffer[ 64 / sizeof( uint32_t )]; 

When there is a 0 remainder this is ok.  If there is a change of a non-0 remainder add sizeof type - 1 before the division to size the buffer correctly.

In gcc you can use the attribute options as well but not everybody uses gcc here.
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rorrik on Fri Feb 27 14:44:05 MST 2015
Thanks for the insight, 4k is too large for RAM as a whole and moving it caused RAM to overflow. The good news is, I only want temp to be 1k, so I'm changing its size to 256 and leaving it outside the function. I can now verify that the memcpy is moving data into temp. I think I'll move the commands and results to a higher scope as well so I can see their contents.
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by starblue on Fri Feb 27 02:30:23 MST 2015

Quote: Rorrik
while(ProgramLength-idx*1024>0)
{
  int temp[1024];



With a size of 4KB temp may be too big for the stack, which may lead to stack overflow and system crash. Better put the buffer outside of the function.

Alignment is OK, since you use int (unsigned int or uint32_t would be better style, unsigned char or uint8_t could lead to problems with alignment).
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rorrik on Thu Feb 26 14:02:46 MST 2015
Sure, I'm happy to post the project for anyone kind enough to look at it. I hope the attached is what you mean by the entire project.

I haven't dug into project settings, but the debugger seems to be using the correct chip map.

As far as I can tell, my program accesses the same memory locations on the second loop as on the first loop, but I have seen hard faults before when accessing the memory holding the code that is being run at the time. I do not think this is the case right now, but it could be a different memory issue.

The values of my memory pointer variables are optimized out right now. I can't tell from the assembly what they are but someone else may be able to.

Thanks! I'm learning a bunch.
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpc_bloke on Thu Feb 26 01:50:41 MST 2015
There is a statement in the User manual saying that you cannot write to flash and perform read from flash.

This is why mask ROM does the write for us in the first place and why the command is called what it is.  It may be worth checking the call return code there is a good chance that the error code says something like source address is invalid.

The best way around this issue would be to copy the flash block to RAM and then call the copy RAM to flash mask ROM function.

Good luck.
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Wed Feb 25 22:52:58 MST 2015
Perhaps you should post your entire project

If you get those errors when displaying the result, it implies that your memory map does not match the memory of your target.

a Hard Fault implies that you are trying to access non-exitent memory.

Have you tried debugging the code and looking at the values of your memory pointers?
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rorrik on Wed Feb 25 15:54:53 MST 2015
Thank you, great questions.

I've been trying to look at result[0] but the variable space in the but it is not displayed, I get this:

Quote:
Failed to execute MI command:
-data-evaluate-expression results[0]
Error message from debugger back end:
Cannot access memory at address 0xfffff88


I've been trying to get printf to work, but can't get a build to work with a printf in the code, it claims the added line:
printf("Result Message: %d",results[0]);
has increased the size of the code by over 7000 bytes, causing it to overflow the memory. Do you have a different recommendation for checking result[0]?

The destination area appears to be erased completely and never comes to contain any data, though in most of the tests it has begun empty due to having been erased in previous tests.

Before switching to memcpy, the program looped infinitely trying over and over to copy the data and staying in the loop because the compare (seemingly) detected that it had not been copied. In the new code, the program has a hard fault during the second time through the code, at or after the Prepare call (the debug is jumping in large steps and it's hard to say exactly where since it also jumps any breakpoints). If you have insight into why this is happening, that would be helpful.

My program is short enough that it doesn't occupy the space I am writing to, though it would if I expanded its allowed size to accommodate the extra 7000 bytes required by the printf.

Thanks for the clarifying questions. They've given me some ideas of things to look into.
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Wed Feb 25 12:24:43 MST 2015
Have you had a look at result[0] of each command? It reports errors when there is a error. See "22.5.2.11 IAP Status codes"
Have you had a look if the (complete) destination area was erased?
Have you had a look if the (complete) destination area is still empty, or parts contain valid data?
Or is the program crashing, endless looping, what does it do?
Have you checked that your program has not yet reached the position in flash, where you want to store something?

0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rorrik on Wed Feb 25 10:11:51 MST 2015
Sorry, I think I've correctly implemented the code with a memcpy in the right place. (Though admittedly, I'm not sure what "aligned" means in this context.) The following code is identical to before, but with the memcpy implemented, and still does not seem to do anything in the destination region.
int eraseAddress = 0x1000;
int eraseEnd=0x2400;
int sectorSize = 0x400;
unsigned long PrepareCommand[4];
unsigned long results[3];
PrepareCommand[0]=50;
PrepareCommand[1]=eraseAddress/sectorSize;
PrepareCommand[2]=eraseEnd/sectorSize;
iap_entry (PrepareCommand,results);
unsigned long EraseCommand[4];
EraseCommand[0]=52;
EraseCommand[1]=eraseAddress/sectorSize;
EraseCommand[2]=eraseEnd/sectorSize;
EraseCommand[3]=12000;
iap_entry (EraseCommand,results);
iap_entry (PrepareCommand,results);
unsigned long CopyCommand[5];
CopyCommand[0]=51;
CopyCommand[4]=12000;
int startDestAddress=0x1000;
int startSrcAddress=0x2800;
int ProgramLength=0x1800;
int idx=0;
while(ProgramLength-idx*1024>0)
{
  int temp[1024];
  CopyCommand[1]=startDestAddress+idx*1024;
  //Add a memcpy to move to RAM
  memcpy(temp, (void *) startSrcAddress+idx*1024, 1024);
  CopyCommand[2]=*temp;
  //Needs to be a power of 2 greater than 64, up to 1024
  if(ProgramLength-idx*1024>1024)
  {
  CopyCommand[3]=1024;
  }
  else
  {
  CopyCommand[3]=ProgramLength-idx*1024;
  }
  idx++;
  iap_entry (CopyCommand,results);
}

Is my memcpy implemented correctly? Is the default clock really 12 MHz? Is there some reason why any of my addresses wouldn't be on a word boundary?
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rorrik on Wed Feb 18 15:34:20 MST 2015
I was afraid of that. When I wrote the code I figured "it asks for an address. Flash addresses are easier for me to give it than RAM addresses. Maybe it doesn't check where the address I've given it leads."
0 Kudos
Reply

1,555 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Wed Feb 18 14:30:22 MST 2015

Quote:
he copy command is specifically "Copy RAM to Flash" and I am trying to copy Flash to Flash. Could this be the problem?


Of course that is the problem. Why do you think it is called that? You cannot copy Flash to Flash. You will have to copy the Flash to RAM (hint: use memcpy and make sure it is aligned) and then use the IAP command.
0 Kudos
Reply