EmbDev.net

Forum: ARM programming with GCC/GNU tools Bug using memcpy for large data


von Angelo D. (polux_rsv)


Rate this post
useful
not useful
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

von Spencer O. (ntfreak)


Rate this post
useful
not useful
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

von Angelo D. (polux_rsv)


Rate this post
useful
not useful
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

von Angelo D. (polux_rsv)


Rate this post
useful
not useful
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

von Spencer O. (ntfreak)


Rate this post
useful
not useful
> 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

von Angelo D. (polux_rsv)


Rate this post
useful
not useful
Problem found. It is not a memcpy bug. My ram variable was overlaping
with stack initialized in boot.s

Thanks for the help.

Angelo

von Clifford S. (clifford)


Rate this post
useful
not useful
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

von Angelo D. (polux_rsv)


Rate this post
useful
not useful
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

von Clifford S. (clifford)


Rate this post
useful
not useful
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
No account? Register here.