реклама на сайте
подробности

 
 
> Как лучше описать регистры, оставить как есть в uint32_t или в битовых полях
toweroff
сообщение Aug 8 2014, 21:43
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Доброго времени

Есть у меня некий хидер для LPC177x
Там описан volatile регистр, к примеру IOCON, потом регистр пина, к которым доступ примерно такой - LPC_IOCON->P0_0 = xxx;
Я тут устал считать биты, описал в виде полей типы вот так:
Код
typedef struct
{
    union
    {
        __IO uint32_t D_IOCON;
        struct
        {
            __IO uint32_t FUNC        : 3;
            __IO uint32_t MODE        : 2;
            __IO uint32_t HYS        : 1;
            __IO uint32_t INV        : 1;
                 uint32_t RESERVED0    : 2;
            __IO uint32_t SLEW        : 1;
            __IO uint32_t OD        : 1;
                 uint32_t RESERVED1    : 21;
        };
    };
} LPC_PIN_TypeD_TypeDef;


но, разумеется, из-за vilatile код генерится в два этапа:
Код
;;;75         LPC_IOCON->P2_24.FUNC = 0; // GPIO pin
00000c  4921              LDR      r1,|L1.148|
00000e  f8d12160          LDR      r2,[r1,#0x160]
000012  f0220207          BIC      r2,r2,#7
000016  f8c12160          STR      r2,[r1,#0x160]
;;;76         LPC_IOCON->P2_24.MODE = 2; // Pullup enabled
00001a  f8d12160          LDR      r2,[r1,#0x160]
00001e  f0220218          BIC      r2,r2,#0x18
000022  3210              ADDS     r2,r2,#0x10
000024  f8c12160          STR      r2,[r1,#0x160]


как можно заставить компилятор генерить код в один этап?
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 14)
AHTOXA
сообщение Aug 8 2014, 22:38
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



1. Убрать volatile (__IO) из структуры, добавить в объявление переменной;
2. Считать в не-volatile переменную, модифицировать, записать обратно в регистр:
Код
    LPC_PIN_TypeD_TypeDef tmp = LPC_IOCON->P2_24;
    tmp.FUNC = 0;
    tmp.MODE = 2;
    LPC_IOCON->P2_24 = tmp;


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
toweroff
сообщение Aug 9 2014, 09:53
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(AHTOXA @ Aug 9 2014, 02:38) *
1. Убрать volatile (__IO) из структуры, добавить в объявление переменной;
2. Считать в не-volatile переменную, модифицировать, записать обратно в регистр:

1. Не спасает
2. Некошерно...

Вообще идея по удобству-то неплохая, т.к. сразу видно по полям, какого типа пин (Analog, Digital< USB и т.д.), но вот это двойное обращение портит всю картину. В принципе, делается оно один раз при инициализации, так что можно и оставить
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 9 2014, 09:59
Сообщение #4


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



А чем хуже, например, такой способ инициализации? Нужные биты описаны в стандартном заголовочном файле в виде uint32_t.
Код
  ADC1_2->CCR =
    ADC12_CCR_MULTI_0    * 0 |    // Multi ADC mode selection: Independent mode
    ADC12_CCR_DELAY_0    * 4 |    // Delay between 2 sampling phases: 5
    ADC12_CCR_DMACFG    * 0 |    // DMA configuration for multi-ADC mode: Circular
    ADC12_CCR_MDMA_0    * 0 |    // DMA mode for multi-ADC mode: disabled
    ADC12_CCR_CKMODE_0    * 1 |    // ADC clock mode: AHB / 1
    ADC12_CCR_VREFEN    * 1 |    // VREFINT enable
    ADC12_CCR_TSEN        * 0 |    // Temperature sensor enable
    ADC12_CCR_VBATEN    * 0;    // VBAT enable
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 9 2014, 18:21
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(toweroff @ Aug 9 2014, 15:53) *
1. Не спасает
2. Некошерно...

Эти два пункта надо было применять вместеsm.gif
Насчёт некошерности - не согласен. Считывание volatile-переменной во временную не-volatile переменную для нескольких последовательных модификаций - очень правильное и грамотное решение. И дело не только в оптимизации. Дело в том, что, например, несколько последовательных записей в регистр конфигурации периферийного устройства могут привести к тому, что между записями устройство окажется в запрещённом/неконсистентном состоянии.
И неважно, структуры там или маски.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 10 2014, 15:07
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Aug 9 2014, 12:59) *
А чем хуже, например, такой способ инициализации?
Позволю немного отшлифовать:
Код
ADC1_2->CCR = 0
    | ADC12_CCR_MULTI_0    * 0     // Multi ADC mode selection: Independent mode
    | ADC12_CCR_DELAY_0    * 4     // Delay between 2 sampling phases: 5
    | ADC12_CCR_DMACFG     * 0     // DMA configuration for multi-ADC mode: Circular
    | ADC12_CCR_MDMA_0     * 0     // DMA mode for multi-ADC mode: disabled
    | ADC12_CCR_CKMODE_0   * 1     // ADC clock mode: AHB / 1
    | ADC12_CCR_VREFEN     * 1     // VREFINT enable
    | ADC12_CCR_TSEN       * 0     // Temperature sensor enable
    | ADC12_CCR_VBATEN     * 0     // VBAT enable
   ;

Так вы можете легко закомментировать любую строку значений. В том числе первую, последнюю и даже все.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 10 2014, 15:20
Сообщение #7


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Aug 10 2014, 18:07) *
Позволю немного отшлифовать:
Так вы можете легко закомментировать любую строку значений. В том числе первую, последнюю и даже все.

А я не комментирую их. Просто умножаю на 0 ненужные биты. rolleyes.gif
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Aug 10 2014, 18:43
Сообщение #8


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(ViKo @ Aug 10 2014, 18:20) *
А я не комментирую их. Просто умножаю на 0 ненужные биты. rolleyes.gif


А в чем великий смысл умножения перед сдвигом?

Мой подход такой:
Код
  FTM1->QDCTRL  = 0
                  + LSHIFT(1, 7) // PHAFLTREN | Phase A Input Filter Enable
                  + LSHIFT(1, 6) // PHBFLTREN | Phase B Input Filter Enable
                  + LSHIFT(0, 5) // PHAPOL    | Phase A Input Polarity
                  + LSHIFT(0, 4) // PHBPOL    | Phase B Input Polarity
                  + LSHIFT(0, 3) // QUADMODE  | Quadrature Decoder Mode  | 0 Phase A and phase B encoding mode.
                  + LSHIFT(0, 2) // QUADIR    | Read Only. FTM Counter Direction in Quadrature Decoder Mode    | 1 Counting direction is increasing
                  + LSHIFT(0, 1) // TOFDIR    | Read Only. Timer Overflow Direction in Quadrature Decoder Mode | 1 TOF bit was set on the top of counting.
                  + LSHIFT(1, 0) // QUADEN    | Quadrature Decoder Mode Enable
;


Смысл в том чтобы максимально соответствоало мануалу как первоисточнику.
Все объявления битов которые достаются из хидеров средств разработки типа Keil, IAR и проч игнорирую.
Не видел еще полных и безошибочных хидеров.
Названия битов даю в коментариях и точно как в мануале. Определения битов тоже copy-paste из мануала.
В макросах стоят номера битовых позиций.
Итого:
все определение битов в одном месте, не надо искать где-то далеко правильно ли определены макросы битов, и вообще определять эти макросы,
номера позиций битов не надо конвертировать в цифры множителей, а можно брать прямо из мануала,
полная информация о битовых полях позволяет быстрее вспомнить контекст, соответсвенно быстрее поиск ошибок и легче модификация.

В RTOS я вижу также отказываются от попыток работы с со структурами с битовыми полями регистров. Потому как это уникальный источник проблем.
Go to the top of the page
 
+Quote Post
toweroff
сообщение Aug 10 2014, 19:59
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Спасибо всем

С volatile действительно нужно быть аккуратнее в плане количества доступа
С объявлениями бит в хидерах кейла для LPC швах, их просто нет, так что либо писать самому, либо искать

AlexandrY, я тоже согласен с таким подходом, но в каментах добавил бы еще ширину полей
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 11 2014, 05:09
Сообщение #10


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



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

В остальном - те же достоинства, что у AlexandrY. Только я копирую описания битов из хидера.

По-моему, мой способ нагляднее. Чем сдвигать 1 на 0, а 0 на 1, я просто умножаю 0x00000001 на 1.
И макрос не нужен.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 11 2014, 06:57
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(AlexandrY @ Aug 11 2014, 00:43) *
Мой подход такой:
Код
  FTM1->QDCTRL  = 0
                  + LSHIFT(1, 7) // PHAFLTREN | Phase A Input Filter Enable
...;

А если вдруг потом вы обнаружите, что PHAFLTREN равно не 7, а 8, то будете перекапывать все свои исходники? Бр-рр.
Лучше, имхо, всё же выносить это в какие-нибудь хидеры:
Код
  FTM1->QDCTRL  = 0
                  | (1UL << PHAFLTREN) // Phase A Input Filter Enable
...;

(Обращаю внимание на UL, иначе могут быть неприятности со старшим битом.)

Вариант с умножением мне не нравится тем, что подразумевает, что каждый раз я должен написать все имеющиеся биты. Для больших 32-разрядных регистров это даёт очень монструозные конструкции на 32 строки.
Цитата(AlexandrY @ Aug 11 2014, 00:43) *
В RTOS я вижу также отказываются от попыток работы с со структурами с битовыми полями регистров. Потому как это уникальный источник проблем.

В какой именно из RTOS-ов вы это видите?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 11 2014, 07:22
Сообщение #12


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(AHTOXA @ Aug 11 2014, 09:57) *
Вариант с умножением мне не нравится тем, что подразумевает, что каждый раз я должен написать все имеющиеся биты. Для больших 32-разрядных регистров это даёт очень монструозные конструкции на 32 строки.

Зачем? Можете описать только те, которые нужны.
Лично я описываю все имеющиеся, для универсальности и простоты модификации.
Опять же, для группы битов я использую только одно умножение (одну строку).
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 11 2014, 07:30
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(ViKo @ Aug 11 2014, 13:22) *
Зачем? Можете описать только те, которые нужны.
Лично я описываю все имеющиеся, для универсальности и простоты модификации.

Вот именно об этом я и говорил. "Подразумевает" sm.gif
Ещё вот о чём подумал. Если бит/группа битов в данный момент не нужна, то вы умножите её на 0. Но ведь при этом у вас теряется информация, на сколько надо сдвигать/умножать! Если это несколько групп битов подряд, то даже из значений соседних ненулевых множителей вы не сможете понять, на сколько надо умножить тот или иной бит/группу битов. И придётся вам лезть в документацию... sm.gif
С этой точки зрения сдвиги + умножения на 0/1 гораздо лучше.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 11 2014, 07:49
Сообщение #14


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



У меня вообще нет сдвигов. Я пользуюсь битовыми масками, описанными в библиотечном заголовке. По большому счету, не представляю, на какой позиции эти биты находятся.
Я умножаю не на сдвиг, а на номер режима.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Aug 11 2014, 10:43
Сообщение #15


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(AHTOXA @ Aug 11 2014, 09:57) *
А если вдруг потом вы обнаружите, что PHAFLTREN равно не 7, а 8, то будете перекапывать все свои исходники? Бр-рр.
Лучше, имхо, всё же выносить это в какие-нибудь хидеры:

В какой именно из RTOS-ов вы это видите?


Хм, так в этом и есть мировозренческое различие подходов.

Случись какая-либо ошибка на уровне периферии, что вы делаете в этом случае?
Ясное деле, перекапываете все исходники.
И приходится параноидально проверять всё и объявления битов в первую очередь.
В таких поисках время можно сэкономить если все деражать в одном месте не делая определения битов где-то еще в макросах.

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

Ну а само содержание комментариев отражает особенности мануалов. У производителей в чьих мануалах биты всегда указываются с паре со своими регистрами не нужно дополнительно именовать биты.
А у Freescale например везде оперируют только с голыми именами битов в описаниях. Ну тогда приходится в исходниках обязательно упоминать имена битов.

Оправдание определению битов в хидерах я вижу только в желании сохранить стилистический подход навязываемый разработчиками библиотек под Keil, IAR, GCC и т.д.
Но ИМХО стоит ломать их подход, хотябы даже для того чтобы сильно к ним не привязываться.

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

С битовыми полями вообще не работают BSP генерируемые инструментиами Freescale для MQX например.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 22:34
Рейтинг@Mail.ru


Страница сгенерированна за 0.05333 секунд с 7
ELECTRONIX ©2004-2016