搜索
bottom↓
回复: 12

开发环境GCC WINAVR AMTEGA64,使用UCOS-II,目前开了两个线程,线程跑几次就挂了........

[复制链接]

出0入0汤圆

发表于 2007-3-10 12:42:16 | 显示全部楼层 |阅读模式
开发环境GCC WINAVR AMTEGA64,使用UCOS-II,目前开了两个线程,一个ADC不停中断循环转换,另外一个中断接受串口数据,发现ADC跑各2-3次就挂了,自动重新启,是不是中断处理不对,或者中断太频繁了,还是其他什么问题,但是我只开一个任务,比如点灯就没有问题,这让我百思不得其解,还望大家指点一下,谢谢



/*

**************************************************************************************************************



  **************************************************************************************************************

*/



#include "includes.h"



/*

***************************************************************************************************

*                                               CONSTANTS

***************************************************************************************************

*/



#define  TASK_STK_SIZE  OS_TASK_DEF_STK_SIZE          // 每个任务的堆栈深度

#define  N_TASKS        4                             // 任务的数量







#define DEBUG



#define UART0_RX_BUF_SIZE 32



/*

***************************************************************************************************

*                                        变量定义

***************************************************************************************************

*/



OS_STK          TaskStk[N_TASKS][TASK_STK_SIZE];        // 任务堆栈

OS_STK          TaskStartStk[TASK_STK_SIZE];





INT8U           UartRxBuf[UART0_RX_BUF_SIZE];           // UART1 接收缓冲区

INT16U          UartRxRdPtr;                            // UART1 接收读指针

INT16U          UartRxWrPtr;                            // UART1 接收写指针

INT16U          UartRxCounter;                          // 收到的字节数

INT8U                        UartCmdRxComplete;                      // 串口命令接受完成

OS_EVENT       *UartRxSem;



OS_EVENT       *ADCOKSem;

OS_EVENT       *SendSem;





void sendChar0(INT8U data)

{

        while ( ! (UCSR0A & (1 << UDRE0) ) );

        UCSR0A |= (1 << TXC0);

        UDR0 = data;

        while ( ! (UCSR0A & (1 << TXC0 ) ) );

}





/*

***************************************************************************************************

*                                              创建任务

***************************************************************************************************

*/





//主要任务

void TaskSerialProcess (void *data)

{

        INT8U err=0;

        data = data;                                        /* Prevent compiler warning                         */

        //INT8U tempstr[10] = {0};

       

        //        把开定时中断0AvrInit()从移到这里

        //        TCCR1B = (1 << CS02);                                            // 时钟预分频为 CLK/1024   

        //        data = data;

       

        PRINT("Waiting User Input Cmd .......\r
");

        for (;;)

        {

                //发送查询当前状态命令

                OSSemPend(UartRxSem,0,&err);

                ProcessComand(UartRxBuf);

                OSTimeDlyHMSM(0,0,0,1);

        }

}







void TaskADCDataDaq (void *data)

{

        unsigned char ADChannel=0;

        INT8U err;

        data = data;   /* Prevent compiler warning                         */

        for(ADChannel=0;ADChannel<4;ADChannel++)

        {

                g_adc_data_point[ADChannel] = 0;

        }

        ADChannel=0;

        ADMUX = 0x40+(ADChannel);//参考源VCC,右对齐,选择0通道。

        ADCSRA|=(1<<ADSC);//启动转换

        for (;;)

        {

                OSSemPend(ADCOKSem,0,&err);



                g_adc_data_point[ADChannel] = g_adc_data*7;

                //PRINT("g_adc_data_point[%d] = %d,g_adc_data = %d\r
",ADChannel,g_adc_data_point[ADChannel],g_adc_data);

                g_adc_data = 0;

                ADChannel=(ADChannel<3)?(ADChannel+1):0;

                ADMUX = 0x40+(ADChannel);//参考源VCC,右对齐,选择0通道。

                //_delay_us(1);

                OSTimeDlyHMSM(0,0,0,1);

                ADCSRA|=(1<<ADSC);//启动转换

        }

}



void TaskStart (void *data)

{

        INT8U   i;

        //char    s[10];

       

        data = data;                                        /* Prevent compiler warning                         */

                                                                                                                /*

                                                                                                                * Enabling of timer interrupt is moved from AvrInit() to here as suggested by to book

                                                                                                                * JLu 01/2003        */

        PRINT(">>>>>>>>>>The Real-Time Kernel,Vision %d<<<<<<<<<<<<<<<",(INT16U)OSVersion());

        g_speaker_time = 5;

        Speaker_ON();

        OS_ENTER_CRITICAL();

        /*   TCCR0=0x05;                                 /\* on some processors other than mega128 *\/ */

        TCCR0=0x07;                                         /* Set TIMER0 prescaler to CLK/1024                 */

        TIMSK=_BV(TOIE0);                                                                        /* Enable TIMER0 overflow interrupt                 */

        //#define TCNT0     _SFR_IO8(0x32)

        TCNT0=256-(CPU_CLOCK_HZ/OS_TICKS_PER_SEC/1024);     /* Set the counter initial value                    */

        OS_EXIT_CRITICAL();

       

        OSStatInit();                                       /* Initialize uC/OS-II's statistics */

        UartRxSem  = OSSemCreate(0);   

        UsbEventSem = OSSemCreate(0);

        ADCOKSem = OSSemCreate(0);

        OSTaskCreate(TaskSerialProcess, (void *)0, (void *)&TaskStk[0][TASK_STK_SIZE - 1], 1);



        OSTaskCreate(TaskADCDataDaq, (void *)0, (void *)&TaskStk[2][TASK_STK_SIZE - 1], 3);

       

        //PRINT("#TasksID         : 0x%05x  CPU Usage: %02d%\r
",(INT16U)OSTaskCtr,OSCPUUsage);

        //PRINT("#Task switch/sec : %d \r
",(INT16U)OSCtxSwCtr);

        OSCtxSwCtr = 0;

        /////////////////////////使能看看门狗//////////////////////////////////////

        /*

        PRINT("Star Watch Dog....\r
");

        WDR();

        WDTCR = (1<<WDCE)|(1<<WDE);

        WDTCR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);

        //g_WatchDogEn = 1;

        */

        //////////////////////////////////////////////////////////////////////////

        Speaker_OFF();

        while(1)

        {

                WDR();

                LedRun_ON();

                for(i=0;i<5;i++)

                {

                        OSTimeDlyHMSM(0,0,0,10);

                        OSTimeDly(1);            // 延时0.1秒

                        if(g_speaker_time>0)

                        {

                                g_speaker_time--;

                        }

                }

                //OSTimeDlyHMSM(0,0,0,4);

                LedRun_OFF();

                for(i=0;i<5;i++)

                {

                        OSTimeDly(10);            // 延时0.5秒

                        if(g_speaker_time>0)

                        {

                                g_speaker_time--;

                        }

                }

                if(g_speaker_time>0)

                {

                        Speaker_ON();

                }

                else

                {

                        Speaker_OFF();

                }

                //OSSemPost(UsbEventSem);

        }

}

/*

*************************************************************************************************

*                                           硬件的初始化

*************************************************************************************************

*/

void PortInit(void)

{

        //不用的管脚使能内部上拉电阻。

        DDRA=0xFF;

        PORTA=0xFF;

               

}

//#define BAUDRATE 57600UL

#define BAUDRATE 115200UL

void AvrInit (void)

{

        /////////////////////////关闭看门狗////////////////////////////////////

        WDR();

        WDTCR = (1<<WDCE)|(1<<WDE);

        WDTCR |= 0B00010111;//(0<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);

        //////////////////////////////////////////////////////////////////////////

        //串口0初始化

        UCSR0B = 0x00;

        UCSR0C = (1<<UCSZ1)|(1<<UCSZ0);        //(1<<URSEL)|异步,8位数据,无奇偶校验,一个停止位,无倍速

        UBRR0L = (F_CPU/BAUDRATE/16-1)%256;                        //设定波特率

        UBRR0H = (F_CPU/BAUDRATE/16-1)/256;

        UCSR0A = 0x00;

        UCSR0B = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);                                //使能接收,使能发送

        //UCSR0B = (1<<TXCIE)|(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);//使能接收中断,使能接收,使能发送

       

        //外部SRAM/XMEM 使能       

        MCUCR |= (1 << SRE) | (1 << SRW10);

        //等待两个时钟周期

        XMCRA |= (1 << SRW11) | (1 << SRW01) | (1 << SRW00);

       

        PortInit();



       

       

        ADMUX = (0<<REFS1)|(1<<REFS0)|(0<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);//参考源VCC,右对齐,选择0通道。

        ADCSRA= (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0); //使能ADC,时钟128分频 125KHz@8MHz system clock



        fdevopen((void*)sendChar0,0);     //使用sendChar0作为输出

       

}

int main (void)

{

        AvrInit(); // 硬件初始化



        OSInit();

       

        OSTaskCreate(TaskStart, (void *)0, (void *)&TaskStartStk[TASK_STK_SIZE - 1], 0);

       

        PRINT("OS Star.....\r
");

        OSStart();                                          // 开始多任务处理



        return 0;

}





/****************************************************************************************/

/************************************OS中断处理******************************************/

/****************************************************************************************/



UCOSISR(SIG_ADC) //ADC中断服务程序

{

       

        PushRS();

        OSIntEnter();

        if (OSIntNesting == 1)

                OSTCBCur->OSTCBStkPtr = (OS_STK *)SP;

        //硬件自动清除ADIF标志位

        //int data;

    g_adc_data=ADC; //读取结果

        //g_adcInt_OK=1;

        OSSemPost(ADCOKSem);//发送转换完成信号

        OSIntExit();

        PopRS();

}









//串口1接收到数据

UCOSISR(SIG_UART0_RECV)

{

        uint8_t status,data;

        PushRS();

        OSIntEnter();

        if (OSIntNesting == 1)

                OSTCBCur->OSTCBStkPtr = (OS_STK *)SP;

       

        //        UartRxBuf[UartRxCounter++] = UDR0;

    status=UCSR0A;

    data=UDR0;

    if ((status & (_BV(FE) | _BV(DOR) | _BV(UPE)))==0)

    {

        UartRxBuf[UartRxCounter]=data;

        if (++UartRxCounter == UART0_RX_BUF_SIZE)

        {

            UartRxCounter=0;

        }

    }

        sendChar0(data);

        if(data=='\r')

        {

                unsigned char i;

                if(UartRxCounter<UART0_RX_BUF_SIZE)

                {

                        for(i = UartRxCounter;i<UART0_RX_BUF_SIZE;i++)

                                UartRxBuf = '\0';

                        UartRxCounter = 0;

                        sendChar0('
');

                        sendChar0('-');

                        sendChar0('>');

                        OSSemPost(UartRxSem);//发送数据接受完成信号

                }

        }

       

        OSIntExit();

        PopRS();

}

出0入0汤圆

 楼主| 发表于 2007-3-10 13:06:12 | 显示全部楼层
是不是在中断里不能POST 信号量????,不明白,现在没有办法试,板子在家里

出0入0汤圆

 楼主| 发表于 2007-3-10 13:07:17 | 显示全部楼层
那位DX有过类似的应用,还望能够得到指点,谢谢

出0入0汤圆

发表于 2007-3-10 13:32:37 | 显示全部楼层
*                                     (标志信号量的旗帜,标志某事件发生)

*                                                     |

*                                                     |

*                     OSSemCreate()                   |           OSSemAccept()

*                     OSSemDel()                      |           OSSemPend()

*        |----------| OSSemPost()                     V           OSSemquery() |--------|

*        |   TASK   |--------------|                           |-------------->|  TASK  |

*        |----------|              |         (0)    |--|       |               |--------|

*                                  |          |     |  |       |

*                                  |--------> |- 或 |--| ----->|

*                                  |          |-    |          |

*        |----------|  OSSemPost() |                           | OSSemAccept() |--------|

*        |    ISR   |--------------|          ^                |-------------->|   ISR  |

*        |----------|                         |                                |--------|

*                                      (互斥条件的钥匙)

*

出0入0汤圆

 楼主| 发表于 2007-3-10 13:37:06 | 显示全部楼层
这样来看,在中断里发送信号量应该没有问题啊

出0入0汤圆

发表于 2007-3-10 15:47:07 | 显示全部楼层
懒得看楼主的代码,直接说说个人的一点猜测好了



一般初学者用RTOS最常出现的一个问题就是



堆栈溢出



再加上m64只有区区4K RAM……



请仔细计算一下每个任务的最大栈消耗(不要光看明面上的变量定义,也要把任务切换和函数调用的隐含开销算进去),然后看看你分配的到底够不够吧

出0入0汤圆

 楼主| 发表于 2007-3-10 16:13:16 | 显示全部楼层
谢谢watercat的指导,感谢

出0入0汤圆

 楼主| 发表于 2007-3-10 16:15:40 | 显示全部楼层
我现在的堆栈是128字节,我想可能是ADC消耗较多,但我不知道如何计算应该用多大的堆栈,

出0入0汤圆

发表于 2007-3-10 22:41:33 | 显示全部楼层
感觉像是中断问题引起的 ................感觉中断应该用汇编处理好再调用C函数入口........

出0入0汤圆

发表于 2008-3-11 18:45:26 | 显示全部楼层
laoma大虾,我也是遇到了ucos中使用串口接收的问题,好像不会中断一样,但初始化都正确了,我也增加了AVRvect.S中有关串口的处理,如下:
.global SIG_UART_RECV
SIG_UART_RECV:
             PUSHREGS
             in        r16,_SFR_IO_ADDR(SREG)
             ori       r16,0x80
             push    r16
  
             lds      r16,OSIntNesting
             inc      r16
             sts      OSIntNesting,r16

             .extern  UART_RECV
             call       UART_RECV

             call     OSIntExit

             pop     r0
             out     _SFR_IO_ADDR(SREG),r0
             POPREGS
             reti
UART_RECV函数是我自己的应用程序,已经有的了,但好像并没有调用到。不知道上面所增加的中断处理是否有问题,请指教,谢谢!

出0入0汤圆

发表于 2008-3-11 20:50:50 | 显示全部楼层
上面程序是正确的,是我在初始化中搞错了。

出0入0汤圆

发表于 2008-3-12 00:50:29 | 显示全部楼层
中断函数不建议由编译器管理,那样会造成重复压栈动作。如9楼里的通过call调用。

中断实现中,除POST等信号之外,尽量不要调用其它函数。

出0入0汤圆

发表于 2011-12-18 13:47:33 | 显示全部楼层
回复【楼主位】redsnow
-----------------------------------------------------------------------

你好 请问你这个问题解决了吗 我现在也遇到了这个问题 回复【2楼】redsnow
-----------------------------------------------------------------------
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 17:35

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表