dmzy 发表于 2017-2-22 16:09:38

ucos多任务单串口打印遇到的问题

目前正在学习ucos,使用的代码版本为ucos 2.92,现在使用多任务单串口打印的时候,发现容易丢字符的现象,即使使用互斥信号量依旧存在该问题,话不多说,上代码给大家看看

main函数代码
int main(void)
{
        CPU_INT08Uerr;

        Bsp_Init();
       
        OSInit();                                                   /* Initialize "uC/OS-II, The Real-Time Kernel"            */
        OSMutexCreate(3, &err);

        OSTaskCreateExt(LED1TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED1TaskStartStk,
                                        LED1_TASK_START_PRIO,
                                        LED1_TASK_START_PRIO,
                                        (OS_STK *)&LED1TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED1_TASK_START_PRIO, "LED1 Task", &err);

        OSTaskCreateExt(LED2TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED2TaskStartStk,
                                        LED2_TASK_START_PRIO,
                                        LED2_TASK_START_PRIO,
                                        (OS_STK *)&LED2TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED2_TASK_START_PRIO, "LED2 Task", &err);

        OSTaskCreateExt(LED3TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED3TaskStartStk,
                                        LED3_TASK_START_PRIO,
                                        LED3_TASK_START_PRIO,
                                        (OS_STK *)&LED3TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED3_TASK_START_PRIO, "LED3 Task", &err);

        OSTaskCreateExt(LED4TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED4TaskStartStk,
                                        LED4_TASK_START_PRIO,
                                        LED4_TASK_START_PRIO,
                                        (OS_STK *)&LED4TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED4_TASK_START_PRIO, "LED4 Task", &err);

        OSTaskCreateExt(LED5TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED5TaskStartStk,
                                        LED5_TASK_START_PRIO,
                                        LED5_TASK_START_PRIO,
                                        (OS_STK *)&LED5TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED5_TASK_START_PRIO, "LED5 Task", &err);

        OSTaskCreateExt(LED6TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED6TaskStartStk,
                                        LED6_TASK_START_PRIO,
                                        LED6_TASK_START_PRIO,
                                        (OS_STK *)&LED6TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED6_TASK_START_PRIO, "LED6 Task", &err);

        OSTaskCreateExt(LED7TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED7TaskStartStk,
                                        LED7_TASK_START_PRIO,
                                        LED7_TASK_START_PRIO,
                                        (OS_STK *)&LED7TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED7_TASK_START_PRIO, "LED7 Task", &err);

        OSTaskCreateExt(LED8TaskStart,                               /* Create the start task                                    */
                                        (void *)0,
                                        (OS_STK *)&LED8TaskStartStk,
                                        LED8_TASK_START_PRIO,
                                        LED8_TASK_START_PRIO,
                                        (OS_STK *)&LED8TaskStartStk,
                                        TASK_START_STK_SIZE,
                                        (void *)0,
                                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

        OSTaskNameSet(LED8_TASK_START_PRIO, "LED8 Task", &err);

        OSStart();
}


任务代码
static void LED1TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(0);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED1TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 1, 0);
        }
}

static void LED2TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(1);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED2TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 2, 0);
        }
}

static void LED3TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(2);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED3TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 3, 0);
        }
}

static void LED4TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(3);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED4TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 4, 0);
        }
}

static void LED5TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(4);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED5TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 5, 0);
        }
}

static void LED6TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(5);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED6TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 6, 0);
        }
}

static void LED7TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(6);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED7TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 7, 0);
        }
}

static void LED8TaskStart(void * p_arg)
{
        INT8U err;
        (void)p_arg;

        while (1)
        {                                          /* Task body, always written as an infinite loop.         */
                BSP_LED_Toggle(8);
                OSMutexPend(ResourceMutex, 0, &err);
                UsartPrintf(USART1, "LED8TaskStart\n");
                OSMutexPost(ResourceMutex);
                OSTimeDlyHMSM(0, 0, 8, 0);
        }
}

打印函数
void UsartPrintf(USART_TypeDef * USARTx, const char * fmt, ...)
{
        va_list args;

        char printf_buffer;
        char * ptr = printf_buffer;

        va_start(args, fmt);

        vsprintf(printf_buffer, fmt, args);

        va_end(args);
/**查询发送************************************************************************/
        while (*ptr != '\0')
        {
                USART_SendData(USARTx, *(ptr++));
                while (!(USARTx->SR & USART_FLAG_TXE));
        }
}


我的疑问如下:
1、我加入了互斥型信号量,为何打印任务仍然被打断了;
2、字符为何丢失,有什么方法可以解决;
请各位高手指点迷津............

dmzy 发表于 2017-2-22 16:17:05

附上软件代码,以供大家测试。

w282529350 发表于 2017-2-23 09:13:36

任务堆栈给大点试试呢

没用过ucos,不知道UsartPrintf里的那个256的数组是不是在任务堆栈里申请

security 发表于 2017-2-23 09:51:21

本帖最后由 security 于 2017-2-23 09:54 编辑

逻辑没有错,退一步说,就算被抢占,也不应该丢失字符。
出现此情况有两种可能:
一是, PC 端的串口软件有 bug。
二是,你的栈溢出了。

你的栈太小了。
#defineTASK_START_STK_SIZE                  216

再看看 UsartPrintf 函数里面,看看那个 printf_buffer 的 size。
正确的做法是:将 printf_buffer定义为 static 类型吧,减少对宿主 thread 栈的依赖。

dmzy 发表于 2017-2-23 12:05:52

security 发表于 2017-2-23 09:51
逻辑没有错,退一步说,就算被抢占,也不应该丢失字符。
出现此情况有两种可能:
一是, PC 端的串口软件有 ...

您好,感谢您的回复。我将TASK_START_STK_SIZE设置为416,并且将printf_buffer定义为 static 类型后,问题依旧存在。还恳请指点一下。

w282529350 发表于 2017-2-23 13:54:50

本帖最后由 w282529350 于 2017-2-23 13:56 编辑

w282529350 发表于 2017-2-23 09:13
任务堆栈给大点试试呢

没用过ucos,不知道UsartPrintf里的那个256的数组是不是在任务堆栈里申请 ...

还有一个错误,你创建的信号量返回值没有给变量

security 发表于 2017-2-23 13:59:14

dmzy 发表于 2017-2-23 12:05
您好,感谢您的回复。我将TASK_START_STK_SIZE设置为416,并且将printf_buffer定义为 static 类型后, ...

那你就要检查下互斥量是否有效,
你有初始化 ResourceMutex 吗?往这边看看。

hswkcg 发表于 2017-2-23 14:27:52

我感觉不是栈的问题,我曾看到过这样的问题,串口打印输出乱码,原因是printf函数打印输出时,被别的任务抢占,而抢占任务也用到了printf,最后解决是将打印输出放在临界段里面,或者加任务锁。你可以这么试一下,看看管不管用,只是个猜测。

dmzy 发表于 2017-2-24 09:15:45

w282529350 发表于 2017-2-23 13:54
还有一个错误,你创建的信号量返回值没有给变量

我检查了下,的确是的,改成如下代码,经测试过后就没有问题了。感谢指点,错误太低级了.........
ResourceMutex = OSMutexCreate(10, &err);

dmzy 发表于 2017-2-24 09:17:00

security 发表于 2017-2-23 13:59
那你就要检查下互斥量是否有效,
你有初始化 ResourceMutex 吗?往这边看看。 ...

问题是互斥变量忘记初始化了,改成如下就好了,测试没问题,谢谢指点。
ResourceMutex = OSMutexCreate(10, &err);
页: [1]
查看完整版本: ucos多任务单串口打印遇到的问题