Здравствуйте! У меня следующая проблема: мне необходимо задать структуру в виде битовых полей. Проблема в том, что мне необходимо, чтобы эта структура занимала в памяти меньше 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-битные целые беззнаковые, но это снижает наглядность кода, хотя и уменьшает объём кода и прошивки.
|