Hi all,
I have recently developed a technique for the STM8 platform to have
assembly code functions automatically placed in RAM by SDCC's bootstrap
process and have this RAM-resident code be callable from C code. I
thought I would share this technique on the mailing list in case anyone
else finds it useful.
It takes advantage of how the SDCC bootstrap code (which is generated in
the 'main' module, jumped to upon reset) copies data from flash to RAM
in order to initialise the values of global variables. What that does is
simply copy a defined number of bytes from the INITIALIZER section (in
flash) to the INITIALIZED section (in RAM). We can co-opt this process
to have executable code copied as well.
Put briefly, what we do is tell the assembler to put the code
implementing our functions in the INITIALIZER section (as opposed to
CODE section), but not export those particular labels. Instead, we put
the exported labels (i.e. the function call entry points) in the
INITIALIZED section and tell the assembler to reserve an amount of space
there for each equivalent to the size of the code of the corresponding
implementing function. This reserved space is what the bootstrap process
will copy into.
Let me illustrate the technique by way of example. Say we are writing
two assembly code functions that are exported to our C code (using a
header file) with the following function declarations:
extern unsigned char add_10_func(unsigned char val);
extern unsigned char sub_10_func(unsigned char val);
If we want them to be RAM-resident, our assembly code file would be as
follows:
.module foo
.globl _add_10_func
.globl _sub_10_func
;
------------------------------------------------------------------------------
; Must define default segment ordering for linker, in case this is
linked first.
.area DATA
.area INITIALIZED
.area SSEG
.area DABS (ABS)
.area HOME
.area GSINIT
.area GSFINAL
.area CONST
.area INITIALIZER
.area CODE
;
------------------------------------------------------------------------------
.area INITIALIZER
; At startup, the __sdcc_init_data() procedure (in main module) will
copy data
; from INITIALIZER to INITIALIZED. We place the actual function code
here in the
; former, but will be executed from the copy in the latter at run-time.
add_10_func:
ld a, (3, sp)
add a, #10
ret
ADD_10_FUNC_CODE_SIZE = (. - add_10_func)
sub_10_func:
ld a, (3, sp)
sub a, #10
ret
SUB_10_FUNC_CODE_SIZE = (. - sub_10_func)
;
------------------------------------------------------------------------------
.area INITIALIZED
; Here we reserve space for the RAM-resident function code to live. These
; locations are also the callable labels for the exported function names.
; IMPORTANT: these must be in the same order as the actual function code!
_add_10_func:
.ds ADD_10_FUNC_CODE_SIZE
_sub_10_func:
.ds SUB_10_FUNC_CODE_SIZE
Some notes:
- A function's code size is calculated by taking the position of the
start of the function (i.e. its label) and subtracting that from the
current position (using '.' keyword) after the function. The resultant
value is assigned to a symbol for use later with a '.ds' assembler
directive.
- The exported function labels in the INITIALIZED section *must* be in
the same order as the function implementation code in the INITIALIZER
section.
- The bunch of '.area' statements listing every section name SDCC
utilises is there in case the object file is linked first, before any C
code. It seems SDCC determines the order of sections to declare to the
linker by the order they are first encountered. Without this, things
went wrong if the assembly code's .rel file was given to the linker first.
- The assembly code should be built with the command 'sdasstm8 -ff -w -l
-p -o foo.rel foo.s' and the output object file linked as per normal.
If anyone has an questions, feel free to ask. :)
Regards,
Basil Hussain
P.S. In case you're wondering why I needed this, it's because I was
experimenting with self-modifying assembly code, which of course needs
to be in RAM in order for it to be modifiable.
_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user