本文根据上一篇TQ2440开发板学习纪实(1)—最简单的独立运行汇编程序进化而来。
0 ARM堆栈(Stack)基础知识
ARM支持满减类型的堆栈,满的意思是说堆栈指针SP(即R13)总是指向刚刚入栈的数据单元。与满相对应的就是不满,这种类型的栈指针SP指向栈顶的下一个空白单元。减的意思是说,栈底的内存地址大,栈顶地址小,压入数据时,栈向地址小的方向扩展。
目前我们只有4KB的内存可用,范围为:0x00000000-0x00000FFF,如下图:
为了充分利用这4KB的内存,我们把堆栈
指针SP初始指向0x00001000。这样设置有如下考虑:
必须4字节对齐,这是ARM的要求。也就是最后两位二进制位必须为0.
虽然最大可用内存地址为0x00000FFF,但是这里仍然可以设置SP=0x00001000。因为ARM堆栈是”满减”,所以后续使用时并不会使用0x00001000这个内存单元。
C语言的函数的实现,严重依赖于堆栈,虽然参数较少时,直接使用寄存器传参,但是调用函数前其返回地址必须存放到堆栈上供被调用函数返回使用。
1 项目源码
从本文开始,项目源码不再在文中完整列出,有需要的朋友,请自行去CSDN的git库中下载。本次源码的tag为v0.1。
设置堆栈代码就一行:
/* set statck, must be aligned by 4 bytes */
ldr sp, =0x00001000
调用C函数也非常简单
b Main
注意这里没有使用bl,也就意味着,永远不会执行后面的代码。
需要说明的是,s3c2440有好几个运行模式,不同的模式下有各自独立的堆栈指针寄存器,需要分别设置。目前我们只工作在默认的SVC模式下,也只是设置了该模式下的堆栈而已。
有了堆栈,C语言的函数就可以顺利执行,有了C语言,谁还会用汇编呢?所以后面是用C语言写的一个LED流水灯程序。
void Main(void)
{
led_init();
while(1){
int i=0;
for(i=1; i<=4; i++) {
led_off( i-1 < 1 ? 4 : i-1);
led_on(i);
delay(10000);
}
}
}
2 编译说明
详见Makefile文件。
3 运行说明
参加TQ2440开发板学习纪实(1)—最简单的独立运行汇编程序中的说明。
关键字:TQ2440 设置堆栈 调用C函数
引用地址:
TQ2440开发板学习纪实(2)--- 设置堆栈并调用C函数
推荐阅读最新更新时间:2024-11-07 05:13
IAR MSP430设置合理堆栈大小
最近在MSP430-169LCD(MSP430F169,RAM为2KB)调试一些ucos演示例子,IAR for MSP430默认的堆栈大小是80字节,编译可以通过,运行结果不确定性,调试过程会提示 the stack pointer for stack is outside the stack range ,堆栈溢出。那么,到底设置多大的堆栈够用且不浪费呢。 一、合理设置堆栈大小 首先,查看程序共需要多大的堆栈,生成map文件,方法如下: 图1 生成map文件 生成的map文件在项目目录下的/Debug/List,打开map文件在CALL GRAPH找到找到栈的最大使用量(我的理解是main主函数,用栈最多,所以
[单片机]
将TQ2440的ADS工程文件移植到KEIL5中
TQ2440的例程都是ADS环境下的,ADS已经是古董级的软件,win7都不带支持何况WIN10。考虑需求就尝试将工程移植到keil5上。查找了大量资料,试验加修改总算是移植成功了。文后附上所参考的地址。这里总结一下,方便查看: keil环境配置 打开keil,下载相关的内核,sumsung2440的。 新建工程,选择相关内核(会提示添加源文件,如果自己有就不要添加了,直接导入),将文件导入到工程,此处和导入STM32的h文件,c文件一样 注意拷贝文件时inc文件一定要和源文件在一个文件夹(不是指工程中,是你实际存放文件的文件夹里)就是和2440init.s文件放一块 设置Target选项卡 这里SIZE可以自行设置10000
[单片机]
STM32 KEIL下的堆栈设置
刚接手STM32时,你只编写一个 int main() { while(1); } BUILD://Program Size: Code=340 RO-data=252 RW-data=0 ZI-data=1632 编译后,就会发现这么个程序已用了1600多的RAM,要是在51单片机上,会心疼死了,这1600多的RAM跑哪儿去了,分析map,你会发现是堆和栈占用的 在startup_stm32f10x_md.s文件中,它的前面几行就有以上定义,这下该明白了吧。 Stack_Size EQU 0x00000400 Heap_Size EQU 0x00000200 顺便记号,关注
[单片机]
TQ2440按键中断
有几点需要注意: 1、需要调用MMU函数,实现内存的映射; 2、在中断触发跳入中断处理函数后,首先要清除SRCPND和INTPND相应的位,如果用到次级中断源,如这里用到了EINT4_7中的EINT4,就要清除EINTPEND相应的位。一般来说,应该先清除次级中断源相应的位,再清除中断源,否则中断源会发生多次中断。在完成清除后再进行具体的处理。 #include def.h #include option.h #include 2440addr.h #include 2440lib.h #include 2440slib.h #include mmu.h #define LED1 (1 5) //must be (
[单片机]
TQ2440 AD中断方式采集数据
经过不懈的努力 发现自己的错误在于不知道ADC的中断有两个子中断 2440的ADC中断包括INT_ADC_S和INT_TC 需要先处理一下子中断INT_ADC_C 再处理INT_ADC 另外要感谢21icbbs上的网友hbicecream的帮助 我才想起来Uart_Printf函数也是需要中断的 所以最好不要在中断服务程序中使用Uart_Printf 最终整理的程序如下: 使用的板子为TQ2440 #define EnableIrq(bit) rINTMSK &= ~(bit) #define DisableIrq(bit) rINTMSK |= (bit) #define Ena
[单片机]
TQ2440启动代码分析(二)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;; When EINT0 is pressed, Clear SDRAM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; check if EIN0 button is pressed ;这一段检测EINT0是否被按下,假如EINT0被按下,则清空SDRAM
[单片机]