Bitshifting против индексации массива, которая больше подходит для интерфейсов usart на 32-битных MCU - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть встроенный проект с USART HAL.Этот USART может передавать или принимать только 8 или 16 битов за раз (в зависимости от выбранного нами регистра usart, т.е. одиночный / двойной вход / выход).Поскольку это 32-битный MCU, я подумал, что мог бы также обойти 32-битные поля, поскольку (из того, что я уже понял), это более эффективное использование битов для MPU.То же самое относится и к 64-битному MPU, то есть к 64-битным целым числам.Возможно, это неверный совет или совет, вырванный из контекста.

Имея это в виду, я упаковал 8 бит в 32-битное поле с помощью сдвига битов.Я делаю это как для TX, так и для RX на Usart.

Код только для 8-битного регистра следующий (16-битный регистр имеет только половину количества циклов для сдвига битов):

int zg_usartTxdataWrite(USART_data*         MPI_buffer,
                        USART_frameconf*    MPI_config,
                        USART_error*        MPI_error)
{

MPI_error = NULL;

if(MPI_config != NULL){
    zg_usartFrameConfWrite(MPI_config);
}

HPI_usart_data.txdata = MPI_buffer->txdata;

    for (int i = 0; i < USART_TXDATA_LOOP; i++){
        if((USART_STATUS_TXC & usart->STATUS) > 0){
            usart->TXDATAX = (i == 0 ? (HPI_usart_data.txdata & USART_TXDATA_DATABITS) : (HPI_usart_data.txdata >> SINGLE_BYTE_SHIFT) & USART_TXDATA_DATABITS);
        }
        usart->IFC |= USART_STATUS_TXC;
    }
    return 0;
}

РЕДАКТИРОВАТЬ: RE-ВВОДНАЯ ЛОГИКА ВЫШЕГО КОДА С ДОБАВЛЕННЫМИ ОПРЕДЕЛЕНИЯМИ ДЛЯ ЯСНОСТИ ПРОБЛЕМЫ НЕЗАКОННОГО ПРОДВИЖЕНИЯ ТЕРНАРНОГО ОПЕРАТОРА, ОБСУЖДЕННОЙ В РАЗДЕЛЕ КОММЕНТАРИЙ

(структуры HPI_usart и USART_data - это те же самые разные уровни, с тех пор я удалил слой HPI_usart, норади этого примера я оставлю его в этом)

#define USART_TXDATA_LOOP 4
#define SINGLE_BYTE_SHIFT 8

typedef struct HPI_USART_DATA{

   ...
   uint32_t txdata;
   ...

}HPI_usart

HPI_usart HPI_usart_data = {'\0'};

const uint8_t USART_TXDATA_DATABITS = 0xFF;

int zg_usartTxdataWrite(USART_data*         MPI_buffer,
                        USART_frameconf*    MPI_config,
                        USART_error*        MPI_error)
{

MPI_error = NULL;

if(MPI_config != NULL){
    zg_usartFrameConfWrite(MPI_config);
}

HPI_usart_data.txdata = MPI_buffer->txdata;

    for (int i = 0; i < USART_TXDATA_LOOP; i++){
        if((USART_STATUS_TXC & usart->STATUS) > 0){
            usart->TXDATAX = (i == 0 ? (HPI_usart_data.txdata & USART_TXDATA_DATABITS) : (HPI_usart_data.txdata >> SINGLE_BYTE_SHIFT) & USART_TXDATA_DATABITS);
        }
        usart->IFC |= USART_STATUS_TXC;
    }
    return 0;
}

Однако теперь я понимаю, что это потенциально вызывает больше проблем, чем решает, потому что я по сути внутренне кодирую эти биты, которые затем должны быть декодированы почти немедленнокогда они передаются в / из разных слоев данных.Я чувствую, что это умное и сексуальное решение, но сейчас я пытаюсь решить проблему, которую я не должен был создавать в первую очередь.Например, как извлечь переменные битовые поля, когда есть смещение, то есть в предложениях gps nmea, где первые 8 битов могут быть одним релевантным полем, а затем остальные являются 32-битными полями.В итоге получается так:

32-битный член массива 0:

 bits 24-31      bits 15-23          bits 8-15            bits 0-7

|8-битное значение |32-битное значение A, биты 24-31 |32-битное значение A, биты 16-23 |32-битное значение A, биты 8-15 |

32-битный элемент массива 1:

 bits 24-31             bits 15-23           bits 8-15               bits 0-7

|32-битное значение A, биты 0-7 |32-битное значение B, биты 24-31 |32-битное значение B, биты 16-23 |32-битное значение B, биты 8-15 |

32-битный элемент массива 2:

 bits 24-31        15-23 8-15 ...

|32-битное значение B, биты 0-7 |и т.д ... |.... |.... |

Приведенный выше пример требует ручного декодирования, что, я думаю, хорошо, но оно отличается для каждого предложения nmea и кажется более ручным, чем программным.

У меня такой вопрос: битовое смещение против индексации массива, что более уместно?

Должен ли я просто назначить каждое входящее / исходящее значение 32-битному элементу массива, а затем просто индексировать таким образом?Я чувствую, что это решение, так как оно не только облегчит прохождение данных на других уровнях, но я смогу устранить всю эту логику сдвига битов, и тогда единственная разница между функцией rx или tx будетнаправление данных идет.

Это означает небольшую переписку интерфейса и получающегося слоя модуля gps, но это похоже на меньшую работу, а также дешевый урок в начале моего проекта.

Также любые мысли и общий опыт по этому поводу были бы великолепны.

1 Ответ

0 голосов
/ 20 февраля 2019

Поскольку это 32-битный MCU, я подумал, что мог бы также обойти 32-битные поля

На самом деле это не вызов программиста.Поместите 8 или 16-битную переменную в структуру.Позвольте компилятору добавить отступы, если это необходимо.В качестве альтернативы вы можете использовать uint_fast8_t и uint_fast16_t.

Мой вопрос таков: битовое смещение против индексации массива, что более подходит?

Индексация массивов предназначена для доступа к массивам.Если у вас есть массив, используйте его.Если нет, то не надо.

Хотя можно пролистывать большие куски данных побайтно, такой код должен быть написан гораздо более тщательно, чтобы не допустить попадания в различные ошибки при преобразовании тонких типов и сглаживании указателей.

InВообще, битовый сдвиг предпочтителен при доступе к данным до размера слова ЦП, в данном случае 32 битЭто быстрый и портативный, так что вам не нужно принимать во внимание endianess.Это предпочтительный метод сериализации / десериализации целых чисел.

...