U-Boot-C语言环境初始化

Posted _WILLPOWER_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了U-Boot-C语言环境初始化相关的知识,希望对你有一定的参考价值。

  • 概念解析
    • 空/满栈
    • 升/降栈
    • 栈帧
  • 栈作用
    • 保存局部变量
    • 参数传递
    • 保存寄存器值
  • 栈初始化编程

栈初始化

栈是一种具有后进先出性质的数据组织方式,也就是说后存放的先取出,先存放的后取出。栈底是第一个进栈的数据所处的位置,栈顶是最后一个进栈的数据所处的位置。

满/空栈

根据SP指针指向的位置,栈.可以分为满栈空栈

  1. 满栈:当堆栈指针SP总是指向最后压入堆栈的数据
  2. 空栈:当堆栈指针SP总是指向下一个将要放入数据的空位置

ARM采用满栈!

生/降栈

根据P指针移动的方向,栈可以分为升栈降栈

  1. 升栈:随着数据的入栈,SP指针从低地址->高地址移动
  2. 降栈:随着数据的入栈,SP指针从高地址->低地址移动

ARM采用降栈!

栈帧

简单的讲,栈帧(stack frame)就是一个函数所使用的那部分栈,所有函数的栈帧串起来就组成了一个完整的栈。栈帧的两个边界分别由 fp(r11)sp(r13) 来限定。

栈作用

保存局部变量

传递参数

C语言传递参数,如果参数小于等于4个的时候,用r0-r3来传递1-4个参数,大于4个的参数,用栈来保存。

保存寄存器的值

栈初始化编程

给64M(210的内存是从0x20000000开始的)

init_stack:
    ldr sp, =0x24000000
    mov pc, lr

初始化BSS段

Block Started bySymbol”的缩写,意为“以符号开始的块”
初始化的全局:数据段
局部变量:栈
malloc:堆
未初始化全局:BSS段
为什么要初始化

为了防止未初始化的全局变量在使用的时候,拿到了其不确定的值来使用,因此提前清零。

如何清零

只要我们找到bss段的起始地址,结束地址,然后清零即可。

clean_bss:
    ldr r0, =bss_start
    ldr r1, =bss_end
    cmp r0, r1
    moveq pc, lr
clean_loop:
    mov r2, #0
    str r2, [r0], #4
    cmp r0, r1
    bne clean_loop    
    mov pc, lr

进入C语言

采用绝对跳转

注意,在ldr跳转后,直接就到内存的地址去运行命令去了

//@宏定义控制与数据寄存器
#define GPCCON (volatile unsigned long *)0xE0200060
#define GPCDAT (volatile unsigned long *)0xE0200064
int gboot_main()
{
    *GPCCON = 0x11000;
    *GPCDAT = 0x18;
    return 0;
}

注意210中有加头操作,因此在复制代码到dram中的时候,需要跳过头!

这个头是16字节,因此不再是用0xd0020000而是0xd0020010


注意指定的地址如果4字节对齐,那么起始地址不能0x20000000,至少为0x20000004,反正用0x20000000有问题

C与汇编混合编程

汇编语言
执行效率高;编写繁琐,能够更直接地控制处理器
C语言
可读性强,移植性好,调试方便

  • 汇编调用C函数
  • C调用汇编函数
  • C内嵌汇编
    • 格式
    • 范例
    • 优化

汇编调用C函数


C调用汇编函数


C内嵌汇编

格式

_asm_(
汇编语句部分
:输出部分(修改C语言的参数)
:输入部分(拿C语言中的参数)
:破坏描述部分
);
C内嵌汇编以关键字"_asm_“或"asm"开始,下面4个部分,各部分使用”:"分开,第一部分是必须写的,后面三部分是可以省略的,但是分号:不能省略

范例

void write_p15_c1(unsigned long value)
{
    __asm__(
        "mcr p15, 0, %0, c1, c0, 0\\n"
        :
        : "r"(value) @编译器选择一个R * 寄存器);
}

r表示通用寄存器,这里面的值从value参数而来

案例2

unsigned long read_p15_c1(void)
{
    unsigned long value;
    __asm__(
        "mrc p15, 0, %0, c1, c0, 0\\n"
        : "=r"(value) @‘=’表示只写操作数,用于输出部
        :
        : "memory");
    return value;
}

memory表示内存的意思,表示value的值被修改了

优化

unsigned long old;
unsigned long temp;
__asm__ volatile(
    "mrs %0, cpsr \\n"
    "orr %1, %0, #128 \\n"
    "msr cpsr_c, %1\\n"
    : "=r"(old), "=r"(temp)
    :
    : "memory");

使用volatile来告诉编译器,不要对接下来的这部分代码进行优化。
如果在操作硬件的收,比如你代码如p1=0x01;然后又写p1=0x10;那么编译器可能认为你前一句是多余的,将前一句给删除.

使用内嵌汇编点亮LED

//@宏定义控制与数据寄存器
#define GPCCON (volatile unsigned long *)0xE0200060
#define GPCDAT (volatile unsigned long *)0xE0200064
int gboot_main()
{
    // *GPCCON = 0x11000;
    // *GPCDAT = 0x18;
    // light_led();
    __asm__(
        "ldr r1, =0x11000\\n"
        "str r1, [%0]\\n"
        "ldr r1, =0x18\\n"
        "str r1, [%1]\\n"
        :
        : "r"(GPCCON), "r"(GPCDAT)
        : "r1");
    return 0;
}

破坏部(修改了r1)因此还是需要写的

以上是关于U-Boot-C语言环境初始化的主要内容,如果未能解决你的问题,请参考以下文章

环境初始化 Build and Install the Apache Thrift IDL Compiler Install the Platform Development Tools(代码片段

如何使用 Swift 使用此代码片段为 iOS 应用程序初始化 SDK?

更改语言环境后未调用 onConfigurationChange

jodatime DateTime 对象和语言环境

vscode 开发微信小程序环境配置

C 语言:使用计算初始化浮点变量