位掩碼 及在 ucos ii 中一段位掩碼

編輯個目錄,直接跳轉到總結。


作爲計算機專業的,數學不好,對數字相當不敏感。誒,悲催。

每次碰到個啥位操作,總是轉不過來,非得仔細地慢慢地看,好吧,寫在這裏。

在看ucos 源碼時,看到TCB 結構裏有四個變量,分別爲:

     	INT8U          OSTCBX;             /* Bit position in group  corresponding to task 
	priority   (0..7) */ 
    	INT8U      OSTCBY;           /* Index into ready table corresponding to task priority */ 
    	INT8U          OSTCBBitX;         /* Bit mask to access bit position in ready table */  
    	INT8U          OSTCBBitY;        /* Bit mask to access bit p osition in ready group*/  

下面這段是在TCB 初始化裏,根據優先級對這幾個變量的給值。

	ptcb->OSTCBY         = prio >> 3;                  /* Pre-compute X, Y, BitX and BitY          */
        ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];
        ptcb->OSTCBX         = prio & 0x07;
        ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];

另外有個OSMapTbl ,如下:

/*
*********************************************************************************************************
*                              MAPPING TABLE TO MAP BIT POSITION TO BIT MASK
*
* Note: Index into table is desired bit position, 0..7
*       Indexed value corresponds to bit mask
*********************************************************************************************************
*/

INT8U  const  OSMapTbl[]   = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

/*

還有我搜到的一篇關於位掩碼的文:位掩碼


ucos ii 中任務優先級表是一個8x8 的表(8個UINT8),另設一個 8 位對應每一行,用以標識該行是否有 1 (即優先級是否用了)假設橫向是X,縱向是Y 。OSTCBY呢 是對應於Group , 縱向的。OSTCBX 是橫向的,根據(OSTCBX ,OSTCBY) 就可以很方便的找到 優先級對應的地方並且判斷 其 是 0 還是 1。 

創建任務的時候,只是給了一個優先級,那麼,怎麼樣根據優先級來設置這橫座標和縱座標呢?

1. OSTCBY 的設置,右移三位,即 除 8,還好理解。儘管對數字不敏感,見了幾次還是知道意思的。

2. OSTCBX 的設置, &0x07 ,根據實驗結果, 即取後三位,64個優先級 用 6 位可以表示,那麼高三位就是表示 Y,低三位就是表示 X(好吧,到這裏已經把前面的自己全部推翻了。標記爲紅色吧。)

3. 相應位掩碼的設置。位掩碼是幹啥用的?上面文裏的大神說:有這麼一種技術,叫做位掩碼技術,用來處理存在多個布爾值的情況。哦,理解了,記得看飛思卡爾 K60 的寄存器定義經常有這種MASK,一般說來,寄存器的某一位即可以看做一個開關,或者說裏面的值就代表將要使開關撥到何種狀態,那麼這種就是布爾型的。

如這一段:

//開啓各個GPIO口的轉換時鐘
	SIM->SCGC5 = SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK;
/* SCGC5 Bit Fields */
#define SIM_SCGC5_LPTIMER_MASK                   0x1u
#define SIM_SCGC5_LPTIMER_SHIFT                  0
#define SIM_SCGC5_REGFILE_MASK                   0x2u
#define SIM_SCGC5_REGFILE_SHIFT                  1
#define SIM_SCGC5_TSI_MASK                       0x20u
#define SIM_SCGC5_TSI_SHIFT                      5
#define SIM_SCGC5_PORTA_MASK                     0x200u
#define SIM_SCGC5_PORTA_SHIFT                    9
#define SIM_SCGC5_PORTB_MASK                     0x400u
#define SIM_SCGC5_PORTB_SHIFT                    10
#define SIM_SCGC5_PORTC_MASK                     0x800u
#define SIM_SCGC5_PORTC_SHIFT                    11
#define SIM_SCGC5_PORTD_MASK                     0x1000u
#define SIM_SCGC5_PORTD_SHIFT                    12
#define SIM_SCGC5_PORTE_MASK                     0x2000u
#define SIM_SCGC5_PORTE_SHIFT                    13
每一個對應一位開關,開了五個開關。(至於SHIFT是做什麼用的,就不知道了)

好吧,再回到ucos 中來,爲了在寫的時候 只需要寫一個 | , 設置下位掩碼,位掩碼指示多個開關中的某一位的開關狀態(0/1)


20130528

那麼對這種位掩碼的操作我見到了的有三種形式

總結三種常見的位掩碼操作形式

1. 設置相應位

操作方法:“ |= ”。  如STM32中有關時鐘配置的一個函數

  RCC->APB2ENR |= RCC_APB2Periph

2. 清除相應位 

操作方法 :“ |= ” “~” 

如 :RCC->APB2ENR &= ~RCC_APB2Periph

貼上整個函數:

/**
  * @brief  Enables or disables the High Speed APB (APB2) peripheral clock.
  * @param  RCC_APB2Periph: specifies the APB2 peripheral to gates its clock.
  *   This parameter can be any combination of the following values:
  *     @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
  *          RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
  *          RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
  *          RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
  *          RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
  *          RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
  *          RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11     
  * @param  NewState: new state of the specified peripheral clock.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB2ENR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2ENR &= ~RCC_APB2Periph;
  }
}

3. 檢查 位狀態

操作方法:“ & ”  後判斷

如: ucos 中掛起任務的一段,用來判斷任務就緒表的某一行中是否有其他就緒任務的一段。

if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb ->OSTCBBitX) == 0x00) {  // 如果該位的其他位沒有
就緒任務,就將 OSRdyGrp  的對應位(指示對應一行中是否有就緒任務)清除 
         OSRdyGrp &= ~ptcb->OSTCBBitY; 
     } 
     ptcb ->OSTCBStat |= OS_STAT_SUSPEND;  





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章