Position independent code with position dependent data ?

Hi there !

My CPU has no MMU, very little RAM (8KB), and is running a modified FreeRTOS. I'd like to have the ability to "load" and run some code from USART/DATAFLASH to FLASH as a RTOS task. Of course, for convenience, the compiled code must be fully position independent. Using the -fPIC or -fpic option, looking at the assembler, the code seems OK : a dynamically computed offset is applied to every operations.

BUT, looking deeply, both DATA and CODE are applied the base offset ! While this is the expected behavior for CODE (running anywhere in FLASH), moving my CODE over the entire flash space doesn't mean moving my RAM ! This make only sense when executing everything from SDRAM !

I'm looking for a solution to generate position independent *code*, but with position dependent *data* using GCC/LD... Any help ?

Reply to
nono240
Loading thread data ...

What processor?

Is the generated code using only relative branch instructions, or is it using absolute branches in a '.o' file format that requires a loader to fix up the absolute addresses? If so, why not fix up the code addresses when you fix up the absolute ones?

You may be able to do this by not using any statically allocated memory at all -- i.e., no file-extent variables. Allocate everything from within a function (so it'll go on the stack) or explicitly allocate from "malloc" (and make sure that heap fragmentation won't kill your app after running for a bit longer than you ever tested for).

--
Tim Wescott
Wescott Design Services
 Click to see the full signature
Reply to
Tim Wescott

Define your variables in the other module, refer to it as "external".

VLV

Reply to
Vladimir Vassilevsky

Unless you want to download multiple tasks like this, and have them stored in arbitrary places in flash (and ram), then there is no need for position-independent data or code. Simple arrange (by linker script magic, typically) for the code and data to link at the specific addresses of the flash and ram slots you have available.

Reply to
David Brown

Position independent code (in my mind, anyway) is machine code that does not require a relinking or fixup phase in order to be moved to a different address in memory. There are a lot of assumptions in that statement.

Since your program requires _flash_ and _sram_ to operate and you don't say that much about the cpu and software environs, I can only add a few thoughts.

Code and constants used, either directly as data, such as a table of values, or else copied into sram prior to the start of the program to initialize writable variable instances that need specific initial values to be present, can be placed into flash either as a single segment or multiple ones.

However, with sram fixed in one place and flash in another place (I'm assuming that's the case as you point out there is no MMU), there is no question about the fact that there are at least two separate segments in your situation. The base address of the flash-located segment might be the PC register so that this flash block can be moved around freely and uses the PC register as a cheap way to figure out where it's own stuff is at (assuming the processor supports that), but that won't work for the sram data instance segment which is obviously located "elsewhere." Somehow, a base address for that region needs to be made available to your code and applied at run time. What mechanism is available for that? Can you reserve a segment for it located at a physical address that is not permitted to change, for example? In other words, reserve it?

Also, there are (not infrequently) specific hardware peripherals and other features that may be "memory mapped" to specific addresses. Clearly, these should not depend upon the flash memory locations of your code.

How all this gets done does depend on what else you are doing. And you haven't talked about that. I don't think there is a universal, always-works-everywhere, answer. More info is needed, I believe.

The above is general theory and applies broadly.

Jon

Reply to
Jon Kirwan

And I'm still not sure _why_ you actually want position independence in code and data. If this is the entire application and there is nothing else present, no operating system for example, then why do you care? Just let the tools do their job using mainstream approaches.

Jon

Reply to
Jon Kirwan

A few decades ago, this was a typical minicomputer configuration with

8-64 KiD of core, occupying at least one rack.

Running any kind of pre-emptive multi tasking requires some kind of per task stack.

To be practical, this requires a processor with a stack pointer and addressing modes that are stack pointer relative. As an absolute minimum, some index register+offset addressing is required (unless self modified code is used :-).

You really have to study the instruction set of your processor very carefully to find the most effective way of handling things.

There is no single "correct" answer to your problem.

Reply to
Paul Keinanen

I find, in resource starved applications, using interpreters is a big win. If you're loading apps dynamically, I suspect the speed penalty would be insignificant (esp with careful choice of language)

Reply to
D Yuniskis

Dynamic data, stack and heap (even if static) typically isn't a problem with PI code because you always need to specify where their locations and those values can be set dynamically when the code is loaded ... it's usually only compile time static data that you need to worry about when relocating code - you either need to copy the static data with the code maintaining the relative spacing or rebase the data to where it will be when the code runs.

There ought to be a compiler option to base data references at a different address from the code. Unfortunately, I have never needed to do this using GCC so I can't tell you how. A quick manual search didn't turn up anything, but GCC has so many switches you can go blind trying to find the right one.

Even so, it won't necessarily help you unless you know at compile time where the static data will be. Once you rebase, ALL relative addressing will use the new base - if your CPU has a range limit for relative addressing, it may not be possible to do what you want.

George

Reply to
George Neuner

Any suggestions for such interpretters, Don? Experiences?

Peter

Reply to
Peter Dickerson

Remember, this is c.a.e so, for the most part, you *know* what the application is -- and what it will *remain* (i.e., we're not looking at an environment where you have to be able to handle infinite variety of applications).

In the past, I've written C-ish, PL/M-ish and BASIC-ish interpreters along with Forth. Note that you can use these as guidelines for a pseudo-language without strictly complying with any formal language definition.

E.g., you can opt to implement integer only math instead of supporting "doubles", etc. You can force limits to be defined for string lengths (static memory allocation). You can discount recursion, etc.

The advantage of interpreters has always seemed to be coming up with really tight representations of algorithms and spend "ROM" instead of needing space in (loadable) RAM...

Reply to
D Yuniskis

Hi there ! Thank you for reply !

I'm running FreeRTOS. We need "dynamic task loading".

IT IS my case. It's a (commercial) product, letting the user to load multiple (so named) "tasklets" into FLASH, but its only allowed to run ONE at a time. So, we need those "tasklets" to be CODE position independent, but share DATA.

is PC relative offset : before any IO operations, the *real* offset from original linkage is computed and added automatically :

For example, the following code :

extern int myarray[]; // @0x4000 (DATA) int foo() { return myarray[0]; }

Give :

80018196: lddpc r6, 80018204
Reply to
nono240

Why don't you provide a function call to get the address of the shared data in your code and use that within a tasklet. You might put the relevant data into a structure: ditto ROM data.

Andrew

Reply to
Andrew Jackson

If you can run only one task at a time, why do you need position independent code ? Just link each program to the same fixed load address. You need PIC code only when there are _multiple_ programs to be loaded somewhere into the RAM.

If you want to share data between these programs, first link the data area to a fixed address and then link each program to that address.

This is how it was done half a century ago. In FORTRAN, create a COMMON area, install it into a fixed address (usually at the top of the core) and then load each "transient program" into low memory, since the whole program could not fit into the core at once. No base/stack pointer relative addressing needed, since the data addresses were known at compile time.

With modern processors with versatile addressing modes, why not reserve one data area pointer at a known location (such as the first or last address in RAM or ROM) and use this to access the shared variables in each program ?

Data = GetPersistentDataAreaPointer() ; ... Data->SharedVar1 = Data->SharedVar2 ;

Reply to
Paul Keinanen

A basic concept in linking ( ld program) is the ``section''. A section is an area of memory belonging together, such that e.g. distances within the section are fixable. A section may have a relocation table identifying the places in the section that still needs to be adjusted to the final place it will be used in the program.

Now you want to have different sections behave differently regards location.

What the linker (ld) does is combine sections from different object modules together into larger sections with names like .bss .text .data and possible fixing the relocation table. From that point whatever went into such a section will be treated in the same way, i.e. once you combined DATA and CODE into one section, data and code will be either fixed at a position or have a relocation table. The linker is blind to the difference between code and data, the only information it gets is by naming convention of input sections. This information is generated by the compiler.

Now you have to understand which sections you have, then tell the linker what to do with it. Using the --debug option to the linker you get a so called linker script which details what the linker does. What you want can be accomplished by adapting the linker script, which is -- I admit -- not necessarily easy.

Groetjes Albert

--

--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
 Click to see the full signature
Reply to
Albert van der Horst

Thanks for all your replies !

Because those "tasklets" are stored in different places in FLASH : we ship the device with 4 embedded tasklets, but a dozen more are available to download and free to be uploaded at any of those 4 slots, we don't want the user to take care about "link address" ! Moreover, if we update our CPU to more FLASH, we don't want to deal with multiple tasklets version.

Relocating a tasklet "on demand" to an "predefined fixed area" will prematurely kill the FLASH since there's not enough RAM to run code from...

Because we want the tasklets to be "RTOS" unaware. Our FreeRTOS is running as an "hypervisor" (we did have an MPU though).

I just need a way to tell LD that my DATA section is ABSOLUTE, and not relative from CODE..

Reply to
nono240

I don't see that Paul's suggestion makes your tasklet RTOS aware. Furthermore, I would have thought that the tasklets do need to be RTOS aware because they are manipulating a common data area.

What does your link script look like at present?

Andrew

Reply to
Andrew Jackson

OK, different aim. In my case I have a scientific instrument that is making various low level measurements. Users, who are typically chemists or biochemists, want real answers not raw measurements. For this the apply "Methods" that turn instrumental measurements into stuff like concentrations. These methods are all pretty standard but there are lots of them, with the occasional new one turning up. I'd prefer the applications chemists to be able to implement the methods so that I can concentrate on measuring femtoamps. So, I'm looking scriptable.

Peter

Reply to
Peter Dickerson

Yes, we wrote/implemented a "QBASIC" for some of our instruments for just this reason (blood assays). Allowed the customer to design new tests without having to contract with us to code them. I.e., we just provided a device that came up with the raw data and let the customer come up with the means of interpreting that data based on the reagents, etc. that he was using in the assay.

Note that you can do this two different ways:

- *source* level interpreter in the instrument

- "bytecode" interpreter in the instrument with an external "compiler/parser".

(I'm talking *really* limited resources, here)

If you have a more fleshy implementation to work with, look at Lua. Lately I am doing a lot with Inferno/Limbo (but would not suggest it for "end users")

Reply to
D Yuniskis

[snip]

Yes, I'd go for source since that is conceptually the simplest. Otherwise I need a bytecode compiler somewhere in the machine or on a PC.

I did get Lua linked in but ran out of memory almost immediately. In particular I couldn't measure anything. The problem seems to be that a lot of stuff gets stored in RAM - dictionaries, strings etc. I'd prefer to be able to keep that stuff in Flash only even at the cost of performance.

Peter

Reply to
Peter Dickerson

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.