/*
*********************************************************************************************************
* 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等更流弊的东西也可以,单片机处理不了太多任务不代表没有工程有那么多任务,所以这里的更改还是很必要的!以上纯属个人观点,大神不喜勿喷!