只是篇随笔。
今天在测试自己修改后的SCI模块的时候发生了很奇怪的事情,很简单的三个任务互斥地往SCI口发送数据:
static void SCI0Task(void *p_arg){
char str[] = "This is from Lin.\r\n";
while (DEF_TRUE)
{
SCI_PutCharsB_Mutex(SCI0,str,(sizeof(str)/sizeof(str[0]) - 1),0);
OSTimeDlyHMSM(0,0,0,250);
}
}
static void SCI0Task1(void *p_arg){
char str[] = "This is from mama.\r\n";
while (DEF_TRUE)
{
SCI_PutCharsB_Mutex(SCI0,str,(sizeof(str)/sizeof(str[0]) - 1),0);
OSTimeDlyHMSM(0,0,0,300);
}
}
static void SCI0Task2(void *p_arg){
char str[] = "This is from dogssssssssssssssss\r\n";
while (DEF_TRUE)
{
SCI_PutCharsB_Mutex(SCI0,str,(sizeof(str)/sizeof(str[0]) - 1),0);
OSTimeDlyHMSM(0,0,0,333);
}
}
正常情况下应该出现:
可实际输出却成了:
折腾了一晚上,各种设断点观测点,发现RAM中存放字符串的地方被不知道什么东西动了,值经常变化,导致输出异常,百思不得其解。
一觉起来,突然灵光一闪,该不会是哪个任务的栈溢出了冲进了“mama”的那个栈了吧,以前从没考虑过这个问题,一直以为128的栈大小够用了。现在看来必须要认真考虑这个问题了。于是正好用之前碰巧看到的(http://blog.csdn.net/u012252959/article/details/73741130)堆栈检测的方法试了试。
结果发现,果然是栈爆掉了。
于是乎一切就合理了,因为Lin、mama、dogs三个任务的栈是从低到高连续分配的,而栈是从高到低使用的,于是dogs的栈用完了之后就冲进了mama的栈中,正好把其中的字符串给改掉了,然后就出现了如上现象。将dogs的栈改大了之后就一切正常了。然后来看下实际使用了多少栈空间。
一看吓一跳,居然dogs用了140的堆栈,其他两个也快爆掉了,这样是很不安全的,起码要留20%的堆栈以防万一。而且可以看到下图的堆栈量和上图的使用量不太一样。这是因为堆栈的使用涉及很多因素,各种函数嵌套、中断等都会占用堆栈,需要检测一段时间等其稳定了才能大概确定潜在的最大值。
另:没想到一个任务居然会占到这么大的堆栈,以前一直以为只用占到几十就差不多了。
具体的检测方法就不详述了,上面那篇博文里有写。我就直接把这段测试的代码贴上来吧。
记得把OS_TASK_STAT_STK_CHK_EN和OS_TASK_CREATE_EXT_EN都设为1。
基于MC9S12XEP100和uCOS-II的SCI的驱动在此http://blog.csdn.net/lin_strong/article/details/73662524。
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* Framework
*
* By : Lin Shijun
* Note: This is a framework for uCos-ii project with only S12CPU, none float, banked memory model.
* You can use this framework with same modification as the start point of your project.
* I've removed the os_probe module,since I thought it useless in most case.
* This framework is adapted from the official release.
*********************************************************************************************************
*/
#include "includes.h"
#include "SCI_def.h"
#include <string.h>
/*
*********************************************************************************************************
* STACK SPACE DECLARATION
*********************************************************************************************************
*/
static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
static OS_STK Sci0TaskStk[SCI0_TASK_STK_SIZE];
static OS_STK Sci0Task1Stk[SCI0_TASK1_STK_SIZE];
static OS_STK Sci0Task2Stk[SCI0_TASK2_STK_SIZE];
static OS_STK StkCheckTaskStk[STK_CHECK_STK_SIZE];
/*
*********************************************************************************************************
* TASK FUNCTION DECLARATION
*********************************************************************************************************
*/
static void AppTaskStart(void *p_arg);
static void SCI0Task(void *p_arg);
static void SCI0Task1(void *p_arg);
static void SCI0Task2(void *p_arg);
static void StkCheckTask(void *p_arg);
/*
*********************************************************************************************************
* LOCAL FUNCTION DECLARE
*********************************************************************************************************
*/
// 初始化看门狗
static void INIT_COP(void);
/*
*********************************************************************************************************
* MAIN FUNCTION
*********************************************************************************************************
*/
void main(void) {
INT8U err;
BSP_IntDisAll(); /* Disable ALL interrupts to the interrupt controller */
OSInit(); /* Initialize uC/OS-II */
err = OSTaskCreate(AppTaskStart,
NULL,
(OS_STK *)&AppTaskStartStk[APP_TASK_START_STK_SIZE - 1],
APP_TASK_START_PRIO);
OSStart();
}
static void AppTaskStart (void *p_arg)
{
INT8U data,err,i = 0;
char buf[30];
(void)p_arg; /* Prevent compiler warning */
BSP_Init();
SCI_Init(SCI0);
SCI_EnableTrans(SCI0);
SCI_EnableRxInt(SCI0);
SCI_EnableRecv(SCI0);
SCI_Init(SCI1);
SCI_EnableTrans(SCI1);
SCI_EnableRxInt(SCI1);
SCI_EnableRecv(SCI1);
SCI_BufferInit();
err = OSTaskCreate(StkCheckTask,
NULL,
(OS_STK *)&StkCheckTaskStk[STK_CHECK_STK_SIZE - 1],
STK_CHECK_TASK_PRIO);
err = OSTaskCreateExt(SCI0Task,
NULL,
(OS_STK *)&Sci0TaskStk[SCI0_TASK_STK_SIZE - 1],
SCI0_TASK_PRIO,
SCI0_TASK_PRIO,
(OS_STK *)&Sci0TaskStk[0],
SCI0_TASK_STK_SIZE,
NULL,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
err = OSTaskCreateExt(SCI0Task1,
NULL,
(OS_STK *)&Sci0Task1Stk[SCI0_TASK1_STK_SIZE - 1],
SCI0_TASK1_PRIO,
SCI0_TASK1_PRIO,
(OS_STK *)&Sci0Task1Stk[0],
SCI0_TASK1_STK_SIZE,
NULL,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
err = OSTaskCreateExt(SCI0Task2,
NULL,
(OS_STK *)&Sci0Task2Stk[SCI0_TASK2_STK_SIZE - 1],
SCI0_TASK2_PRIO,
SCI0_TASK2_PRIO,
(OS_STK *)&Sci0Task2Stk[0],
SCI0_TASK2_STK_SIZE,
NULL,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
// 初始化看门狗
// INIT_COP();
while (DEF_TRUE)
{
buf[i++] = data = SCI_GetCharB(SCI0,0,&err);
if(data == '\n' || i >= 30){
SCI_PutCharsB_Mutex(SCI0,buf,i,0);
i = 0;
}
}
}
static void SCI0Task(void *p_arg){
char str[] = "This is from Lin.\r\n";
while (DEF_TRUE)
{
SCI_PutCharsB_Mutex(SCI0,str,(sizeof(str)/sizeof(str[0]) - 1),0);
OSTimeDlyHMSM(0,0,0,250);
}
}
static void SCI0Task1(void *p_arg){
char str[] = "This is from mama.\r\n";
while (DEF_TRUE)
{
SCI_PutCharsB_Mutex(SCI0,str,(sizeof(str)/sizeof(str[0]) - 1),0);
OSTimeDlyHMSM(0,0,0,300);
}
}
static void SCI0Task2(void *p_arg){
char str[] = "This is from dogssssssssssssssss\r\n";
while (DEF_TRUE)
{
SCI_PutCharsB_Mutex(SCI0,str,(sizeof(str)/sizeof(str[0]) - 1),0);
OSTimeDlyHMSM(0,0,0,333);
}
}
// 检测堆栈用
static void StkCheckTask(void *p_arg){
INT8U i;
char str[40];
OS_STK_DATA StackBytes;
OSTimeDlyHMSM(0,0,1,0);
while (DEF_TRUE)
{
OSTaskStkChk(SCI0_TASK_PRIO,&StackBytes);
i = sprintf(str,"Lin Free:%u,Used:%u\r\n",(INT16U)StackBytes.OSFree,(INT16U)StackBytes.OSUsed);
SCI_PutCharsB_Mutex(SCI1,str,i,0);
OSTaskStkChk(SCI0_TASK1_PRIO,&StackBytes);
i = sprintf(str,"mama Free:%u,Used:%u\r\n",(INT16U)StackBytes.OSFree,(INT16U)StackBytes.OSUsed);
SCI_PutCharsB_Mutex(SCI1,str,i,0);
OSTaskStkChk(SCI0_TASK2_PRIO,&StackBytes);
i = sprintf(str,"dogs Free:%u,Used:%u\r\n",(INT16U)StackBytes.OSFree,(INT16U)StackBytes.OSUsed);
SCI_PutCharsB_Mutex(SCI1,str,i,0);
OSTimeDlyHMSM(0,0,0,111);
}
}
void INIT_COP(void)
{
COPCTL = 0x07; //设置看门狗复位间隔为1.048576s
}