jusan520 发表于 2010-5-26 13:55:32

是UCOS-II问题还是硬件中断出了问题

各位长辈及兄弟朋友:



我目前在做一项目,先描述一下大致应用情况:

板上MCU是LPC1766 Cortex-M3,UCOS-II移植的是V2.89

MCU外设使用情况:

串口0:用于上位机RS485通信,

串口1:用于GPRS模块,

串口2:用于采集数据(RS485总线挂了6个从设备),

串口3:用于液晶模块(192*64)

每个串口配置均为:115200,8,1 , 使能FIFO为一字节触发

每个串口独享一任务,任务优先级分别为:6,5,3,4。另外还有三个任务用于其他,优先级为:7,8,9

为了大致了解任务运行情况,7,8两个任务分别用于点亮两个LED,优先级7任务2秒闪烁一次,8一秒闪烁一次,

现在的情况是,在未加GPRS的串口通信模块,两个LED闪烁正常,但加上后出现奇怪的现象,两个LED就不再对称地闪烁,

用J-LINK仿真,观察串口1(用于GPRS模块)的接收和发送,发现发送正常,短信也能发出去,但中断接收确出现了

未接收完数据就自动退出中断的现象,如:本应该接收78字节数据,只接收了10几个字节。

实在是找不到原因了,还请各位高人指点一二,实乃感激不尽!

songzi2018 发表于 2010-5-26 20:05:48

ucos2一般不会出问题的,我们电力产品都在用,没有啥问题,
一定是你任务处理的问题,最重要的一点,中断里不要做太多的事情,还有高优先级的任务处理的事情不能太占时间,不然低优先级的任务就抢占不到cpu了,你的点灯就不准了

jusan520 发表于 2010-5-26 20:34:23

楼上的朋友,谢谢你回复,你说的情况我注意到了,关键是我把其他串口相关任务都屏蔽了,只留串口1还是只能收到部分数据就

退出中断了,真是奇怪之极。所以我开始怀疑我的初始化代码,我把代码贴出来,希望得到大家提点意见。需要说明的是串口1是

全功能串口,我初始化的时候我配置成普通串口在用,以下是这4个串口初始化的代码

/*
*********************************************************************************************************
*
* Added by Xiongpinghai,3/27/2010. $ Multi-serial can be INIT
*
*********************************************************************************************************
*/

voidUART_InitTarget (INT32Ubaud_rate, INT8U uart_x)
{   
    INT16Udiv;                                          
    INT8U       divlo;
    INT8U       divhi;
    INT32U      pclk_freq;
                                                               
                                                               

    pclk_freq= BSP_PM_PerClkFreqGet(BSP_PM_PER_NBR_UART0);
   
    div       = (INT16U)(((2 * pclk_freq / 16 / baud_rate) + 1) / 2);
    divlo   =div & 0x00FF;                              
    divhi   = (div >> 8) & 0x00FF;

    switch (uart_x)
    {
#if (LPC17_CFG_UART0_EN == DEF_ENABLED)
    case LPC17_UART_0:
      BSP_PM_PerClkEn(BSP_PM_PER_NBR_UART0);                        
      
                                                                     
      BSP_GPIO_Cfg(BSP_GPIO_PORT0_FAST,                              
                     USER_SER_U0_PINS,                              
                     BSP_GPIO_OPT_FNCT_2);
            
                                                                        
      U0LCR   = DEF_BIT_07;                                       
      U0DLL   = divlo;                                             
      U0DLM   = divhi;
      U0LCR   = 0x03;                                             
      U0IER   = 0x00;                                             
      U0FDR   = 0x00;                                             
      U0FCR   = 0x01;                                             
      
                                                                        
      BSP_IntVectSet((INT8U   )BSP_INT_SRC_NBR_UART0,      
                     (CPU_FNCT_VOID)UART0_ISR_Handler);
      
      BSP_IntEn(BSP_INT_SRC_NBR_UART0);
      break;
#endif
      
#if (LPC17_CFG_UART1_EN == DEF_ENABLED)
      case LPC17_UART_1:
            BSP_PM_PerClkEn(BSP_PM_PER_NBR_UART1);                     
      
                                                                     
            BSP_GPIO_Cfg(BSP_GPIO_PORT0_FAST,                        
                         USER_SER_U1_PINS,                              
                         BSP_GPIO_OPT_FNCT_2);
            
                                                                        
            U1LCR   = DEF_BIT_07;                                    
            U1DLL   = divlo;                                          
            U1DLM   = divhi;
            U1LCR   = 0x03;                                          
            U1IER   = 0x00;                                          
            U1FDR   = 0x00;                                          
            U1FCR   = 0x01;                                          
      
                                                                        
            BSP_IntVectSet((INT8U   )BSP_INT_SRC_NBR_UART1,      
                           (CPU_FNCT_VOID)UART1_ISR_Handler);
      
            BSP_IntEn(BSP_INT_SRC_NBR_UART1);
      break;
#endif
      
#if (LPC17_CFG_UART2_EN == DEF_ENABLED)
      case LPC17_UART_2:
            BSP_PM_PerClkEn(BSP_PM_PER_NBR_UART2);                     
                                                                        
            BSP_GPIO_Cfg(BSP_GPIO_PORT0_FAST,                           
                         USER_SER_U2_PINS,                           
                         BSP_GPIO_OPT_FNCT_2);
            
                                                                     
            U2LCR   = DEF_BIT_07;                                    
            U2DLL   = divlo;                                          
            U2DLM   = divhi;
            U2LCR   = 0x03;                                          
            U2IER   = 0x00;                                          
            U2FDR   = 0x00;                                          
            U2FCR   = 0x01;                                          
      
                                                                     
            BSP_IntVectSet((INT8U   )BSP_INT_SRC_NBR_UART2,      
                           (CPU_FNCT_VOID)UART2_ISR_Handler);
      
            BSP_IntEn(BSP_INT_SRC_NBR_UART2);
      break;
#endif
      
#if (LPC17_CFG_UART3_EN == DEF_ENABLED)
      case LPC17_UART_3:
            BSP_PM_PerClkEn(BSP_PM_PER_NBR_UART3);                     
               
                                                                     
            BSP_GPIO_Cfg(BSP_GPIO_PORT4_FAST,                           
                         USER_SER_U3_PINS,                           
                         BSP_GPIO_OPT_FNCT_4);
            
                                                                        
            U3LCR   = DEF_BIT_07;                                    
            U3DLL   = divlo;                                       
            U3DLM   = divhi;
            U3LCR   = 0x03;                                          
            U3IER   = 0x01;                                          
            U3FDR   = 0x00;                                          
            U3FCR   = 0x01;                                          
      
                                                                        
            BSP_IntVectSet((INT8U   )BSP_INT_SRC_NBR_UART3,      
                           (CPU_FNCT_VOID)UART3_ISR_Handler);
      
            BSP_IntEn(BSP_INT_SRC_NBR_UART3);
      break;
#endif
      
    default:
          break;
    }
}

songzi2018 发表于 2010-5-26 20:43:45

你可以停掉所有任务,就用一个任务点灯任务和一个GPRS任务来调试,不相关的中断也关掉,紧留下tick中断和uart中断(GPRS占用的那个口,其他的也停掉);这样排除一下,就可以确定是你的GPRS关联串口处理问题还是其他干扰问题了。
GPRS的设置,我就不大清楚了

jusan520 发表于 2010-5-26 21:27:23

回复【3楼】songzi2018
-----------------------------------------------------------------------

其实,我已经这样做了,屏蔽其他所有,只留串口1的相关代码,中断接收里面只有两行:

如:rx_buf = data;
    rx_ctr %= RX_BUF_MAX_MASK;

在这种情况下,都只能接收一部分就推出接受中断了,同事朋友都咨询了,没一个遇见这种情形过,后来我换了板子,还是一样。。。

我也是第一次遇见。。

还有一点就是,单步运行发现检测的中断标志位中,接收中断标志清零后才退出的,可明明有数据,因为我用另外的串口检测有完整的数据包回来。。

jusan520 发表于 2010-5-27 10:07:02

补充:

首先感谢你能看完我的帖子,再次我再补充点代码,以便大家能帮我解答。


下面是串口1中断处理:
#if (LPC17_CFG_UART1_EN == DEF_ENABLED)
voidUART1_ISR_Handler (void)
{
    INT8U lsr, iir, rx_data;
    pUART_SEM_t puart_sem;

    puart_sem   =UART_GetSem(LPC17_UART_1);
   
    iir = U1IIR & 0x0F;
    while (iir != 1)
    {
      switch (iir)
      {
      case2:                                          /* Transmitted character                               */
            BSP_OS_SemPost(&puart_sem->SerTxWait);          /* 信号量传递 */
            break;
      
      case4:                                          /* Received a character                              */
            lsr       = U1LSR;
            RxBuf   = U1RBR;
            RxCtr %= RX_BUF_MAX_MASK;      /* RX_BUF_MAX_MASK = 255 */

            break;
      
      default:
            break;
      }
      
      iir = U1IIR & 0x0F;
    }
}
#endif


下面是我的串口1初始化部分(补加了点注释):

#if (LPC17_CFG_UART1_EN == DEF_ENABLED)
      case LPC17_UART_1:
            PM_PerClkEn(PM_PER_NBR_UART1);          /* 使能外设时钟 */         
      
                                                                     
            GPIO_Cfg(GPIO_PORT0_FAST,                     
                         USER_SER_U1_PINS,                              
                         GPIO_OPT_FNCT_2);               /* 引脚配置RXD1,TXD1 */
            
                                                                        
            U1LCR   = DEF_BIT_07;                                     /* 使能存入分频值 */
            U1DLL   = divlo;                                          
            U1DLM   = divhi;
            U1LCR   = 0x03;                                           /* 8位            */
            U1IER   = 0x00;                                           /* 先禁止接收和发送中断 ,用的时候再开启*/
            U1FDR   = 0x00;                                          
            U1FCR   = 0x01;                                           /* 使能 FIFO, Rx & Tx   ,触发深度一字节             */
      

            BSP_IntVectSet((INT8U   )BSP_INT_SRC_NBR_UART1,       /* 配置中断入口 */
                           (CPU_FNCT_VOID)UART1_ISR_Handler);
      
            BSP_IntEn(BSP_INT_SRC_NBR_UART1);          /* 使能串口1中断 */
      break;
#endif



我之所以说“本应该接收78但只接收10几个字节”,只是想说明串口中断没有接完就退出了中断,即:U1IIR的BIT0已经为1,

指示串口无中断挂起,所以才退出了串口接收中断,但是我并接在485总线上的用于监视的串口调试助手确能接收完全部,

更让我困惑的是同样的方式,为什么串口0、2、3都是正常的,未读就串口1出现怪事,还请大家帮我看看!!

jusan520 发表于 2010-5-27 19:21:30

今天又折腾了一天。。。不过有点意外发现。

串口1我不接GPRS模块,而换接上PC的串口,并开启LPC1766的接收中断,板子运行起来后,用PC串口调试助手发一条字符串:

123456789112233445566778899

事先在串口1中断里面设置了断电,所以理所当然的进入了接收中断,F10单步执行,一直到退出中断,发现缓冲区里面接收到的

数据为:1234567891122334   

正好是FIFO的最大长度。。。FIFO我配置的是单字节触发,其他三个串口也一样的配置,为什么这个就只能接收16字节,后面的

数据全部丢失。。。其他的串口,如串口2是收集485总线上数据的,每次都是140~160的接收。

另外,不管我把FIFO设置 成1、4、8、14来触发,结果都一样。。奇怪了!!!

请各位朋友帮忙分析下,感激不尽啊!!

yuhui 发表于 2010-5-27 22:19:32

我曾经碰到过一个类似的问题,就是用调试器单步调试的时候,串口中断是进去了,而且在中断入口的地方 IIR最低位是1 是有中断挂起的,可一但按单步运行,就发现最低位就奇怪的变成0了。最后发现原因竟然出在调试器!

调试的时候我们会把某些寄存器如U0IIR U0LCR等等放在watch窗口看其实时的值,而你每按一次单步运行,调试器就会自动去读取这些寄存器的值,而调试器去读寄存器的作用和你的程序代码去读这些寄存器的效果是相同的,也就是说在你程序访问这些寄存器之前,调试器已经读过一次了!而常常我们会碰到一些状态寄存器的某些状态位只能被读一次就会自动清零。

你可以仔细查查,有可能是这方面的原因。

akin 发表于 2010-5-27 23:53:07

回复【7楼】yuhui
我曾经碰到过一个类似的问题,就是用调试器单步调试的时候,串口中断是进去了,而且在中断入口的地方 iir最低位是1 是有中断挂起的,可一但按单步运行,就发现最低位就奇怪的变成0了。最后发现原因竟然出在调试器!
调试的时候我们会把某些寄存器如u0iir u0lcr等等放在watch窗口看其实时的值,而你每按一次单步运行,调试器就会自动去读取这些寄存器的值,而调试器去读寄存器的作用和你的程序代码去读这些寄存器的效果是相同的,也就是说在你程序访问这些寄存器之前,调试器已经读过一次了!而常常我们会碰到一些状态寄存器的某些状态位只能被读一次就会自动清零。
你可以仔细查查,有可能是这方面的原因。
-----------------------------------------------------------------------
调试器是不能用于调试外设的。 printf 之类的函数插入到代码中作为调试手段才比较可靠对外设进行调试。

akin 发表于 2010-5-27 23:56:13

楼主的问题估计和7楼说的一致。
还是建议LZ用printf之类的函数把相关信息输出到一个调试用的串口进行观察。

jusan520 发表于 2010-5-31 13:30:34

7、8、9楼的三位仁兄,我的问题解决了。

在回复完6楼内容的当天,还未来得及看到你们的留言就已发现了是我手中J-LINK的“问题”,只因项目比较紧,未来得及查看论
坛帖子,对此深表歉意!

“J-LINK问题”我何处此言?

调试程序的时候我(或许大家)基本上都是单步走,而问题的关键就在这,手中的仿真器如若单步走下去将出现困扰我这几天来

的问题,但一旦全速运行就不会出现次问题。。。

其实我也是无意中解决问题的,正当对百思不得其解问题困惑、发愁、郁闷,甚至想拔掉电源时,无意中点了到了全速运行,

大概10秒钟我暂停后,发现串口缓冲区已收到串口助手发送的几十个字符。

就这样我屡试不爽!!!

问题解决之时,静下心来思考问题,为什么我总是一味重复单一的用同一种方式去解决问题?为什么不知道:“退一步海阔天空!”

痛定思痛啊!!!

在此,谢谢三位予我分享你们的成长经验!

虽然我此次算是解决了问题,但思来想去,最好的方式还是你们的printf方式!

river0830 发表于 2010-6-2 09:03:34

mark study!

yankaiyutong 发表于 2011-11-17 10:27:14

貌似我也遇到这样的问题了,UCOS下,在中断函数中停一下,在运行就出现硬件中断错误。全速运行正常。但是有个问题需要注意,如果取消PendSV_Handler的使用,则在中断函数中怎么停都没问题。不知道这是不是也是仿真器的问题。今晚回去换上ULINK试试看。
页: [1]
查看完整版本: 是UCOS-II问题还是硬件中断出了问题