Hi, I am facing a strange behaviour of memcpy. I want to initialise ram variables with backup datas in flash. For a "small" variable, 140 bytes, everything is ok. But for a bigger one, 1296 bytes, memcpy executes and never return. I got a dabt exeption. My code is similar to: Var140bytes_ram = Var140bytes_flash ; // everything ok Var1296bytes_ram = Var1296bytes_flash ; // -> dabt exeption memcpy(Var140bytes_ram, Var140bytes_flash, sizeof Var140bytes_ram); I checked: -no compile time errors or warnings on these 3 lines. -alignment: all variables, source and destination are aligned on 4 byte bound. -the assembly code is similar for the 3 lines: load R0,R1 and R2 then call memcpy. -the three lines call the same memcpy. -the last 2 lines generates the same assembly, and R2 is loaded with 1296. With gdb on eclipse, I stepped thru the code to verify everything. I checked from ARM and Thumb modes. In Thumb mode, a swith to ARM is made before calling memcpy. Stepping through memcpy, I found the problem. Here are the phases: -Entering memcpy, R4, R5 and LR registers are pushed on the stack. -The copy is made, using registers and LR as a counter. -Then R4, R5 and LR are poped from the stack with a pop instruction. -Return to calling code is made with "bx LR". The problem is that LR doesn't contain the return adress, but is made of 4 bytes comming from the data area. Is there a known bug or a limitation using memcpy ? I use Yagarto with GCC version 4.2.1. I also tried GCC 4.2.2 without success. This problem was not present on my older GCC distribution, but I can't remember the exact version and were I downloaded it. I am quite sure it was > 4.0. Angelo
Angelo De Pascale wrote: > Hi, > I am facing a strange behaviour of memcpy. I want to initialise ram > variables with backup datas in flash. For a "small" variable, 140 bytes, > everything is ok. But for a bigger one, 1296 bytes, memcpy executes and > never return. I got a dabt exeption. My code is similar to: > > Var140bytes_ram = Var140bytes_flash ; // everything ok > Var1296bytes_ram = Var1296bytes_flash ; // -> dabt exeption > memcpy(Var140bytes_ram, Var140bytes_flash, sizeof Var140bytes_ram); > Are these global or local variables? Is your stack/heap large enough? Cheers Spen
Spencer Oliver wrote: > > Are these global or local variables? > Is your stack/heap large enough? > > Cheers > Spen They are global, declared in the same way, but flash values are located in a flash sector at link time. The problem occur in main, wich runs with the 1k bytes stack declared in boot.s. SP point to 0x7be0, close to the 32k (0x8000) ram limit. I am probably wrong, but a stack problem would only cause problems when execution continue after memcpy exit. But in my case, return adress is wrong before returning to main. Debugging with GDB, I can assume memcpy can use all 0x7be0 bytes as stack. Angelo
Angelo De Pascale wrote: Even more strange: using gdb and stopping just before the memcpy call, I changed manualy the length parameter stored in R2. Up to 1072, memcpy copies my datas and return to main. With 1073, I got the dabt exeption. I will change the stack size and chek again. Stay tuned :-) Angelo
> The problem occur in main, wich runs with the 1k bytes stack declared in > boot.s. SP point to 0x7be0, close to the 32k (0x8000) ram limit. > I am probably wrong, but a stack problem would only cause problems when > execution continue after memcpy exit. But in my case, return adress is > wrong before returning to main. Debugging with GDB, I can assume memcpy > can use all 0x7be0 bytes as stack. > > Angelo Just tried a small test copying a 16k buffer - no problems. My only other suggestion is provide a testcase that we can have a look at. I am using IDEaliST toolchain - based on gcc 4.2.1 (eabi) codesourcery branch. Cheers Spen
Problem found. It is not a memcpy bug. My ram variable was overlaping with stack initialized in boot.s Thanks for the help. Angelo
Angelo De Pascale wrote: > Var140bytes_ram = Var140bytes_flash ; // everything ok > Var1296bytes_ram = Var1296bytes_flash ; // -> dabt exeption > memcpy(Var140bytes_ram, Var140bytes_flash, sizeof Var140bytes_ram); Without knowing what Var140bytes_ram, Var140bytes_flash, Var1296bytes_ram, Var1296bytes_flash are and how they are declared, defined, initialised assigned or wharever up to that point it is impossible to tell what the problem is. It is certainly not memcpy() itself, but the parameters you are passing to it. Are you saying that the data abort occurs on the following line?: > Var1296bytes_ram = Var1296bytes_flash ; // -> dabt exeption Is so why do you suspect memcpy() which has not been called at that point? Either way the code looks suspicious. For "sizeof Var140bytes_ram" to make any kind of sense Var140bytes_ram must be an array, but you cannot assign an array like: > Var140bytes_ram = Var140bytes_flash ; and have it compile, so Var140bytes_ram must be a pointer. Therefore "sizeof Var140bytes_ram" would be 4. But if that were the case the assignment would mean that both Var140bytes_ram and Var140bytes_flash will have the same value, so you are trying to copy 4 bytes to themselves! Moreover the destination is presumably in Flash (because of the assignment) which you cannot write to with a simple memcpy(); Anyway I cannot see any way in which that code could possibly be correct or what you intended, but without any information about these variables and their values it is hard to tell what you intended to do. You mentioned using GDB. Did you inspect the source and destination pointers to determine that they point to the same thing. Anyway it seems that you believe that you have solved your problem, but I'd be interested in how you might explain how it now works, because it still looks very wrong to me. You may have more than one bug here and have just solved the one that caused the abort. Clifford
Clifford, When writting my first post, I was not at home and have no access to the pc were the source was. The variable is a structure containing arrays, ints,etc. The code I wrote was to illustrate the problem. The real code is: SysParmsRAM=SysParmsFlash; memcpy (&SysParmsRAM,&SysParmsFlash,sizeof SysParmsRAM); Yes, as you can see, parameters are pointers. And the 3d param is probably not correct, but it works as is. I made all my checking by stepping at assembly level. With GDB, all registers were correct, containing adresses of ram and flash variables. GCC compiles the first line using memcpy. Thats why I tried to make the same copy using directly memcpy, just to see if it makes any difference. The ram variables overlaps the stack. The 1073th byte is at the bottom of the stack. I checked this in GDB, calculating adresses in registers, count and SP. That's why the return address poped from the stack equals datas copied from the flash to ram by memcpy. I resolved this by lowering the stack size. I also checked by changing declaration order of all global variables. Thanks for your help. Angelo
Angelo De Pascale wrote: > > Thanks for your help. > I am pretty sure that I was of no help whatsoever. Given that the code that you posted was all we had to go on, and it was not real or even illustrative of your problem (in fact it would have caused quite a different problem), I am not sure how you possibly expected to get any useful help. I think you just wasted others' time.
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.