Browse Source

+ riscv32-freertos: first version of TlinkerFreeRTOS.GenerateDefaultLinkerScripts

florian 2 years ago
parent
commit
30cb20bccd
1 changed files with 292 additions and 2 deletions
  1. 292 2
      compiler/systems/t_freertos.pas

+ 292 - 2
compiler/systems/t_freertos.pas

@@ -39,9 +39,9 @@ implementation
        TlinkerFreeRTOS=class(texternallinker)
        private
           Function  WriteResponseFile: Boolean;
-{$ifdef XTENSA}
+{$if defined(XTENSA) or defined(RISCV32)}
           procedure GenerateDefaultLinkerScripts(var memory_filename,sections_filename: AnsiString);
-{$endif XTENSA}
+{$endif (XTENSA) or defined(RISCV32)}
        public
           constructor Create; override;
           procedure SetDefaultInfo; override;
@@ -1193,6 +1193,296 @@ end;
 {$endif XTENSA}
 
 
+{$ifdef RISCV32}
+{ If espX.project.ld or espX_out.ld scripts cannot be located, generate
+  default scripts so that linking can proceed.  Note: the generated
+  scripts may not match the actual options chosen when the libraries
+  were built. }
+procedure TlinkerFreeRTOS.GenerateDefaultLinkerScripts(var memory_filename,
+  sections_filename: AnsiString);
+type
+  Tesp_idf_index=(esp32c3_v5_0=0);
+const
+  esp_fragment_list: array[esp32c3_v5_0..esp32c3_v5_0] of array of string=(
+    ('riscv/linker',
+     'esp_ringbuf/linker',
+     'driver/linker',
+     'esp_pm/linker',
+     'esp_mm/linker',
+     'spi_flash/linker',
+     'esp_system/linker',
+     'esp_system/app',
+     'esp_rom/linker',
+     'hal/linker',
+     'log/linker',
+     'heap/linker',
+     'soc/linker',
+     'esp_hw_support/linker',
+     'freertos/linker',
+     'freertos/linker_common',
+     'newlib/newlib',
+     'newlib/system_libs',
+     'esp_common/common',
+     'esp_common/soc',
+     'app_trace/linker',
+     'esp_event/linker',
+     'esp_phy/linker',
+     'lwip/linker',
+     'esp_netif/linker',
+     'esp_wifi/linker',
+     'bt/linker',
+     'esp_adc/linker',
+     'esp_gdbstub/linker',
+     'esp_lcd/linker',
+     'esp_psram/linker',
+     'espcoredump/linker'));
+
+var
+  S: Ansistring;
+  t: Text;
+  hp: TCmdStrListItem;
+  filepath: TCmdStr = '';
+  i,j: integer;
+  idf_index: Tesp_idf_index;
+  lib,
+  binstr,
+  cmdstr: AnsiString;
+  success: boolean;
+begin
+  { generate a sdkconfig.h if none is provided,
+    only a few fields are provided to far.
+    Assume that if linker scripts are not located,
+    sdkconfig.h is also missing }
+  Assign(t,outputexedir+'/sdkconfig.h');
+  {$push}{$I-}
+  Rewrite(t);
+  if ioresult<>0 then
+    exit;
+
+  if (current_settings.controllertype = ct_esp32c3) then
+    begin
+      writeln(t,'#pragma once');
+      writeln(t,'#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1');
+    end;
+
+  Close(t);
+  if ioresult<>0 then
+    exit;
+  {$pop}
+
+  { generate an sdkconfig if none is provided,
+    this is a dummy so far }
+  if not(Sysutils.FileExists(outputexedir+'/sdkconfig')) then
+    begin
+      Assign(t,outputexedir+'/sdkconfig');
+      {$push}{$I-}
+      Rewrite(t);
+      if ioresult<>0 then
+        exit;
+
+      writeln(t);
+
+      Close(t);
+      if ioresult<>0 then
+        exit;
+      {$pop}
+    end;
+
+  { generate an Kconfig if none is provided,
+    this is a dummy so far }
+  if not(Sysutils.FileExists(outputexedir+'/Kconfig')) then
+    begin
+      Assign(t,outputexedir+'/Kconfig');
+      {$push}{$I-}
+      Rewrite(t);
+      if ioresult<>0 then
+        exit;
+
+      writeln(t);
+
+      Close(t);
+      if ioresult<>0 then
+        exit;
+      {$pop}
+    end;
+
+  { generate an Kconfig.projbuild if none is provided,
+    this is a dummy so far }
+  if not(Sysutils.FileExists(outputexedir+'/Kconfig.projbuild')) then
+    begin
+      Assign(t,outputexedir+'/Kconfig.projbuild');
+      {$push}{$I-}
+      Rewrite(t);
+      if ioresult<>0 then
+        exit;
+
+      writeln(t);
+
+      Close(t);
+      if ioresult<>0 then
+        exit;
+      {$pop}
+    end;
+
+  { generate an kconfigs.in if none is provided,
+    this is a dummy so far }
+  if not(Sysutils.FileExists(outputexedir+'/kconfigs.in')) then
+    begin
+      Assign(t,outputexedir+'/kconfigs.in');
+      {$push}{$I-}
+      Rewrite(t);
+      if ioresult<>0 then
+        exit;
+
+      writeln(t);
+
+      Close(t);
+      if ioresult<>0 then
+        exit;
+      {$pop}
+    end;
+
+  { generate an kconfigs_projbuild.in if none is provided,
+    this is a dummy so far }
+  if not(Sysutils.FileExists(outputexedir+'/kconfigs_projbuild.in')) then
+    begin
+      Assign(t,outputexedir+'/kconfigs_projbuild.in');
+      {$push}{$I-}
+      Rewrite(t);
+      if ioresult<>0 then
+        exit;
+
+      writeln(t);
+
+      Close(t);
+      if ioresult<>0 then
+        exit;
+      {$pop}
+    end;
+
+  { generate a config.env if none is provided,
+    COMPONENT_KCONFIGS and COMPONENT_KCONFIGS_PROJBUILD are dummy fields and might
+    be needed to be filed properly }
+  Assign(t,outputexedir+'/config.env');
+  {$push}{$I-}
+  Rewrite(t);
+  if ioresult<>0 then
+    exit;
+
+  writeln(t,'{');
+  if (current_settings.controllertype = ct_esp32c3) then
+    begin
+      writeln(t,'    "COMPONENT_KCONFIGS": "Kconfig",');
+      writeln(t,'    "COMPONENT_KCONFIGS_PROJBUILD": "Kconfig.projbuild",');
+      writeln(t,'    "IDF_CMAKE": "y",');
+      writeln(t,'    "IDF_TARGET": "esp32c3",');
+      writeln(t,'    "IDF_ENV_FPGA": "",');
+      writeln(t,'    "IDF_PATH": "'+TargetFixPath(idfpath,false)+'",');
+      writeln(t,'    "COMPONENT_KCONFIGS_SOURCE_FILE": "'+outputexedir+'/kconfigs.in",');
+      writeln(t,'    "COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE": "'+outputexedir+'/kconfigs_projbuild.in"');
+    end;
+  writeln(t,'}');
+
+  Close(t);
+  if ioresult<>0 then
+    exit;
+  {$pop}
+
+  { generate ldgen_libraries }
+  Assign(t,outputexedir+'/ldgen_libraries');
+  {$push}{$I-}
+  Rewrite(t);
+  if ioresult<>0 then
+    exit;
+
+  { extract libraries from linker options and add to static libraries list }
+  Info.ExtraOptions:=trim(Info.ExtraOptions);
+  i := pos('-l', Info.ExtraOptions);
+  while i > 0 do
+   begin
+     j:=pos(' ',Info.ExtraOptions);
+     if j=0 then
+       j:=length(Info.ExtraOptions)+1;
+     lib:=copy(Info.ExtraOptions,i+2,j-i-2);
+     AddStaticCLibrary(lib);
+     delete(Info.ExtraOptions,i,j);
+     trim(Info.ExtraOptions);
+     i := pos('-l', Info.ExtraOptions);
+   end;
+  hp:=TCmdStrListItem(StaticLibFiles.First);
+  while assigned(hp) do
+    begin
+      FindLibraryFile(hp.Str,target_info.staticClibprefix,target_info.staticClibext,filepath);
+      writeln(t,filepath);
+      hp:=TCmdStrListItem(hp.Next);
+    end;
+
+  Close(t);
+  if ioresult<>0 then
+    exit;
+  {$pop}
+
+  memory_filename:=IncludeTrailingPathDelimiter(outputexedir)+memory_filename;
+  cmdstr:='-C -P -x c -E -o '+memory_filename+' -I $OUTPUT ';
+  binstr:='gcc';
+  if current_settings.controllertype = ct_none then
+    Message(exec_f_controllertype_expected)
+  else if current_settings.controllertype = ct_esp32c3 then
+    begin
+      if idf_version>=40400 then
+        cmdstr:=cmdstr+'-I $IDF_PATH/components/esp_system/ld $IDF_PATH/components/esp_system/ld/esp32c3/memory.ld.in'
+      else
+        cmdstr:=cmdstr+'$IDF_PATH/components/esp32/ld/esp32c3.ld';
+    end;
+  Replace(cmdstr,'$IDF_PATH',idfpath);
+  Replace(cmdstr,'$OUTPUT',outputexedir);
+  success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,true);
+
+  { generate linker maps }
+{$ifdef UNIX}
+  binstr:=TargetFixPath(idfpath,false)+'/tools/ldgen/ldgen.py';
+{$else}
+  binstr:='python';
+{$endif UNIX}
+  if source_info.exeext<>'' then
+    binstr:=binstr+source_info.exeext;
+
+  sections_filename:=IncludeTrailingPathDelimiter(outputexedir)+sections_filename;
+
+  cmdstr:={$ifndef UNIX}'$IDF_PATH/tools/ldgen/ldgen.py '+{$endif UNIX}
+          '--config $OUTPUT/sdkconfig --fragments';
+
+  { Pick corresponding linker fragments list for SDK version }
+  if (current_settings.controllertype = ct_esp32c3) then
+    idf_index:=esp32c3_v5_0;
+
+  for S in esp_fragment_list[idf_index] do
+    cmdstr:=cmdstr+' $IDF_PATH/components/'+S+'.lf';
+
+  if (current_settings.controllertype = ct_esp32c3) then
+    begin
+     if idf_version>=40400 then
+       cmdstr:=cmdstr+' --input $IDF_PATH/components/esp_system/ld/esp32c3/sections.ld.in'
+     else
+       cmdstr:=cmdstr+' --input $IDF_PATH/components/esp32/ld/esp32c3.project.ld.in';
+    end
+  else;
+
+  S:=FindUtil(utilsprefix+'objdump');
+  cmdstr:=cmdstr+' --output '+sections_filename+
+          ' --kconfig $IDF_PATH/Kconfig'+
+          ' --env-file $OUTPUT/config.env'+
+          ' --libraries-file $OUTPUT/ldgen_libraries'+
+          ' --objdump '+S;
+
+  Replace(cmdstr,'$IDF_PATH',idfpath);
+  Replace(cmdstr,'$OUTPUT',outputexedir);
+  if success then
+    success:=DoExec(binstr,cmdstr,true,false);
+end;
+{$endif RISCV32}
+
+
 function TlinkerFreeRTOS.MakeExecutable:boolean;
 var
   StaticStr,