瀏覽代碼

+ Xtensa: generate all helper files to fpc can successfully compile a single program

git-svn-id: trunk@44461 -
florian 5 年之前
父節點
當前提交
aab0884182
共有 1 個文件被更改,包括 218 次插入257 次删除
  1. 218 257
      compiler/systems/t_freertos.pas

+ 218 - 257
compiler/systems/t_freertos.pas

@@ -74,7 +74,15 @@ const
 begin
   with Info do
    begin
-     ExeCmd[1]:='ld -g '+platform_select+' $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP -L. -o $EXE -T $RES';
+     if target_info.system=system_xtensa_freertos then
+       ExeCmd[1]:='ld -g '+platform_select+' $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP -L. -o $EXE -T $RES '+
+         '-u call_user_start_cpu0 -u ld_include_panic_highint_hdl -u esp_app_desc -u vfs_include_syscalls_impl -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u newlib_include_locks_impl -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -u app_main -u uxTopUsedPriority '+
+         '-L $IDF_PATH/components/esp_rom/esp32/ld -T esp32.rom.newlib-funcs-time.ld '+
+         '-T esp32.rom.ld -T esp32.rom.libgcc.ld -T esp32.rom.newlib-data.ld -T esp32.rom.syscalls.ld -T esp32.rom.newlib-funcs.ld '+
+         '-L . -T esp32_out.ld -T esp32.project.ld '+
+         '-L $IDF_PATH/components/esp32/ld -T esp32.peripherals.ld'
+     else
+       ExeCmd[1]:='ld -g '+platform_select+' $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP -L. -o $EXE -T $RES';
    end;
 end;
 
@@ -158,60 +166,44 @@ begin
    end;
 
   { Write staticlibraries }
-  if not StaticLibFiles.Empty then
-   begin
-    { vlink doesn't need, and doesn't support GROUP }
-    if (cs_link_on_target in current_settings.globalswitches) then
-     begin
+  if not(StaticLibFiles.Empty) then
+    begin
       LinkRes.Add(')');
       LinkRes.Add('GROUP(');
-     end;
-    while not StaticLibFiles.Empty do
-     begin
-      S:=StaticLibFiles.GetFirst;
-      LinkRes.AddFileName((maybequoted(s)));
-     end;
-   end;
+      while not StaticLibFiles.Empty do
+        begin
+          S:=StaticLibFiles.GetFirst;
+          LinkRes.AddFileName((maybequoted(s)));
+        end;
+    end;
 
-  if (cs_link_on_target in current_settings.globalswitches) then
-   begin
-    LinkRes.Add(')');
+   LinkRes.Add(')');
 
-    { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
-      here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
-    linklibc:=false;
-    while not SharedLibFiles.Empty do
-     begin
-      S:=SharedLibFiles.GetFirst;
-      if s<>'c' then
-       begin
-        i:=Pos(target_info.sharedlibext,S);
-        if i>0 then
-         Delete(S,i,255);
-        LinkRes.Add('-l'+s);
-       end
-      else
-       begin
-        LinkRes.Add('-l'+s);
-        linklibc:=true;
-       end;
-     end;
-    { be sure that libc&libgcc is the last lib }
-    if linklibc then
-     begin
-      LinkRes.Add('-lc');
-      LinkRes.Add('-lgcc');
-     end;
-   end
-  else
-   begin
-    while not SharedLibFiles.Empty do
-     begin
-      S:=SharedLibFiles.GetFirst;
-      LinkRes.Add('lib'+s+target_info.staticlibext);
-     end;
-    LinkRes.Add(')');
-   end;
+   { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+     here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+   linklibc:=false;
+   while not SharedLibFiles.Empty do
+    begin
+     S:=SharedLibFiles.GetFirst;
+     if s<>'c' then
+      begin
+       i:=Pos(target_info.sharedlibext,S);
+       if i>0 then
+        Delete(S,i,255);
+       LinkRes.Add('-l'+s);
+      end
+     else
+      begin
+       LinkRes.Add('-l'+s);
+       linklibc:=true;
+      end;
+    end;
+   { be sure that libc&libgcc is the last lib }
+   if linklibc then
+    begin
+     LinkRes.Add('-lc');
+     LinkRes.Add('-lgcc');
+    end;
 
   { objects which must be at the end }
   if linklibc then
@@ -1354,205 +1346,12 @@ begin
   {$ifdef XTENSA}
   with linkres do
     begin
-      Add('/* Script for -z combreloc: combine and sort reloc sections */');
-      Add('/* Copyright (C) 2014-2018 Free Software Foundation, Inc.');
-      Add('   Copying and distribution of this script, with or without modification,');
-      Add('   are permitted in any medium without royalty provided the copyright');
-      Add('   notice and this notice are preserved.  */');
-      Add('ENTRY(_start)');
-      Add('SEARCH_DIR("=/builds/idf/crosstool-NG/builds/xtensa-esp32-elf/xtensa-esp32-elf/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");');
       Add('SECTIONS');
       Add('{');
-      Add('  /* Read-only sections, merged into text segment: */');
-      Add('  PROVIDE (__executable_start = 0x400000); . = 0x400000 + SIZEOF_HEADERS;');
-      Add('  .interp         : { *(.interp) }');
-      Add('  .note.gnu.build-id : { *(.note.gnu.build-id) }');
-      Add('  .hash           : { *(.hash) }');
-      Add('  .gnu.hash       : { *(.gnu.hash) }');
-      Add('  .dynsym         : { *(.dynsym) }');
-      Add('  .dynstr         : { *(.dynstr) }');
-      Add('  .gnu.version    : { *(.gnu.version) }');
-      Add('  .gnu.version_d  : { *(.gnu.version_d) }');
-      Add('  .gnu.version_r  : { *(.gnu.version_r) }');
-      Add('  .rela.dyn       :');
-      Add('    {');
-      Add('      *(.rela.init)');
-      Add('      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)');
-      Add('      *(.rela.fini)');
-      Add('      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)');
-      Add('      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)');
-      Add('      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)');
-      Add('      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)');
-      Add('      *(.rela.ctors)');
-      Add('      *(.rela.dtors)');
-      Add('      *(.rela.got)');
-      Add('      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)');
-      Add('    }');
-      Add('  .rela.plt       : { *(.rela.plt) }');
-      Add('  /* .plt* sections are embedded in .text */');
-      Add('  .text           :');
-      Add('  {');
-      Add('    *(.got.plt* .plt*)');
-      Add('    KEEP (*(.init.literal))');
-      Add('    KEEP (*(SORT_NONE(.init)))');
-      Add('    *(.literal .text .stub .literal.* .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)');
-      Add('    /* .gnu.warning sections are handled specially by elf32.em.  */');
-      Add('    *(.gnu.warning)');
-      Add('    KEEP (*(.fini.literal))');
-      Add('    KEEP (*(SORT_NONE(.fini)))');
-      Add('  } =0');
-      Add('  PROVIDE (__etext = .);');
-      Add('  PROVIDE (_etext = .);');
-      Add('  PROVIDE (etext = .);');
-      Add('  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }');
-      Add('  .rodata1        : { *(.rodata1) }');
-      Add('  .got.loc        : { *(.got.loc) }');
-      Add('  .xt_except_table   : ONLY_IF_RO { KEEP (*(.xt_except_table .xt_except_table.* .gnu.linkonce.e.*)) }');
-      Add('  .eh_frame_hdr : { *(.eh_frame_hdr) }');
-      Add('  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }');
-      Add('  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }');
-      Add('  /* Adjust the address for the data segment.  We want to adjust up to');
-      Add('     the same address within the page on the next page up.  */');
-      Add('  . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));');
-      Add('  /* Exception handling  */');
-      Add('  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }');
-      Add('  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }');
-      Add('  /* Thread Local Storage sections  */');
-      Add('  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }');
-      Add('  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }');
-      Add('  .preinit_array     :');
-      Add('  {');
-      Add('    PROVIDE_HIDDEN (__preinit_array_start = .);');
-      Add('    KEEP (*(.preinit_array))');
-      Add('    PROVIDE_HIDDEN (__preinit_array_end = .);');
-      Add('  }');
-      Add('  .init_array     :');
-      Add('  {');
-      Add('     PROVIDE_HIDDEN (__init_array_start = .);');
-      Add('     KEEP (*(SORT(.init_array.*)))');
-      Add('     KEEP (*(.init_array))');
-      Add('     PROVIDE_HIDDEN (__init_array_end = .);');
-      Add('  }');
-      Add('  .fini_array     :');
-      Add('  {');
-      Add('    PROVIDE_HIDDEN (__fini_array_start = .);');
-      Add('    KEEP (*(SORT(.fini_array.*)))');
-      Add('    KEEP (*(.fini_array))');
-      Add('    PROVIDE_HIDDEN (__fini_array_end = .);');
-      Add('  }');
-      Add('  .ctors          :');
-      Add('  {');
-      Add('    /* gcc uses crtbegin.o to find the start of');
-      Add('       the constructors, so we make sure it is');
-      Add('       first.  Because this is a wildcard, it');
-      Add('       doesn''t matter if the user does not');
-      Add('       actually link against crtbegin.o; the');
-      Add('       linker won''t look for a file to match a');
-      Add('       wildcard.  The wildcard also means that it');
-      Add('       doesn''t matter which directory crtbegin.o');
-      Add('       is in.  */');
-      Add('    KEEP (*crtbegin.o(.ctors))');
-      Add('    KEEP (*crtbegin?.o(.ctors))');
-      Add('    /* We don''t want to include the .ctor section from');
-      Add('       the crtend.o file until after the sorted ctors.');
-      Add('       The .ctor section from the crtend file contains the');
-      Add('       end of ctors marker and it must be last */');
-      Add('    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))');
-      Add('    KEEP (*(SORT(.ctors.*)))');
-      Add('    KEEP (*(.ctors))');
-      Add('  }');
-      Add('  .dtors          :');
-      Add('  {');
-      Add('    KEEP (*crtbegin.o(.dtors))');
-      Add('    KEEP (*crtbegin?.o(.dtors))');
-      Add('    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))');
-      Add('    KEEP (*(SORT(.dtors.*)))');
-      Add('    KEEP (*(.dtors))');
-      Add('  }');
-      Add('  .jcr            : { KEEP (*(.jcr)) }');
-      Add('  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }');
-      Add('  .xt_except_table   : ONLY_IF_RW { KEEP (*(.xt_except_table .xt_except_table.* .gnu.linkonce.e.*)) }');
-      Add('  .dynamic        : { *(.dynamic) }');
-      Add('  .got            : { *(.got) }');
-      Add('  .data           :');
+      Add('  .data :');
       Add('  {');
-      Add('    *(.data .data.* .gnu.linkonce.d.*)');
-      Add('    SORT(CONSTRUCTORS)');
       Add('    KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
       Add('  }');
-      Add('  .data1          : { *(.data1) }');
-      Add('  .xt_except_desc   :');
-      Add('  {');
-      Add('    *(.xt_except_desc .xt_except_desc.* .gnu.linkonce.h.*)');
-      Add('    *(.xt_except_desc_end)');
-      Add('  }');
-      Add('  .lit4           :');
-      Add('  {');
-      Add('    PROVIDE (_lit4_start = .);');
-      Add('    *(.lit4 .lit4.* .gnu.linkonce.lit4.*)');
-      Add('    PROVIDE (_lit4_end = .);');
-      Add('  }');
-      Add('  _edata = .; PROVIDE (edata = .);');
-      Add('  __bss_start = .;');
-      Add('  .bss            :');
-      Add('  {');
-      Add('   *(.dynbss)');
-      Add('   *(.bss .bss.* .gnu.linkonce.b.*)');
-      Add('   *(COMMON)');
-      Add('   /* Align here to ensure that the .bss section occupies space up to');
-      Add('      _end.  Align after .bss to ensure correct alignment even if the');
-      Add('      .bss section disappears because there are no input sections.');
-      Add('      FIXME: Why do we need it? When there is no .bss section, we don''t');
-      Add('      pad the .data section.  */');
-      Add('   . = ALIGN(. != 0 ? 32 / 8 : 1);');
-      Add('  }');
-      Add('  . = ALIGN(32 / 8);');
-      Add('  . = ALIGN(32 / 8);');
-      Add('  _end = .; PROVIDE (end = .);');
-      Add('  /* Stabs debugging sections.  */');
-      Add('  .stab          0 : { *(.stab) }');
-      Add('  .stabstr       0 : { *(.stabstr) }');
-      Add('  .stab.excl     0 : { *(.stab.excl) }');
-      Add('  .stab.exclstr  0 : { *(.stab.exclstr) }');
-      Add('  .stab.index    0 : { *(.stab.index) }');
-      Add('  .stab.indexstr 0 : { *(.stab.indexstr) }');
-      Add('  .comment       0 : { *(.comment) }');
-      Add('  /* DWARF debug sections.');
-      Add('     Symbols in the DWARF debugging sections are relative to the beginning');
-      Add('     of the section so we begin them at 0.  */');
-      Add('  /* DWARF 1 */');
-      Add('  .debug          0 : { *(.debug) }');
-      Add('  .line           0 : { *(.line) }');
-      Add('  /* GNU DWARF 1 extensions */');
-      Add('  .debug_srcinfo  0 : { *(.debug_srcinfo) }');
-      Add('  .debug_sfnames  0 : { *(.debug_sfnames) }');
-      Add('  /* DWARF 1.1 and DWARF 2 */');
-      Add('  .debug_aranges  0 : { *(.debug_aranges) }');
-      Add('  .debug_pubnames 0 : { *(.debug_pubnames) }');
-      Add('  /* DWARF 2 */');
-      Add('  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }');
-      Add('  .debug_abbrev   0 : { *(.debug_abbrev) }');
-      Add('  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }');
-      Add('  .debug_frame    0 : { *(.debug_frame) }');
-      Add('  .debug_str      0 : { *(.debug_str) }');
-      Add('  .debug_loc      0 : { *(.debug_loc) }');
-      Add('  .debug_macinfo  0 : { *(.debug_macinfo) }');
-      Add('  /* SGI/MIPS DWARF 2 extensions */');
-      Add('  .debug_weaknames 0 : { *(.debug_weaknames) }');
-      Add('  .debug_funcnames 0 : { *(.debug_funcnames) }');
-      Add('  .debug_typenames 0 : { *(.debug_typenames) }');
-      Add('  .debug_varnames  0 : { *(.debug_varnames) }');
-      Add('  /* DWARF 3 */');
-      Add('  .debug_pubtypes 0 : { *(.debug_pubtypes) }');
-      Add('  .debug_ranges   0 : { *(.debug_ranges) }');
-      Add('  /* DWARF Extension.  */');
-      Add('  .debug_macro    0 : { *(.debug_macro) }');
-      Add('  .debug_addr     0 : { *(.debug_addr) }');
-      Add('  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }');
-      Add('  .xt.lit       0 : { KEEP (*(.xt.lit .xt.lit.* .gnu.linkonce.p.*)) }');
-      Add('  .xt.insn      0 : { KEEP (*(.xt.insn .gnu.linkonce.x.*)) }');
-      Add('  .xt.prop      0 : { KEEP (*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*)) }');
-      Add('  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink)  *(.gnu.lto_*) }');
       Add('}');
     end;
 {$endif XTENSA}
@@ -1568,21 +1367,174 @@ end;
 
 function TlinkerFreeRTOS.MakeExecutable:boolean;
 var
+  StaticStr,
+  S,
   binstr,
   cmdstr,
-  mapstr: TCmdStr;
+  mapstr: Ansistring;
   success : boolean;
-  StaticStr,
   GCSectionsStr,
   DynLinkStr,
   StripStr,
   FixedExeFileName: string;
+  t: Text;
+  hp: TCmdStrListItem;
+  filepath: TCmdStr;
 begin
   { for future use }
   StaticStr:='';
   StripStr:='';
   mapstr:='';
   DynLinkStr:='';
+
+  Result:=false;
+
+  if target_info.system=system_xtensa_freertos then
+    begin
+      { generate a sdkconfig.h if none is provided,
+        only a few fields are provided to far }
+      if not(Sysutils.FileExists('sdkconfig.h')) then
+        begin
+          Assign(t,'sdkconfig.h');
+          {$push}{$I-}
+          Rewrite(t);
+          if ioresult<>0 then
+            exit;
+          writeln(t,'#pragma once');
+          writeln(t,'#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1');
+          writeln(t,'#define CONFIG_BT_RESERVE_DRAM 0x0');
+          writeln(t,'#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0');
+          writeln(t,'#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0');
+
+          Close(t);
+          if ioresult<>0 then
+            exit;
+          {$pop}
+        end;
+
+      { generate an sdkconfig if none is provided,
+        this is a dummy so far }
+      if not(Sysutils.FileExists('sdkconfig')) then
+        begin
+          Assign(t,'sdkconfig');
+          {$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('kconfigs.in')) then
+        begin
+          Assign(t,'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('kconfigs_projbuild.in')) then
+        begin
+          Assign(t,'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 }
+      if not(Sysutils.FileExists('config.env')) then
+        begin
+          Assign(t,'config.env');
+          {$push}{$I-}
+          Rewrite(t);
+          if ioresult<>0 then
+            exit;
+
+          writeln(t,'{');
+          writeln(t,'    "COMPONENT_KCONFIGS": "",');
+          writeln(t,'    "COMPONENT_KCONFIGS_PROJBUILD": "",');
+          writeln(t,'    "IDF_CMAKE": "y",');
+          writeln(t,'    "IDF_TARGET": "esp32",');
+          writeln(t,'    "IDF_PATH": "'+GetEnvironmentVariable('IDF_PATH')+'",');
+          writeln(t,'    "COMPONENT_KCONFIGS_SOURCE_FILE": "kconfigs.in",');
+          writeln(t,'    "COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE": "kconfigs_projbuild.in"');
+          writeln(t,'}');
+
+          Close(t);
+          if ioresult<>0 then
+            exit;
+          {$pop}
+        end;
+
+      { generate ldgen_libraries }
+      Assign(t,'ldgen_libraries');
+      {$push}{$I-}
+      Rewrite(t);
+      if ioresult<>0 then
+        exit;
+
+      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}
+
+      binstr:='xtensa-esp32-elf-gcc';
+      cmdstr:='-C -P -x c -E -o esp32_out.ld -I . $IDF_PATH/components/esp32/ld/esp32.ld';
+
+      Replace(binstr,'$IDF_PATH',maybequoted(GetEnvironmentVariable('IDF_PATH')));
+      Replace(cmdstr,'$IDF_PATH',maybequoted(GetEnvironmentVariable('IDF_PATH')));
+      success:=DoExec(binstr,cmdstr,true,true);
+
+      { generate linker maps for esp32 }
+      binstr:='$IDF_PATH/tools/ldgen/ldgen.py';
+      cmdstr:='--config sdkconfig --fragments $IDF_PATH/components/xtensa/linker.lf $IDF_PATH/components/soc/linker.lf $IDF_PATH/components/esp_event/linker.lf '+
+        '$IDF_PATH/components/spi_flash/linker.lf $IDF_PATH/components/esp_wifi/linker.lf $IDF_PATH/components/lwip/linker.lf $IDF_PATH/components/log/linker.lf '+
+        '$IDF_PATH/components/heap/linker.lf $IDF_PATH/components/esp_ringbuf/linker.lf $IDF_PATH/components/espcoredump/linker.lf $IDF_PATH/components/esp32/linker.lf '+
+        '$IDF_PATH/components/esp32/ld/esp32_fragments.lf $IDF_PATH/components/freertos/linker.lf $IDF_PATH/components/newlib/newlib.lf '+
+        '$IDF_PATH/components/app_trace/linker.lf $IDF_PATH/components/esp_gdbstub/linker.lf '+
+        '--input $IDF_PATH/components/esp32/ld/esp32.project.ld.in --output ./esp32.project.ld --kconfig $IDF_PATH/Kconfig --env-file config.env '+
+        '--libraries-file ldgen_libraries --objdump xtensa-esp32-elf-objdump';
+      Replace(binstr,'$IDF_PATH',maybequoted(GetEnvironmentVariable('IDF_PATH')));
+      Replace(cmdstr,'$IDF_PATH',maybequoted(GetEnvironmentVariable('IDF_PATH')));
+      if success and not(cs_link_nolink in current_settings.globalswitches) then
+        success:=DoExec(binstr,cmdstr,true,false);
+    end;
+
   FixedExeFileName:=maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.elf')));
 
   GCSectionsStr:='--gc-sections';
@@ -1591,7 +1543,7 @@ begin
    Message1(exec_i_linking,current_module.exefilename);
 
   if (cs_link_map in current_settings.globalswitches) then
-   mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
+    mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
 
 { Write used files and libraries }
   WriteResponseFile();
@@ -1599,6 +1551,8 @@ begin
 { Call linker }
   SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
   Replace(cmdstr,'$OPT',Info.ExtraOptions);
+  if target_info.system=system_xtensa_freertos then
+    Replace(cmdstr,'$IDF_PATH',maybequoted(GetEnvironmentVariable('IDF_PATH')));
   if not(cs_link_on_target in current_settings.globalswitches) then
    begin
     Replace(cmdstr,'$EXE',FixedExeFileName);
@@ -1619,7 +1573,8 @@ begin
     Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
     Replace(cmdstr,'$DYNLINK',DynLinkStr);
    end;
-  success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+  if success and not(cs_link_nolink in current_settings.globalswitches) then
+    success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
 
 { Remove ReponseFile }
   if success and not(cs_link_nolink in current_settings.globalswitches) then
@@ -1629,16 +1584,22 @@ begin
   if success and not(cs_link_nolink in current_settings.globalswitches) then
     success:=PostProcessExecutable(FixedExeFileName,false);
 
-  if success and (target_info.system in [system_arm_embedded,system_avr_embedded,system_mipsel_embedded,system_xtensa_embedded]) then
+  if success and (target_info.system=system_xtensa_freertos) then
     begin
-      success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O ihex '+
+      binstr:='$IDF_PATH/components/esptool_py/esptool/esptool.py';
+      Replace(binstr,'$IDF_PATH',maybequoted(GetEnvironmentVariable('IDF_PATH')));
+      success:=DoExec(binstr,'--chip esp32 elf2image --flash_mode dio --flash_freq 40m '+
+        '--flash_size '+tostr(embedded_controllers[current_settings.controllertype].flashsize div (1024*1024))+'MB '+
+        '--elf-sha256-offset 0xb0 '+
+        '-o '+maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin')))+' '+
+        FixedExeFileName,
+        true,false);
+    end
+  else
+    if success then
+      success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+
         FixedExeFileName+' '+
-        maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.hex'))),true,false);
-      if success then
-        success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+
-          FixedExeFileName+' '+
-          maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin'))),true,false);
-    end;
+        maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin'))),true,false);
 
   MakeExecutable:=success;   { otherwise a recursive call to link method }
 end;