自适应分级轮询超时机制

自适应分级轮询超时机制

    • 超时概念
    • 实现原理
      • 基础:
      • 目标:
      • 实现:
      • 示例:



超时概念

程序运行中,操作后需要等待某个状态,正常返回,但实际未按预期状态出现,此时应该超时异常返回,不然会造成死循环。


实现原理

超时计数时间轴如下:

微秒计数
毫秒计数
开始: 0
微秒结束, 毫秒开始:N
超时:M

0到N为微秒计数,N到M为毫秒计数。计数从0开始,直到M表示超时异常返回,中间均为正常返回。

基础:

以vxwork系统为例,taskDelay(0)可为微秒级延时(cpu任务优先级调度);taskDelay(1)可为毫秒级延时(cpu释放一个时钟片)。
对于一个超时检测来说,超时计数粒度越小,返回越及时,保证运行速度,但会加重cpu负担;相反超时计数粒度越大,返回越慢,运行速度慢,但会释放更多的cpu。

目标:

a、保证程序正常运行时调整超时计数在微秒计数(0 -N)内,达到运行速度;
b、保证程序异常运行时调整超时计数在毫秒计数(N-M)内,达到cpu释放。

实现:

1、初始化超时M,为一个大于0的较小的值,最好按实际测试情况给定。毫秒计数(N-M)固定不变。
2、正常运行时,正常返回,若此时超时计数用到了毫秒计数(N-M),自动按步长L加到M上,如此多次调整后,超时计数最终落在微秒计数(0 -N)内。
3、异常运行时,超时返回,此时必定落在M点上,为了减小cpu的消耗,N和M同时按步长L减小,让超时计数尽可能落在N-M内。

示例:

可用在i2c、spi、eth等总线轮询等待情况。

/*
 * Function to ensure that the previous transaction was completed before
 * initiating a new transaction. It can also be used in polling mode to
 * check status of completion of a command
 * 注意: 此超时机制会自动调整超时次数。
 * 1,超时次数过短的话会自动增加超时次数,保证读取速率。
 * 2,总线异常的话会调整超时次数到最小值,控制cpu占用率。
 */
#define I2C_REG_R_TIMES_MIN     500 
unsigned int i2c_reg_r_times = 1000;/* 测试发现大约为1200,可自动向上调整修正 */
unsigned int i2c_reg_r_times_ajust_step = 10;
static int iproc_i2c_startbusy_wait(unsigned char bus)
{
    unsigned int reg_val;
    unsigned int check_times = 0;
    unsigned int check_times_now = i2c_reg_r_times;
    /* 末尾用10ms */
    unsigned int check_times_10ms = check_times_now - 3;

    do{
        /* 检查ok */
        reg_val = iproc_i2c_reg_read(bus, CCB_SMB_MSTRCMD_REG);
        if(0 == (reg_val & CCB_SMB_MSTRSTARTBUSYCMD_MASK)){
        
            /* 1,用到10ms延时,说明微秒级延时不够,需增加超时次数 */
            if(check_times > check_times_10ms){
                i2c_reg_r_times += i2c_reg_r_times_ajust_step;
            }
                
            return 0;
        }

        /* 10ms延时 */
        if(check_times > check_times_10ms){
            taskDelay(1);
        }
        /* 微秒级延时 */
        else{
            taskDelay(0);
        }

    }while(check_times++ < check_times_now);

    /* 2,超时,说明总线异常,大幅减少超时次数 */
    if(i2c_reg_r_times > I2C_REG_R_TIMES_MIN){
        i2c_reg_r_times -= i2c_reg_r_times_ajust_step * 4;
    }
    
    return -ETIMEDOUT;
}

你可能感兴趣的:(笔记,经验分享,程序人生,恰饭)