1

stm32f334 (LED 点滅のみ) の例をいくつか作成しようとしています。(初期化されたグローバル変数を使用して) .data セクションを使用して制約したい場合、リンカーに問題がありました。問題が発生しました。グローバル変数の値が正しくありません!

これは私のコードです:

startup.s:

    .global _start
    .thumb_func
    _start:
    .word 0x20003000
    .word reset
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang

    .thumb_func
    reset:
        bl main
        b hang
    .thumb_func
    hang:   b .

blink.c:

    #define RCCBASE 0x40021000
    #define GPIOBBASE 0x48000400

    static int wymuszenie_bss;
    int wymuszenie_data = GPIOBBASE;

    int main ( void )
    {
        unsigned int* ptr;

        wymuszenie_bss = 0x40021000;

        ptr = (unsigned int*)(wymuszenie_bss+0x14);
        *ptr |= 1<<18; //enable port B;
        //moder
        ptr = (unsigned int*)(wymuszenie_data+0x00);
        *ptr &= ~(3<<24); //PB12
        *ptr |= 1<<24; //PB12
        //OTYPER
        ptr = (unsigned int*)(wymuszenie_data+0x04);
        *ptr &= ~(1<<6); //PB12
        //ospeedr
        ptr = (unsigned int*)(GPIOBBASE+0x08);
        *ptr |= ~(3<<24); //PB12
        //pupdr
        ptr = (unsigned int*)(GPIOBBASE+0x0C);
        *ptr &= ~(3<<24); //PB12

        while(1)
        {
            ptr = (unsigned int*)(GPIOBBASE+0x18);
            *ptr = (1<<12)<<0;
            for(int ra=0;ra<400000;ra++) asm("NOP");;
            ptr = (unsigned int*)(GPIOBBASE+0x18);
            *ptr = (1<<12)<<16;
            for(int ra=0;ra<400000;ra++) asm("NOP");;
        }
        return(0);
    }

リンカー スクリプト:

    MEMORY
    {
        flash : ORIGIN = 0x08000000, LENGTH = 0x1000
        SRAM  : ORIGIN = 0x20000000, LENGTH = 12K
    }

    SECTIONS
    {
        .text : 
        {
            __text_start__ = .;
            *(.text) 
            startup.o (.text);
            blink.o (.text);
            __text_end__ = .;
        } > flash

        .data :
        {
            __data_start__ = .;
            KEEP (*(.data))
            KEEP (*(.data*))
            __data_end__ = .;
        } > SRAM AT > flash 

        .bss : 
        {
             __bss_start__ = .;
            *(.bss)
            __bss_end__ = .;
        } > SRAM
    }

makefile:

    ARMGNU = arm-none-eabi

    gcc : blink.bin 

    all : gcc

    clean:
        rm -f *.bin
        rm -f *.o
        rm -f *.elf
        rm -f *.list
        rm -f *.bc
        rm -f *.opt.s
        rm -f *.norm.s
        rm -f *.nm

    startup.o : startup.s
        $(ARMGNU)-as --warn --fatal-warnings -mcpu=cortex-m4 startup.s -o startup.o

    blink.o : blink.c
        $(ARMGNU)-gcc -Wall -Wint-to-pointer-cast -g -c -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -c blink.c -o blink.o

    blink.bin : startup.o blink.o
        $(ARMGNU)-ld -o blink.elf -T startup.ld startup.o blink.o
        $(ARMGNU)-objdump -D blink.elf > blink.list
        $(ARMGNU)-nm blink.elf > blink.nm
        $(ARMGNU)-objcopy blink.elf blink.bin -O binary

.list に正しい値とアドレスが表示されます。

Disassembly of section .data:

20000000 <wymuszenie_data>:
20000000:   48000400    stmdami r0, {sl}

Disassembly of section .bss:

20000004 <__bss_start__>:
20000004:   00000000    andeq   r0, r0, r0

しかし、変数 "wymuszenie_data" のコード値をデバッグすると、破損しています (0x2e006816)。

グローバル変数の値が間違っている理由が本当にわかりません。

よろしく、 マルシン

4

1 に答える 1

6

この行

} > SRAM AT > flash

前のブロックのセクションを RAM に配置されているかのようにリンクする必要があることをリンカに伝えますが、実際にはフラッシュ内の別のアドレスに配置されます。コードは RAM 内のデータを探しますが、まだそこにはありません。を呼び出す前に、コピーするように手配する必要がありますmain()。ベア メタル組み込みプラットフォームであるため、このタスクを実行するためのオペレーティング システム ローダーはありません。

まず、リンカ スクリプトで宛先アドレスを使用してシンボルを作成します。

__data_destination__ = LOADADDR(.data);

次に、 を呼び出す前にからに(&__data_end__ - &__data_start__)バイトをコピーします。&__data_start__&__data_destination__main()

次の驚きを避けるために、クリアする必要があります.bss。つまり、ゼロで埋めます。

C ライブラリとリンクしている場合は、 と を使用できますmemcpy()memset()それ以外の場合は、C またはアセンブリで独自のコードを記述する必要があります。

于 2018-11-12T15:47:42.087 に答える