tiny4412 裸机程序 四、设置栈和C语言点亮LED
2014-07-05 23:48
399 查看
一、为什么调用C函数要设置栈
1. 栈的整体作用
1) 保存现场;2) 传递参数:汇编代码调用C函数时,需传递参数;
3) 保存临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量;
2. 详细解释
1) 保存现场
现场,意思就相当于案发现场,总有一些现场的情况,要记录下来的,否则被别人破坏掉之后,你就无法恢复现场了。而此处说的现场,就是指CPU运行的时候,用到了一些寄存器,比如r0,r1等等,对于这些寄存器的值,如果你不保存而直接跳转到子函数中去执行,那么很可能就被其破坏了,因为其函数执行也要用到这些寄存器。因此,在函数调用之前,应该将这些寄存器等现场,暂时保持起来(入栈push),等调用函数执行完毕返回后(出栈pop),再恢复现场。这样CPU就可以正确的继续执行了。保存寄存器的值,一般用的是push指令,将对应的某些寄存器的值,一个个放到栈中,把对应的值压入到栈里面,即所谓的压栈。然后待被调用的子函数执行完毕的时候,再调用pop,把栈中的一个个的值,赋值给对应的那些你刚开始压栈时用到的寄存器,把对应的值从栈中弹出去,即所谓的出栈。其中保存的寄存器中,也包括lr的值(因为用bl指令进行跳转的话,那么之前的PC的值是存在lr中的),然后在子程序执行完毕的时候,再把栈中的lr的值pop出来,赋值给PC,这样就实现了子函数的正确的返回。2) 传递参数
C语言进行函数调用的时候,常常会传递给被调用的函数一些参数,对于这些C语言级别的参数,被编译器翻译成汇编语言的时候,就要找个地方存放一下,并且让被调用的函数能够访问,否则就没发实现传递参数了。对于找个地方放一下,分两种情况。一种情况是,本身传递的参数不多于4个,就可以通过寄存器r0~r3传送参数。因为在前面的保存现场的动作中,已经保存好了对应的寄存器的值,那么此时,这些寄存器就是空闲的,可以供我们使用的了,那就可以放参数。另一种情况是,参数多于4个时,寄存器不够用,就得用栈了。3) 临时变量保存在栈中
包括函数的非静态局部变量以及编译器自动生成的其他临时变量。二、程序说明
完整代码见目录3_led_c_sp。1. start.S
本章我们将使用C函数来实现点灯和延时的功能,在代码3_led_c_sp中,start.S的作用如下:第一步 关闭看门狗;
第二步 设置栈;
第三步 调用C函数led_blink(),实现LED闪烁;
设置栈,其实就是设置sp寄存器,让其指向一块可用的内存,我们将其指向0x0205_0000,原因如下:iRAM的最顶地址是0x0206_0000,这里我二了一把,一开始,我不确定Exynos4412堆栈是向上增长还是向下递减的,为给自己开脱,就当我想试试其他地址行不行,所以直接写了0x0205_0000。其实应是向下递减的,因为U-Boot程序的sp地址是指向0x0206_0000。所以这个值可以改回0x0206_0000,让其指向顶部比较好吧。
2、led.c
led.c中编写了两个C函数,led_blink()实现LED闪烁,delay()实现延时功能,代码如下, 代码里的注释已经写得非常清楚了。相比起汇编,使用C语言来操作LED显得简洁,也容易了许多,也更加好看明白了。#define GPM4CON (*(volatileunsigned long *) 0x110002E0)
#define GPM4DAT (*(volatile unsigned long *)0x110002E4)
void delay(int r0) //延时
{
volatile int count = r0;
while (count--) ;
}
void led_blink() //LED闪烁
{
GPM4CON = 0x00001111; // 配置引脚
while(1)
{
GPM4DAT = 0; // LED on
delay(0x200000);
GPM4DAT =0xf; //LED off
delay(0x200000);
}
}
三、完整的烧写过程
已将SD卡插入电脑,假设linux识别了SD卡,其识别号为sdb。执行下面命令:# chmod 777 –R 3_leds_c_sp
# cd 3_leds_c_sp
# make
# cd sd_fuse
# make
# ./ fast_fuse /dev/sdb
四、上电实验
将sd卡插入Tiny4412中,选择sd卡启动,然后上电,可以看到以下现象:LED正常闪烁,设置栈以后,我们的程序就能调用C函数,这样将大大提升我们编写代码的速度。下一章我们将学习如何打开和关闭icache,体验一下icache的威力。
相关文章推荐
- 裸机程序二:GPIO点亮led灯 c语言
- tiny4412 裸机程序 二、汇编点亮LED灯
- 1.点亮1个led程序分析(C语言)
- Tiny4412-LED小灯裸机程序
- c语言多文件 6410 led裸机程序
- 基于Cortex-A8裸机,点亮LED灯程序分析
- 分享一个香橙派PC2的C语言点亮LED程序
- mini2440裸机程序之二--点亮LED灯
- 友坚4412开发板设置栈和C语言点亮LED
- 【OK6410裸机程序】点亮LED
- 4412裸机程序之点亮LED
- Tiny4412使用C语言实现流水灯的裸机程序
- Eclipse开发调试ARM裸机程序(三)C语言LED_LINUX使用DNW
- Tiny4412-LED小灯裸机程序
- Mini 2440 LED、按键和蜂鸣器裸机测试程序(C语言)
- Mkefile文件编写及点亮两个led的mini2440裸机程序
- mini2440裸机程序--完善点亮LED(c…
- 分享一个香橙派PC2的C语言点亮LED程序
- 一灯大师之点亮OK6410开发板上4个LED裸机程序---嵌入式回归第十篇
- 第一个裸机程序---点亮led小灯