ARM启动代码栈和调用C语言以及volatile简单使用

上一篇写了要关闭看门狗,后面需要用到的时候再开

下面的启动代码依然要用汇编写

为什么用汇编不用C语言

因为这时候不具备C语言的运行环境,所以需要创造一个环境给C语言。

为什么要设置栈

因为C语言的局部变量都是用栈来实现的。只有设置了合法的栈地址,局部变量才可以定义。

为什么平时的不用设置

单片机程序(譬如51单片机)或者编写应用程序时并没有去设置栈,但是C程序还是可以运行的。原因是:在单片机中由硬件初始化时提供了一个默认可用的栈,在应用程序中我们编写的C程序其实并不是全部,编译器(gcc)在链接的时候会帮我们自动添加一个头,这个头就是一段引导我们的C程序能够执行的一段汇编实现的代码,这个代码中就帮我们的C程序设置了栈及其他的运行时需要。

那么栈设置在哪里?

这个要去看开发板的数据手册
现在用的这个开发板是

可以看到有个SVC Stack,这个就是栈了。
SVC:supervisor ,因为系统复位是默认进入SVC的(课程这样讲)

那到底是哪个地址,上面还是下面

在ARM中,ATPCS(ARM关于程序应该怎么实现的一个规范)要求使用满减栈,所以不出意外都是用满减栈
结合iROM_application_note中的memory map,可知SVC栈应该设置为0xd0037D80

满增、满减、空增、空减栈

满、空栈区别:根据当前指针所在位置是否有东西。
满栈(full stack):栈指针指向最后压入栈的数据,数据入栈时,sp先减一(或加一)再入栈。
空栈(empty stack):栈指针指向下一个将要放入数据的位置,数据入栈时,先入栈sp再减一(或加一)。

引用的。

知道了地址之后怎么设置,放在哪个寄存器里面?

栈嘛,需要用到栈指针,stack pointer ,即上面讲到的sp,只需要把sp跟上述的数据手册的地址挂钩即可。
ldr sp = 0xd0037D80
然后执行完之后就可以用c语言了

设置完之后怎么用C语言?

使用bl命令
bl:branch with link 跳转并链接的意思
b :branch 跳转的意思
直接后面
bl clanguage
bl + 函数名 即可
最后Makefile会做好编译链接的。
最后记得不要漏死循环
b . //到这就一直循环,防止执行了后面未知位置的东西跑飞。

volatile

volatile是一个类型修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。

一点C语言语法技巧

宏定义的位置,下面那段话是自己第一次学的时候的笔记。

unsigned int p= (unsigned int)0xE0200240
//定义一个类型为unsigned int的指针p,把0xE0200240这个值强制转换成unsigned int类型,保持与指针p的类型一致,然后把这个值赋值给指针p即p,可以理解为现在p指着的地址就是0xE0200240

unsigned int p1= (unsigned int)0xE0200244
//这句话跟上面一样理解

*p= 0x11111111 //因为经过上面第一句,*p已经指向那个地址了,现在是往那个地址里面赋值,初始化GPJOCON

#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中设置为输出模式
	//volatile unsigned int *p = (unsigned int *)GPJ0CON;
	//volatile unsigned int *p1 = (unsigned int *)GPJ0DAT;
	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
}

	
发布了38 篇原创文章 · 获赞 1 · 访问量 1032

猜你喜欢

转载自blog.csdn.net/qq_40897531/article/details/104295737