[RFC] Aligning to flash sector & support of H/W peripherals.
Ulf Samuelsson
binutils@emagii.com
Wed Mar 8 14:10:09 GMT 2023
One issue which remains to make life easier for embedded control
is that you want to align your .text area on a flash sector boundary.
Many microcontrollers have an irregular set of sectors.
For instance, the TMS570LC4357 which I worked on has:
* 6 x 16kB sectors
* 1 x 32 kB sector
* 6 x 256 kB sectors
* 19 x 128 kB sectors.
To align on a sector boundary, the linker needs to know where the
sectors start and end.
I can see two ways of doing that.
1. Use the existing linker features (which are user unfriendly)
2. Extend the linker to understand the flash organisation.
=========================================================
It is actually possible to do this today with the linker, but it is
massively unfriendly to the user,
You can start by:
"bank0#00#start" = 0x00000000;
"bank0#00#end" = 0x00003fff;
"bank0#00#size" = 0x00004000;
...
"bank0#15#start" = 0x001c0000;
"bank0#15#end" = 0x001fffff;
"bank0#15#size" = 0x00040000;
Then when you want to align to a sector boundary you do:
. = ((. >= "bank0#00#start") && (. <= "bank0#00#end")) ?
ALIGN("bank0#00#size") : .;
...
. = ((. >= "bank0#15#start") && (. <= "bank0#15#end")) ?
ALIGN("bank0#15#size") : .;
This checks if the current location counter ('.') is within a sector,
and then aligns to the sector size.
If not, then the location counter is set to itself.
=========================================================
A much more friendly approach inside the linker would extend the syntax by:
FLASH bank0 {
SECTOR "16 kB";
SECTOR "16 kB";
...
SECTOR "256 kB";
};
SECTOR_ALIGN;
Every SECTOR command would add the sector to a list and create the
"start", "end" and "size" symbols above.
The SECTOR_ALIGN command would generate the expressions above for each
sector.
A location counter starts at 0, and if the flash starts at another
location, you can
add dummy sectors or add some ORIGIN command.
When you want to align the flash you create the expressions above, one
per flash segment.
Any flash segment named "dummy..." is ignored.
The syntax changes would be something like this:
ifile_p1:
...
| flash
;
flash : FLASH NAME {
lang_add_bank($2); // Provides the name for the flash
bank. "dummy..." is ignored.
} '{' sector_list '}'
;
sector_list: sector_list sector
|
;
sector: SECTOR NAME {
lang_add_sector($2); // Adds symbols "begin", "end" and
"size" for the sector.
}
| ';'
;
statement:
...
| ALIGN_SECTOR {
lang_align_sector(); // Adds expressions to update the
location counter.
}
;
=========================================================
If people think don't like supporting the sectors inside the linker in
this way,
then I think we should consider another addition.
Several microcontroller vendors provide a GNU toolchain for their vendors.
The would want to supply include files for each and every part they have.
When you have 100s or 1000s of microcontrollers, this quickly becomes messy.
I am thinking that there should be environment variables that specifies
* VENDOR_BINUTILS_SCRIPTDIR
* USER_BINUTILS_SCRIPTDIR
and then a directive that adds a subdirectory.
CHIP "<chipname>"
would add
${USER_BINUTILS_SCRIPTDIR}/<chipname>
${VENDOR_BINUTILS_SCRIPTDIR}/<chipname>
to the search path for INCLUDE commands.
It should also INCLUDE both the
${VENDOR_BINUTILS_SCRIPTDIR}/<chipname>/<chipname>.inc
${USER_BINUTILS_SCRIPTDIR}/<chipname>/<chipname>.inc
if present (or is it better to select the USER if present, and if not
the VENDOR version).
This way, a vendor can add chip specific include files to an existing
toolchain,
and a user can override or extend the "known" chips.
Ideally, you should be able to override the CHIP directive with a
command line parameter.
=========
This feature is obviously very useful when you have a lot of peripherals
that you want to access.
You can define all the base addresses of the microcontroller peripherals
in the CHIP file
Best Regards
Ulf Samuelsson
More information about the Binutils
mailing list