[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