xtensa-esp32-elf-ld 使用链接器脚本链接文件时出错

问题描述 投票:0回答:1

我试图通过用 c 编写一个简单的闪烁程序并使用 xtensa 工具编译和链接它来了解 esp32 在低级别的工作原理。但是当我到达链接步骤时,我收到链接错误。

以下是 .c 文件、其标头和使用的链接器脚本:

测试.c:


//esp_rom_gpio_connect_out_signal and GPIO are defined in script.ld file

#include "gpio_struct.h"
#include<stdbool.h>

void esp_rom_gpio_connect_out_signal(uint32_t gpio_num, uint32_t signal_idx, bool out_inv, bool oen_inv);

int main(void){
    esp_rom_gpio_connect_out_signal(2, 256, false, false);

    while(1){
        GPIO.out_w1ts = (1 << 2);
        for(int i = 0; i < 100000; i++);
        GPIO.out_w1tc = (1 << 2);
        for(int i = 0; i < 100000; i++);
    }
}

gpio_struct.h:

#include <stdint.h>

typedef volatile struct gpio_dev_s {
    uint32_t bt_select;                             /*NA*/
    uint32_t out;                                   /*GPIO0~31 output value*/
    uint32_t out_w1ts;                              /*GPIO0~31 output value write 1 to set*/
    uint32_t out_w1tc;                              /*GPIO0~31 output value write 1 to clear*/
    union {
        struct {
            uint32_t data:       8;                 /*GPIO32~39 output value*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } out1;
    union {
        struct {
            uint32_t data:       8;                 /*GPIO32~39 output value write 1 to set*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } out1_w1ts;
    union {
        struct {
            uint32_t data:       8;                 /*GPIO32~39 output value write 1 to clear*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } out1_w1tc;
    union {
        struct {
            uint32_t sel:        8;                 /*SDIO PADS on/off control from outside*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } sdio_select;
    uint32_t enable;                                /*GPIO0~31 output enable*/
    uint32_t enable_w1ts;                           /*GPIO0~31 output enable write 1 to set*/
    uint32_t enable_w1tc;                           /*GPIO0~31 output enable write 1 to clear*/
    union {
        struct {
            uint32_t data:        8;                /*GPIO32~39 output enable*/
            uint32_t reserved8:  24;
        };
        uint32_t val;
    } enable1;
    union {
        struct {
            uint32_t data:        8;                /*GPIO32~39 output enable write 1 to set*/
            uint32_t reserved8:  24;
        };
        uint32_t val;
    } enable1_w1ts;
    union {
        struct {
            uint32_t data:        8;                /*GPIO32~39 output enable write 1 to clear*/
            uint32_t reserved8:  24;
        };
        uint32_t val;
    } enable1_w1tc;
    union {
        struct {
            uint32_t strapping: 16;
            uint32_t reserved16:16;
        };
        uint32_t val;
    } strap;
    uint32_t in;                                    /*GPIO0~31 input value*/
    union {
        struct {
            uint32_t data:       8;                 /*GPIO32~39 input value*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } in1;
    uint32_t status;                                /*GPIO0~31 interrupt status*/
    uint32_t status_w1ts;                           /*GPIO0~31 interrupt status write 1 to set*/
    uint32_t status_w1tc;                           /*GPIO0~31 interrupt status write 1 to clear*/
    union {
        struct {
            uint32_t intr_st:    8;                 /*GPIO32~39 interrupt status*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } status1;
    union {
        struct {
            uint32_t intr_st:    8;                 /*GPIO32~39 interrupt status write 1 to set*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } status1_w1ts;
    union {
        struct {
            uint32_t intr_st:    8;                 /*GPIO32~39 interrupt status write 1 to clear*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } status1_w1tc;
    uint32_t reserved_5c;
    uint32_t acpu_int;                              /*GPIO0~31 APP CPU interrupt status*/
    uint32_t acpu_nmi_int;                          /*GPIO0~31 APP CPU non-maskable interrupt status*/
    uint32_t pcpu_int;                              /*GPIO0~31 PRO CPU interrupt status*/
    uint32_t pcpu_nmi_int;                          /*GPIO0~31 PRO CPU non-maskable interrupt status*/
    uint32_t cpusdio_int;                           /*SDIO's extent GPIO0~31 interrupt*/
    union {
        struct {
            uint32_t intr:       8;                 /*GPIO32~39 APP CPU interrupt status*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } acpu_int1;
    union {
        struct {
            uint32_t intr:       8;                 /*GPIO32~39 APP CPU non-maskable interrupt status*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } acpu_nmi_int1;
    union {
        struct {
            uint32_t intr:       8;                 /*GPIO32~39 PRO CPU interrupt status*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } pcpu_int1;
    union {
        struct {
            uint32_t intr:       8;                 /*GPIO32~39 PRO CPU non-maskable interrupt status*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } pcpu_nmi_int1;
    union {
        struct {
            uint32_t intr:       8;                 /*SDIO's extent GPIO32~39 interrupt*/
            uint32_t reserved8: 24;
        };
        uint32_t val;
    } cpusdio_int1;
    union {
        struct {
            uint32_t reserved0:     2;
            uint32_t pad_driver:    1;              /*if set to 0: normal output  if set to 1: open drain*/
            uint32_t reserved3:     4;
            uint32_t int_type:      3;              /*if set to 0: GPIO interrupt disable  if set to 1: rising edge trigger  if set to 2: falling edge trigger  if set to 3: any edge trigger  if set to 4: low level trigger  if set to 5: high level trigger*/
            uint32_t wakeup_enable: 1;              /*GPIO wake up enable  only available in light sleep*/
            uint32_t config:        2;              /*NA*/
            uint32_t int_ena:       5;              /*bit0: APP CPU interrupt enable  bit1: APP CPU non-maskable interrupt enable  bit3: PRO CPU interrupt enable  bit4:  PRO CPU non-maskable interrupt enable  bit5: SDIO's extent interrupt enable*/
            uint32_t reserved18:   14;
        };
        uint32_t val;
    } pin[40];
    union {
        struct {
            uint32_t rtc_max:     10;
            uint32_t reserved10:  21;
            uint32_t start:        1;
        };
        uint32_t val;
    } cali_conf;
    union {
        struct {
            uint32_t value_sync2: 20;
            uint32_t reserved20:  10;
            uint32_t rdy_real:     1;
            uint32_t rdy_sync2:    1;
        };
        uint32_t val;
    } cali_data;
    union {
        struct {
            uint32_t func_sel:    6;                /*select one of the 256 inputs*/
            uint32_t sig_in_inv:  1;                /*revert the value of the input if you want to revert  please set the value to 1*/
            uint32_t sig_in_sel:  1;                /*if the slow signal bypass the io matrix or not if you want  setting the value to 1*/
            uint32_t reserved8:  24;                /*The 256 registers below are selection control for 256 input signals connected to GPIO matrix's 40 GPIO input  if GPIO_FUNCx_IN_SEL is set to n(0<=n<40): it means GPIOn input is used for input signal x  if GPIO_FUNCx_IN_SEL is set to 0x38: the input signal x is set to 1   if GPIO_FUNCx_IN_SEL is set to 0x30: the input signal x is set to 0*/
        };
        uint32_t val;
    } func_in_sel_cfg[256];
    union {
        struct {
            uint32_t func_sel:     9;               /*select one of the 256 output to 40 GPIO*/
            uint32_t inv_sel:      1;               /*invert the output value  if you want to revert the output value  setting the value to 1*/
            uint32_t oen_sel:      1;               /*weather using the logical oen signal or not using the value setting by the register*/
            uint32_t oen_inv_sel:  1;               /*invert the output enable value  if you want to revert the output enable value  setting the value to 1*/
            uint32_t reserved12:  20;               /*The 40 registers below are selection control for 40 GPIO output  if GPIO_FUNCx_OUT_SEL is set to n(0<=n<256): it means GPIOn input is used for output signal x  if GPIO_FUNCx_OUT_INV_SEL is set to 1  the output signal x is set to ~value.  if GPIO_FUNC0_OUT_SEL is 256 or GPIO_FUNC0_OEN_SEL is 1 using GPIO_ENABLE_DATA[x] for the enable value else using the signal enable*/
        };
        uint32_t val;
    } func_out_sel_cfg[40];
} gpio_dev_t;


extern gpio_dev_t GPIO;

脚本.ld:

PROVIDE ( GPIO = 0x3ff44000 );
PROVIDE ( esp_rom_gpio_connect_out_signal = 0x40009f0c );

然后我用

xtensa-esp32-elf-gcc
xtensa-esp32-elf-ld
编译并链接 test.c:

xtensa-esp32-elf-gcc.exe -c test.c
xtensa-esp32-elf-ld.exe -T script.ld test.o

但是执行

xtensa-esp32-elf-ld
时出现以下错误:

test.o: in function `main':
test.c:(.text+0xe): dangerous relocation: call8: call target out of range: esp_rom_gpio_connect_out_signal

我尝试过函数指针以及

--no-relax
--relax
上的
xtensa-esp32-elf-ld
选项,但没有任何效果。 在
--verbose
上使用
xtensa-esp32-elf-ld
不会提供有用的信息:

GNU ld (crosstool-NG esp-2022r1) 2.35.1.20201223
  Supported emulations:
   elf32xtensa
opened script file script.ld
using external linker script:
==================================================
PROVIDE ( GPIO = 0x3ff44000 );
PROVIDE ( esp_rom_gpio_connect_out_signal = 0x40009f0c );
==================================================
xtensa-esp32-elf\bin\xtensa-esp32-elf-ld.exe: mode elf32xtensa
attempt to open test.o succeeded
test.o
test.o: in function `main':
test.c:(.text+0xe): dangerous relocation: call8: call target out of range: esp_rom_gpio_connect_out_signal
xtensa-esp32-elf-ld.exe: link errors found, deleting executable `a.out'

感谢任何形式的帮助

编辑:

感谢jcmvbkbc的回答!

使用后

-mlongcalls
我收到了新的错误

test.c:(.text+0xe): dangerous relocation: windowed longcall crosses 1GB boundary; return may fail: esp_rom_gpio_connect_out_signal
collect2.exe: error: ld returned 1 exit status

经过快速搜索后,我尝试使用

-mabi=call0
选项(如这篇文章中建议的那样),但编译器似乎不支持它:

 warning: incompatible Xtensa configuration (ABI does not match)
gcc ld esp32 xtensa
1个回答
0
投票

你还在挖掘这个吗?

ESP32 有 MMU。您需要知道代码将被加载的确切地址。在链接器脚本的开头,我添加了以下内容:

MEMORY {
    FLASH_BL (rx)  : ORIGIN = 0x400f0000, LENGTH = 1024
}
© www.soinside.com 2019 - 2024. All rights reserved.