2

I am compiling baremetal software (no OS) for the Beagleboard (ARM Cortex A8) with Codesourcerys GCC arm EABI compiler. Now this compiles to a binary or image file that I can load up with the U-Boot bootloader.

The question is, Can I load hexdata into memory dynamically in runtime (So that I can load other image files into memory)? I can use gcc objcopy to generate a hexdump of the software. Could I use this information and load it into the appropriate address? Would all the addresses of the .text .data .bss sections be loaded correctly as stated in the linker script?

The hexdata output generated by

$(OBJCOPY) build/$(EXE).elf -O binary build/$(EXE).bin
od -t x4 build/$(EXE).bin > build/$(EXE).bin.hex

look like this:

0000000 e321f0d3 e3a00000 e59f1078 e59f2078
0000020 e4810004 e1510002 3afffffc e59f006c
0000040 e3c0001f e321f0d2 e1a0d000 e2400a01
0000060 e321f0d1 e1a0d000 e2400a01 e321f0d7

... and so on.

Is it as simple as to just load 20 bytes for each line into the desired memory address and everything would work by just branching the PC into the correct address? Did I forget something?

Ry-
  • 218,210
  • 55
  • 464
  • 476
MrGigu
  • 1,729
  • 3
  • 23
  • 37

3 Answers3

4

when you use -O binary you pretty much give up your .text, .data. .bss control. For example if you have one word 0x12345678 at address 0x10000000 call that .text, and one word of .data at 0x20000000, 0xAABBCCDD, and you use -O binary you will get a 0x10000004 byte length file which starts with the 0x12345678 and ends with 0xAABBCCDD and has 0x0FFFFFFC bytes of zeros. try to dump that into a chip and you might wipe out your bootloader (uboot, etc) or trash a bunch of registers, etc. not to mention dealing with potentially huge files and an eternity to transfer to the board depending on how you intend to do that.

What you can do which is typical with rom based bootloaders, is if using gcc tools

MEMORY
{
   bob : ORIGIN = 0x10000000, LENGTH = 16K
   ted : ORIGIN = 0x20000000, LENGTH = 16K
}

SECTIONS
{
   .text : { *(.text*) } > bob
   .bss  : { *(.bss*) } > ted AT > bob
   .data : { *(.data*) } > ted AT > bob
}

The code (.text) will be linked as if the .bss and .data are at their proper places in memory , 0x20000000, but the bytes are loaded by the executable (an elf loader or -O binary, etc) tacked onto the end of .text. Normally you use more linkerscript magic to determine where the linker did this. On boot, your .text code should first zero the .bss and copy the .data from the .text space to the .data space and then you can run normally.

uboot can probably handle formats other than .bin yes? It is also quite easy to write an elf tool that extracts the different parts of binaries and makes your own .bins, not using objcopy. It is also quite easy to write code that never relies on .bss being zero nor has a .data. solving all of these problems.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • I kind of expected that, with the linker script I have complete control over where all sections should be located. Uboot loads this file for me with the loady command. However I have no idea how to load the contents of another binary file in runtime after I loaded my software. Just reading all the contents of the binary and loading it to a specific address would not work as i understand from your answer. Guess I have to read some elf documents in order to know how to parse it! THx – MrGigu Mar 18 '12 at 22:05
  • 1
    If you want to have your program load other programs, yes, you need to make a loader. I suggest the intel hex format first or motorola srec, with objcopy -O ihex or -O srec, ascii formats, easy to parse, and dont have the -O binary problem. http://github.com/dwelch67 I have probably more than one intel hex parser (again super easy) in the simulators. Note that for each target type the length and address definitions as well as endian change for ihex, I wonder what I did for the amber_samples, which is basically arm, that might be ihex. – old_timer Mar 18 '12 at 22:36
  • Thx, intel hex format solved the problem! Just had to convert the endian of the data and parse it into memory! – MrGigu Mar 20 '12 at 19:53
3

If you can write to random addresses without an OS getting in the way, there's no point in using some random hex dump format. Just load the binary data directly to the desired address. Converting on the fly from hex to binary to store in memory buys you nothing. You can load binary data to any address using plain read() or fread(), of course.

If you're loading full-blown ELF files (or similar), you of course need to implement whatever tasks that particular format expects from the object loader, such as allocating memory for BSS data, possibly resolving any unresolved addresses in the code (jumps and such), and so on.

unwind
  • 391,730
  • 64
  • 469
  • 606
2

Yes, it is possible to write to memory (on an embedded system) during run-time.

Many bootloaders copy data from a read-only memory (e.g. Flash), into writeable memory (SRAM) then transfer execution to that address.

I've worked on other systems that can download a program from a port (USB, SD Card) into writeable memory then transfer execution to that location.

I've written functions that download data from a serial port and programmed it into a Flash Memory (and EEPROM) device.

For memory to memory copies, use either memcpy or write your own, use pointers that are assigned a physical address.

For copying data from a port to memory, figure out how to get data from a device (such as a UART) then copy the data from its register into your desired location, via pointers.

Example:

#define UART_RECEIVE_REGISTER_ADDR (0x2000)
//...
volatile uint8_t * p_uart_receive_reg = (uint8_t*) UART_RECEIVE_REGISTER_ADDR;
*my_memory_location = *p_uart_receive_reg; // Read device and put into memory.

Also, search Stack Overflow for "embedded C write to memory"

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154