以太网DMA方式,定时器4中断延后的原因?

[复制链接]
4388|7
 楼主| buyadong 发表于 2012-4-12 15:51 | 显示全部楼层 |阅读模式
本帖最后由 buyadong 于 2012-4-12 15:52 编辑

在做的一个项目中,使用STM32F107VCT6,同时需要使用红外遥控,其中,ETH使用DMA方式,38K载波使用定时器1产生,同时定时器4控制每段载波的长度,在启动时,设置定时器4的CCR1值,与CNT值比较匹配后产生中断,模式为TIM_OCMode_Timing,
    问题是  当有网络数据交换时,定时器4进入中断的时间后延后,比如置CCR1为560,定时器4分频后时钟为1MHz,但是进入比较中断时,读取CNT值,约为650,在拔掉网线后,读取CNT值就是560。
     关于定时器4的中断优先级,设置的分组2,TIM4中断先占优先级为0,以太网中断先占优先级为3,同时在以太网中断中只是发送信号量,并且未使用OS_ENTER_CRITICAL,即定时器4为最高优先级,可以在以太网中断中进行嵌套。
     不明白是何原因导致的,下面是代码:

  1. void ethernetif_input_task(void *arg)
  2. {
  3.     unsigned char  temp_err;

  4.     unsigned short count = 1;
  5.     while (1)
  6.     {
  7.         OSSemPend(Lwip_EthInputSem,20, &temp_err);
  8.         if (temp_err == OS_ERR_NONE)
  9.         {
  10.                while(ETH_GetRxPktSize() != 0)
  11.                 {     
  12.                    temp_err = ethernetif_input(g_pNetif);
  13.                 }
  14.         }
  15.         else if (temp_err == OS_TIMEOUT)
  16.         {
  17.         }
  18.     }
  19. }

  1. void ETH_IRQHandler(void)
  2. {
  3.   err_t err;
  4.   OS_CPU_SR  cpu_sr = 0u;
  5.   //OS_ENTER_CRITICAL();
  6.   OSSemPost(Lwip_EthInputSem);
  7.   ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
  8.   ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
  9.   //OS_EXIT_CRITICAL();
  10. }
TIM4进入中断后,改变CCR1的值,同时将CNT清0.
 楼主| buyadong 发表于 2012-4-12 15:59 | 显示全部楼层
本帖最后由 buyadong 于 2012-4-12 16:01 编辑

下面是定时器4部分代码:

  1. TIM_BaseInitStructure.TIM_Period = 20000;       /* 超时时间20ms */
  2.     TIM_BaseInitStructure.TIM_Prescaler = 71;
  3.     TIM_BaseInitStructure.TIM_ClockDivision = 0;
  4.     TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  5.     TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
  6.     TIM_TimeBaseInit(TIM4, &TIM_BaseInitStructure);
  7.    
  8.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;                             
  9.     TIM_OCInitStructure.TIM_Pulse = 20000;                                          
  10.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  11.     TIM_OC1Init(TIM4, &TIM_OCInitStructure);  
  12.    
  13.     TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
  14.     TIM_ITConfig(TIM4, TIM_IT_CC1, DISABLE);
  15.     TIM_Cmd(TIM4, DISABLE);

  16. uint8_t IRSendStart(uint8_t id)
  17. {
  18.     uint8_t err = 0;                                                   
  19.     memset((void *)&IRListSendbuf,0,sizeof(IRListFlashTypedef));
  20.     err = IRReadList(&IRListSendbuf,id); /* 查看是否成功读取到所要的数据*/
  21.     if(err > 0)                                               
  22.       return err;
  23.     IRSendPend();
  24.     IRPWMEnable(1);
  25.    
  26.    
  27.     TIM_Cmd(TIM4, ENABLE);
  28.     TIM_SetCounter(TIM4,IRListSendbuf.IRPointTimeValue[0]);   /* 手动清除定时器计数值     */
  29.     TIM_SetCompare1(TIM4,IRListSendbuf.IRPointTimeValue[0]+3);
  30.     TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
  31.     TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);
  32.     return err;
  33. }
  34. static void IRPWMEnable(uint8_t flag)
  35. {
  36.   TIM_SetCounter(TIM1,0);        /* 手动清除定时器计数值     */
  37.   if(flag){
  38.     TIM_CtrlPWMOutputs(TIM1,ENABLE);
  39.   }
  40.   else{
  41.     TIM_CtrlPWMOutputs(TIM1,DISABLE);
  42.   }
  43. }
  44. void TIM4_IRQHandler(void)
  45. {
  46.     uint16_t szValue  = 0;
  47. #if USE_OS_EN  
  48.     OS_CPU_SR  cpu_sr = 0u;
  49.     OS_ENTER_CRITICAL();
  50. #endif //USE_OS_EN
  51.   szValue = TIM_GetCounter(TIM4);
  52.   if(TIM_GetITStatus(TIM4, TIM_IT_CC1) == SET){   /* 查询是否是溢出中断 */
  53.     TIM_ClearFlag(TIM4, TIM_FLAG_CC1);            /* 清除中断标志       */
  54.     if(IRListSendbuf.IRPointTimeValue[1] == 0){   /* 若第二个字节为0,则说明为空*/
  55.       IRErr = IR_SEND_ERR;                        /* 发送错误        */
  56.       OSMboxPost(IRSendMbox,&IRErr);              /* 发送邮箱         */
  57.       IRPWMEnable(0);
  58.       TIM_ITConfig(TIM4, TIM_IT_CC1, DISABLE);
  59.       IRListSendIndex  = 0;
  60.       IRListSendCnt    = 0;
  61.       return;
  62.     }
  63.     if(((IRListSendbuf.IRPointTimeValue[IRListSendIndex] == 0x00)&&(IRListSendIndex != 0))\
  64.       ||(IRListSendIndex >= IRMAXPOINT - 2)){       /* 判断是否已经到最后 */
  65.                                                     /* 结束发送 */
  66.       IRPWMEnable(0);                               /* 禁止输出 */
  67.       TIM_ITConfig(TIM4, TIM_IT_CC1, DISABLE);
  68.       IRErr = IR_SEND_COMP;                         /* 发送完成         */
  69.       OSMboxPost(IRSendMbox,&IRErr);                /* 发送邮箱         */
  70.       IRListSendIndex  = 0;
  71.       IRListSendCnt    = 0;
  72.     }else{
  73.       IRListSendIndex++;
  74.       TIM_SetCompare1(TIM4,IRListSendbuf.IRPointTimeValue[IRListSendIndex]);
  75.       if((IRListSendIndex%2) != 0){        /* 奇数位为输出载波                 */
  76.         IRPWMEnable(1);                     /* 允许输出 */
  77.       }else{                               /* 偶数位为不输出载波               */
  78.         IRPWMEnable(0);                    /* 禁止输出 */
  79.       }
  80.       TIM_SetCounter(TIM4,0);              /* 手动清除定时器计数值 */
  81.     }
  82.   }
  83. #if USE_OS_EN
  84.     OS_EXIT_CRITICAL();
  85. #endif //USE_OS_EN
  86. }
 楼主| buyadong 发表于 2012-4-12 16:02 | 显示全部楼层
呼叫版主@版主 @香水城
 楼主| buyadong 发表于 2012-4-12 16:07 | 显示全部楼层
特别是这段
while(ETH_GetRxPktSize() != 0)
{     
      temp_err = ethernetif_input(g_pNetif);
}
经常有很多包,要循环读取直到所有包读取完,将这个地方如果注释掉,就没有问题。
香水城 发表于 2012-4-12 16:20 | 显示全部楼层
呼叫版主@版主 @香水城
buyadong 发表于 2012-4-12 16:02


对不起,对于你的问题,我无能为力。

评分

参与人数 1威望 +1 收起 理由
buyadong + 1 很给力!

查看全部评分

 楼主| buyadong 发表于 2012-4-12 16:35 | 显示全部楼层
对不起,对于你的问题,我无能为力。
香水城 发表于 2012-4-12 16:20

还是谢谢版主的支持
river_huang 发表于 2012-4-13 12:11 | 显示全部楼层
以太网是选用的那一颗?  DM9000还是DM9161
 楼主| buyadong 发表于 2014-11-20 09:51 | 显示全部楼层
最后原因还是由于以太网的中断优先级比较高,导致定时器中断呗延后导致
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

11

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部