新闻中心

EEPW首页 > 牛人业话 > 任务堆栈不是系统堆栈 搞混了就会完蛋

任务堆栈不是系统堆栈 搞混了就会完蛋

作者:三昧道人时间:2019-04-24来源:电子产品世界收藏

但是,代码可不像大妹子那么好看。一眼望去,好几个.c文件中密密麻麻的字符,简直是老鼠拉乌龟,没有下手的地方呀!

本文引用地址:http://www.eepw.com.cn/article/201904/399825.htm

1556075978925524.jpg

有些人总是有着鹰一般锐利的眼睛,比如他们会发现,新版倚天屠龙记中张无忌和赵敏居然足足吻了25秒钟,而且张无忌一边吻还一边贪婪地咽口水。好吧,我承认,我也发现了张无忌咽口水的猥琐模样,但是对于枯燥的代码,我实在没有这般锐利的眼睛,只好一行代码一行代码地硬着头皮看。

I2C部分自然是不用看的。只看上层驱动就可以了,很快,我把目光放在了函数atsha204_mac身上,这正是我最终调用的那个函数。

这个函数实在也太显眼了,因为这个函数不仅调用了好几个函数,里面还有三个大数组形式的局部变量:

uint8_t transmit_buffer[SHA204_CMD_SIZE_MAX];

uint8_t response_buffer[SHA204_RSP_SIZE_MAX];

uint8_t soft_digest[32];

单单是这三个局部变量就足足用掉了151个字节!再加上其他局部变量,快到200字节了,要知道,在调用这个函数时,它里面的所有局部变量都是要放到堆栈上的,这样的话,才可能会在中断发生时保存现场,以在中断服务程序完成后再度恢复现场。

现场当然不止包括局部变量,还要再加上调用的子函数,这样算下来,atsha204_mac这个函数运行时消耗掉的堆栈还不得快到300字节了?齐工调用这个函数的主程序是裸机形式,消耗的是的默认配置是512字节,可是我是在带有操作系统的任务里面调用这个函数的,消耗的是,我对的默认配置是256字节!!

问题一目了然了,我轻轻地挥了挥手,把齐工提溜了过来,

or

和齐工说完问题的原因之后,我心情大好,问起了齐工:“你知道不知道你的主程序设置的堆栈空间有多大?”根据我对齐工的了解,一心扑在炒股上面的他,应该不知道在哪里设置堆栈空间,更遑论堆栈空间有多大了。

果然,他瞪着无辜的小眼神扫了我一眼,嘴角弯出一抹笑意,等着我的科普。

1556076019727872.jpg

我满意地看着他的表情,鼓起腮帮子说了起来,“在prm文件里面,你看一下这个设置STACKSIZE 0x200,512个字节。你验证加密认证模块时,用的就是这个堆栈,你可以看一下MCU初始化时对SP寄存器的设置和堆栈区域的初始化,SP寄存器设置堆栈栈顶,初始化程序里,从栈顶开始,根据STACKSIZE把用作堆栈的那部分RAM初始化为0。”

“哦,那按你的意思,如果Atmel的那个函数在裸机里面运行,消耗的就是系统堆栈,但是这个函数一旦在你的任务里面运行,消耗的就是任务堆栈了,为什么呢?”齐工精灵剔透,一下子就提问到了问题的本质。

‘孺子可教也!’我一边在心里嘀咕着,一边组织着语言,回答他的问题。

“你来看一下在我用的这个ucos操作系统里,任务切换时到底执行了什么就清楚了。”我一边划拉着鼠标转轮,一边在屏幕上找着对SP指针进行操作的地方。嗯?那双发现张无忌咽口水的鹰一般锐利的眼睛哪里去了?找了半天后,我突然意识到,应该翻到汇编代码里面去找,于是我翻到os_cpu_a.s文件里面,终于找到了下面这条语句:

lds 0,x ;  3~, Load the SP of the next task

这是任务切换时将SP寄存器设置为待切换任务结构体中的堆栈指针内容的地方,它和裸机形式里只初始化一次SP的方式不一样,每次切换到新的任务时都要设置一次,所以如果任务堆栈设计地过小,就无法运行atsha204_mac这个消耗大量堆栈的函数。

“那怎么解决呢?”齐工怯怯地问,显然,他不想改这个函数的实现方式。

从脸盲症中恢复的我定定地看了一下齐工,想到他上次给我推荐了一只好股票的“恩惠”,大手一挥,朗然道:“你不用管了,我可以在创建任务之前调用这个函数,这时它用的还是系统堆栈。也可以在任务中调用它,把调用位置所在的任务堆栈加大也可以。”

看到他渐渐轻松了的笑容,我又加上了一句科普:任务堆栈不是系统堆栈,搞混了就会完蛋啊!


上一页 1 2 下一页

评论


技术专区

关闭