pico_set_binary_type(binary blocked_ram) causes link failure #203

Closed
opened 2021-03-01 07:40:51 -06:00 by le-jzr · 14 comments
le-jzr commented 2021-03-01 07:40:51 -06:00 (Migrated from github.com)

I want to use Pico's SRAM in unstriped configuration so that I can manage who accesses which bank manually. However, using pico_set_binary_type(blink blocked_ram) causes linking to fail with the message below (here I modified the blink example with the single additional line for demonstration and easy reproduction).

[ 0%] Linking CXX executable blink.elf
ERROR: Memory segment 21000a4c->21000d14 is outside of valid address range for device
make[2]: *** [blink/CMakeFiles/blink.dir/build.make:677: blink/blink.elf] Error 253
make[2]: *** Deleting file 'blink/blink.elf'
make[1]: *** [CMakeFiles/Makefile2:3535: blink/CMakeFiles/blink.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

The address range rejected by the linker seems to be exactly the place code should be, so I suspect the linker is just misconfigured.

I want to use Pico's SRAM in unstriped configuration so that I can manage who accesses which bank manually. However, using `pico_set_binary_type(blink blocked_ram)` causes linking to fail with the message below (here I modified the blink example with the single additional line for demonstration and easy reproduction). > [ 0%] Linking CXX executable blink.elf ERROR: Memory segment 21000a4c->21000d14 is outside of valid address range for device make[2]: *** [blink/CMakeFiles/blink.dir/build.make:677: blink/blink.elf] Error 253 make[2]: *** Deleting file 'blink/blink.elf' make[1]: *** [CMakeFiles/Makefile2:3535: blink/CMakeFiles/blink.dir/all] Error 2 make: *** [Makefile:84: all] Error 2 The address range rejected by the linker seems to be exactly the place code should be, so I suspect the linker is just misconfigured.
lurch commented 2021-03-01 07:45:07 -06:00 (Migrated from github.com)

Do you get the same thing when using the develop branch of pico-sdk?

Do you get the same thing when using the `develop` branch of pico-sdk?
le-jzr commented 2021-03-01 07:57:18 -06:00 (Migrated from github.com)

I switched to develop branch, created a new build directory, same problem. It just occurred to me that some of the tooling actually comes from the distribution, which in my case is Ubuntu 20.04.2 LTS. That might be an important information. I think I should test this on Raspberry Pi OS, but I don't think I have a board with it available right now.

I switched to `develop` branch, created a new build directory, same problem. It just occurred to me that some of the tooling actually comes from the distribution, which in my case is Ubuntu 20.04.2 LTS. That might be an important information. I think I should test this on Raspberry Pi OS, but I don't think I have a board with it available right now.
lurch commented 2021-03-01 08:05:18 -06:00 (Migrated from github.com)

To answer my own question... I get this when using the master branch of pico-sdk:

[100%] Linking CXX executable blink.elf
ERROR: Memory segment 21000a50->21000d1c is outside of valid address range for device
blink/CMakeFiles/blink.dir/build.make:671: recipe for target 'blink/blink.elf' failed
make[3]: *** [blink/blink.elf] Error 253
make[3]: *** Deleting file 'blink/blink.elf'
CMakeFiles/Makefile2:3550: recipe for target 'blink/CMakeFiles/blink.dir/all' failed
make[2]: *** [blink/CMakeFiles/blink.dir/all] Error 2
CMakeFiles/Makefile2:3557: recipe for target 'blink/CMakeFiles/blink.dir/rule' failed
make[1]: *** [blink/CMakeFiles/blink.dir/rule] Error 2
Makefile:157: recipe for target 'blink' failed
make: *** [blink] Error 2

and this when using the develop branch of pico-sdk:

[100%] Linking CXX executable blink.elf
ERROR: Memory segment 21000230->210005f8 is outside of valid address range for device
blink/CMakeFiles/blink.dir/build.make:671: recipe for target 'blink/blink.elf' failed
make[3]: *** [blink/blink.elf] Error 253
make[3]: *** Deleting file 'blink/blink.elf'
CMakeFiles/Makefile2:3571: recipe for target 'blink/CMakeFiles/blink.dir/all' failed
make[2]: *** [blink/CMakeFiles/blink.dir/all] Error 2
CMakeFiles/Makefile2:3578: recipe for target 'blink/CMakeFiles/blink.dir/rule' failed
make[1]: *** [blink/CMakeFiles/blink.dir/rule] Error 2
Makefile:157: recipe for target 'blink' failed
make: *** [blink] Error 2
To answer my own question... I get this when using the `master` branch of pico-sdk: ``` [100%] Linking CXX executable blink.elf ERROR: Memory segment 21000a50->21000d1c is outside of valid address range for device blink/CMakeFiles/blink.dir/build.make:671: recipe for target 'blink/blink.elf' failed make[3]: *** [blink/blink.elf] Error 253 make[3]: *** Deleting file 'blink/blink.elf' CMakeFiles/Makefile2:3550: recipe for target 'blink/CMakeFiles/blink.dir/all' failed make[2]: *** [blink/CMakeFiles/blink.dir/all] Error 2 CMakeFiles/Makefile2:3557: recipe for target 'blink/CMakeFiles/blink.dir/rule' failed make[1]: *** [blink/CMakeFiles/blink.dir/rule] Error 2 Makefile:157: recipe for target 'blink' failed make: *** [blink] Error 2 ``` and this when using the `develop` branch of pico-sdk: ``` [100%] Linking CXX executable blink.elf ERROR: Memory segment 21000230->210005f8 is outside of valid address range for device blink/CMakeFiles/blink.dir/build.make:671: recipe for target 'blink/blink.elf' failed make[3]: *** [blink/blink.elf] Error 253 make[3]: *** Deleting file 'blink/blink.elf' CMakeFiles/Makefile2:3571: recipe for target 'blink/CMakeFiles/blink.dir/all' failed make[2]: *** [blink/CMakeFiles/blink.dir/all] Error 2 CMakeFiles/Makefile2:3578: recipe for target 'blink/CMakeFiles/blink.dir/rule' failed make[1]: *** [blink/CMakeFiles/blink.dir/rule] Error 2 Makefile:157: recipe for target 'blink' failed make: *** [blink] Error 2 ```
lurch commented 2021-03-01 08:13:44 -06:00 (Migrated from github.com)

Ahhhh, looks like the error is actually coming from elf2uf2, rather than the linker https://github.com/raspberrypi/pico-sdk/blob/master/tools/elf2uf2/main.cpp#L134
(so I guess elf2uf2 just needs to be taught about blocked_ram builds?)

Ahhhh, looks like the error is actually coming from elf2uf2, rather than the linker https://github.com/raspberrypi/pico-sdk/blob/master/tools/elf2uf2/main.cpp#L134 (so I guess elf2uf2 just needs to be taught about blocked_ram builds?)
le-jzr commented 2021-03-01 08:26:49 -06:00 (Migrated from github.com)

I'd say the proper solution here would be to not just check that the addresses are in correct range, but also that the different segments don't alias. Having segments in 20xxxxxx is correct, as is having them in 21xxxxxx, but having both at the same time is probably an error unless they use disjoint address ranges.

I'd say the proper solution here would be to not just check that the addresses are in correct range, but also that the different segments don't alias. Having segments in 20xxxxxx is correct, as is having them in 21xxxxxx, but having both at the same time is probably an error unless they use disjoint address ranges.
kilograham commented 2021-03-01 08:34:35 -06:00 (Migrated from github.com)

yes the problem is with elf2uf2, but actually the bootrom doesn't accept blocked RAM binaries eiither - this is OK though as the memory is indeed aliased, so we nee to make elf2uf2 smart enough to re-order a striped binary, and add a small trampoline to the start of striped ram binaries which jumps across aliases

yes the problem is with elf2uf2, but actually the bootrom doesn't accept blocked RAM binaries eiither - this is OK though as the memory is indeed aliased, so we nee to make elf2uf2 smart enough to re-order a striped binary, and add a small trampoline to the start of striped ram binaries which jumps across aliases
le-jzr commented 2021-03-01 08:47:59 -06:00 (Migrated from github.com)

The reordering sounds simple enough for me to whip up a patch. The trampoline would just be a single instruction at an arbitrary unused address jumping to the real start address, right?

The reordering sounds simple enough for me to whip up a patch. The trampoline would just be a single instruction at an arbitrary unused address jumping to the real start address, right?
kilograham commented 2021-03-01 08:57:03 -06:00 (Migrated from github.com)

The reordering sounds simple enough for me to whip up a patch. The trampoline would just be a single instruction at an arbitrary unused address jumping to the real start address, right?

cool yes thanks

the trampoline needs to be something like (in the original frame)

0x21000000 ldr r0, [pc, #0] // or whatever the correct offset is; i thing this is right for 0x20000004
           bx r0
0x21000004 real_entry point: whatever fits here in 12 bytes, or a jmp
0x21000010 .word 0x21000008

which would map to these addresses in unstriped RAM

0x20000000 ldr r0, [pc, #0]
           bx r0
0x20000004 .wordd 0x21000008
> The reordering sounds simple enough for me to whip up a patch. The trampoline would just be a single instruction at an arbitrary unused address jumping to the real start address, right? cool yes thanks the trampoline needs to be something like (in the original frame) ``` 0x21000000 ldr r0, [pc, #0] // or whatever the correct offset is; i thing this is right for 0x20000004 bx r0 0x21000004 real_entry point: whatever fits here in 12 bytes, or a jmp 0x21000010 .word 0x21000008 ``` which would map to these addresses in unstriped RAM ``` 0x20000000 ldr r0, [pc, #0] bx r0 0x20000004 .wordd 0x21000008 ```
le-jzr commented 2021-03-01 14:23:06 -06:00 (Migrated from github.com)

That would work if the default address range was unstriped, and 0x21xx striped, but it's actually the opposite.
So, considering that we can't load a register and jump in a single word, the only option is to use an immediate jump.
I'm thinking the following "universal" starting sequence (don't know the proper syntax):

0x21000000   BL to PC + 16
0x21000004   BL to PC + 16M - 16
0x21000008   nop
0x2100000c   nop
0x21000010   start of other code

this will map to the following in striped mapping

0x20000000   BL to PC + 16
0x20000004   ? <bank 1>
0x20000008   ? <bank 2>
0x2000000c   ? <bank 3>
0x20000010   BL to PC + 16M - 16
That would work if the default address range was unstriped, and 0x21xx striped, but it's actually the opposite. So, considering that we can't load a register and jump in a single word, the only option is to use an immediate jump. I'm thinking the following "universal" starting sequence (don't know the proper syntax): ``` 0x21000000 BL to PC + 16 0x21000004 BL to PC + 16M - 16 0x21000008 nop 0x2100000c nop 0x21000010 start of other code ``` this will map to the following in striped mapping ``` 0x20000000 BL to PC + 16 0x20000004 ? <bank 1> 0x20000008 ? <bank 2> 0x2000000c ? <bank 3> 0x20000010 BL to PC + 16M - 16 ```
le-jzr commented 2021-03-01 14:31:43 -06:00 (Migrated from github.com)

Oh wait, I took a better look at your suggestion and see we actually can load and jump in a single word. I was thinking 32b instructions and forgot about thumb...

Oh wait, I took a better look at your suggestion and see we actually can load and jump in a single word. I was thinking 32b instructions and forgot about thumb...
kilograham commented 2021-03-01 17:18:29 -06:00 (Migrated from github.com)

also of course I forgot the thumb bit in the jump target, because that's the law!

also of course I forgot the thumb bit in the jump target, because that's the law!
kilograham commented 2021-03-22 09:05:26 -05:00 (Migrated from github.com)

Note, that I forgot that blocked_ram is a with flash binary type, so all my talk of entry points are irrelevant in the context of the existing blocked_ram.

However, I think RAM layout should be orthogonal to the binary type so this is probably a good time to make that change since the existing blocked_ram is broken anyway

Note, that I forgot that `blocked_ram` is a with flash binary type, so all my talk of entry points are irrelevant in the context of the existing blocked_ram. However, I think RAM layout should be orthogonal to the binary type so this is probably a good time to make that change since the existing blocked_ram is broken anyway
kilograham commented 2021-03-22 09:07:30 -05:00 (Migrated from github.com)

note if you want to workaround for now, i imagine just allowing BSS in 21000000-21040000 range in elf2u2 should unblock you. There should be no need to reorder the data (which is quite painful) since all the initialized data should be stored in flash and copied to RAM after startup.

note if you want to workaround for now, i imagine just allowing BSS in `21000000-21040000` range in `elf2u2` should unblock you. There should be no need to reorder the data (which is quite painful) since all the initialized data should be stored in flash and copied to RAM after startup.
kilograham commented 2021-04-01 17:38:52 -05:00 (Migrated from github.com)

note the original issue is fixed - blocked_ram and non flash combinations were never supported before, so this was a bit of a tangeny

note the original issue is fixed - blocked_ram and non flash combinations were never supported before, so this was a bit of a tangeny
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk#203
No description provided.