Author Topic: GCC ARM32 32F417 how to call or jump to a specific address?  (Read 2421 times)

0 Members and 1 Guest are viewing this topic.

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #25 on: June 14, 2022, 06:42:24 am »
Quote
possibly because they all were already collected in previous sections

This is not happening. The .map file shows KDE_main_stub at 0x8008000, or not, according to whether the entry point main() is referenced somewhere, or not.

Is it actually possible to do a simple asm jump to an address of a GCC function, without setting up some registers etc?
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #26 on: June 14, 2022, 06:51:46 am »
The .map file shows KDE_main_stub at 0x8008000
Where? In the screenshots you showed it shows that KDE_main_stub.o is at that address with no code used from this file. The same file can provide code for multiple locations.

Is it actually possible to do a simple asm jump to an address of a GCC function, without setting up some registers etc?

This does jump to a (void) function
Code: [Select]
  asm("bx %0"::"r" (addr));
addr must have LSB set.

Or, if address is fixed then "bl" instruction would do the same.
Alex
 

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16670
  • Country: 00
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #27 on: June 14, 2022, 06:54:04 am »
Of course, the "answers" are all over the internet, but none of them compile, or (if they compile) none work.

I have what is basically an overlay at FLASH base+32k ie.. 0x08008000 and need to jump to that address.

Push it on the stack and do a RET.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #28 on: June 14, 2022, 07:04:06 am »
Quote
This does jump to a (void) function

Main() is an "int" not a "void". I can't change that; the compiler requires a function called "main" to be "int" :)

Quote
addr must have LSB set.

This matters. Now it works. Previously I tested with and without, and was misguided by this example above :) The compiler does not "figure it out".




But the bit in yellow (which never runs) is still needed to prevent the target code disappearing.

Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #29 on: June 14, 2022, 07:08:20 am »
Main() is an "int" not a "void".
I meant the arguments. Return type does not matter, but you have to fill out the arguments if the function takes them.

The compiler does not "figure it out".
Why would it? This is a behaviour specific to the implementation. On device with full ARM/Thumb-2 support either one will work and will switch the mode. On Thump-2 only devices you must remain in the Thumb-2 state, so LSB=1 is mandatory on all calls. Otherwise you will get INSTATE exception.

But again, let me advocate for your customers. What you are doing is just stupid. Don't do this. Place the vector table directly at the 0x08008000 address and jump there as a normal bootloader would. This way customers won't have to see with linker scripts.
« Last Edit: June 14, 2022, 07:10:53 am by ataradov »
Alex
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #30 on: June 14, 2022, 07:12:49 am »
What arguments does a
int main(void)
have, and how do I set them up in assembler?

Quote
Place the vector table directly at the 0x08008000 address and jump there as a normal bootloader would.

Yes; that would address the code removal because main() will have something pointing to it, which normally happens in a ST arm32 environment. Thanks.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #31 on: June 14, 2022, 07:14:31 am »
What arguments does a
int main(void)
have, and how do I set them up in assembler?
None. That's why I said it must be a (void) function. You don't need to do anything extra.
Alex
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #32 on: June 14, 2022, 07:58:41 am »
OK, thanks. This all works now.

I actually did it a bit differently. This is the vector table in the "overlay". It is a copy of the standard table.



The _estack word should be redundant since SP is already set to top of RAM from the boot block, but putting 0 in there bombs it all, and I found it is required because the RTOS directly fetches that value for its internal use :)

The reset_handler is indeed redundant and I can't see it being used because a reset also clears VTOR, so the table in the boot block gets used instead, which is as intended.

If one did this scheme where the vector table, instead of main(), is at the base of the overlay, one would have to enter the overlay by faking a hardware reset (but without changing VTOR - how?) to produce a jump to the 2nd vector and that would say

 .word main

Or one would read out the 2nd vector value with code, and jmp to that, which doesn't actually get you anything.

I eliminated the code disappearance with



so there is a permanent (if unused) reference to main() which is non-removable because it is in an asm file.

The reason what I am doing seems weird is partly because I am not fully familiar with the arm32 environment (who is, at ~10k pages?) and partly because I am juggling multiple objectives which I have not posted here, partly for brevity and partly because I don't want to tell you all what I am developing ;)

The reason why the various "keep" directives (in the C source and in the linkfile) seem to do nothing, remains unsolved. But I am not surprised; most websites that list compiler and linker directives are duff because there are so many versions. One can spend literally days on that.
« Last Edit: June 14, 2022, 08:37:53 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #33 on: June 14, 2022, 04:17:25 pm »
SP is not redundant, If the code is compiled in the outside project, the project may want to place SP in a different place.

Same with the reset handler. The secondary project will need to initialize its own memory. You are thinking about your embedded project. But this will not work with the standalone project at all.

Right now it all works because reset handler of your main project loads the data for the initialized variables from the second part. But as soon as you replace the second part, none of this data would be valid.

Do not deviate from standard stuff. You are just going to miss something like this. You need to have both values.

And it is much better to develop systems like this with the outside project first and then implement embedded projects. You will immediately see all the issues I'm describing.
« Last Edit: June 14, 2022, 04:20:30 pm by ataradov »
Alex
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #34 on: June 14, 2022, 05:27:07 pm »
Not quite, but I can see I didn't describe it fully.

The boot block always gets entered after a reset. There is no way for a 32F4 to do otherwise, because VTOR is set to zero.

The boot block is standalone; it doesn't call anything outside and nothing outside of it calls it. There is no variable sharing either. No data is passed between the two (except via data in a serial FLASH).

When control is passed to the "overlay" the SP is set to top of the RAM. C doesn't move the SP. That stack is also used for interrupts. FreeRTOS sets up its own task stacks in a chunk of RAM you give it and it does its own SP switching there.

The "overlay" never runs standalone. The boot block always runs first, and initialises most of the hardware.

This separation was done to enable later replacement of the "overlay".

I've designed other products like this. In one of them, the "overlay" can call functions in the boot block (due to memory limits, the boot block contained bulky functions like float maths) but to prevent obvious address problems across code versions, the boot block has a function address table in a fixed location and calls go via that. On this product there is no such function sharing.

I had some fun and games e.g. there was a data copy loop in the boot block which the compiler detected could be replaced with a memcpy() but memcpy is in a huge code library which wasn't in the boot block. There is probably a way to check for this by doing sed/grep on the symbol table. So that function is compiled with a -O0 attribute.

In a scenario where I know the overlay will never be replaced, I would build the project as a single project, but the above mentioned separation can be maintained even though it is not needed.

One reason for the boot block is to prevent a corrupted (or buggy) overlay from bricking the device. A "standard factory overlay" will always be available in a serial FLASH from where it can be restored.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #35 on: June 14, 2022, 05:36:02 pm »
I understand you perfectly and saying that you are wrong. If you put an arbitrary standalone project binary into the second part, but skip the reset handler, what code would be initializing the global variables for that code? You main boot program can't do that  because it does not know anything about that binary. So, if you jump into the main() directly, all your BSS memory would not be zeroed out and initialized memory would not  be initialized.

SP is less critical, but it is still a good idea to give control over it to the application. It might not want to have it at the end of SRAM. The binary may want to reserve some SRAM at the end.
Alex
 
The following users thanked this post: newbrain, SiliconWizard

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #36 on: June 14, 2022, 06:29:33 pm »
Indeed, any development environment which generates just the "overlay" would have code in main() which sets up the BSS and the initialised statics.

I had the same issue with the boot loader. There, it was done in C:

Code: [Select]
extern char _loader_start;
extern char _loader_end;
extern char _loader_loadaddr;
extern char _loader_bss_start;
extern char _loader_bss_end;

// Copy loader code to RAM. This also sets up its initialised data.
B_memcpy(&_loader_start, &_loader_loadaddr, &_loader_end - &_loader_start);

// Clear loader's BSS and COMMON
B_memset(&_loader_bss_start, 0, &_loader_bss_end - &_loader_bss_start);

extern void loader_entry() __attribute__((long_call));
loader_entry();

// never get here (loader always reboots)
for (;;);
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #37 on: June 14, 2022, 06:38:05 pm »
Indeed, any development environment which generates just the "overlay" would have code in main() which sets up the BSS and the initialised statics.
But why? All the reset handler is doing is this initialization and a call to main, except if you instruct people to place main() a a reset vector, you will also have to explain to them rules for BSS and data initialization and have them copy the code from the reset handler. And all you had to do to avoid all this is literally do nothing. Just keep the reset handler in the vector table and everything will work with standard environments.

All you have here is a standard bootloader, just behave like normal bootloaders behave and people will have no issues using your stuff. But you are inventing something that would be confusing to anyone familiar with how any of this works.
Alex
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #38 on: June 14, 2022, 07:38:03 pm »
A development environment which builds just the overlay would be the same as my current one, minus the boot block.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #39 on: June 14, 2022, 07:53:04 pm »
Why are you mandating the development environment? Why not let user pick what they want to do?

Anyway, do whatever you want, I'm not going to be the user, and that makes me happy.
Alex
 
The following users thanked this post: langwadt, newbrain

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: GCC ARM32 32F417 how to call or jump to a specific address?
« Reply #40 on: June 14, 2022, 08:26:41 pm »
This is a product which my little company will have to support (possibly for a long time; it's been running since 1991) and not everybody is as clever as you :) I certainly am not. But I much prefer working with people who are much more clever than I am, so if I am looking for somebody one day I will give you a shout ;)

Thanks everyone for all your help. It's running fine now.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf