我的stm32上的arm-none-eabi-gcc项目有什么问题?

r7xajy2e  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(204)

我只想通过arm-none-eabi-gcc从头开始处理stm32编程,只通过寄存器工作,而不是驱动程序!因此,非常简单的一段代码将PortC.8设置为1,并打开stm32 f1发现板上的LED。我正在通过以下脚本进行编译:

arm-none-eabi-gcc --specs=nosys.specs -T *.ld -o main.elf main.c system_*.c  *.s

和main.elf文件已成功制作...但不工作!!!和LED是关闭的。
目录中的文件为:

core_cm3.c
core_cm3.h
main.c
main.elf
startup_stm32f100xb.s
STM32F100RBTx_FLASH.ld
stm32f10x.h
system_stm32f10x.c
system_stm32f10x.h

从st官方网站下载STM32F10x_StdPeriph_Lib_V3.5.0文件夹中所有文件
主.c:

#include "stm32f10x.h"
void EnableClock(void);
void InitPort(void);
int main(void)
{
    EnableClock();
    InitPort();

}

void EnableClock(void)
{
    //Enable HSI
    RCC->CR |= (uint32_t)(0x00000001);  
    //APB2 Prescalar to 1(HCLK not devided)
    RCC->CFGR &= (uint32_t)(0xFFFFFF0F);
    //APB2 GPIOC Enable
    RCC->APB2ENR |= (uint32_t)(0x00000010);
}

void InitPort(void)
{
    //PORTC Bit 8 set as output max speed 2MHz GPIOC_CRH->Mode8
    //PORTC Bit 8 set as Push Pull
    GPIOC->CRH &= (uint32_t)(0x00000002);
    GPIOC->ODR |= (uint32_t)(0x00000100);
}

我不知道问题出在哪里......任何人都可以帮助我??

qncylg1j

qncylg1j1#

这里是一个完整的例子,从一个闪烁的pc 13(未测试在pc 8,但在pc 13工作,可以测试它,如果你有问题)
闪存.s

@.cpu cortex-m0
@.cpu cortex-m3
.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.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 notmain
    b hang
.thumb_func
hang:   b .

.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr

.thumb_func
.globl GET32
GET32:
    ldr r0,[r0]
    bx lr

.thumb_func
.globl dummy
dummy:
    bx lr

blinker01.c

void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );

#define GPIOCBASE 0x40011000
#define RCCBASE   0x40021000

int notmain ( void )
{
    unsigned int ra;

    ra=GET32(RCCBASE+0x18);
    ra|=1<<4; //enable port c
    PUT32(RCCBASE+0x18,ra);
    //config
    ra=GET32(GPIOCBASE+0x04);
    ra&=~(0xF<<0);   //PC8
    ra|= (0x1<<0);   //PC8
    PUT32(GPIOCBASE+0x04,ra);
    while(1)
    {
        PUT32(GPIOCBASE+0x10,1<<(8+0));
        for(ra=0;ra<200000;ra++) dummy(ra);
        PUT32(GPIOCBASE+0x10,1<<(8+16));
        for(ra=0;ra<200000;ra++) dummy(ra);
    }
    return(0);
}

flash.ld

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}

生成文件

ARMGNU = arm-none-eabi
#ARMGNU = arm-linux-gnueabi

AOPS = --warn --fatal-warnings -mcpu=cortex-m0
AOPS3 = --warn --fatal-warnings -mcpu=cortex-m3
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0 -march=armv6-m
COPS32 = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m3 -march=armv7-m

all : blinker01.bin

clean:
    rm -f *.bin
    rm -f *.o
    rm -f *.elf
    rm -f *.list

flash.o : flash.s
    $(ARMGNU)-as $(AOPS) flash.s -o flash.o

blinker01.o : blinker01.c
    $(ARMGNU)-gcc $(COPS) -mthumb -c blinker01.c -o blinker01.o

blinker01.bin : flash.ld flash.o blinker01.o
    $(ARMGNU)-ld -o blinker01.elf -T flash.ld flash.o blinker01.o
    $(ARMGNU)-objdump -D blinker01.elf > blinker01.list
    $(ARMGNU)-objcopy blinker01.elf blinker01.bin -O binary

arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0 -march=armv6-m -mthumb -c blinker01.c -o blinker01.o
arm-none-eabi-ld -o blinker01.elf -T flash.ld flash.o blinker01.o
arm-none-eabi-objdump -D blinker01.elf > blinker01.list
arm-none-eabi-objcopy blinker01.elf blinker01.bin -O binary

你不需要弄乱时钟最初它出来的重置使用内部振荡器。所以除非你有自己的固件设置它为其他东西,你不需要设置它为HSI。一个时钟init将需要改变它使用外部时钟和/或使用PLL。

GPIOC->CRH &= (uint32_t)(0x00000002);

这会将寄存器从0x 4444444更改为0x 44444444(对不起,请参阅下面的编辑)。这是另一种说法,说你什么也没做。你想要0x 4444442的2 mhz,如果你想读-修改-写,这是干净的,但不是必需的,因为我们知道上电复位状态,您应该像我上面所做的那样,将值掩码从位读取为零,然后设置您想要的位,或者你也可以直接把0x 4444442或者0x 44444441或者0x 444444443推进去。
如果你做了一个或相等,那么它会产生0x 44444446,这是一个开漏输出。所以如果有一个上拉,那么它会点亮LED,也许,取决于,但是你会想要使用开漏来下沉比下沉更多。led的哪一端是GPIO引脚连接的,你需要源它还是下沉来打开它?您将输出设置为1以将输出设置为高,这在开漏上只是意味着不下沉。虽然对于输入设置,odr将其拉高以进行输入上拉/下拉,但作为一个开漏输出,不确定是否设置odr拉高它。更容易尝试推-先拉,如果你只是想让它打开,那么BSRR可以很容易地设置或重置端口中的单个引脚,而不是用odr触摸整个端口。
开漏模式:输出寄存器中的“0”激活N-MOS,而输出寄存器中的“1”使端口处于Hi-Z状态。(P-MOS永远不会激活)
所以第一步修改你的代码,将端口设置为推挽输出,然后如果你想从头开始,你可以替换你借用的其余代码,并拥有它的所有权。不必使用我使用的put 32/get 32汇编,我有很多理由和大量的经验,但这就是裸机的美妙之处,做你自己的事情,您也可以使用volatile pointer方法,这很可能是您链接的头文件所做的,并简化引导。如果您确保您的入口点函数永远不会退出,并且您既不依赖.data也不依赖.bss,那么您可以将您的引导减少到

.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word main
.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
hang: b hang

或者为其他向量定义一个C函数,或者为未使用的向量定义一个转储区。注意,我没有将所有向量都放在引导程序中,这取决于芯片和内核,但可能是数百个向量(最多128个或256个)
并与堆栈指针初始化值(上例中为0x 20001000)所拥有的RAM量相匹配。
编辑,实际上,对不起,0x 4444444 &= 0x 00000002 = 0x 00000000,它将所有端口设置为模拟输入。您希望它是0x 44444441或0x 444444442或0x 444444443吗

3duebb1j

3duebb1j2#

您的main()终止。接下来发生的事情取决于startup_stm32f100xb.s中__main调用之后的内容;可能是强制复位或无限循环(如果启用,则直到看门狗复位)。
在嵌入式系统中,main()返回是不正常的。
Enable HSI“可能是不必要的,甚至是不正确的。默认情况下,核心时钟是HSI--必须已经为要执行的代码建立了时钟,启用HSI要么没有任何效果,要么禁用以前建立的时钟,系统时钟将在system_stm32f10x. c中设置,如果您有特定的时钟要求,直接使用HSI允许8 MHz工作,将其馈入PLL支持高达64 MHz,当PLL从外部4- 16 MHz振荡器(HSE)馈入时,芯片将以高达72 MHz的频率运行。
如果您没有在system_stm32f10x.c中正确建立时钟(或让其运行HSI-direct),则执行可能在system_stm32f10x.c的SystemInit()中暂停,等待PLL锁定,或者如果您确实错误,则根本不运行。
要在任何裸机处理器上进行板级启动,最好有一个硬件调试器(JTAG/SWI),这样您就可以使用工具链的调试器来确定代码正在执行什么操作以及在哪里出错。您至少可以确定代码是否运行到main()-startup_stm32f100xb.s和system_stm32f10x.c。后者通常需要修改以适合您的目标。

相关问题