Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как лучше описать регистры
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
toweroff
Доброго времени

Есть у меня некий хидер для 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]


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

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

Вообще идея по удобству-то неплохая, т.к. сразу видно по полям, какого типа пин (Analog, Digital< USB и т.д.), но вот это двойное обращение портит всю картину. В принципе, делается оно один раз при инициализации, так что можно и оставить
ViKo
А чем хуже, например, такой способ инициализации? Нужные биты описаны в стандартном заголовочном файле в виде 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
AHTOXA
Цитата(toweroff @ Aug 9 2014, 15:53) *
1. Не спасает
2. Некошерно...

Эти два пункта надо было применять вместеsm.gif
Насчёт некошерности - не согласен. Считывание volatile-переменной во временную не-volatile переменную для нескольких последовательных модификаций - очень правильное и грамотное решение. И дело не только в оптимизации. Дело в том, что, например, несколько последовательных записей в регистр конфигурации периферийного устройства могут привести к тому, что между записями устройство окажется в запрещённом/неконсистентном состоянии.
И неважно, структуры там или маски.
Сергей Борщ
Цитата(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
   ;

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

А я не комментирую их. Просто умножаю на 0 ненужные биты. rolleyes.gif
AlexandrY
Цитата(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 я вижу также отказываются от попыток работы с со структурами с битовыми полями регистров. Потому как это уникальный источник проблем.
toweroff
Спасибо всем

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

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

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

По-моему, мой способ нагляднее. Чем сдвигать 1 на 0, а 0 на 1, я просто умножаю 0x00000001 на 1.
И макрос не нужен.
AHTOXA
Цитата(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-ов вы это видите?
ViKo
Цитата(AHTOXA @ Aug 11 2014, 09:57) *
Вариант с умножением мне не нравится тем, что подразумевает, что каждый раз я должен написать все имеющиеся биты. Для больших 32-разрядных регистров это даёт очень монструозные конструкции на 32 строки.

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

Вот именно об этом я и говорил. "Подразумевает" sm.gif
Ещё вот о чём подумал. Если бит/группа битов в данный момент не нужна, то вы умножите её на 0. Но ведь при этом у вас теряется информация, на сколько надо сдвигать/умножать! Если это несколько групп битов подряд, то даже из значений соседних ненулевых множителей вы не сможете понять, на сколько надо умножить тот или иной бит/группу битов. И придётся вам лезть в документацию... sm.gif
С этой точки зрения сдвиги + умножения на 0/1 гораздо лучше.
ViKo
У меня вообще нет сдвигов. Я пользуюсь битовыми масками, описанными в библиотечном заголовке. По большому счету, не представляю, на какой позиции эти биты находятся.
Я умножаю не на сдвиг, а на номер режима.
AlexandrY
Цитата(AHTOXA @ Aug 11 2014, 09:57) *
А если вдруг потом вы обнаружите, что PHAFLTREN равно не 7, а 8, то будете перекапывать все свои исходники? Бр-рр.
Лучше, имхо, всё же выносить это в какие-нибудь хидеры:

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


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

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

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

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

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

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

С битовыми полями вообще не работают BSP генерируемые инструментиами Freescale для MQX например.
AHTOXA
Цитата(AlexandrY @ Aug 11 2014, 16:43) *
В таких поисках время можно сэкономить если все деражать в одном месте

Вот про это я вам и говорюsm.gif А у вас они лежат в каждом файле, где вы обращаетесь к соответствующему регистру. Если потребуется что-то исправить, то будет кошмар. В отличие от "определения битов где-то еще в макросах". Там всё в одном месте, и потребуется всего одно исправление для всех мест в проекте и всех проектов.
Цитата(AlexandrY @ Aug 11 2014, 16:43) *
Если мне нужно еще раз использовать тот-же регистр в другом месте, то я опять копирую все определения битов в присваивании. Дело в том, что таких повторных использований реально очень мало.

Кошмар.
Цитата(AlexandrY @ Aug 11 2014, 16:43) *
Но избыточность оправдывается экономией времени на входжение в контекст.

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

Не вижу экономии, вижу как раз наоборот.
AlexandrY
Цитата(AHTOXA @ Aug 11 2014, 14:59) *
Вот про это я вам и говорюsm.gif А у вас они лежат в каждом файле, где вы обращаетесь к соответствующему регистру. Если потребуется что-то исправить, то будет кошмар. В отличие от "определения битов где-то еще в макросах". Там всё в одном месте, и потребуется всего одно исправление для всех мест в проекте и всех проектов.


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

Цитата(AHTOXA @ Aug 11 2014, 14:59) *
Кошмар.

Назовите хоть пару кофигурационных периферийных регистров которые вы больше 3-х раз где-то используете.

Цитата(AHTOXA @ Aug 11 2014, 14:59) *
При наличии современных IDE - никакой разницы. Подношу мышку к названию бита - получаю всплывающую подсказку с его значением.


Ага навел мышку на макрос запомнил, навел мышку на другой опять запомнил, ... навел на десятый, а про первый уже и забыл. И так пол дня мышкой возить пока все не запомниться. biggrin.gif
А зачем запоминать? Только ради призрачной надежды что когда-то получиться одновремено аж в трех местах изменить бит?
На моей практике такого как-то не удавалось.

Цитата(AHTOXA @ Aug 11 2014, 14:59) *
Не вижу экономии, вижу как раз наоборот.


Еще бы вы это видели. Это чисто психологические неосознаваемые моменты.
Возможно у вас другой тип памяти.

Но опытные тренеры говорят, что все профессионалы рано или поздно приходят к одной технике.
Программирую уже лет 15-ть, а вы?
AHTOXA
Цитата(AlexandrY @ Aug 11 2014, 18:40) *
Правильно, в каждом файле своя периферия. Гораздо быстрее прочитать название файла и понять для какой он периферии. Открыл и знаешь, что больше никаких файлов и зависимостей.
И не надо гадать где бы еще поискать источники влияния на периферию.

Так и у меня может быть по файлу на каждую периферию. Это не суть. Суть в том, что у меня есть мнемоники/дефайны для битов/групп бит конфигурации, а у вас они циферками. Мои мнемоники - определены в одном файле, используются везде где надо. Ваши циферки - определены в каждом файле, где используются.
Ваш вариант:
Код
  FTM1->QDCTRL  = 0
                  + LSHIFT(1, 7) // PHAFLTREN | Phase A Input Filter Enable

Мой вариант:
Код
FTM1->QDCTRL  = 0
                  | (1UL << PHAFLTREN) // Phase A Input Filter Enable
,
и PHAFLTREN определён в отдельном файле.
Вообще, я был уверен, что уже давно все поняли полезность дефайнов и отстойность "магических чисел". Оказывается, нет.

Цитата(AlexandrY @ Aug 11 2014, 18:40) *
Назовите хоть пару кофигурационных периферийных регистров которые вы больше 3-х раз где-то используете.

Ну, например, я работаю с пятью таймерами, и включаю/выключаю их по хитрой программе.
Кроме того, каждый периферийный регистр используется явно более чем в одном проекте.
Цитата(AlexandrY @ Aug 11 2014, 18:40) *
Ага навел мышку на макрос запомнил, навел мышку на другой опять запомнил, ... навел на десятый, а про первый уже и забыл.

Зачем запоминать? Вы свои циферки запоминаете что ли? Какой кошмарsm.gif
Цитата(AlexandrY @ Aug 11 2014, 18:40) *
А зачем запоминать? Только ради призрачной надежды что когда-то получиться одновремено аж в трех местах изменить бит?

Я вот тоже не понимаю, зачем запоминать.
Цитата(AlexandrY @ Aug 11 2014, 18:40) *
Но опытные тренеры говорят, что все профессионалы рано или поздно приходят к одной технике.
Программирую уже лет 15-ть, а вы?

Насколько я могу судить, практически все профессионалы, кроме вас, всё-таки избегают использования "magic numbers".
ЗЫ. Профессионально программирую уже более 20 лет. А до этого был любителемsm.gif
AlexandrY
Цитата(AHTOXA @ Aug 11 2014, 17:50) *
Насколько я могу судить, практически все профессионалы, кроме вас, всё-таки избегают использования "magic numbers".
ЗЫ. Профессионально программирую уже более 20 лет. А до этого был любителемsm.gif


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

Я не поверю чтобы вы без мануала смогли бы в течении хотя бы 10-и минут что-то попрограммировать с использованием регистров в периферийных модулях.
Так если все равно перед вами постоянно открытый мануал, зачем еще скрывать биты за бессмысленными названиями?
Или таким образом закрепить ассоциативные связи в памяти?

Я не прикалываюсь, действительно интересно как структурировать исходники чтобы не перенапрягать мозг.
Скажем одно только рутинное переключенеие экрана с текстов на хидеры в процессе редактирования я уже считаю вредным, и рассеивающим внимание. А сколько сил уходит на придумывание именований дефайнов для битов? Это все надо учитывать.

20 лет программировать на C-и встраиваемые системы... Что-то мало правдоподобно.
AHTOXA
Цитата(AlexandrY @ Aug 11 2014, 23:22) *
Магическими числа называют так потому что не ясен их смысл.

В вашем варианте смысл как раз неясен. Вы сами пишете рядом с числом его мнемонику. Видимо, чем-то она вам помогает?
Опять же, вы уже несколько раз аккуратно проигнорировали мой аргумент о возможной многократной правке кучи файлов в случае ошибки. Ещё плохой сценарий - в паре мест исправили, в третьем -- забыли. И самое главное - ради чего всё это? Пока не прозвучало ни одного внятного аргумента "за". Только отсылки к какому-то высшему знанию.
Кстати, вы знакомы с понятием "нормализация"? Вот, вынос дефайна в отдельный хидер - это как раз она и есть. Исключение дублирования информации.
Цитата(AlexandrY @ Aug 11 2014, 23:22) *
Я не поверю чтобы вы без мануала смогли бы в течении хотя бы 10-и минут что-то попрограммировать с использованием регистров в периферийных модулях.

Мануал открыт при написании хидера. Описываем регистр (адрес), описываем маски для полей регистра. Пишем коммент (копипастим из мануала). Всё. В дальнейшем мануал не нужен - у нас есть хидер.
Кроме того, важно не только удобство программирования, но и удобство сопровождения. А сопровождать гораздо удобнее мнемоники, нежели магические цифры. Искать по тексту - тоже удобнее мнемоники.
Цитата(AlexandrY @ Aug 11 2014, 23:22) *
Я не прикалываюсь, действительно интересно как структурировать исходники чтобы не перенапрягать мозг.
Что-то малоправдоподобно sm.gif
AlexandrY
Цитата(AHTOXA @ Aug 11 2014, 21:24) *
В вашем варианте смысл как раз неясен. Вы сами пишете рядом с числом его мнемонику. Видимо, чем-то она вам помогает?


Да пишу чтобы по принятой производителем мнемонике легче организовать поиск в мануале.
Ибо без мануала исходники инициализации периферии нет смысла даже открывать.


Цитата(AHTOXA @ Aug 11 2014, 21:24) *
Опять же, вы уже несколько раз аккуратно проигнорировали мой аргумент о возможной многократной правке кучи файлов в случае ошибки. Ещё плохой сценарий - в паре мест исправили, в третьем -- забыли. И самое главное - ради чего всё это? Пока не прозвучало ни одного внятного аргумента "за". Только отсылки к какому-то высшему знанию.


Не проигнорировал, а наверно я непонятно написал.
Дело в том, что если вам пришлось менять позицию бита или маску во многих местах проекта да еще в нескольких проектах, то это уже катастрофа.
Это сбой в методологии.
После каждой новой строчки в процедурах работы с периферией у меня следует немедленное тестирование.
Как тут может оказаться неправильный бит?
Это может оказаться только по причине плохого качества документации.
Но если почувствовали подвох в документации то уж будьте уверены перепроверите все свои макросы, и вот тогда встанет в полный рост проблема избыточных дифайнов.
И это более реалистичный сценарий, чем какой-то перепутанный бит.

Цитата(AHTOXA @ Aug 11 2014, 21:24) *
Кстати, вы знакомы с понятием "нормализация"? Вот, вынос дефайна в отдельный хидер - это как раз она и есть. Исключение дублирования информации.

Эт мимо, исходники нужны человеку. А человеку чем больше избыточность тем лучше работает память.

Цитата(AHTOXA @ Aug 11 2014, 21:24) *
Мануал открыт при написании хидера. Описываем регистр (адрес), описываем маски для полей регистра. Пишем коммент (копипастим из мануала). Всё. В дальнейшем мануал не нужен - у нас есть хидер.
Кроме того, важно не только удобство программирования, но и удобство сопровождения. А сопровождать гораздо удобнее мнемоники, нежели магические цифры. Искать по тексту - тоже удобнее мнемоники.

Вот в эти байки я и не верю, якобы хидеры заменяют мануал.
Сопровождение тоже этакий миф. Удобство сопровождения кому. Стороннему программисту?
Так стороннему программисту что угодно напиши он всегда будет плеваться.
А автору исходников мало что облегчит если он вздумает вдруг поменять скажем битовую маску в хидере. Все равно придется лезть во все исходники где она применялась и разбираться с каждым случаем.
Так что же тогда облегчают хидеры? (Еще напомню, что говорим только о битах периферии, а не о всем на свете biggrin.gif )

AHTOXA
Цитата(AlexandrY @ Aug 12 2014, 01:03) *
Да пишу чтобы по принятой производителем мнемонике легче организовать поиск в мануале.
Ибо без мануала исходники инициализации периферии нет смысла даже открывать.

Если у вас в исходниках (в соответствующем хидере) продублировано описание регистров из мануала, то зачем мануал? sm.gif
Опять же, поиск по исходникам обеспечивает IDE, не надо переключать внимание код<==>мануал.
Если правильно организовать имена, то автодополнение тоже очень помогает: пишу
FLASH->CR |= FLASH_CR_
, нажимаю комбинацию клавиш, вуяля, передо мной все нужные варианты.

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
Дело в том, что если вам пришлось менять позицию бита или маску во многих местах проекта да еще в нескольких проектах, то это уже катастрофа.
Это сбой в методологии.

Или банальная ошибка/опечатка. Скажете, с вами такого не бывает? Значит вы второй такой уникум в мире (после меняsm.gif)

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
После каждой новой строчки в процедурах работы с периферией у меня следует немедленное тестирование.

Ну это уже совсем "что-то малоправдоподобно" sm.gif. К тому же, не все ошибки можно быстро выявить тестированием.

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
Как тут может оказаться неправильный бит?
Это может оказаться только по причине плохого качества документации.

Да, бывают ошибки в документации. И тут ваш подход в пролёте - вам придётся исправлять во многих файлах. Причём поиск будет возможен только по комментарию (мнемоника-то только там), и ничто не может гарантировать, что комментарий соответствует значению. Этого даже тестирование после каждой строчки не выявит.
Я же исправлю в одном хидере, и всё. Причём найду нужный дефайн безошибочно, потому что в его имени есть мнемоника от производителя.

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
Но если почувствовали подвох в документации то уж будьте уверены перепроверите все свои макросы, и вот тогда встанет в полный рост проблема избыточных дифайнов.
И это более реалистичный сценарий, чем какой-то перепутанный бит.

Какие-такие "все макросы"? Один дефайн, в одном файле. А вот вы помучаетесь.

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
Эт мимо, исходники нужны человеку. А человеку чем больше избыточность тем лучше работает память.

Во-первых, память не бездонна. Во-вторых, незачем забивать её несущественными деталями. Номер бита - информация лишняя. Мне нужно взвести/сбросить бит разрешения работы (EN) в регистре BDCR, я просто пишу RCC->BDCR |= RCC_BDCR_RTCEN. И мне неважно, какой номер у этого регистра.

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
Вот в эти байки я и не верю, якобы хидеры заменяют мануал.

Если перепишете всё из мануала в хидер, то почему нет? sm.gif

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
Сопровождение тоже этакий миф. Удобство сопровождения кому. Стороннему программисту?

В первую очередь себе. Удобства сопровождения я описал уже несколько раз.

Цитата(AlexandrY @ Aug 12 2014, 01:03) *
А автору исходников мало что облегчит если он вздумает вдруг поменять скажем битовую маску в хидере. Все равно придется лезть во все исходники где она применялась и разбираться с каждым случаем.

Зачем лезть во все исходники, где применялась маска? Исправлять нужно только в одном месте - где маска определялась. А в остальных местах её новое значение подставит препроцессорsm.gif
menzoda
Цитата(AHTOXA @ Aug 12 2014, 01:54) *
Пишем коммент (копипастим из мануала)...
Если перепишете всё из мануала в хидер, то почему нет?..

Вот это точно бестолковое занятие. В большинстве ситуаций одним небольшим комментарием работу с регистром не опишешь, да что там, и большим тоже не опишешь. Что теперь, перепечатывать 200-страничный документ в заголовочный файл? Нет конечно! Никаких комментариев тут вообще не нужно, пустая трата времени.

Насчет именования конкретных битов регистра. В принципе, несмотря на громоздкость, это довольно удобно, за исключением случаев, где регистр имеет нетривиальную структуру, а не несколько битов вкл/выкл. К сожалению, регистры в основном имеют как раз сложную структуру, и красивый по задумке код:
Код
TIMCON = TIMCON_ENA
       | TIMCON_RST
       | TIMCON_UP
       | TIMCON_DOWN;

превращается в шараду:
Код
TIMCON &= ~TIMCON_ENA & ~TIMCON_PSC_2;
TIMCON |= TIMCON_ENA
       | TIMCON_RST
       | TIMCON_PSC_1
       | TIMCON_PSC_3

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

Лично мне лень этим заниматься, да и от чтения документации все эти имена меня не особо спасают, поэтому я делаю совсем просто: магическое число и комментарий о том, что там делается:
Код
// Останавливает таймер, задает значения предделителя и период таймера,
// разрешает прерывание, активирует режим захвата, запускает таймер.
TIMCON &= 0xA0FF;
TIMCON |= 0x8001;

Комментарий помогает в общих чертах понять суть действа, а если нужно что-то поменять - то так и так лезть в даташит. Да и редко, на самом деле, приходится что-то менять в низкоуровневых модулях, общающихся с периферией.
ViKo
Для menzoda - мне ваш первый пример логичнее, понятнее. А во втором легко сделать ошибку.
Кстати, первый пример можно упростить.
AlexandrY
Цитата(AHTOXA @ Aug 12 2014, 00:54) *
Во-первых, память не бездонна. Во-вторых, незачем забивать её несущественными деталями. Номер бита - информация лишняя. Мне нужно взвести/сбросить бит разрешения работы (EN) в регистре BDCR, я просто пишу RCC->BDCR |= RCC_BDCR_RTCEN. И мне неважно, какой номер у этого регистра.


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

Лучше написать длинный коментарий но прямо радом с битом, чем обозвать бит мнемоникой у вместе с комментариями увести в хидер.
А номера битов конечно я не запоминаю, главное здесь комментрарии. Они понятно не полные, но мощнее активизируют ассоциации чем мнемоники.
С удовольствием вставлял бы линки прямо на мануал, но редакторы такой технологии не поддерживают.
AHTOXA
Цитата(menzoda @ Aug 12 2014, 18:44) *
Вот это точно бестолковое занятие.

Это была гипербола, мне жаль, что вы не поняли.

Цитата(menzoda @ Aug 12 2014, 18:44) *
поэтому я делаю совсем просто: магическое число и комментарий о том, что там делается:

Вы тоже начинали с PIC-ов? sm.gif

AlexandrY, поздравляю, ваш тонкий троллинг уже даёт всходы.

Цитата(AlexandrY @ Aug 12 2014, 19:48) *
Наша память ассоциативна. В этом смысле она бездонна.

Эот вы ещё маловато программируете, всего 15 лет. Вот после 20 лет вы поймёте, что у нашей памяти есть дноsm.gif
Цитата(AlexandrY @ Aug 12 2014, 19:48) *
Лучше написать длинный коментарий но прямо радом с битом, чем обозвать бит мнемоникой у вместе с комментариями увести в хидер.

Я так и не услышал от вас аргументов, чем этот подход лучше. И не услышу, по всей видимости.
Свои аргументы, чем этот подход хуже, я уже привёл.
menzoda
Цитата(AHTOXA @ Aug 12 2014, 18:20) *
Это была гипербола, мне жаль, что вы не поняли.

Там же я процитировал и предыдущую твою фразу (извини, не люблю ВЫкать в интернетах), которая была не гиперболой. Странно, что ты ее не заметил, или только сделал вид? Кроме того я высказался не только и не сколько про абсурдное "переписать весь мануал", которое и так всем понятно, сколько про "копипастим коммент из мануала".

Цитата(AHTOXA @ Aug 12 2014, 18:20) *
Вы тоже начинали с PIC-ов? sm.gif

Нет, с TMS32F28xx от Texas Instruments и LH75401 от тогда еще Phillips, если это имеет какое-то значение. С PIC приходится иметь дело всего в одном устройстве, и мне не особо нравятся эти моменты.
Herz
Цитата(menzoda @ Aug 12 2014, 17:57) *
(извини, не люблю ВЫкать в интернетах)

Я всё же попросил бы Вас об этом одолжении. Не все любят, когда им ТЫкают,особенно незнакомые люди, и интернеты - не исключение.
AHTOXA
Цитата(menzoda @ Aug 12 2014, 20:57) *
Там же я процитировал и предыдущую твою фразу (извини, не люблю ВЫкать в интернетах), которая была не гиперболой. Странно, что ты ее не заметил, или только сделал вид? Кроме того я высказался не только и не сколько про абсурдное "переписать весь мануал", которое и так всем понятно, сколько про "копипастим коммент из мануала".


Я не против общения на "ты", но продолжу на "вы", тут так принято.
По вашему примеру кода я сразу понял, что случай клинический, поэтому не стал на ваш пост реагировать всерьёз. Вы уж извините.
menzoda
Цитата
По вашему примеру кода я сразу понял, что случай клинический, поэтому не стал на ваш пост реагировать всерьёз. Вы уж извините.

Спасибо, доктор! Как же я раньше такой больной то ходил. Попытки принижения собеседника при отсутствии аргументов - это обязательный элемент твоей вашей стратегии спора? Это - риторический вопрос. Если уж притворяешся притворяетесь умным и вежливым человеком - так притворяйся притворяйтесь до конца.
adnega
Цитата(menzoda @ Aug 14 2014, 11:19) *
Спасибо, доктор! Как же я раньше такой больной то ходил. Попытки принижения собеседника при отсутствии аргументов - это обязательный элемент твоей вашей стратегии спора? Это - риторический вопрос. Если уж притворяешся притворяетесь умным и вежливым человеком - так притворяйся притворяйтесь до конца.

Вы не воспринимайте близко к сердцу, действительно, остаивать магические числа - это, мягко говоря, странно. И случай такой можно назвать
клиническим, но это не означает, что вы не здоровы. Естественный процесс развития от простого к сложному. Магические числа - это самый первый этап.
Затем, если разработчик чувствует перспективу и не ленится, то найдет/напишет библиотеки и будет ими пользоваться. Вы же признались, что лень
в вас победила здравый смысл. Отсюда и диагнозы. Вот если бы вы не ленились - вы бы сделали по-другому?
ViKo
Я показал лучшее решение в сообщении #4, но "опытным профессионалам" лень разобраться и оценить его по-достоинству. Обратите внимание на XX * N.
dxp
QUOTE (ViKo @ Aug 14 2014, 14:37) *
Я показал лучшее решение в сообщении #4, но "опытным профессионалам" лень разобраться и оценить его по-достоинству. Обратите внимание на XX * N.

Чем это лучше, чем просто комментить строку? Закомментированная строка сразу видна в редакторе с подсветкой синтактсиса, что, имхо, является плюсом, т.к. сразу видно, что активно, а что нет. Или вы что-то иное, нежели механизм оперативного включения/выключения битов, имели в виду?
ViKo
Цитата(dxp @ Aug 15 2014, 08:58) *
Чем это лучше, чем просто комментить строку? Закомментированная строка сразу видна в редакторе с подсветкой синтактсиса, что, имхо, является плюсом, т.к. сразу видно, что активно, а что нет. Или вы что-то иное, нежели механизм оперативного включения/выключения битов, имели в виду?

Иное. Хотя и с вашим утверждением не согласен. Умножил на 0, и знаешь, что этот бит в нуле. Нужна 1, заменил 0 на 1. Однообразие.
Имею же в виду следующее, покажу конкретно на примере из сообщения №4.
Код
    ADC12_CCR_DELAY_0    * 4 |    // Delay between 2 sampling phases: 5

Из stm32f30x.h имеем
Код
#define ADC12_CCR_DELAY_0           ((uint32_t)0x00000100) /*!< DELAY bit 0 */

Из мануала на STM32F303xx
Цитата
Bits 11:8 DELAY: Delay between 2 sampling phases
Set and cleared by software. These bits are used in dual interleaved modes.
...
0100 5 * TADC_CLK

0x00000100 * 0x4 = 0x00000400
Таким образом, умножив маску младшего бита на номер режима, я задаю все нужные биты режима одним махом. Не нужно устанавливать/сбрасывать все биты по-отдельности. Получается не 32 строчки (о чем писалось в начале темы), а намного меньше, столько, сколько есть полей для выбора режимов (в некоторых исключительных случаях поля режимов разбиты на 2, один бит где-то в другом месте болтается, тогда приходится описывать его отдельно).
И тогда - пробежался взглядом по инициализации, и все установки - как на ладони.

Для демонстрации красоты способа, вот другой пример (табуляция сползает, надоело править!):
Код
  DAC->CR =
    DAC_CR_EN1        *  1 |     // DAC channel1 enable
    DAC_CR_BOFF1        *  0 |     // DAC channel1 output buffer disable
    DAC_CR_TEN1        *  1 |     // DAC channel1 Trigger enable
    DAC_CR_TSEL1_0      *  3 |     // DAC channel1 Trigger selection: TIM15
    DAC_CR_WAVE1_0    *  2 |     // DAC channel1 noise/triangle wave generation
    DAC_CR_MAMP1_0     * 11 | // DAC channel1 Mask/Amplitude selector: 12 bit
    DAC_CR_DMAEN1      *  0 |     // DAC channel1 DMA enable
    DAC_CR_EN2             *  1 |     // DAC channel2 enable
    DAC_CR_BOFF2        *  0 |     // DAC channel2 output buffer disable
    DAC_CR_TEN2           *  0 |     // DAC channel2 Trigger enable
    DAC_CR_TSEL2_0      *  7 |     // DAC channel2 Trigger selection: Software
    DAC_CR_WAVE2_0    *  0 |     // DAC channel2 noise/triangle wave generation enable
    DAC_CR_MAMP2_0     *  0 |     // DAC channel2 Mask/Amplitude selector
    DAC_CR_DMAEN2      *  0;     // DAC channel2 DMA enable
demiurg_spb
Поддержу в этом споре Антоху.
Есть системный подход и есть всё остальное...
Повторное использование кода - это благо и на этом в основном и зиждиться программирование.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.