编译器(gcc)在链接的时候会帮我们自动添加一个头,这个头就是一段引导我们的C程序能够执行的一段汇编实现的代码,这个代码中就帮我们的C程序设置了栈及其他的运行时需要。
CPU模式下有各种栈,如果使用一种栈,应用程序如果一旦出错(譬如栈溢出),就会连累操作系统的栈也损坏,整个操作系统的程序就会崩溃。这样的操作系统设计是非常脆弱的,不合理的。
#define WTCON 0xE2700000
#define SVC_STACK 0xd0037d80
.global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
// 第1步:关看门狗(向WTCON的bit5写入0即可)
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]
// 第2步:设置SVC栈
ldr sp, =SVC_STACK
// 从这里之后就可以开始调用C程序了
3.关看门狗,设置栈后就可以调用C语言
#define WTCON 0xE2700000
#define SVC_STACK 0xd0037d80
.global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
// 第1步:关看门狗(向WTCON的bit5写入0即可)
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]
// 第2步:设置SVC栈
ldr sp, =SVC_STACK
// 从这里之后就可以开始调用C程序了
bl led_blink // led_blink是C语言实现的一个函数
// 汇编最后的这个死循环不能丢
b .
C语言实现的流水灯代码:
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
#define rGPJ0CON *((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT *((volatile unsigned int *)GPJ0DAT)
void delay(void);
// 该函数要实现led闪烁效果
void led_blink(void)
{
// led初始化,也就是把GPJ0CON中设置为输出模式
rGPJ0CON = 0x11111111;
while (1)
{
// led亮
rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
// 延时
delay();
// led灭
rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
// 延时
delay();
}
}
void delay(void)
{
volatile unsigned int i = 900000; // volatile 让编译器不要优化,这样才能真正的减
while (i--); // 才能消耗时间,实现delay
}
4.汇编写启动代码之开iCache
-> 什么是cache,有什么用
cache是一种内存,叫高速缓存,从速度来说:CPU > 寄存器 > cache > DDR。
cache的存在,是因为寄存器和ddr之间速度差异太大,ddr的速度远不能满足寄存器的需要,从DDR中读给寄存器,再由寄存器送给cpu,DDR的速度和寄存器(代表的就是CPU)相差太大,解决方案就是icache。
-> 汇编代码读写cp15以开关icache
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/6186542)