Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как уменьшить размер структуры из битовых полей, Регистры контроллера в виде битовых поле 
:(
    Опции темы
Курсант
Дата 18.5.2016, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Здравствуйте!
У меня следующая проблема: мне необходимо задать структуру в виде битовых полей. Проблема в том, что мне необходимо, чтобы эта структура занимала в памяти меньше 32 бит, хотя, судя по информации, компилятор устанавливает размер таких структур кратным процессорному слову, т.е. в моём случае это 32 бита.
Теперь рассказываю подробно: есть микроконтроллер, у которого одно из периферийных устройств (контроллер Ethernet) настраивается с помощью 16-разрядных регистров, при этом в каждом регистре есть битовые поля. Я хочу описать эти регистры в виде структур битовых полей, а затем весь блок регистров описать в виде структуры структур. Примерно так (структура структур в самом низу, если кому надоест читать битовые поля):
Код

#pragma anon_unions
#pragma pack (push, 1)
typedef union {
    uint32_t VALUE;
    struct {
        unsigned COL_WND : 8;                                        // Размер "окна коллизий" ( в битовых интервалах x4 )
        unsigned PAUSE_EN : 1;                                        // Режим автоматической обработки пакета PAUSE ( 0 - включен, 1 - отключен )
        unsigned DTRM_EN : 1;                                        // Режим детерминированного времени доставки ( 0 - выключен, 1 - включен )
        unsigned HD_EN : 1;                                            // Полудуплексный режим работы ( 0 - выключен, 1 - включен )
        unsigned EXT_EN : 1;                                        // Включение режима дополнения коротких пакетов до размера slotTime полем "Extension" (При приёме отбрасывание слова осуществляется по полю length пакета, если оно отражает длину пакета ( 0 - выключен, 1 - включен )
        unsigned BUFF_MODE : 2;                                        // Режим работы буфера ( 00 - линейный режим, 1 - режим с автоматическим изменением указателей, 2 - режим FIFO, 3 - зарезервировано (линейный режим) )
        unsigned RCLR_EN : 1;                                        // Сброс регистров статуса (IFR) ( 0 - производится записью в регистры статуса, 1 - регистры статуса сбрасываются при чтении )
        unsigned : 1;                                                // Зарезервировано
        unsigned XRST : 1;                                            // Сброс передатчика ( 0 - работает, 1 - сброшен )
        unsigned RRST : 1;                                            // Сброс приёмника ( 0 - работает, 1 - сброшен )
        unsigned DLB : 1;                                            // Режим КЗ ( 0 - выключен, 1 - включен )
        unsigned : 9;                                                // Зарезервировано
        unsigned DBG_RF_EN : 1;                                        // Разрешение автоматического изменения указателей FIFO приёмника в режиме отладки ( 0 - запрещено, 1 - разрешено )
        unsigned DGB_XF_EN : 1;                                        // Разрешение автоматического изменения указателей FIFO передатчика ( 0 - запрещено, 1 - разрешено )
        unsigned DBG_MODE : 2;                                        // Режим работы в режиме отладки ( 0 - Free Run, 2 - Halt, 3 - Stop )
    };
} MDR32_ETHERNET_G_CFG_TypeDef;

typedef union {
    uint16_t VALUE;
    struct {
        unsigned RTRY_CNT : 4;                                        // Максимальное кол-во попыток отправки пакета
        unsigned IPG_EN : 1;                                        // Режим выдержки паузы между отправкой пакетов ( 0 - выключен, 1 - включен )
        unsigned CRC_EN : 1;                                        // Дополнение пакета автоматически вычисленным CRC ( 0 - выключено, 1 - включено )
        unsigned PRE_EN : 1;                                        // Дополнение пакета преамбулой ( 0 - выключено, 1 - включено )
        unsigned PAD_EN : 1;                                        // Дополнение пакета до минимальной длины PAD-ами ( 0 - выключено, 1 - включено )
        unsigned EVNT_MODE : 3;                                        // Выбор режима работы вывода EVNT[1] ( более подробно см. спецификацию )
        unsigned : 1;                                                // Зарезервировано
        unsigned MSB1st : 1;                                        // Порядок следования бит при передаче байтов данных ( 0 - первым передаётся LSB, 1 - первым передаётся MSB )
        unsigned BE : 1;                                            // Порядок следования байт в слове передатчика ( 0 - LittleEndian, 1 - BigEndian )
        unsigned : 1;                                                // Зарезервировано
        unsigned EN : 1;                                            // Разрешение работы передатчика ( 0 - остановлен, 1 - разрешена работа )
    };
} MDR32_ETHERNET_X_CFG_TypeDef;

typedef union {
    uint16_t VALUE;
    struct {
        unsigned MCA_EN : 1;                                    // Приём пакетов с групповым MAC-адресом с фильтрацией по HASH-таблице ( 0 - выключен, 1 - включен )
        unsigned BCA_EN : 1;                                    // Приём пакетов с широковощательным MAC-адресом ( 0 - выключен, 1 - включен )
        unsigned UCA_EN : 1;                                    // Приём пакетов с MAC-адресом, указанным в регистре MAC_ADDRESS ( 0 - выключен, 1 - включен )
        unsigned AC_EN : 1;                                        // Приём пакетов без фильтрации MAC-адреса ( 0 - выключен, 1 - включен )
        unsigned EF_EN : 1;                                        // Разрешение приёма пакетов с ошибками ( 0 - выключено, 1 - включено )
        unsigned CF_EN : 1;                                        // Разрешение приёма управляющих пакетов ( 0 - выключено, 1 - включено )
        unsigned LF_EN : 1;                                        // Разрешение приёма пакетов длиной больше максимальной ( 0 - выключено, 1 - включено )
        unsigned SF_EN : 1;                                        // Разрешение приёма пакетов длиной меньше минимальной ( 0 - выключено, 1 - включено )
        unsigned EVNT_MODE : 3;                                    // Выбор режима работы вывода EVNT[1] ( более подробно см. спецификацию )
        unsigned : 1;                                            // Зарезервировано
        unsigned MSB1st : 1;                                    // Порядок следования бит при приёме байтов данных ( 0 - первым принимается LSB, 1 - первым принимается MSB )
        unsigned BE : 1;                                        // Порядок следования байт в слове ( 0 - LittleEndian, 1 - BigEndian )
        unsigned : 1;                                            // Зарезервировано
        unsigned EN : 1;                                        // Разрешение работы приёмника ( 0 - приёмник остановлен, 1 - разрешена работа )
    };
} MDR32_ETHERNET_R_CFG_TypeDef;

typedef union {
    uint16_t VALUE;
    struct {
        unsigned RF_OK : 1;                                        // Индикатор успешно принятого пакета
        unsigned MISSED_F : 1;                                    // Индикатор потери пакета из-за отсутствия места в буфере приёмника
        unsigned OVF : 1;                                        // Индикатор переполнения буфера приёмника
        unsigned SMB_ERR : 1;                                    // Индикатор наличия ошибок в данных при приёме пакета
        unsigned CRC_ERR : 1;                                    // Индикатор наличия несовпадения CRC пакета принятых данных с CRC пакета
        unsigned CF : 1;                                        // Индикатор приёма управляющих пакетов
        unsigned LF : 1;                                        // Индикатор приёма пакета длиной больше максимальной
        unsigned SF : 1;                                        // Индикатор приёма пакета длиной меньше минимальной
        unsigned XF_OF : 1;                                        // Индикатор успешной отправки пакета
        unsigned XF_ERR : 1;                                    // Индикатор наличия ошибок при передаче пакета
        unsigned UNDF : 1;                                        // Индикатор опустошения буфера передатчика
        unsigned LC : 1;                                        // Индикатор наличия LateCollision в линии
        unsigned CRS_LOST : 1;                                    // Индикатор потери несущей во время передачи в полудуплексном режиме работы
        unsigned : 1;                                            // Зарезервировано
        unsigned MDIO_INT : 1;                                    // Индикатор наличия прерывания по MDIO интерфейсу
        unsigned MII_RDY : 1;                                    // Индикатор завершения текущей команды обмена по MDIO интерфейсу
    };
} MDR32_ETHERNET_IMR_IFR_TypeDef;

....
и так далее
.....

typedef struct {
    uint16_t DELIMITER;                                            // Регистр границы буферов приёмника и передатчика ( размер буфера приёмника/начало буфера передатчика)
    MDR32_ETHERNET_MAC_ADDRESS_TypeDef MAC_ADDRESS;            // Регистр индивидуального MAC-адреса
    MDR32_ETHERNET_HASH_TypeDef HASH;
    uint16_t IPG;
    uint16_t PSC;
    uint16_t BAG;
    uint16_t JitterWnd;
    MDR32_ETHERNET_R_CFG_TypeDef R_CFG;
    MDR32_ETHERNET_X_CFG_TypeDef X_CFG;
    MDR32_ETHERNET_G_CFG_TypeDef G_CFG;
    MDR32_ETHERNET_IMR_IFR_TypeDef IMR;
    MDR32_ETHERNET_IMR_IFR_TypeDef IFR;
    MDR32_ETHERNET_MDIO_CTRL_TypeDef MDIO_CTRL;
    uint16_t MDIO_DATA;
    uint16_t R_Head;
    uint16_t X_Tail;
    uint16_t R_Tail;
    uint16_t X_Head;
    MDR32_ETHERNET_STAT_TypeDef STAT;
    MDR32_ETHERNET_PHY_CONTROL_TypeDef PHY_CONTROL;
    MDR32_ETHERNET_PHY_STATUS_TypeDef PHY_STATUS;
} MDR32_ETHERNET_TypeDef;
#pragma pack ( pop )
#pragma no_anon_unions

Предыдущие устройства у меня настроить получилось, т.к. там регистры были 32-разрядные, а здесь 16-разрядные, поэтому устройство не настраивается и не работает.
Конечно, можно писать в регистры как в 16-битные целые беззнаковые, но это снижает наглядность кода, хотя и уменьшает объём кода и прошивки.
PM ICQ Skype   Вверх
DarthTon
Дата 21.5.2016, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: нет
Всего: 6



Замените unsigned на uint16_t в битовых полях тех структур которые должны быть выровнены на 2 байта.

Это сообщение отредактировал(а) DarthTon - 21.5.2016, 12:54
PM MAIL   Вверх
Курсант
Дата 3.1.2017, 17:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Цитата(DarthTon @ 21.5.2016,  12:54)
Замените unsigned на uint16_t в битовых полях тех структур которые должны быть выровнены на 2 байта.

Спасибо за ответ. К сожалению, выравнивание нужно не на байты, а на биты.

Это сообщение отредактировал(а) Курсант - 3.1.2017, 17:26
PM ICQ Skype   Вверх
миг
Дата 3.1.2017, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 15.9.2008

Репутация: нет
Всего: 1



в файле limits.h
#define CHAR_BIT      8         /* number of bits in a char */
в файле stdint.h
typedef short int_least16_t; если я правильно понимаю это и есть 16 бит.
--------------------
Oaks may fall when reeds stand the storm.
PM MAIL   Вверх
xvr
Дата 16.1.2017, 23:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(Курсант @  3.1.2017,  17:20 Найти цитируемый пост)
Спасибо за ответ. К сожалению, выравнивание нужно не на байты, а на биты.

Структуру целиком нельзя выровнять до бита. Она в любом случае будет начинаться как минимум с байта (если поставить атрибут упакованости, если не поставить - то и со слова). 

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0897 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.