Комментарии 28
Очень хорошо, что вы описываете подобные тонкости и хитрости, для меня, как для начинающего на этом поприще, очень интересно и полезно читать вас!
в первом листинге:
#define IO_STATUS_CMD_BIT 0x28
в 10-чной это будет 40, а не 28. Как я понял сдвинуть то вы на 28 собирались
#define IO_STATUS_CMD_BIT 0x28
в 10-чной это будет 40, а не 28. Как я понял сдвинуть то вы на 28 собирались
Легко написать макрос, который из битовой маски сделает битовую маску с единственным младшим битом
#define LOWBIT(MASK) ((((MASK)-1) <<1 ) & (MASK)) #define LOWBIT(MASK) (~(MASK << 1) & (MASK))
Первая реализация просто неправильная: при MASK = 0x3 она даёт 0 вместо 1.
Вторая не работает с битовыми полями в которых есть разрывы: при MASK = 0x5 она даёт 0x5 вместо 1.
Идиома в данном случае — #define LOWBIT(MASK) (-(MASK) & MASK)
труднее (у меня не получилось), макрос выделяющий номер младшего бита
Простейшее решение:
#define LOWBITIDX(MASK) ((LOWBIT(MASK) > 0x1) + (LOWBIT(MASK) > 0x2) + (LOWBIT(MASK) > 0x4) + (LOWBIT(MASK) > 0x8) +… )
Больше битовых трюков: см. www.hackersdelight.org/
этот метод я конечно нашел, но речь то идет о красивых решениях ))
а не в переборных, а этот можно и упростить, если работать по байтам, но коряво до ужаса
а не в переборных, а этот можно и упростить, если работать по байтам, но коряво до ужаса
Что тут некрасивого? Получается константа времени компиляции. Ну или вот, более короткое решение:
#define LOWBITIDX(MASK) LOWBITIDX32(MASK)
#define LOWBITIDX32(MASK) ((MASK) >= (1 << 16) ? LOWBITIDX16(MASK >> 16) + 16 : LOWBITIDX16(MASK))
#define LOWBITIDX16(MASK) ((MASK) >= (1 << 8) ? LOWBITIDX8(MASK >> 8) + 8 : LOWBITIDX8(MASK))
#define LOWBITIDX8(MASK) ((MASK) >= (1 << 4) ? LOWBITIDX4(MASK >> 4) + 4 : LOWBITIDX4(MASK))
#define LOWBITIDX4(MASK) ((MASK) >= (1 << 2) ? LOWBITIDX2(MASK >> 2) + 2 : LOWBITIDX2(MASK))
#define LOWBITIDX2(MASK) ((MASK) >= (1 << 1) ? LOWBITIDX1(MASK >> 1) + 1 : LOWBITIDX1(MASK))
#define LOWBITIDX1(MASK) ((MASK) >= 0x1 ? 0 : -1)
Замечание верное, но все таки среди разработчиком МК не так много людей, получающих ищвращенно удовольствие от издевательства над разработчиком устройств и, как правило, порядок битов в регистре подразумевает нативный порядок байтов. Другое дело, что многие ядра поддерживают любой порядок байтов, ну так и следует выбирать такой, который не приведет к разрыву полей.
Я доброжелательно отношусь к критике, но во втором случае если бы ВЫ показали, как можно хорошо сделать при помощи битовых масок, я бы согласился, а пока что — согласится с мыслью о вредности вывода не могу.
Я доброжелательно отношусь к критике, но во втором случае если бы ВЫ показали, как можно хорошо сделать при помощи битовых масок, я бы согласился, а пока что — согласится с мыслью о вредности вывода не могу.
То есть пока смею настаивать — при соблюдении должных мер предосторожности битовые поля очень удобный инструмент.
Можно перефразировать известное изречение «Битовые поля — наихудший способ, если не считать всех остальных»
Можно перефразировать известное изречение «Битовые поля — наихудший способ, если не считать всех остальных»
Я пока не видел системы, в которой одновременно есть устройства и с B и с L-endian. Если знаете такую, скажите, может, мне просто везло. И если такая есть, то какой способ можно предложить вместо превратившихся в тыкву битовых полей? Маски с пробелами и чередованием старших и младших битов?
Речь шла об УДОБНОМ и обозримом способе.
Вместо пары
читать регистр (read{l,w}, переворачивать (le{32,16}_to_cpu)лучше использовать io{read,write}{8,16,32}{,be} — это более современный и рекомендованный интерфейс.
Пост датируется 2004 годом
С тех пор вышли новые книги/написаны новые письма утверждающие обратное?
Хотите пример свежее: вот.
Ну и на наших target-платформах нету
а немного раньше
я могу сказать по опыту, что разработчики SoC-ов очень любят лицензировать чужие блоки
а на их платформах — вполне могут быть.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Работа с регистрами внешних устройств в языке C, часть 2