[fpc-devel] Patch for uf2 support in freePascal

Michael Ring mail at michael-ring.org
Fri Jan 22 23:37:52 CET 2021


Hi Florian, im Anhang der Path für den UF2 Support in freepascal, ich 
hoffe er passt so für Dich...

Das UF2 File wird nur erzeugt wenn die Startadresse ungleich $00000000 
ist da normalerweise der UF2 Bootloader ab Addresse 0 steht und es damit 
keinen sinnmacht ein uf2 file zu erzeugen wenn die Startaddresse auf 
default für Arm steht da dann der uf2 loader mit dem eigentlichen code 
kollidiert.

Der Fall das eine Startadresse via -Ttext angepasst wird ist auch mit 
drin, habe ich noch was vergessen?

Für den vollen Support muss auch noch das vtor Register umgeschrieben 
werden damit man interrupt-Handler im eigenen Code definieren kann, ich 
habe dazu bei mir den Startup Code for cortex M0,M3,M4F angepasst, keine 
Ahnung warum dieser Teil in dem {$ifdef REMAP_VECTTAB} define steht, 
denn dies muss dann in jeder Unit für einen Controller gesetzt werden 
obwohl bei den default Einstellungen der Remap korrekt ist.

Hast Du eine Ahnung warum das so gemacht wurde?

Ist nur ein Detail, wenn ich in der unit für den Raspi Pico den wert 
definiere dann wird vtor ja richtig gesetzt.

Michael


Mein Startup Code:

   ldr r0, .Lvtor
   ldr r1, .Ltext_start
   str r1, [r0]

   bl PASCALMAIN
   b HaltProc
   .balign 4
.L_bss_start:
   .long _bss_start
.L_bss_end:
   .long _bss_end
.L_etext:
   .long _etext
.L_data:
   .long _data
.L_edata:
   .long _edata
.Lvtor:
   .long 0xE000ED08


statt original startup Code:


{$ifdef REMAP_VECTTAB}
   ldr r0, .Lvtor
   ldr r1, .Ltext_start
   str r1, [r0]
{$endif REMAP_VECTTAB}

   bl PASCALMAIN
   b HaltProc

.L_bss_start:
   .long _bss_start
.L_bss_end:
   .long _bss_end
.L_etext:
   .long _etext
.L_data:
   .long _data
.L_edata:
   .long _edata
{$ifdef REMAP_VECTTAB}
.Lvtor:
   .long 0xE000ED08

-------------- next part --------------
diff --git a/compiler/systems/t_embed.pas b/compiler/systems/t_embed.pas
index 1b6d8d0065..c52fb4903e 100644
--- a/compiler/systems/t_embed.pas
+++ b/compiler/systems/t_embed.pas
@@ -39,6 +39,7 @@ implementation
        TlinkerEmbedded=class(texternallinker)
        private
           Function  WriteResponseFile: Boolean;
+          Function  GenerateUF2(binFile,uf2File : string;baseAddress : longWord):boolean;
        public
           constructor Create; override;
           procedure SetDefaultInfo; override;
@@ -2847,6 +2848,10 @@ begin
         success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+
           FixedExeFileName+' '+
           maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin'))),true,false);
+        if success then
+          success := GenerateUF2(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin'))),
+                                 maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.uf2'))),
+                                 embedded_controllers[current_settings.controllertype].flashbase);
 {$ifdef ARM}
       if success and (current_settings.controllertype = ct_raspi2) then
         success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+ FixedExeFileName + ' kernel7.img',true,false);
@@ -2863,6 +2868,105 @@ function TLinkerEmbedded.postprocessexecutable(const fn : string;isdll:boolean):
   end;
 
 
+function TlinkerEmbedded.GenerateUF2(binFile,uf2File : string;baseAddress : longWord):boolean;
+type 
+  TFamilies= record
+    k : String;
+    v : longWord;
+  end;
+  tuf2Block = record
+    magicStart0,
+    magicStart1,
+    flags,
+    targetAddr,
+    payloadSize,
+    blockNo,
+    numBlocks,
+    familyid : longWord;
+    data : array[0..255] of byte;
+    padding : array[0..511-256-32-4] of byte;
+    magicEnd : longWord;
+  end;
+
+const
+  Families : array of TFamilies = (
+    (k:'SAMD21'; v:$68ed2b88),
+    (k:'SAML21'; v:$1851780a),
+    (k:'SAMD51'; v:$55114460),
+    (k:'NRF52';  v:$1b57745f),
+    (k:'STM32F0';v:$647824b6),
+    (k:'STM32F1';v:$5ee21072),
+    (k:'STM32F2';v:$5d1a0a2e),
+    (k:'STM32F3';v:$6b846188),
+    (k:'STM32F4';v:$57755a57),
+    (k:'STM32F7';v:$53b80f00),
+    (k:'STM32G0';v:$300f5633),
+    (k:'STM32G4';v:$4c71240a),
+    (k:'STM32H7';v:$6db66082),
+    (k:'STM32L0';v:$202e3a91),
+    (k:'STM32L1';v:$1e1f432d),
+    (k:'STM32L4';v:$00ff6919),
+    (k:'STM32L5';v:$04240bdf),
+    (k:'STM32WB';v:$70d16653),
+    (k:'STM32WL';v:$21460ff0)
+  );
+
+var
+  f,g : file;
+  uf2block : Tuf2Block;
+  totalRead,numRead : longWord;
+  familyId,i : longWord;
+  ExtraOptions : String;
+
+begin
+  if pos('-Ttext=',Info.ExtraOptions) > 0 then
+  begin
+    ExtraOptions := copy(Info.ExtraOptions,pos('-Ttext=',Info.ExtraOptions)+7,length(Info.ExtraOptions));
+    for i := 1 to length(ExtraOptions) do
+      if pos(copy(ExtraOptions,i,1),'0123456789abcdefxABCDEFX') = 0 then
+        ExtraOptions := copy(ExtraOptions,1,i);
+    baseAddress := StrToIntDef(ExtraOptions,0);
+  end;
+
+  familyId := 0;
+  for i := 0 to length(Families)-1 do
+  begin
+    if pos(Families[i].k,embedded_controllers[current_settings.controllertype].controllerunitstr) = 1 then
+      familyId := Families[i].v;
+  end;
+
+  if (baseAddress and $07ffffff) <> 0 then
+  begin
+    totalRead := 0;
+    assign(f,binfile);
+    reset(f,1);
+    assign(g,uf2file);
+    rewrite(g,1);
+
+    repeat
+      fillchar(uf2block,sizeof(uf2block),0);
+      uf2block.magicStart0 := $0A324655; // "UF2\n"
+      uf2block.magicStart1 := $9E5D5157; // Randomly selected
+      if familyId = 0 then
+        uf2block.flags := 0
+      else
+        uf2block.flags := $2000;
+      uf2block.targetAddr := baseAddress + totalread;
+      uf2block.payloadSize := 256;
+      uf2block.blockNo := (totalRead div sizeOf(uf2block.data));
+      uf2block.numBlocks := (filesize(f) + 255) div 256;
+      uf2block.familyId := familyId;
+      uf2block.magicEnd := $0AB16F30; // Randomly selected
+      blockRead(f,uf2block.data,sizeof(uf2block.data),numRead);
+      blockwrite(g,uf2block,sizeof(uf2block));
+      inc(totalRead,numRead);
+    until (numRead=0) or (NumRead<>sizeOf(uf2block.data));
+    close(f);
+    close(g);
+  end;
+  Result := true;
+end;
+
 {*****************************************************************************
                               TlinkerEmbedded_SdccSdld
 *****************************************************************************}


More information about the fpc-devel mailing list