|
@@ -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,
|