Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1148024
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: 嵌入式

2015-07-25 16:45:14

//如果你看不懂,不防先看我的博客里uC/OS-II的最高优先级查找和查表机制。




/*
*********************************************************************************************************
*                                  CPU COUNT LEAD ZEROs LOOKUP TABLE
*
* Note(s) : (1) Index into bit pattern table determines the number of leading zeros in an 8-bit value :
*
*                         b07  b06  b05  b04  b03  b02  b01  b00    # Leading Zeros
*                         ---  ---  ---  ---  ---  ---  ---  ---    ---------------
*                          1    x    x    x    x    x    x    x            0
*                          0    1    x    x    x    x    x    x            1
*                          0    0    1    x    x    x    x    x            2
*                          0    0    0    1    x    x    x    x            3
*                          0    0    0    0    1    x    x    x            4
*                          0    0    0    0    0    1    x    x            5
*                          0    0    0    0    0    0    1    x            6
*                          0    0    0    0    0    0    0    1            7
*                          0    0    0    0    0    0    0    0            8
*********************************************************************************************************
*/
cpu_core.c 
#if (!(defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) || \
      (CPU_CFG_DATA_SIZE_MAX > CPU_CFG_DATA_SIZE))
static  const  CPU_INT08U  CPU_CntLeadZerosTbl[256] = {                             /* Data vals :                      */
/*   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   */
    8u,  7u,  6u,  6u,  5u,  5u,  5u,  5u,  4u,  4u,  4u,  4u,  4u,  4u,  4u,  4u,  /*   0x00 to 0x0F                   */
    3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  3u,  /*   0x10 to 0x1F                   */
    2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  /*   0x20 to 0x2F                   */
    2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  2u,  /*   0x30 to 0x3F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x40 to 0x4F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x50 to 0x5F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x60 to 0x6F                   */
    1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  1u,  /*   0x70 to 0x7F                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0x80 to 0x8F                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0x90 to 0x9F                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xA0 to 0xAF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xB0 to 0xBF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xC0 to 0xCF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xD0 to 0xDF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  /*   0xE0 to 0xEF                   */
    0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u   /*   0xF0 to 0xFF                   */
};
#endif 
////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
************************************************************************************************************************
*                                           GET HIGHEST PRIORITY TASK WAITING
*
* Description: This function is called by other uC/OS-III services to determine the highest priority task
*              waiting on the event.
*
* Arguments  : none
*
* Returns    : The priority of the Highest Priority Task (HPT) waiting for the event
*
* Note(s)    : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
os_prio.c 
OS_PRIO  OS_PrioGetHighest (void)
{
    CPU_DATA  *p_tbl;
    OS_PRIO    prio;

    prio  = (OS_PRIO)0;
    p_tbl = &OSPrioTbl[0];
    while (*p_tbl == (CPU_DATA)0) {     /* Search the bitmap table for the highest priority       */
        prio += DEF_INT_CPU_NBR_BITS;   /* Compute the step of each CPU_DATA entry*/
                                              //一个OSPrioTbl成员有32个位,分别代表
                                              //32((CPU_CFG_DATA_SIZE  * DEF_OCTET_NBR_BITS))个优先级。所以step是32.
                                             
//优先级33 = 1*32 +1 = OSPrioTbl[ 1 ] |= 1<<30; 查表知道0b0100 0000 =64;
                                              //CPU_CntLeadZerosTbl[ 64 ] = 1;所以1*32+1=33
                                              //优先级33是最高的当然 OSPrioTbl[ 0]就全部为0了。所以循环1次。
                                              //所以1*32 +
CPU_CntLeadZeros(*p_tbl);   
                                              //OSPrioTbl[ ix ] ,ix最小的  OSPrioTbl[ ix ]不为0.说明最高的优先级在这个成员ix里(OSPrioTbl[ ix ])里         


        p_tbl++;
    }
    prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl);              /* Find the position of the first bit set at the entry    */

    return (prio);
}

lib_def.h                                                               /* --------------- CPU INTEGER DEFINES ---------------- */
#define  DEF_INT_CPU_NBR_BITS                           (CPU_CFG_DATA_SIZE     * DEF_OCTET_NBR_BITS)
#define  CPU_CFG_DATA_SIZE              CPU_WORD_SIZE_32        /* Defines CPU data    word size  (in octets). 
#define  CPU_WORD_SIZE_32                          4    /* 32-bit word size (in octets).
#define  DEF_OCTET_NBR_BITS                                8u

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
************************************************************************************************************************
*                                                  INSERT PRIORITY
*
* Description: This function is called to insert a priority in the priority table.
*
* Arguments  : prio     is the priority to insert
*
* Returns    : none
*
* Note(s)    : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
os_prio.c  
void  OS_PrioInsert (OS_PRIO  prio)
{
    CPU_DATA  bit;
    CPU_DATA  bit_nbr;
    OS_PRIO   ix;

    ix             = prio / DEF_INT_CPU_NBR_BITS; //我们以32位机为准,那么此处DEF_INT_CPU_NBR_BITS为32(4*8)
    bit_nbr        = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);
                            //prio&0b11111之所以是与31因为超过31就是进位到下一个OSPrioTbl成员去记录了。
                            //一个OSPrioTbl只有32位,所以只能记录32个优先级
    bit            = 1u;
    bit          <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;
    OSPrioTbl[ix] |= bit;
//假如插入优先级33,ix=33/32=1,  bit_nbr = 33 & 31 = 0b1 00001 & 0b 11111 = 1
//bit = 1 << (31 - 1)  为什么不bit <<= bit_nbr;查找最低位为1的是哪位呢。用第0位为1就+0优先级,如果最低位是第一位为1则+1优先级。
//作者为什么反而从高位开始查,若最高位为1的是31位则+0优先级。作者是考虑到位越高优先级越高?但是反而不好理解代码。
// OSPrioTbl[ 1 ] |= 30 .就是OSPrioTbl[ 1 ]的第30位置1了。第30位是+1,所以取优先级就是prio = ix*32 + 1=1 *32 +1 = 33.

}
/*
************************************************************************************************************************
*                                                   REMOVE PRIORITY
*
* Description: This function is called to remove a priority in the priority table.
*
* Arguments  : prio     is the priority to remove
*
* Returns    : none
*
* Note(s)    : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
os_prio.c  
void  OS_PrioRemove (OS_PRIO  prio)
{
    CPU_DATA  bit;
    CPU_DATA  bit_nbr;
    OS_PRIO   ix;

    ix             = prio / DEF_INT_CPU_NBR_BITS;
    bit_nbr        = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);
    bit            = 1u;
    bit          <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;
    OSPrioTbl[ix] &= ~bit;
//插入是将位相或置1,移除优先级是将相应位相与置0,OSPrioTbl[ix]的32个位代表32个优先级,最高位是哪位置1就是哪个优先级最高。
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
*********************************************************************************************************
*                                         CPU_CntLeadZeros()
*
* Description : Count the number of contiguous, most-significant, leading zero bits in a data value.
*
* Argument(s) : val         Data value to count leading zero bits.
*
* Return(s)   : Number of contiguous, most-significant, leading zero bits in 'val', if NO error(s).
*
*               DEF_INT_CPU_U_MAX_VAL,                                              otherwise.
*
* Caller(s)   : CPU_CntTrailZeros(),
*               Application.
*
*               This function is a CPU module application programming interface (API) function & MAY
*               be called by application function(s).
*
* Note(s)     : (1) (a) Supports the following data value sizes :
*
*                       (1)  8-bits
*                       (2) 16-bits
*                       (3) 32-bits
*                       (4) 64-bits
*
*                       See also 'cpu_def.h  CPU WORD CONFIGURATION  Note #1'.
*
*                   (b) (1) For  8-bit values :
*
*                                  b07  b06  b05  b04  b03  b02  b01  b00    # Leading Zeros
*                                  ---  ---  ---  ---  ---  ---  ---  ---    ---------------
*                                   1    x    x    x    x    x    x    x            0
*                                   0    1    x    x    x    x    x    x            1
*                                   0    0    1    x    x    x    x    x            2
*                                   0    0    0    1    x    x    x    x            3
*                                   0    0    0    0    1    x    x    x            4
*                                   0    0    0    0    0    1    x    x            5
*                                   0    0    0    0    0    0    1    x            6
*                                   0    0    0    0    0    0    0    1            7
*                                   0    0    0    0    0    0    0    0            8
*
*
*                       (2) For 16-bit values :
*
*                             b15  b14  b13  ...  b04  b03  b02  b01  b00    # Leading Zeros
*                             ---  ---  ---       ---  ---  ---  ---  ---    ---------------
*                              1    x    x         x    x    x    x    x            0
*                              0    1    x         x    x    x    x    x            1
*                              0    0    1         x    x    x    x    x            2
*                              :    :    :         :    :    :    :    :            :
*                              :    :    :         :    :    :    :    :            :
*                              0    0    0         1    x    x    x    x           11
*                              0    0    0         0    1    x    x    x           12
*                              0    0    0         0    0    1    x    x           13
*                              0    0    0         0    0    0    1    x           14
*                              0    0    0         0    0    0    0    1           15
*                              0    0    0         0    0    0    0    0           16
*
*$PAGE*
*                       (3) For 32-bit values :
*
*                             b31  b30  b29  ...  b04  b03  b02  b01  b00    # Leading Zeros
*                             ---  ---  ---       ---  ---  ---  ---  ---    ---------------
*                              1    x    x         x    x    x    x    x            0
*                              0    1    x         x    x    x    x    x            1
*                              0    0    1         x    x    x    x    x            2
*                              :    :    :         :    :    :    :    :            :
*                              :    :    :         :    :    :    :    :            :
*                              0    0    0         1    x    x    x    x           27
*                              0    0    0         0    1    x    x    x           28
*                              0    0    0         0    0    1    x    x           29
*                              0    0    0         0    0    0    1    x           30
*                              0    0    0         0    0    0    0    1           31
*                              0    0    0         0    0    0    0    0           32
*
*
*                       (4) For 64-bit values :
*
*                             b63  b62  b61  ...  b04  b03  b02  b01  b00    # Leading Zeros
*                             ---  ---  ---       ---  ---  ---  ---  ---    ---------------
*                              1    x    x         x    x    x    x    x            0
*                              0    1    x         x    x    x    x    x            1
*                              0    0    1         x    x    x    x    x            2
*                              :    :    :         :    :    :    :    :            :
*                              :    :    :         :    :    :    :    :            :
*                              0    0    0         1    x    x    x    x           59
*                              0    0    0         0    1    x    x    x           60
*                              0    0    0         0    0    1    x    x           61
*                              0    0    0         0    0    0    1    x           62
*                              0    0    0         0    0    0    0    1           63
*                              0    0    0         0    0    0    0    0           64
*
*
*                       See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE  Note #1'.
*********************************************************************************************************
*/
#ifndef   CPU_CFG_LEAD_ZEROS_ASM_PRESENT
CPU_DATA  CPU_CntLeadZeros (CPU_DATA  val)
{
    CPU_DATA  nbr_lead_zeros;

#if   (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_08)
    nbr_lead_zeros = CPU_CntLeadZeros08((CPU_INT08U)val);
#elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16)
    nbr_lead_zeros = CPU_CntLeadZeros16((CPU_INT16U)val);
#elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32)
    nbr_lead_zeros = CPU_CntLeadZeros32((CPU_INT32U)val);
#elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_64)
    nbr_lead_zeros = CPU_CntLeadZeros64((CPU_INT64U)val);
#else                                                           /* See Note #1a.                                        */
    nbr_lead_zeros = DEF_INT_CPU_U_MAX_VAL;
#endif

    return (nbr_lead_zeros);
}
#endif

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
cpu_core.c
/*
*********************************************************************************************************
*                                        CPU_CntLeadZeros32()
*
* Description : Count the number of contiguous, most-significant, leading zero bits in a 32-bit data value.
*
* Argument(s) : val         Data value to count leading zero bits.
*
* Return(s)   : Number of contiguous, most-significant, leading zero bits in 'val'.
*
* Caller(s)   : CPU_CntLeadZeros(),
*               CPU_CntTrailZeros32(),
*               Application.
*
*               This function is a CPU module application programming interface (API) function & MAY be
*               called by application function(s).
*
* Note(s)     : (1) Supports 32-bit values :
*
*                          b31  b30  b29  ...  b04  b03  b02  b01  b00    # Leading Zeros
*                          ---  ---  ---       ---  ---  ---  ---  ---    ---------------
*                           1    x    x         x    x    x    x    x            0
*                           0    1    x         x    x    x    x    x            1
*                           0    0    1         x    x    x    x    x            2
*                           :    :    :         :    :    :    :    :            :
*                           :    :    :         :    :    :    :    :            :
*                           0    0    0         1    x    x    x    x           27
*                           0    0    0         0    1    x    x    x           28
*                           0    0    0         0    0    1    x    x           29
*                           0    0    0         0    0    0    1    x           30
*                           0    0    0         0    0    0    0    1           31
*                           0    0    0         0    0    0    0    0           32
*
*
*                   See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE  Note #1'.
*********************************************************************************************************
*/


#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_32)
CPU_DATA  CPU_CntLeadZeros32 (CPU_INT32U  val)
{
#if  (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
        (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32)))
    CPU_DATA  ix;
#endif
    CPU_DATA  nbr_lead_zeros;
                                                                                /* ---------- ASM-OPTIMIZED ---汇编版本的查找prio%32的余数的办法-------- */
#if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
     (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32))
    nbr_lead_zeros  =  CPU_CntLeadZeros((CPU_DATA)val);
                  //见文件cpu_a.asm 里汇编函数CPU_CntLeadZeros
                 //CLZ     R0, R0; Count leading zeros
                 //BX      LR
                 //stm32(ARM-CORTEX)里R0就是用来传参数的(可用作别用处)所以此处R0的值就是val的值。我就不去追踪反汇编了。
                 //CLZ R1, R2 ; 计算前导零个数(例如,如果是3个1则返回5)《CORTEX-M3权威指南》
                 //CLZ就是计算R1(或者R2,我不清楚那个是用来存结果,那个是用来算前导0)有从最高位开始有几个0,
                //也就是从最高位开始第几个位是1.例如,如果是3个1则返回5,应该是返回5+24=29吧,32位机器,不是8位机。

    nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_32) * DEF_OCTET_NBR_BITS;

#else                                                                           /* ----------- C-OPTIMIZED ------------ */
    if (val > 0x0000FFFFu) {
        if (val > 0x00FFFFFFu) {                                                /* Chk bits [31:24] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (CPU_DATA)(val >> 24u);                            /* .. lookup tbl ix  = 'val' >> 24 bits */
            nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix] +  0u);         /* .. plus nbr msb lead zeros =  0 bits.*/
        //优先级32  = 1*32 + 0 = OSPrioTbl[ 1 ] |= 1<<31;查表知道0b1000 0000 =128;CPU_CntLeadZerosTbl[ 128 ] = 0;所以1*32+0=32
        //优先级33 = 1*32 +1 = OSPrioTbl[ 1 ] |= 1<<30; 查表知道0b0100 0000 =64;CPU_CntLeadZerosTbl[ 64 ] = 1;所以1*32+1=33

 
        } else {                                                                /* Chk bits [23:16] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (CPU_DATA)(val >> 16u);                            /* .. lookup tbl ix  = 'val' >> 16 bits */
            nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix] +  8u);         /* .. plus nbr msb lead zeros =  8 bits.*/
        }
    } else {
        if (val > 0x000000FFu) {                                                /* Chk bits [15:08] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (CPU_DATA)(val >>  8u);                            /* .. lookup tbl ix  = 'val' >>  8 bits */
            nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix] + 16u);         /* .. plus nbr msb lead zeros = 16 bits.*/
        } else {                                                                /* Chk bits [07:00] :                   */
                                                                                /* .. Nbr lead zeros =               .. */
            ix             = (CPU_DATA)(val >>  0u);                            /* .. lookup tbl ix  = 'val' >>  0 bits */
            nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix] + 24u);         /* .. plus nbr msb lead zeros = 24 bits.*/
        }
    }
#endif

    return (nbr_lead_zeros);
}
#endif 
 
 
ucos-iii依旧定义了一个数组OSPrioTbl[]进行优先级的逐位映射,但是不同的是,这里每个元素32位(不愧是为了32Bit和64Bit量身定做),随后,检测每个元素是否全零,与ucos-ii一样,当元素为零时,说明此优先级“段”中没有任务就绪,假设我们的prio为60的任务就绪了,那么显然OSPrioTbl[0]=0x0000,执行循环语句,此处有一个名为DEF_INT_CPU_NBR_BITS的宏,这个宏的最终数值为32,也就是一次要跨过32个优先级,对于例子来说就是说明了0~31的优先级都没有就绪,之后指针自加,指向OSPrioTbl[1],因为60在32~63之间,所以OSPrioTbl[1] != 0,跳出循环,下面的是“精找”,是利用了汇编语句找到OSPrioTbl[1]中最左端首先为1的位并算出位数,例如prio为60,明显OSPrioTbl[1]=0001 0000 0000 0000 0000 0000 0000 0000 b,算出的是第18位,注意从0开始计数!所以最终prio = 0+32+18=60,刚好满足。在这里有的同学可能不理解了,为什么不使用ucos-ii的位图方式了呢,毕竟这里多了一个while,会不会影响实时性,在这里我也发表一下自己的观点:首先,这里一次循环就能解决32个优先级问题,注意仅仅是一次,而且用的仅仅是比较和相加指令,必须一瞬间的事情,能满足一般用户的优先级设计了(我想事情再多也不能超过31个吧?);其次,ucos-iii对于任务数没有了限制,优先级也没有了限制,所以必须要适应这样的变化,当然不能一叶障目,ucos不仅仅能移植在单片机上,DSP等更流弊的东西也可以,单片机处理不了太多任务不代表没有工程有那么多任务,所以这里的更改还是很必要的!以上纯属个人观点,大神不喜勿喷!
 
阅读(4594) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

tianqi9112019-02-27 10:06:05

你咋不继续写了呢?提一个建议,最好能整理下代码格式,好乱。而且能不能给个实际的例子呢?比如说在电脑上运行的例子。