Вы можете использовать битовые поля, несмотря на то, что говорят все паникёры. Вам просто нужно знать, как компилятор (ы) и системный ABI (ы), с которым вы собираетесь работать, определяют аспекты битовых полей, «определяемые реализацией». Не пугайтесь педантов, выделяющих жирным шрифтом такие слова, как «реализация определена».
Однако то, что другие, похоже, до сих пор упускали из виду, — это различные аспекты поведения аппаратных устройств с отображением памяти, которые могут быть нелогичными при работе с языком более высокого уровня, таким как C, и функциями оптимизации, предлагаемыми такими языками. Например, каждое чтение или запись аппаратного регистра иногда может иметь побочные эффекты, даже если биты не изменяются при записи. Между тем оптимизатор может затруднить определение того, когда сгенерированный код действительно читает или записывает адрес регистра, и даже когда объект C, описывающий регистр, тщательно квалифицирован как volatile
, требуется большая осторожность, чтобы контролировать, когда ввод-вывод имеет место.
Возможно, вам потребуется использовать какой-то особый метод, определенный вашим компилятором и системой, чтобы правильно манипулировать аппаратными устройствами с отображением памяти. Это характерно для многих встроенных систем. В некоторых случаях поставщики компиляторов и систем действительно будут использовать битовые поля, как это делает в некоторых случаях Linux. Я бы посоветовал сначала прочитать руководство по компилятору.
Таблица описания битов, которую вы цитируете, относится к регистру управления ядра контроллера Intel Avalon DMA. Столбец «чтение/запись/очистка» дает подсказку о том, как ведет себя конкретный бит при чтении или записи. В регистре состояния для этого устройства есть пример бита, в котором запись нуля очищает значение бита, но он может не считывать обратно то же значение, которое было записано, т. е. запись в регистр может иметь побочный эффект в устройстве, в зависимости от значения бита DONE. Интересно, что они документируют бит SOFTWARERESET как «RW», но затем описывают процедуру как двойную запись в него 1 для запуска сброса, а затем они также предупреждают: Выполнение программного сброса DMA при активной передаче DMA может привести к постоянная блокировка шины (до следующего сброса системы). Поэтому бит SOFTWARERESET не следует записывать, кроме как в крайнем случае. Управление сбросом в C потребует некоторого тщательного кодирования, независимо от того, как вы описываете регистр.
Что касается стандартов, ISO/IEC выпустила «технический отчет», известный как «ISO/IEC TR 18037», с подзаголовком «Расширения для поддержки встроенных процессоров». В нем обсуждается ряд вопросов, связанных с использованием C для управления аппаратной адресацией и вводом-выводом устройства, и, в частности, для типов битовых регистров, которые вы упоминаете в своем вопросе, он документирует ряд макросов и методов, доступных через включаемый файл, который они позвоните <iohw.h>
. Если ваш компилятор предоставляет такой заголовочный файл, вы можете использовать эти макросы.
Доступны черновики TR 18037, последний из которых TR 18037(2007), хотя и предполагает довольно сухое прочтение. Однако он содержит пример реализации <iohw.h>
.
Возможно, хорошим примером реальной реализации <iohw.h>
является QNX. Документация QNX предлагает достойный обзор (и пример, хотя я бы настоятельно рекомендовал использовать enum
s для целых значений, а не для макросов): QNX <iohw.h>
02.11.2018
enum
вместо определения переменных-констант, потенциально вызывающих проблемы ODR? 02.11.2018