[U-Boot] Problem with ll_entry_* before relocation
Heiko Schocher
hs at denx.de
Fri Feb 1 10:53:50 CET 2013
Hello,
I am currently trying to get rid of some externs in the new i2c
multibus approach, specially this externs:
http://git.denx.de/?p=u-boot/u-boot-i2c.git;a=blob;f=drivers/i2c/i2c_core.c;h=2a559c9d81a945f219eab49d11e70c0ac4a6d6a4;hb=83ffd31c590dd5aedfef0c195b1ffc406e6d0e37#l31
I tried to use the ll_entry_* defines see:
include/linker_lists.h
so the compiler will collect all i2c adapter(s), and no
need to declare in the config file a list of used adapters.
This approach works fine for using i2c after relocation, but
did not work before, which is a must have for i2c ...
Therefore I describe (Sorry, for the long EMail) here, whats
I see on an arm926ejs based board, using eldk 5.2 with
[hs at pollux u-boot]$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (GCC) 4.6.4 20120303 (prerelease)
and hope someone has an idea or at least an explanation,
why it is not working ...
First the defines I used for include/i2c.h (here shortened
the defines just using one unsigned long var, not the
"struct i2c_adap"):
#define U_BOOT_I2C_MKENT_COMPLETE_TRY(_hwadapnr) \
_hwadapnr;
#define U_BOOT_I2C_ADAP_COMPLETE_TRY(_name, _hwadapnr) \
ll_entry_declare(unsigned long, _name, try, try) = \
U_BOOT_I2C_MKENT_COMPLETE_TRY( _hwadapnr);
which i can use in drivers/i2c/soft_i2c.c as
U_BOOT_I2C_ADAP_COMPLETE_TRY(soft0, 0)
U_BOOT_I2C_ADAP_COMPLETE_TRY(soft1, 1)
Following printf in for example i2c_set_bus_num():
int i2c_set_bus_num(unsigned int bus)
{
extern unsigned long _u_boot_list_try__start;
printf("%08lx %08lx\n", (unsigned long)_u_boot_list_try__start,
(unsigned long)&_u_boot_list_try__start);
results in an output:
before relocation
e59ff00c 00000000
^
wrong address (Explanation see below)
after relocation:
00000000 a7fb5d08
^
correct address
so, "&_u_boot_list_try__start" is only valid after relocation!
Debugging deeper in it ...
Objdump:
000000a4 <i2c_set_bus_num>:
extern unsigned long _u_boot_list_try__start;
printf("%08lx %08lx\n", (unsigned long)_u_boot_list_try__start,
(unsigned long)&_u_boot_list_try__start);
a4: e59f2014 ldr r2, [pc, #20] ; c0 <i2c_set_bus_num+0x1c>
* bus - bus index, zero based
*
* Returns: 0 on success, not 0 on failure
*/
int i2c_set_bus_num(unsigned int bus)
{
a8: e92d4008 push {r3, lr}
extern unsigned long _u_boot_list_try__start;
printf("%08lx %08lx\n", (unsigned long)_u_boot_list_try__start,
(unsigned long)&_u_boot_list_try__start);
ac: e5921000 ldr r1, [r2]
b0: e59f000c ldr r0, [pc, #12] ; c4 <i2c_set_bus_num+0x20>
b4: ebfffffe bl 0 <printf>
i2c_mux_set_all();
breakpoint in i2c_set_bus_num
System.map:
c001221c T i2c_set_bus_num
Core#0>bi 0xc001221c
Breakpoint identification is 0
Core#0>g
- TARGET: core #0 has entered debug mode
Core#0>i
Core number : 0
Core state : debug mode (ARM)
Debug entry cause : Breakpoint
Current PC : 0xc001221c
Current CPSR : 0x600000d3 (Supervisor)
Core#0>r
GPR00: 00000000 c0030aeb 00000060 c001f028
GPR04: c0038ea4 fffffffc a7fb46c4 c0000b70
GPR08: a0000f00 00000001 c0000164 00000001
GPR12: 00000000 a0000ee0 c0000b80 c001221c
PC : c001221c CPSR: 600000d3
Core#0>md 0xc001221c
c001221c : e59f2014 e92d4008 e5921000 e59f000c . ... at -.........
c001222c : ebffe57c e3a00000 e8bd8008 00000000 |...............
^
wrong should be
c003bd08
c001223c : c003674c e92d4008 ebffc80c e3a00000 Lg... at -.........
c001224c : e8bd4008 eafffff1 e92d40f8 e598307c . at .......@-.|0..
[...]
Core#0>r
GPR00: 00000000 c0030aeb 00000060 c001f028
GPR04: c0038ea4 fffffffc a7fb46c4 c0000b70
GPR08: a0000f00 00000001 c0000164 00000001
GPR12: 00000000 a0000ee0 c0000b80 c001221c
PC : c001221c CPSR: 600000d3
from objdump pc @ 0xc001221c:
a4: e59f2014 ldr r2, [pc, #20] ; c0 <i2c_set_bus_num+0x1c>
load r2 with c001221c + 1c (0xc0012238) = 0 ....
thats wrong, as _u_boot_list_try__start is c003bd08 ...
System.map:
c003bd08 D _u_boot_list_i2c__end
c003bd08 D _u_boot_list_try__start
c003bd08 D _u_boot_list_try_soft0
c003bd0c D _u_boot_list_try_soft1
c003bd10 A __image_copy_end
[...]
After relocation:
relo addr from i2c_set_bus_num:
c001221c + 0xE7F7A000 = a7f8c21c
Core#0>bi 0xa7f8c21c
Breakpoint identification is 0
Core#0>g
- TARGET: core #0 has entered debug mode
Core#0>i
Core number : 0
Core state : debug mode (ARM)
Debug entry cause : Breakpoint
Current PC : 0xa7f8c21c
Current CPSR : 0x600000d3 (Supervisor)
Core#0>r
GPR00: 00000000 a7ec8e50 00000060 00000083
GPR04: 00000000 a7fb5940 00000000 a7ec9ec8
GPR08: a7ec9f60 00000000 00000003 a7ec92d1
GPR12: 00000034 a7ec9280 a7f7dcf8 a7f8c21c
PC : a7f8c21c CPSR: 600000d3
Core#0>
Core#0>md 0xa7f8c21c
a7f8c21c : e59f2014 e92d4008 e5921000 e59f000c . ... at -.........
a7f8c22c : ebffe57c e3a00000 e8bd8008 a7fb5d08 |............]..
^
a7f8c23c : a7fb074c e92d4008 ebffc80c e3a00000 L.... at -.........
a7f8c24c : e8bd4008 eafffff1 e92d40f8 e598307c . at .......@-.|0..
a7f8c25c : e3a0601c e0030396 e59f5028 e1a07000 .`......(P...p..
[...]
Core#0>
a4: e59f2014 ldr r2, [pc, #20] ; c0 <i2c_set_bus_num+0x1c>
load r2 with pc:0xa7f8c21c + 1c = 0xa7f8c238 = a7fb5d08 ....
thats the correct value ... because:
c003bd08 + 0xE7F7A000 = 1a7fb5d08 relocated addr from
_u_boot_list_try__start
with:
c003bd08 D _u_boot_list_try__start
c003bd08 D _u_boot_list_try_soft0
c003bd0c D _u_boot_list_try_soft1
c003bd10 A __image_copy_end
So, the question is, why is in the u-boot image the
wrong value 0 for _u_boot_list_try__start?
Additionally, if I print "_u_boot_list_try_soft0" with
printf("%08lx %08lx\n", (unsigned long)_u_boot_list_try_soft0,
(unsigned long)&_u_boot_list_try_soft0);
It has the correct value before and after relocation ... !!
objdump:
printf("%08lx %08lx\n", (unsigned long)_u_boot_list_try__start,
(unsigned long)&_u_boot_list_try__start);
a8: e59f2024 ldr r2, [pc, #36] ; d4 <i2c_set_bus_num+0x30>
ac: e59f4024 ldr r4, [pc, #36] ; d8 <i2c_set_bus_num+0x34>
b0: e5921000 ldr r1, [r2]
b4: e1a00004 mov r0, r4
b8: ebfffffe bl 0 <printf>
printf("%08lx %08lx\n", (unsigned long)_u_boot_list_try_soft0,
(unsigned long)&_u_boot_list_try_soft0);
bc: e59f2018 ldr r2, [pc, #24] ; dc <i2c_set_bus_num+0x38>
c0: e1a00004 mov r0, r4
c4: e5921000 ldr r1, [r2]
c8: ebfffffe bl 0 <printf>
i2c_mux_set_all();
_u_boot_list_try_soft0 in line bc:
load to r2 from c001221c + 0x38 = 0xc0012254
and c0012254 contain c003bd20, which is the correct value
for _u_boot_list_try_soft0 !!
System.map for this case:
c003bd20 D _u_boot_list_try__start
c003bd20 D _u_boot_list_try_soft0
c003bd24 D _u_boot_list_try_soft1
c003bd28 A __image_copy_end
Core#0>r
GPR00: 00000000 c0030b03 00000060 c001f040
GPR04: c0038ebc fffffffc a7fb46dc c0000b70
GPR08: a0000f00 00000001 c0000164 00000001
GPR12: 00000000 a0000ee0 c0000b80 c001221c
PC : c001221c CPSR: 600000d3
Core#0>md 0xc001221c
c001221c : e92d4010 e59f2024 e59f4024 e5921000 . at -.$ ..$@......
c001222c : e1a00004 ebffe57b e59f2018 e1a00004 ....{.... ......
c001223c : e5921000 ebffe577 e3a00000 e8bd8010 ....w...........
c001224c : 00000000 c0036764 c003bd20 e92d4008 ....dg.. .... at -.
^ ^
^ correct value for _u_boot_list_try_soft0
again, wrong value for _u_boot_list_try__start
So the question is, whats the difference between _u_boot_list_try_soft0
and _u_boot_list_try__start ... any ideas?
Thanks in advance.
bye,
Heiko
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
More information about the U-Boot
mailing list