Как вывести 63 бит из 64 - PullRequest
       13

Как вывести 63 бит из 64

0 голосов
/ 04 марта 2020

У меня есть некоторая 32-битная область памяти, заполненная аппаратным обеспечением данными этого типа:

reg1 :    63  |  62  |  ... | 32     |  reg0 :   31| ... | 0
        --------------------------   |          ----------------
         val  | time value upper     |          time value lower

Я пытаюсь получить значение времени и значение 'val' одновременно с struct и union .

Сначала я попробовал:

typedef struct
{
    uint64_t time   : 63;
    uint64_t value  :  1;
} myStruct;

, но это не работает, myStruct.time не может быть больше 32 бит.

Я пробовал несколько вещей, событие somethign, подобное этому:

typedef union
{
    union{
        struct{
            uint32_t lower : 32;
            uint32_t upper : 31;
        } spare;
        uint64_t value;
    } time;
    struct{
        uint32_t spare_low : 32;
        uint32_t spare_upp : 31;
        uint32_t value : 1;
    } pin;
} myStruct;

Но в этом случае myStruct.time.value, очевидно, получает бит 63. Я получаю некоторые значения, например 0x8000_0415_4142_3015 вместо 0x0000_0415_4142_3015.

Как Могу ли я легко получить значение времени в 63 бита и значение 1-битного вывода?

PS: я знаю, что могу создать макрос чего-то подобного, я ищу прямой метод.

Ответы [ 3 ]

2 голосов
/ 04 марта 2020

Битовые поля никогда не должны использоваться, когда важно размещение битов.

Вместо этого используйте битовую маскировку:

uint64_t someValue = ...
uint64_t time = someValue & 0x7fffffffffffffff;
bool pin = someValue >> 63 & 1; 
1 голос
/ 04 марта 2020

Битовые поля дают только головную боль и непереносимый код. Всегда избегайте их.

Предполагая, что 64-битный доступ возможен для вашей указанной c системы, а «reg1» и «reg0» не являются действительными переменными, но что-то помещено в память аппаратно, тогда:

#define reg1 (*(volatile uint32_t*)0x1000) // address of reg1
#define reg0 (*(volatile uint32_t*)0x1004) // address of reg0

const uint32_t VAL_MASK = 1ul << 31;
...
uint64_t time_;
time_  = (uint64_t)(reg1 & (VAL_MASK - 1)) << 32;
time_ |= reg0;

bool val = reg1 & VAL_MASK; 
// or alternatively:
uint64_t val = reg1 >> 31;

(Пожалуйста, не называйте вашу переменную time, поскольку она конфликтует со стандартной библиотекой.)

Если у вас нет 64-битных типов или если они просто слишком медленны, чтобы используйте, тогда вам нужно получить доступ к каждому из 32 битов по отдельности, просто не ИЛИ их вместе, как сделано выше.

0 голосов
/ 04 марта 2020
int getval(uint64_t reg)
{
    return !!(reg & ((uint64_t)1 << 63));
}

uint64_t gettime(uint64_t reg)
{
   return reg & (~((uint64_t)1 << 63));
}
...