Products > Programming

GCC ARM32 32F417 how to call or jump to a specific address?

<< < (7/9) > >>

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.
--- End quote ---

Yes; that would address the code removal because main() will have something pointing to it, which normally happens in a ST arm32 environment. Thanks.


--- Quote from: peter-h 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?

--- End quote ---
None. That's why I said it must be a (void) function. You don't need to do anything extra.

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.

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.

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.


[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod