How to manually (programmatically) place objects in my multi-core project?

I am developing a mutlicore project for embedded architecture using the gnu toolchain. In this architecture, all independent cores have the same global memory space. Each core has its own internal memory, which is addressed from any other core through its global 32-bit address.

There is no OS, and we do low-level programming, but in C instead of assembly. Each core has its own executable file generated with separate compilation. The current method that we use for internuclear communication is the calculation of the absolute addresses of objects in the data space of the target kernel. If we build the same code for all cores, then the objects are located by the linker in the same place, so accessing the object in the remote core simply changes the most significant bits of the address of the object in the current core and makes the transaction. A similar concept allows us to exchange objects located in an external DRAM.

Everything starts to get complicated when:

  • In two cores, the code does not match, so objects cannot be allocated to the same addresses,

  • Sometimes we use a “host”, which is another processor that runs some control code that requires access to objects in the kernels, as well as shared objects in external memory.

To overcome this problem, I am looking for an elegant way to place variables during assembly. I would like to avoid modifying the script linker file as much as possible. However, it seemed that at C level, I could only control the placement before using a combination of the section attribute (which is too crude) and the align attribute (which does not guarantee the exact location).

A possible hack is to use the built-in assembly to define objects and place them explicitly (using the .org and .global ), but this seems a little ugly (and we haven't tested this idea yet ...)

So here are the questions:

  • Is there a semi-standard way or an elegant solution for manually placing objects in C?

  • Is it possible to declare "uber" -extarnel objects in my code and make the linker resolve its addresses using another executable project?

This question describes a similar situation, but there the user refers to a pre-allocated resource (for example, a peripheral device), whose address is known before the build time.

+4
source share
4 answers

Perhaps you should try using the 'placement' tag from the new operator. More precisely, if you already have allocated / shared memory, you can create new objects on it. See: create objects in pre-allocated memory

+3
source

You do not specify exactly what data you will share, but provided that basically these are statically assigned variables of a fixed size, I would put all the data in one structure and separate only that.

The key point here is that this structure must be shared code, even if the rest of the programs are not. Additional fields could be added (possibly with a version field so that the reader can interpret it correctly), but existing fields should not be deleted or modified. structs are already used as an interface between libraries everywhere, so their layout can be relied on (although in a heterogeneous environment a little more attention is required, if the sizes and type alignment are the same, you should be fine).

Then you can share the structures: a) by placing them in a special section and using the script builder to put it in a known place; b) the distribution of the structure in static data and the placement of a pointer to it in a known place, for example, in your assembly launch files; or c) like (b), but allocate the structure on the heap and copy the pointer to the known location of the pointer at runtime. The advantage is that the pointer can be pre-configured for external consumers, which avoids a certain amount of clutter.

Hope that helps

+2
source
  • You are in excellent condition from here - do not expect anything "standard" for any of this :)
  • This answer offers a method for passing the list of source addresses to the linker. When linking an external executable, generate the linker map file, then process it to create this raw symbol table.

You can also try to link the entire program (all kernel programs) with one executable file. Use the section definitions and the linker script to put each main program in the internal memory space; you can create each main program separately, gradually bind it to one .o file, and then use objcopy to rename your sections to contain the kernel identifier for the script linker and rename (hide) private characters if you duplicate the same code on multiple cores. Finally, manually enter the start address for each kernel in your boot code instead of the usual start character.

+1
source

Answer to question 1: no, no.

Otherwise, it depends on the operating system. In our system at the time I was built-in, we only had one processor memory for processing (80186 and 68030), but it had multitasking, but from the same binary file. Our tool chain has been expanded to handle memory in a specific way. The tool chain looked like this (on 80186):

  • Microsoft C 16bit or Borland-C
  • Linker associated with our particular crt.o that defines some special characters and segments.
  • Microsoft linker generating exe and map file using MS-DOS address scheme
  • A locator that adjusted addresses in an executable file and generated a flat binary
  • Address patcher.
  • EPROM burner (later Flash loader).

In our assembly, we determined the symbol that was always at the beginning of the data segment, and we fixed the binary code with a hard-coded value coming from the localized map file. This allowed the library to use all the remaining memory in the form of a heap.

In fact, if you do not have control over the locator (echo sounder loader on linux or exe / dll loader in windows), you will be screwed.

+1
source

Source: https://habr.com/ru/post/1385204/


All Articles