如何使用预定义的掩码生成值

时间:2017-12-06 18:07:48

标签: c bit-manipulation bit-shift bitmask

我正在研究一个有点棘手的硬件......比如一个32位寄存器看起来像这样(高16位都是零)

#define MASK_DBG_CTRL_FIFO_SPLIT            0b0000000000000001
#define MASK_DBG_CTRL_FIFO_ENABLE           0b0000000000000010
#define MASK_DBG_CTRL_ADC_SPLIT             0b0000000000000100
#define MASK_DBG_CTRL_ADC_ENABLE            0b0000000000001000
#define MASK_DBG_CTRL_MAX_COUNTER           0b1111111111110000

#define NO_SPLIT                            0  
#define WITH_SPLIT                          1
#define DISABLE                             0  
#define ENABLE                              1

我的问题是,如何生成一个我需要写入该寄存器的数字。例如。我将有一个函数从用户获取数字并返回准备写入寄存器的值。

这似乎是一个非常痛苦的过程...我有十几个类似的寄存器,它们具有不同的位宽和内容...我怎样才能使这更容易?

首先,我如何在MASK_DBG_CTRL_MAX_COUNTER位写出所需的值?

uint32_t generateDebugRegister(uint8_t fifoSplit, uint8_t fifoEnable,
                                uint8_t adcSplit, uint8_t adcEnable,
                                uint16_t counter) {
    uint32_t output = 0;

    switch(fifoSplit) {
    case NO_SPLIT:
        //do nothing;
        break;
    case WITH_SPLIT:
        output = 1UL >> 1; //set bit 0 to 1
        break;
    }

    switch(fifoEnable) {
    case DISABLE:
        //do nothing;
        break;
    case ENABLE:
        output = 1UL >> 2; //set bit 2 to 1
        break;
    }

    switch(adcSplit) {
    case NO_SPLIT:
        //do nothing;
        break;
    case WITH_SPLIT:
        output = 1UL >> 3; //set bit 3 to 1
        break;
    }

    switch(adcEnable) {
    case DISABLE:
        //do nothing;
        break;
    case ENABLE:
        output = 1UL >> 4; //set bit 4 to 1
        break;
    }

    //how to evenset the counter value???

    return output;
}

调用函数示例:

void setDebugRegister(uint32_t value) { /*write to reg*/ };

uint32_t toWrite = generateDebugRegister(NO_SPLIT, DISABLE, WITH_SPLIT, ENABLE, 4256);

setDebugRegister( toWrite);

这是另一组寄存器掩码......这里我需要将低10位拼接成两个5位:

#define MASK_DAD_NUM_ADDR                   0b0000000000011111
#define MASK_DAD_NUM_DECI                   0b0000001111100000

这里,前8位和低8位:

#define MASK_DBG_REG_ID                     0b1111111100000000;
#define MASK_DBG_REG_CNTR                   0b0000000011111111;

1 个答案:

答案 0 :(得分:1)

  

如何使用预定义的掩码(?)

生成值

解决OP的第一部分:

考虑重写函数签名。其他建议的更改如下作为评论代码。

// uint32_t generateDebugRegister(uint8_t fifoSplit, uint8_t fifoEnable,
//     uint8_t adcSplit, uint8_t adcEnable, uint16_t counter) { ...

// use bool for simple T/F values
uint32_t generateDebugRegister(bool fifoSplit, bool fifoEnable, bool adcSplit, 
    bool adcEnable, uint16_t counter) {

  uint32_t output = 0;
  if (fifoSplit == WITH_SPLIT) {   // use an `if()`
    output |= MASK_DBG_CTRL_FIFO_SPLIT; // use an 'or' of the mask
  } 
  if (fifoEnable == ENABLE) {
    output |= MASK_DBG_CTRL_FIFO_ENABLE;
  }
  .... // like-wise with  adcSplit, adcEnable

  // add an `offset` to simplify shifting needs
  #define MASK_DBG_CTRL_MAX_BIT_OFFSET 4
  #define MASK_DBG_CTRL_MAX_MAX (MASK_DBG_CTRL_MAX_COUNTER >> MASK_DBG_CTRL_MAX_BIT_OFFSET)

  // test, since 16 bits do not fit in 12
  if (counter > MASK_DBG_CTRL_MAX_MAX) {
    Handle_error_with_TBD_Code();
  }
  else { 
    output |= (uint32_t)counter << MASK_DBG_CTRL_MAX_BIT_OFFSET;
  }

  return out;
}
  

我有十几个类似的寄存器,它们具有不同的位宽和内容...我怎样才能使这更容易?

需要查看其中的一些内容以获得良好的一般性答案。