堆栈,我们说它常常用于在一些函数调用、中断及异常处理中,用于保存发生函数调用、中断和异常发生前的现场,待函数调用、中断和异常结束后,用于恢复先前的现场。
比如主程序正在用W0 计算数据,被中断打断了,要执行中断程序,而中断程序里也要使用W0这个寄存器。 这时候就可以先把W0压栈,等中断结束后,再弹栈将W0数据恢复,主程序继续执行。
任何时候想保存临时数据,都可以使用堆栈。
那么,我们说堆栈的方向有向上生长和向下生长两种,dspace单片机的生长方向是向上生长的,先进后出的原则
如果我们不自己去设置堆栈的空间的话,那么就是使用编译器默认分配的空间。
如何设置一段堆栈空间
堆栈的起始地址我们是需要知道,在dspac单片机中,W15寄存器是被用作堆栈指针的。所以,在我们设置的时候,就需要给W15寄存器给定一个初始地址,作为堆栈空间的起始地址。然后,堆栈空间是不是不能无穷大是吧,是需要有一个范围的是把?所以,我们需要给堆栈空间设置一个大小。在程序写之前,我们谁都不知道多大最合适。
所以,我们开始给一个尽量大一点的空间,不影响我们对RAM的使用就可以了。
这段代码就是设置堆栈空间的。
这两段代码合起来就实现了堆栈空间设置功能。
. stack 1050 相当于定义段的起始地址。__SP_init = .;/*-堆栈起始地址为0x1050--*/ 然后这里注意一下 = 前后需要有一个空格。不然会报错的。
堆栈设置的区域就是从 0x1050 到 0x10F8。使用w0是为了传递中间设置的数据。
这个地方是设置一个堆栈空间,这个空间的起始地址是0x1050,这句话是把当前地址给到 __SP_init这个变量里面。可以认为它是一个常量,我们现在是在给这个常量赋值。
__SP_init = .;,这个“.”就是1050吗?即 “ .”代表当前地址。
它都可以表示当前地址。
W14是作为在堆栈里面又划分了一小段空间来作为临时使用的地址指针。
堆栈设置,为什么放在了数据存储器里面?堆栈是用来保存数据的,保存数据的话都是在RAM里面操作的,那么堆栈空间肯定要设置在RAM里面了。堆栈区域中的数据都是临时数据。也就是说,所以RAM中的数据,都是临时数据,掉电就会消失。
. += 0x00a8;/*--堆栈大小为168字节---*/
. += 0x00a8;/*--堆栈大小为168字节---*/ -------> 当前地址 = 0x1050 + 0x00a8 = 0x10F8。
__SPLIM_init = .; ----> __SPLIM_init = 0x10F8。
. += 0x0008; ------> 当前地址 = 0x10F8 + 0x0008。
加个0X0008是留有一个余量,以防溢出之后,我们还有可以挽救的空间。
假设要存放的临时数据太多了,那么是不是可能导致堆栈溢出啊?这里多留一段空间,可以起到缓冲的效果。
向上生长的一般放在最底部,如果向下生长的,一般放在最顶部。
如果堆栈超出了我们设置的这段空间,那么他会产生一个堆栈错误陷阱。可以编写堆栈错误陷阱服务程序,来做相关处理。
用C的话,可以不用考虑堆栈。