luozhongchao123 发表于 2012-9-26 22:33:11

FreeRTOS 还叫实时系统吗?STM32F4中断延迟居然>100us.

本帖最后由 luozhongchao123 于 2012-9-26 22:36 编辑

rt
FreeRTOS 是7.20版支持 FPU的,单片机主频168M,平台是 STM32F4-Discovery

不知道是不是我的测试方法有问题?进入定时器中断后立刻读取TIM7的计数器值,然后保存在一个数组中,等1000次中断后开始计算!!

那里有问题?麻烦高手指点一二啊!!谢过!!!
下面是测试代码:
void TIM7_IRQHandler(void)
{
        //在主频为168MHz时机器周期为 5.95 ns 左右
        static uint32_t time=0,time3=0;
        static uint32_t time2=0xffffffff;
        static u16 time_temp=0;
        static u8 isFirst=1;
        u32 temp;
        u16 loop;
        time_temp= TIM7->CNT;
        ttt = time_temp;//用1000个数组存储定时器进入中断后自动将计数值清理
        if(iii == 1000)
        {
                if(isFirst == 1)//第一次的数据不能用
                {
                        iii   =0;
                        temp=0;               
                        isFirst = 0;
                  
                }
                else
                {
                        iii   =0;
                        temp=0;
                        for(loop = 0; loop < 1000;loop++)
                        {       
                                temp += ttt;                                       
                                if(time<ttt)
                                {
                                        time = ttt;//测出最大值
                                }
                                if(time2 >ttt)
                                {
                                        time2 = ttt;//测出最小值
                                }                                
                                                 
                        }
       
                        time3 = temp/1000;                //测出平均值
                        loop=0;               
               
                }

         }
               

}

NJ8888 发表于 2012-9-26 22:36:13

for(loop = 0; loop < 1000;loop++)
                        {      
                              temp += ttt;                                       
                              if(time<ttt)
                              {
                                        time = ttt;//测出最大值
                              }
                              if(time2 >ttt)
                              {
                                        time2 = ttt;//测出最小值
                              }                                 
                                                   
                        }
你的中断中为何要写循环?

luozhongchao123 发表于 2012-9-26 22:37:50

为了计算 最大值、最小值、平均值啊!有问题?

luozhongchao123 发表于 2012-9-26 22:49:46

改进一下测试方法?只测试最大值:
void TIM7_IRQHandler(void)
{
        static uint32_t time_max=0x00;       
        uint16_t temp_time;
        temp_time= TIM7->CNT;
        if(temp_time > time_max)
        {
               time_max = temp_time;

        }
    TIM_ClearITPendingBit(TIM7, TIM_IT_Update);

}
测试出来:time_max = 29890最大延迟 = (29890*5.95)/1000 = 177.8 US

luozhongchao123 发表于 2012-9-26 22:51:52

那里出问题了??高人指点一下啊!

liwei_jlu 发表于 2012-9-26 22:54:38

linux中断也能达到40us,何况这种内核,肯定不会100us的

luozhongchao123 发表于 2012-9-26 22:55:58

TIM7的配置:
void TIM_Config(void)
{
/* -----------------------------------------------------------------------
    TIM3 Configuration: Output Compare Timing Mode:
   
    In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1),
    since APB1 prescaler is different from 1.
        PCLK1 = HCLK / 4
        TIM3CLK = 2 * PCLK1   => TIM3CLK = HCLK / 2 = SystemCoreClock /2=84 MHz
                      
        if want To get TIM3 counter clock at 50 MHz, the prescaler is computed as follows:
        Prescaler = (TIM3CLK / TIM3 counter clock) - 1
        Prescaler = ((SystemCoreClock /2) /50 MHz) - 1
----------------------------------------------------------------------- */

        TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);

        /* Time base configuration */
        TIM_TimeBaseStructure.TIM_Period = 30000;
        TIM_TimeBaseStructure.TIM_Prescaler = 0 ;
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;       
        TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
       
        /* TIM Interrupts enable */
        TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
       
        TIM_Cmd(TIM7, ENABLE);

}

luozhongchao123 发表于 2012-9-26 22:56:47

liwei_jlu 发表于 2012-9-26 22:54 static/image/common/back.gif
linux中断也能达到40us,何况这种内核,肯定不会100us的

能说说我出错的地方在那里吗?

trey21ic 发表于 2012-9-26 23:02:50

RTOS进入中断的时延是不是应该如下计算:

void TIM7_IRQHandler(void)
{
      static uint32_t time_max=0x00;      
      uint16_t temp_time;
       temp_time= TIM7->CNT - <理论定时值>;
      if(temp_time > time_max)
      {
               time_max = temp_time;

      }
    TIM_ClearITPendingBit(TIM7, TIM_IT_Update);

}

lbswind 发表于 2012-9-26 23:02:50

不明白你要测什么!
每次进中断读取定时器计数值,有何意义?难道说你设定100us定时,可最大177.8us才中断一次?
FreeRTOS应该不至于此!!是不是你的系统中有其他优先级更高的中断打断了~~

luozhongchao123 发表于 2012-9-26 23:08:42

trey21ic 发表于 2012-9-26 23:02 static/image/common/back.gif
RTOS进入中断的时延是不是应该如下计算:

void TIM7_IRQHandler(void)


因为每次进入中断后TIM的计数器自动清零啊,所以进中断后直接读取从新计数的值就行了啊??有问题?

luozhongchao123 发表于 2012-9-26 23:10:39

lbswind 发表于 2012-9-26 23:02 static/image/common/back.gif
不明白你要测什么!
每次进中断读取定时器计数值,有何意义?难道说你设定100us定时,可最大177.8us才中断 ...

现在只有一个TIM7 向上计数溢出中断啊!
void NVIC_Configuration(void)
{

        NVIC_InitTypeDef NVIC_InitStructure;

        /* Enable the TIMx gloabal Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

}

trey21ic 发表于 2012-9-26 23:13:51

不明白你要怎么测,不过建议你确定如下几点:
1、中断是否有嵌套,是否可能被高优先级的中断打断。
2、检查程序中的临界保护
3、确认每次进入中断后TIMER的计数器是否会自动清零。
4、任务切换是否过于频繁(任务切换时有临界保护)

luozhongchao123 发表于 2012-9-26 23:18:03

trey21ic 发表于 2012-9-26 23:13 static/image/common/back.gif
不明白你要怎么测,不过建议你确定如下几点:
1、中断是否有嵌套,是否可能被高优先级的中断打断。
2、检查 ...

只有一个中断啊?怎么会有中断嵌套呢?定时器的计数器值在每次每次进入中断后回自动清理的啊!所以在中断中直接读取计数器清零后从新计数的值,应该就是中断发生后的延迟啊!!

luozhongchao123 发表于 2012-9-26 23:24:17

本帖最后由 luozhongchao123 于 2012-9-26 23:26 编辑

luozhongchao123 发表于 2012-9-26 23:31:34

怎么没人提示一下那里出问题了呢?

luozhongchao123 发表于 2012-9-26 23:42:57

老是看见大家讨论、比较各种RTOS,怎么就没人去亲自测试一个自己用的RTOS的各种性能呢?

cheungman 发表于 2012-9-26 23:57:50

求freertos, rt-thread, vxwork, linux, wince, android等os的中断延时时间参数.

luozhongchao123 发表于 2012-9-27 20:51:00

cheungman 发表于 2012-9-26 23:57 static/image/common/back.gif
求freertos, rt-thread, vxwork, linux, wince, android等os的中断延时时间参数.

很多人讨论就是没讨论到实质上去!!

BeichenPeng 发表于 2012-9-27 23:12:25

luozhongchao123 发表于 2012-9-26 22:49 static/image/common/back.gif
改进一下测试方法?只测试最大值:
void TIM7_IRQHandler(void)
{


你解释一下你的计算是什么意思,看不懂,你定义了一个1秒的定时器,所以最大延迟就是1秒?

测试出来:time_max = 29890最大延迟 = (29890*5.95)/1000 = 177.8 US

shjw 发表于 2012-12-15 11:29:20

本帖最后由 shjw 于 2012-12-15 11:36 编辑

我的freertos程序中定时中断>2-3ms,怎么回事?时间改短了就会出现数学错误!如果中断代码改少中断时间更少。我怎么把定时时间改的更小呢,只能减小中断代码?
我的用的dspic33fj128gp706A,运行主频40M(指令周期需要两个时钟),用的是Time2
void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void)
{
LedScan(&LedScanData,LEDBlink);        /* Insert ISR Code Here*/       
IFS0bits.T2IF = 0;            /* Clear Timer1 interrupt */
}

void LedScan(unsigned int *Data595,unsigned char blink)
{
   static unsigned char DimmerTimes;
               
PORTD &= ~((1 << 1) + (1 << 2) + (1 << 3) + (1 << 4));
DimmerTimes++;
if((DimmerTimes % DimmerTimesValue) == 1)
{               
    _HC595RCLK_Port        = 0;
    Hc595OutByte(Data595);       
    _HC595RCLK_Port        = 1;
    PORTD |= (1 << 1);          
}
else if((DimmerTimes % DimmerTimesValue) == 2)       
{               
    _HC595RCLK_Port        = 0;
    Hc595OutByte(Data595);       
    _HC595RCLK_Port        = 1;       
    PORTD |= (1 << 2);       
}       
else if((DimmerTimes % DimmerTimesValue) == 3)               
{                               
   _HC595RCLK_Port        = 0;
   Hc595OutByte(Data595);
    _HC595RCLK_Port        = 1;       
    PORTD |= (1 << 3);
}
else if((DimmerTimes % DimmerTimesValue) == 0)                       
{       
    DimmerTimes = 0;                       
    static unsigned char BlinkTimes;
    if(!blink)
    {
      BlinkTimes = 0;               
      _HC595RCLK_Port        = 0;
      Hc595OutByte(Data595);       
      _HC595RCLK_Port        = 1;       
      PORTD |= (1 << 4);                               
    }
    else
    {
      BlinkTimes ++;
      if(BlinkTimes < 50)
      {               
      _HC595RCLK_Port        = 0;
      Hc595OutByte(Data595);               
      _HC595RCLK_Port        = 1;       
      PORTD |= (1 << 4);                                                      
      }
      else
      {
      _HC595RCLK_Port        = 0;
      Hc595OutByte( Data595 & 0x0270);                                     
      _HC595RCLK_Port        = 1;       
      PORTD |= (1 << 4);
      if(BlinkTimes == 100)               
              BlinkTimes = 0;          
      }       
    }
}
}
74hc595的驱动
void Hc595OutByte(unsigned int Data)
{
unsigned char i;
for(i = 0;i < 16;i ++)
{
    if(Data & 0x8000)
    {
      _HC595Data_Port        = 1;
    }
    else
    {
      _HC595Data_Port        = 0;
    }
    Data <<= 1;

    _HC595CLK_Port = 1;
    _HC595CLK_Port = 0;   
}
}
time2初始化
#define T2Period   15000      //40M   八分频   1/40 / 8 * 15000 = 3ms
void T2init(void)
{
//SRbits.IPL = 3;         /* enable CPU priority levels 4-7*/
T2CONbits.TON = 0;// Disable Timer
T2CONbits.TCS = 0;// Select internal instruction cycle clock
T2CONbits.TGATE = 0;// disenable Gated Timer mode
T2CONbits.TCKPS = 0b01;// Select 1:1 Prescaler
TMR2 = 0x00; // Clear timer register
PR2 = T2Period; // Load the period value
IPC1bits.T2IP = 0x01;// Set Timer1 Interrupt Priority Level
IFS0bits.T2IF = 0;// Clear Timer1 Interrupt Flag
IEC0bits.T2IE = 1;// Enable Timer1 interrupt
T2CONbits.TON = 1;// Start Timer
}更改原因:对齐代码

rtems 发表于 2012-12-15 12:50:48

兄弟,标准的测量方法不是这样的。应该这样,中断管脚接一个脉冲源发脉冲,中断服务程序里面第一条指令就是翻转某个I/O的状态,用示波器抓脉冲源和输出I/O翻转,计算时间。

shjw 发表于 2012-12-15 13:28:06

我测试了在中断IO翻转就是3MS,然后才把程序写上去的。
如果中断代码就IO翻转的话,中断时间可以更短。

maimaige 发表于 2012-12-15 15:08:06

你能描述一下,你的测试原理吗?
是这样吗?
1.使能定时器7,给它一个初值,并且使能定时器7定时中断,
2,等到定时器7规定的时间到了,执行那个中断函数TIM7_IRQHandler。
3.TIM7_IRQHandler的作用是读取当前定时器7中的计数器值
如果是这样的话,每次读的值应该一样吧,根据你对定时器初值和定时时间的不同,这个值也不一样

aworker 发表于 2012-12-15 15:18:47

中断和操作系统有关系么?操作系统不能控制外设中断才对啊。

Elec_Ramble 发表于 2012-12-16 19:32:00

同意楼上,我认为中断的响应是硬件的指标,和OS没关系…
来自:amoBBS 阿莫电子论坛 Windows Phone 7 客户端

shjw 发表于 2012-12-17 08:43:22

我认为有关系,中断要占用操作系统的RAM,太频繁中断会一直切换更可能导致系统崩溃,我感觉我的程序就是这样。呵呵

pocker5200 发表于 2012-12-17 10:39:04

测试方法问题……数据处理程序是不能写在中断函数里面的,中断函数尽可能的要短。
1000次循环判断那部分代码结构是造成延迟的最大问题,首先就是循环和判断的代码相关度不高,编译器难以优化,执行过程中要打断指令流水线,
1000次循环跑下来累计的指令周期延时也是相当可观的,22楼的测试方法可以参考,我也这么测试过,一个200M的逻辑分析仪应该是够了。

shjw 发表于 2013-1-8 14:13:07

我把子程序直接写到中断函数,中断时间就可以改短了。不知道是不是函数重入的问题还得去学习一下

hyf88 发表于 2015-7-17 11:34:26

实时是什么概念的?! 快就是实时的指标 吗?

strongking 发表于 2015-7-22 08:43:12

兄弟,标准的测量方法不是这样的。应该这样,中断管脚接一个脉冲源发脉冲,中断服务程序里面第一条指令就是翻转某个I/O的状态,用示波器抓脉冲源和输出I/O翻转,计算时间。
STM32F103 我用示波器测试 二值信号量 中断延迟任务切换只要4-8个us

匿名顽徒 发表于 2015-12-22 12:46:12

应该是你的定时器级别低于任务级别
页: [1]
查看完整版本: FreeRTOS 还叫实时系统吗?STM32F4中断延迟居然>100us.