Linux裸机开发1——点亮第一个LED
声明:以下知识与图片全部来自韦东山裸机开发视频
一、NOR启动与NAND启动
1、2440系统结构图
以SC2440为例,以下是2440的系统结构图
程序可以烧录在NOR Flash 与 Nand Flash里面
2、两种启动方式的特性
二、汇编操作
1、常用汇编指令
//读内存指令 LDR
ldr r0, =0x100 ;伪指令,表示将0x100赋给r0、
ldr r0,[r1] ;读内存指令,假设r1的值为x,读取地址x上的数据,并将该数据赋给r0
//赋值指令 MOV
mov r0, r1; ;赋值指令,将r1的值赋值给r0
mov r0, #0x100 ;赋值指令,将0x100赋给r0
//写内存指令 STR
STR R0,[R1] ;设R1的值为x,将R0的值取出,放入地址x中
//跳转指令 B
2、汇编点亮LED
功能:
控制LED1的亮灭
LED1 B5
汇编代码:
.text
.global _start
_start:
/*设置IO口方向*/
ldr r1, =0x56000010
ldr r0, =0x00000400
str r0, [r1]
/*输出低电平,灯亮*/
ldr r1, =0x56000014
ldr r0, =0
str r0, [r1]
/*死循环*/
halt:
b halt
三、C语言操作
1、C语言——指针的深度解析
指针变量保存的是地址,即他是一个用于存储地址的变量
int *p = 0x100; //表示创建一个指针变量p,p的数据类型为(int *),他保存了0x100(这是一个地址)
*p = 0x01; //*表示解引用,表示将p保存的地址存入0x01
int a = 123 //a是一个普通变量,他存入的值为123
int *pa = &a; //表示创建一个指针变量pa,他所保存的值为a的地址,符号&为取地址符,表示取地址
2、C语言点亮LED灯
1)简单分析启动过程
一、第一大步
nand 启动将nand flash的前4k地址复制到SRAM中
nor 启动则直接在nor flash中运行,不进行代码的复制
二、第二大步
1、sp(栈指针)指向内存——用于为程序运行时变量的保存分配内存
sp(栈指针)指向内存的顶部,向下递减,栈用于保存临时变量,代码在内存中从0开始,确保不会覆盖掉代码。
2、使用R0-R3传参,跳转到所要执行的函数地址
3、寄存器(pc,lp,sp)将值写入内存中保存起来,栈指针下移
4、使用R0-R3传参(在栈中进行操作),完成函数内部的变量赋值与调用
5、函数执行完毕,恢复寄存器的值(pc,lp,sp),sp恢复原来的值,跳转到lp(返回地址),按照小字节序。
2)编写汇编启动代码
功能:启动文件,分配内存,并且完成main函数的执行
.text
.global _start
_start:
/*设置内存,:sp 栈*/
ldr sp, = 4096 /*nand启动*/
//ldr sp, = 4096+0x400,0000 //nor启动
/*调用main函数,跳转到main*/
bl main
/*死循环*/
halt:
b halt
3)编写C语言代码
功能:设置2440的相应寄存器
int main()
{
//定义方向寄存器以及数据寄存器的地址
unsigned int *GPDCON = (unsigned int *)0x56000010;
unsigned int *GPDDAT = (unsigned int *)0x56000014;
//写入寄存器B5
*GPDCON = 0x400;
*GPDDAT = 0;
return 0;
}
四、改进的汇编代码
1)加入延时功能
功能:加入延时,使 r0 进行传参
.text
.global _start
_start:
/*设置内存,:sp 栈*/
ldr sp, = 4096 /*nand启动*/
//ldr sp, = 4096+0x400,0000 //nor启动
/*调用延时函数*/
//将要传递的参数放入r0寄存器中
mov r0, #0x4000
//跳转的delay函数
bl delay
/*调用main函数*/
//传参,点亮灯一
mov r0, #0x01
//跳转到main
bl led_delay
//传参,点亮灯二
mov r0, #0x02
//跳转到main
bl led_delay
/*死循环*/
halt:
b halt
2)加入辨别Nor启动与Nand启动的功能与看门狗功能
.text
.global _start
_start:
//关闭看门狗
mov r0, #0x53000000
mov r1, #0
str r1, [r0]
//根据nand与nor的特性自动辨认nor启动与nand启动
//nor flash可读不可写
mov r1, #0x0 //r1 = 0
ldr r0, [r1] //将0地址的数值保存在r0中
str r1, [r1] //向0地址中写入0
ldr r2, [r1] //取出0地址的值
cmp r1, r2 //比较r1与r2的值,相等则为nand,否则为nor
ldr sp, = 4096+0x4000000
moveq sp, #4096 //r1 = r2,nand启动
streq r0, [r1] //恢复0地址原来的值
/*调用main函数,跳转到main*/
bl main
/*死循环*/
halt:
b halt