打印

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

[复制链接]
3537|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为最高优先级,可以在以太网中断中进行嵌套。
     不明白是何原因导致的,下面是代码:

void ethernetif_input_task(void *arg)
{
    unsigned char  temp_err;

    unsigned short count = 1;
    while (1)
    {
        OSSemPend(Lwip_EthInputSem,20, &temp_err);
        if (temp_err == OS_ERR_NONE)
        {
               while(ETH_GetRxPktSize() != 0)
                {     
                   temp_err = ethernetif_input(g_pNetif);
                }
        }
        else if (temp_err == OS_TIMEOUT)
        {
        }
    }
}

void ETH_IRQHandler(void)
{
  err_t err;
  OS_CPU_SR  cpu_sr = 0u;
  //OS_ENTER_CRITICAL();
  OSSemPost(Lwip_EthInputSem);
  ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
  ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
  //OS_EXIT_CRITICAL();
}
TIM4进入中断后,改变CCR1的值,同时将CNT清0.
沙发
buyadong|  楼主 | 2012-4-12 15:59 | 只看该作者
本帖最后由 buyadong 于 2012-4-12 16:01 编辑

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

TIM_BaseInitStructure.TIM_Period = 20000;       /* 超时时间20ms */
    TIM_BaseInitStructure.TIM_Prescaler = 71;
    TIM_BaseInitStructure.TIM_ClockDivision = 0;
    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM4, &TIM_BaseInitStructure);
   
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;                             
    TIM_OCInitStructure.TIM_Pulse = 20000;                                          
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC1Init(TIM4, &TIM_OCInitStructure);  
   
    TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
    TIM_ITConfig(TIM4, TIM_IT_CC1, DISABLE);
    TIM_Cmd(TIM4, DISABLE);

uint8_t IRSendStart(uint8_t id)
{
    uint8_t err = 0;                                                   
    memset((void *)&IRListSendbuf,0,sizeof(IRListFlashTypedef));
    err = IRReadList(&IRListSendbuf,id); /* 查看是否成功读取到所要的数据*/
    if(err > 0)                                               
      return err;
    IRSendPend();
    IRPWMEnable(1);
   
   
    TIM_Cmd(TIM4, ENABLE);
    TIM_SetCounter(TIM4,IRListSendbuf.IRPointTimeValue[0]);   /* 手动清除定时器计数值     */
    TIM_SetCompare1(TIM4,IRListSendbuf.IRPointTimeValue[0]+3);
    TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
    TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);
    return err;
}
static void IRPWMEnable(uint8_t flag)
{
  TIM_SetCounter(TIM1,0);        /* 手动清除定时器计数值     */
  if(flag){
    TIM_CtrlPWMOutputs(TIM1,ENABLE);
  }
  else{
    TIM_CtrlPWMOutputs(TIM1,DISABLE);
  }
}
void TIM4_IRQHandler(void)
{
    uint16_t szValue  = 0;
#if USE_OS_EN  
    OS_CPU_SR  cpu_sr = 0u;
    OS_ENTER_CRITICAL();
#endif //USE_OS_EN
  szValue = TIM_GetCounter(TIM4);
  if(TIM_GetITStatus(TIM4, TIM_IT_CC1) == SET){   /* 查询是否是溢出中断 */
    TIM_ClearFlag(TIM4, TIM_FLAG_CC1);            /* 清除中断标志       */
    if(IRListSendbuf.IRPointTimeValue[1] == 0){   /* 若第二个字节为0,则说明为空*/
      IRErr = IR_SEND_ERR;                        /* 发送错误        */
      OSMboxPost(IRSendMbox,&IRErr);              /* 发送邮箱         */
      IRPWMEnable(0);
      TIM_ITConfig(TIM4, TIM_IT_CC1, DISABLE);
      IRListSendIndex  = 0;
      IRListSendCnt    = 0;
      return;
    }
    if(((IRListSendbuf.IRPointTimeValue[IRListSendIndex] == 0x00)&&(IRListSendIndex != 0))\
      ||(IRListSendIndex >= IRMAXPOINT - 2)){       /* 判断是否已经到最后 */
                                                    /* 结束发送 */
      IRPWMEnable(0);                               /* 禁止输出 */
      TIM_ITConfig(TIM4, TIM_IT_CC1, DISABLE);
      IRErr = IR_SEND_COMP;                         /* 发送完成         */
      OSMboxPost(IRSendMbox,&IRErr);                /* 发送邮箱         */
      IRListSendIndex  = 0;
      IRListSendCnt    = 0;
    }else{
      IRListSendIndex++;
      TIM_SetCompare1(TIM4,IRListSendbuf.IRPointTimeValue[IRListSendIndex]);
      if((IRListSendIndex%2) != 0){        /* 奇数位为输出载波                 */
        IRPWMEnable(1);                     /* 允许输出 */
      }else{                               /* 偶数位为不输出载波               */
        IRPWMEnable(0);                    /* 禁止输出 */
      }
      TIM_SetCounter(TIM4,0);              /* 手动清除定时器计数值 */
    }
  }
#if USE_OS_EN
    OS_EXIT_CRITICAL();
#endif //USE_OS_EN
}

使用特权

评论回复
板凳
buyadong|  楼主 | 2012-4-12 16:02 | 只看该作者
呼叫版主@版主 @香水城

使用特权

评论回复
地板
buyadong|  楼主 | 2012-4-12 16:07 | 只看该作者
特别是这段
while(ETH_GetRxPktSize() != 0)
{     
      temp_err = ethernetif_input(g_pNetif);
}
经常有很多包,要循环读取直到所有包读取完,将这个地方如果注释掉,就没有问题。

使用特权

评论回复
5
香水城| | 2012-4-12 16:20 | 只看该作者
呼叫版主@版主 @香水城
buyadong 发表于 2012-4-12 16:02


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

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
buyadong + 1 很给力!
6
buyadong|  楼主 | 2012-4-12 16:35 | 只看该作者
对不起,对于你的问题,我无能为力。
香水城 发表于 2012-4-12 16:20

还是谢谢版主的支持

使用特权

评论回复
7
river_huang| | 2012-4-13 12:11 | 只看该作者
以太网是选用的那一颗?  DM9000还是DM9161

使用特权

评论回复
8
buyadong|  楼主 | 2014-11-20 09:51 | 只看该作者
最后原因还是由于以太网的中断优先级比较高,导致定时器中断呗延后导致

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

11

帖子

1

粉丝