函数调用不适用于带有 gnu 工具链的 cortex m0 的裸机 c 代码

我正在基于 arm cortex m0 设计开始构建自定义 SOC。 SOC 现在有一个 cortex mo 核心连接到 AHB lite 总线,上面有一些 ram 和一个 gpio 模块。我目前正在努力使用 gnu 工具链为其编写和编译代码。函数调用不起作用。我尝试了很多东西,但似乎没有任何效果。有趣的是,如果我用 keil 编译相同的代码,它就可以工作。我想问题出在我如何设置堆栈和/或 Liker 脚本的某个地方,或者我缺少一些编译器/链接器选项。

这有效

#include<stdint.h>

volatile uint8_t* led_reg;

int main() {
   led_reg=(uint8_t*)0x50000000;
    while (1) {
        *led_reg=0x8;
        for(int i=0;i<=0x2FFFFF;i++);
        *led_reg=0x4;
        for(int i=0;i<=0x2FFFFF;i++);
        *led_reg=0x2;
        for(int i=0;i<=0x2FFFFF;i++);
        *led_reg=0x1;
        for(int i=0;i<=0x2FFFFF;i++);
    }
 }

但这没有

#include<stdint.h>

volatile uint8_t* led_reg;

void wait(void){
    for(int i=0;i<=0x2FFFFF;i++);

}

void on(uint8_t pat){
    *led_reg=pat;
}

int main() {
    led_reg=(uint8_t*)0x50000000;
    while (1){
        on(0x8);
        wait();
        on(0x4);
        wait();
        on(0x2);
        wait();
        on(0x1);
        wait();
    }
}

这是链接器脚本

ENTRY(Reset_Handler)

STACK_SIZE = 0x1000;

SECTIONS
{
  . = 0x00000000;

  .ram :
    {
        . = ALIGN(4);
        _stext = .;
        KEEP(*(.vectors .vectors.*))
        *(.text .text.*)
        *(.rodata .rodata*)
    
        . = ALIGN(4);
         _sbss = . ;
        *(.bss .bss.*)
        *(COMMON)
        . = ALIGN(4);
        _ebss = . ;

        . = ALIGN(4);
        _sdata = .;
        *(.data .data.*);
        . = ALIGN(4);
        _edata = .;

        . = ALIGN(8);
        _sstack = .;
        . = . + STACK_SIZE;
        . = ALIGN(8);
        _estack = .;
        . = ALIGN(4);
        _end = . ;
    }

}

启动代码的相关部分

/* Exception Table */
__attribute__ ((section(".vectors")))
const DeviceVectors exception_table = {

        /* Configure Initial Stack Pointer,using linker-generated symbols */
        .pvStack                = (void*) (&_estack),.pfnReset_Handler       = (void*) Reset_Handler,.pfnnmI_Handler         = (void*) nmI_Handler,.pfnHardFault_Handler   = (void*) HardFault_Handler,

这里是编译和链接命令示例

arm-none-eabi-gcc -Wall -Werror -g -O0 -std=c99 -ffreestanding -ffunction-sections -fdata-sections  -mcpu=cortex-m0 -mfloat-abi=soft -march=armv6-m   -mthumb  -Wall -Iinclude/headers   -o build/main.o -c src/main.c
arm-none-eabi-gcc -Wall -Werror -g -O0 -std=c99 -ffreestanding -ffunction-sections -fdata-sections  -mcpu=cortex-m0 -mfloat-abi=soft -march=armv6-m   -mthumb  -Wall -Iinclude/headers   -Wl,-Map=build/firmware.map,--gc-sections -T vcoresoc.lds --specs=nano.specs build/main.o build/startup_vcoresoc.o build/syscall.o -o build/firmware.elf 
uhkul 回答:函数调用不适用于带有 gnu 工具链的 cortex m0 的裸机 c 代码

您在此代码中有几个较小的错误。 gcc 可能比 Keil 更好地优化代码,因此可以简单地删除该功能。在某些情况下,您缺少可能会破坏代码的 volatile

另外,我不知道是你写的启动代码还是工具供应商写的,但它有错误。即 .pvStack = (void*) (&_estack) 调用未定义的行为,因为 C 不允许从函数指针到对象指针的转换。您需要使用无符号整数或函数指针类型而不是 void*。正如评论中提到的,在 Cortex M 向量表上放置一些对齐关键字是可疑的 - 它应该在地址 0 处,所以它怎么会错位?看看 DeviceVectors 的定义会很有趣。

此外,裸机微控制器系统不会从 main() 返回。您不应该使用 int main(),因为这可能会导致一些不必要的堆栈开销。使用实现定义的形式,例如 void main (void),然后为嵌入式(“独立”)系统编译。使用 -ffreestanding 的 gcc。

本文链接:https://www.f2er.com/2179.html

大家都在问