Gcc 从头开始创建cortex-m7项目从哪里开始

Gcc 从头开始创建cortex-m7项目从哪里开始,gcc,arm,cortex-m,Gcc,Arm,Cortex M,我想创建自己的启动、链接器脚本和初始化文件,配置makefile和gcc工具链。我在哪里可以找到关于它的资源、教程等?可能是一些最小的示例实现?接近最小引导,当然可以更小 闪光 .thumb .thumb_func .global _start _start: stacktop: .word 0x20001000 .word reset .word hangout .word hangout .word hangout .thumb_func reset: bl notmain

我想创建自己的启动、链接器脚本和初始化文件,配置makefile和gcc工具链。我在哪里可以找到关于它的资源、教程等?可能是一些最小的示例实现?

接近最小引导,当然可以更小

闪光

.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hangout
.word hangout
.word hangout

.thumb_func
reset:
    bl notmain
    b hangout

.thumb_func
hangout:   b .

.align

.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
阅读arm文档,异常和重置表并没有做得那么好,但仍然显示堆栈指针init值是第一位的,重置向量是第二位的,对于内部内核异常,依此类推,然后进入中断,部分内核定义了中断,芯片供应商定义了中断的数量,16、32、64,128,更少或更多

演示C入口点和asm调用的示例程序

诺曼

void PUT32 ( unsigned int, unsigned int );
void notmain ( void )
{
    unsigned int ra;
    for(ra=0;;ra++) PUT32(0x20000100,ra);
}
#define SOME_RAM (*((volatile unsigned int *)0x20000100))
void notmain ( void )
{
    unsigned int ra;
    for(ra=0;;ra++) SOME_RAM=ra;
}
void hangout ( void )
{
    while(1) continue;
}
不是很小的链接器脚本,但已关闭

flash.ld

MEMORY
{
    rom : ORIGIN = 0x00000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}
从技术上讲,向量表重置为0x00000000(VTOR),但一些芯片供应商在启动闪存时将应用程序闪存映射到另一个地址以及零,因此STM32家族树通常为0x08000000,其他一些0x01000000我想可能是0x10000000,不管怎样,但他们需要映射到零进行重置(如果此代码在重置中确实被调用,并且没有引导加载程序伪造重置)。因此,您可以将0x00000000保留为rom或尝试更改它

例如,将堆栈指针和内存大小设置为较小。对于cortex-m7,这些数字应该适用于cortex-m0,也许其他一些数字实际上可能太大而失败

所有cortex ms所有cortex到64位的指令集都支持armv4t的原始thumb指令,您无需冒险通过这些指令就可以获得一个最小的起点,将骨架代码放在您的后袋中并在以后选择内核也不错。基本上,不要借用cortex-m7代码,而构建cortex-m0 w如果不支持同一组thumb2扩展,则可能无法工作

构建(对于cortex-m0,现在支持armv6-m,支持原装thumb和几十个Thumb2)

并非所有的命令行选项都是必需的,这取决于您的项目、gnu的版本等。编写此代码的目的是为了让arm无论如何都可以使用arm linux gnueabi等

为了正确引导,向量表需要预先准备好并正确形成。 在编程到新部件的闪存之前检查是件好事,不要在得到它之后就想用砖块来填充它

Disassembly of section .text:

00000000 <_start>:
   0:   20001000    andcs   r1, r0, r0
   4:   00000015    andeq   r0, r0, r5, lsl r0
   8:   0000001b    andeq   r0, r0, r11, lsl r0
   c:   0000001b    andeq   r0, r0, r11, lsl r0
  10:   0000001b    andeq   r0, r0, r11, lsl r0

00000014 <reset>:
  14:   f000 f808   bl  28 <notmain>
  18:   e7ff        b.n 1a <hangout>

0000001a <hangout>:
  1a:   e7fe        b.n 1a <hangout>
把它改成cortex-m7…在这个项目中,我没有任何东西可以让thumb2指令做得更好

cortex-m架构设计的一个优点

这就是桌子

.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word notmain
.word hangout
.word hangout
.word hangout
诺曼

void PUT32 ( unsigned int, unsigned int );
void notmain ( void )
{
    unsigned int ra;
    for(ra=0;;ra++) PUT32(0x20000100,ra);
}
#define SOME_RAM (*((volatile unsigned int *)0x20000100))
void notmain ( void )
{
    unsigned int ra;
    for(ra=0;;ra++) SOME_RAM=ra;
}
void hangout ( void )
{
    while(1) continue;
}
建造

节的反汇编。文本:
00000000 :
0:20001000和CS r1、r0、r0
4:00000015安第克r0,r0,r5,lsl r0
8:00000025安第克r0,r0,r5,lsr#32
c:00000025安第克r0,r0,r5,lsr#32
10:00000025安第克r0,r0,r5,lsr#32
00000014 :
14:2300 movs r3#0
16:4a02 ldr r2[pc,#8];(20)
18:6013 str r3[r2,#0]
1a:3301加上r3,#1
1c:e7fc b.n 18
1e:bf00 nop
20:20000100和CS r0、r0、r0、lsl#2
00000024 :
24:e7fe b.n 24
26:bf00无
逻辑本身符合ARMs调用约定,因此如果编译器也这样做,并且您不想包装重置处理程序,则不需要这样做

在我的项目中,我从不需要归零.bss或init.data,但很多人都这样做,这使得链接器脚本更复杂,不需要像大多数人那样疯狂。还有一点汇编来做.bss的归零和.data的副本

用于特定cortex-m7微控制器的工作led闪烁器

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

#define RCCBASE 0x40023800
#define RCC_AHB1ENR   (RCCBASE+0x30)
#define RCC_AHB1LPENR (RCCBASE+0x50)

#define GPIOABASE 0x40020000
#define GPIOA_MODER     (GPIOABASE+0x00)
#define GPIOA_OTYPER    (GPIOABASE+0x04)
#define GPIOA_BSRR      (GPIOABASE+0x18)

#define GPIOBBASE 0x40020400
#define GPIOB_MODER     (GPIOBBASE+0x00)
#define GPIOB_OTYPER    (GPIOBBASE+0x04)
#define GPIOB_BSRR      (GPIOBBASE+0x18)

//PA5 or PB0 defaults to PB0
//PB7
//PB14

int notmain ( void )
{
    unsigned int ra;
    unsigned int rx;

    ra=GET32(RCC_AHB1ENR);
    ra|=1<<1; //enable GPIOB
    PUT32(RCC_AHB1ENR,ra);

    ra=GET32(GPIOB_MODER);
    ra&=~(3<<(0<<1)); //PB0
    ra|= (1<<(0<<1)); //PB0
    ra&=~(3<<(7<<1)); //PB7
    ra|= (1<<(7<<1)); //PB7
    ra&=~(3<<(14<<1)); //PB14
    ra|= (1<<(14<<1)); //PB14
    PUT32(GPIOB_MODER,ra);
    //OTYPER
    ra=GET32(GPIOB_OTYPER);
    ra&=~(1<<0); //PB0
    ra&=~(1<<7); //PB7
    ra&=~(1<<14); //PB14
    PUT32(GPIOB_OTYPER,ra);

    for(rx=0;;rx++)
    {
        PUT32(GPIOB_BSRR,((1<<0)<<0)|((1<<7)<<16)|((1<<14)<<0));
        for(ra=0;ra<200000;ra++) dummy(ra);
        PUT32(GPIOB_BSRR,((1<<0)<<16)|((1<<7)<<0)|((1<<14)<<16));
        for(ra=0;ra<200000;ra++) dummy(ra);
    }
    return(0);
}
void PUT32(无符号整数,无符号整数);
unsigned int GET32(unsigned int);
无效虚拟(无符号整数);
#定义RCCBASE 0x40023800
#定义RCC_AHB1ENR(RCCBASE+0x30)
#定义RCC_AHB1LPENR(RCCBASE+0x50)
#定义GPIOABASE 0x40020000
#定义GPIOA_MODER(GPIOABASE+0x00)
#定义GPIOA_OTYPER(GPIOABASE+0x04)
#定义GPIOA_BSRR(GPIOABASE+0x18)
#定义GPIOBBASE 0x40020400
#定义GPIOB_MODER(GPIOBBASE+0x00)
#定义GPIOB_类型(GPIOBBASE+0x04)
#定义GPIOB_BSRR(GPIOBBASE+0x18)
//PA5或PB0默认为PB0
//PB7
//PB14
int notmain(无效)
{
无符号整数ra;
无符号整数rx;
ra=GET32(RCC_AHB1ENR);

ra |=1接近最小自举,当然可以更小

闪光

.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hangout
.word hangout
.word hangout

.thumb_func
reset:
    bl notmain
    b hangout

.thumb_func
hangout:   b .

.align

.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
阅读arm文档,异常和重置表并没有做得那么好,但仍然显示堆栈指针init值是第一位的,重置向量是第二位的,对于内部内核异常,依此类推,然后进入中断,部分内核定义了中断,芯片供应商定义了中断的数量,16、32、64,128,更少或更多

演示C入口点和asm调用的示例程序

诺曼

void PUT32 ( unsigned int, unsigned int );
void notmain ( void )
{
    unsigned int ra;
    for(ra=0;;ra++) PUT32(0x20000100,ra);
}
#define SOME_RAM (*((volatile unsigned int *)0x20000100))
void notmain ( void )
{
    unsigned int ra;
    for(ra=0;;ra++) SOME_RAM=ra;
}
void hangout ( void )
{
    while(1) continue;
}
不是很小的链接器脚本,但已关闭

flash.ld

MEMORY
{
    rom : ORIGIN = 0x00000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}
从技术上讲,向量表重置为0x00000000(VTOR),但一些芯片供应商在启动闪存时将应用程序闪存映射到另一个地址以及零,因此STM32家族树通常为0x08000000,其他一些0x01000000我想可能是0x10000000,不管怎样,但他们需要映射到零进行重置(如果此代码在重置中确实被调用,并且没有引导加载程序伪造重置)。因此,您可以将0x00000000保留为rom或尝试更改它

例如,将堆栈指针和内存大小设置为较小。对于cortex-m7,这些数字应该适用于cortex-m0,也许其他一些数字实际上可能太大而失败

所有cortex ms所有内核到64位指令集都支持armv4t的原始thumb指令,您无需冒险通过这些指令就可以获得一个最小的起点,将骨架代码放在您的后袋中并选择