2017-02-11 4 views
3

В ARM-процессоре (HT32F1655) для конкретного раздела регистров требуется доступ к словам. Из инструкции по эксплуатации:Сила GCC для доступа к структурам со словами

Обратите внимание, что все периферийные регистры на шине AHB поддерживают только доступ к словам.

Но GCC генерирует некоторое ldrb (нагрузки байт) и strb (сохранить байты) инструкцию по упакованным структурам. В Структуры выглядеть следующим образом: использование

typedef union { 
    struct { 
     uint32_t CKOUTSRC : 3; //!< CKOUT Clock Source Selection 
     uint32_t    : 5; 
     uint32_t PLLSRC  : 1; //!< PLL Clock Source Selection 
     uint32_t    : 2; 
     uint32_t CKREFPRE : 5; //!< CK_REF Clock Prescaler Selection 
     uint32_t    : 4; 
     uint32_t URPRE  : 2; //!< USART Clock Prescaler Selection 
     uint32_t USBPRE  : 2; //!< USB Clock Prescaler Selection 
     uint32_t    : 5; 
     uint32_t LPMOD  : 3; //!< Lower Power Mode Status 
    } __attribute__((packed)) __attribute__ ((aligned(4))); 
    uint32_t word; 
} reg; 

Пример:

(*(volatile uint32_t*)0x40088000)->CKOUTSRC = 1; 

Производит что-то похожее на:

ldrb r2, [r1] 
orr r2, r2, #1 
strb r2, [r1] 

Когда мне нужно:

ldr r2, [r1] 
orr r2, r2, #1 
str r2, [r1] 

Есть ли способ заставить gcc только g вызывать инструкции для доступа ко всему слову? Некоторые параметры (-mno-unaligned-access) делают gcc генерировать слова доступа, но только тогда, когда байт не выравнивается по 4 словам.

Существует -mslow-bytes, который должен делать правильные вещи, однако кажется, что опция не существует для arm-none-eabi-gcc.

В идеале был бы способ заставить это только на затронутые структуры.

Пожалуйста, нет ответов «не использовать битподы». Я знаю недостатки, но у меня есть возможность управлять используемыми компиляторами, поэтому я не беспокоюсь о переносимости.

+0

Проводка кода, который делает «упакованное растровое изображение для наложения на регистр устройств», сделает его более понятным и понятным. – chux

+0

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

+0

@DavidSchwartz Существует нетривиальное количество этих регистров для отображения. Отображаемые структуры прекрасно работают, за исключением этой проблемы, поэтому я считаю, что стоит приложить немного усилий, чтобы попытаться полностью работать, прежде чем перейти к другому решению. – Shade

ответ

5

Что вы ищете является ССЗ -fstrict-volatile-bitfields варианта:

Этого параметр следует использовать, если доступ к летучим битовым полеям (или другой полой структуру, хотя компилятор обычно чтит эти типы в любом случае) следует использовать единый доступ к ширине типа поля, если возможно, выровнен к естественному выравниванию. Например, цели с периферийными регистрами с отображением памяти могут требовать, чтобы все такие обращения имели ширину в 16 бит; с этим флагом вы можете объявить все периферийные битовые поля как unsigned short (при условии, что short - это 16 бит на этих целевых объектах), чтобы заставить GCC использовать 16-битные обращения, а не, возможно, более эффективный 32-разрядный доступ.

Если эта опция отключена, компилятор использует самую эффективную инструкцию. В предыдущем примере это может быть 32-разрядная команда загрузки, даже если она обращается к байтам, которые не содержат какой-либо части битового поля или регистров с отображением памяти, не связанных с обновляемым.

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

Примечание: из-за ограничений модели памяти C/C++ 11, обращения на запись не допускаются к касанию элементов без битового поля.Поэтому рекомендуется определять все биты типа поля в качестве элементов битового поля.

Значение по умолчанию этой опции определяется двоичным интерфейсом приложения для целевого процессора.

наряду с использованием ключевого слова volatile. См.: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

-1

Это именно то, для чего предназначалось ключевое слово volatile.

+1

Проблема заключается в том, что gcc генерирует инструкции доступа BYTE в WORD-адресуемой памяти. – Shade

+0

Ключевое слово 'volatile' - это указание компилятору, что некоторая память может быть изменена извне, что делает некоторые оптимизации невозможными. – Chaos

+0

@Chaos Не только это. – o11c