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

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

может наверняка есть какой-то более удобный метод. макрос, определяющий имя байта с флагами по имени бита, что-ли.
Dog Pawlowa
Цитата(amost @ Jun 19 2010, 12:18) *
может наверняка есть какой-то более удобный метод. макрос, определяющий имя байта с флагами по имени бита, что-ли.

С gcc практически не работаю, но сам под ИАРом использую вот такое описание флагов в отдельном файле (см внизу)
Как это макросами развернуть - не показываю, ибо проклянете smile.gif
На самом то деле тот метод, который используете, имеет множество достоинств. Ну включите в имя маски имя переменной, чтобы не ошибиться.

Код
/*     name         var            bit   */

FLAG    (    eeprom_good                ,flags,    0x0001U )
FLAG    (    low_power_enable           ,flags,    0x0002U )
FLAG    (    factory_flag               ,flags,    0x0004U )
FLAG    (    service_calibration        ,flags, 0x0008U )
FLAG    (    remote                     ,flags, 0x0010U )
FLAG    (    show_value              ,flags, 0x0020U )
FLAG    (    blink                   ,flags, 0x0040U )
FLAG    (    missing_pulses          ,flags, 0x0080U )
FLAG    (    remote_change_enabled    ,flags, 0x0100U )
FLAG    (    booster_filled           ,flags, 0x0200U )
FLAG    (    refilling                ,flags, 0x0400U )
FLAG    (    conc_change_enable        ,flags,    0x0800U )
FLAG    (    delivery_passive        ,flags, 0x1000U )
FLAG    (    start_user_menu            ,flags, 0x2000U )
FLAG    (    process_happened           ,flags, 0x4000U )
//FLAG    (    block_booster_error        ,flags, 0x8000U )

FLAGS_VARIABLE ( flags )
M_Andrey
Код
</P><P>union char_by_bit
    {
    struct
        {
        unsigned char D0 :1;
        unsigned char D1 :1;
        unsigned char D2 :1;
        unsigned char D3 :1;
        unsigned char D4 :1;
        unsigned char D5 :1;
        unsigned char D6 :1;
        unsigned char D7 :1;
          }bit;
    unsigned char byte;
    };    //statfl;

#define    NEW_IBUT    mode[0].bit.D0
#define    ERR_I2C        mode[0].bit.D1
#define    GET_KEY        mode[0].bit.D2

union char_by_bit mode[10];



zltigo
QUOTE (amost @ Jun 19 2010, 11:18) *
avr-gcc
раньше....

Как Вам уже сказал Dog Pawlowa - так и продолжайте, только добавьте имя регистра. Типа:
CODE
#define SIS5_LIG(x)    (((x)&0x3)<<6)
#define SIS5_LIM        BIT5
#define SIS5_MCG(x)    (((x)&0x3)<<3)
#define SIS5_MCM        BIT2
#define SIS5_HIM        BIT1
#define SIS5_IIR        BIT0

......
    si_write( SIS5, SIS5_LIG(LIG_20DB)|SIS5_MCG(0)|SIS5_MCM|SIS5_HIM);    // Line Gain +20dB
    si_write( SIS6, SIS6_RXG(RXG_0DB)|SIS6_LO_ON);             // RX 0dB Line Out Active

......
void si_write( int reg, bint data )
{
    if( ( reg >= SIS1 )&&( reg <= SIS9 ) )
    {
        if( !xIsTimeout( si3000_time ) )
            vSmartDelay( 1 );
        fpga_cmd( FCMD_SI3000|FCMD_WR, (reg<<8)|(BYTE)data );
        si_reg[reg] = (BYTE)data;
        si3000_time = xGetTimeout( 1 );
    }
    else
        xprintf( "SI:Invalid REG:%2X\r", reg );
}

Проверено на собственной шкуре многими годами поисков и применения разных "извратов".
demiurg_spb
На платформах, не имеющих атомарного битового доступа к ОЗУ,
использовать битовые переменные нерационально если:
1. они volatile
2. их достаточно мало (не стоит жмотиться и выиграть аж целых 20-50 байт ОЗУ)
3. они не расположены в sfr области (см п.1).

Я в 99% случаев под флаги использую целую ячейку памяти (байт или даже крупнее) и в ус не дую...

Оптимизация ресурсов ОЗУ не должна быть самоцелью...
zltigo
QUOTE (demiurg_spb @ Jun 19 2010, 13:27) *
Я в 99% случаев под флаги использую целую ячейку памяти (байт или даже крупнее) и в ус не дую...

Ну и зря, в тех-же 99 случаях флаги не используются отдельно, а "кучкуются" и лазить за каждым флагом в память, вместо работы с этими флагами в единожды загруженном одном регистре это уже не только растраты памяти, но и производительности. Естественно, случаи бывают разными. И железо бывает разным.
MrYuran
Цитата(zltigo @ Jun 19 2010, 16:00) *
Естественно, случаи бывают разными. И железо бывает разным.

А если флагов под сотню? Никаких регистров не хватит.
Или, к примеру, у MSP430 нет битовых команд. Забавно иногда смотреть, как выкручивается компилятор, доставая бит из середины, к примеру, четырьмя сдвигами подряд и переходом по флагу
rezident
Цитата(MrYuran @ Jun 19 2010, 19:40) *
Или, к примеру, у MSP430 нет битовых команд. Забавно иногда смотреть, как выкручивается компилятор, доставая бит из середины, к примеру, четырьмя сдвигами подряд и переходом по флагу
По этой причине я для MSP430 не использую битовых переменных. Работаю с битовыми масками.
zltigo
QUOTE (MrYuran @ Jun 19 2010, 15:40) *
А если флагов под сотню? Никаких регистров не хватит.

Вы хоть поняли, о чем речь-то идет? Количество флагов к количеству регистров регистров у контроллера отношения не имеет.
Serj78
Цитата(zltigo @ Jun 19 2010, 21:08) *
Вы хоть поняли, о чем речь-то идет? Количество флагов к количеству регистров регистров у контроллера отношения не имеет.


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

Я при переносе проекта на STM32 с avr решил не извращаться и все флаги просто байтовые сделал. Правда их не много - 30шт всего.
zltigo
QUOTE (Serj78 @ Jun 19 2010, 20:03) *
Я не телепат но похоже он имел...

Так зачем, то, что "он имел", Вы переносите на то, что писал я sad.gif. Причем в том числе и по помянутой Вами причине, следует использовать битовые маски в большинстве случаев.
MrYuran
Цитата(zltigo @ Jun 19 2010, 21:08) *
Вы хоть поняли, о чем речь-то идет?

Перечитал ещё раз. Теперь понял.

Цитата(rezident @ Jun 19 2010, 19:20) *
По этой причине я для MSP430 не использую битовых переменных. Работаю с битовыми масками.

А компиляторы нынче умные шибко пошли. Он и с маской может то же самое сделать, если посчитает, что это "дешевле" по времени или размеру
В общем, я к такому выводу пришёл, на основании своих наблюдений, что нет особой разницы, как писать.
Компилятор сам не дурак, решит, где удобнее маску наложить, где подвигать, а где битовые команды (если они есть) использовать.
Таким образом, надо писать так, как удобнее.
Вот ещё бы научить компилятор, чтобы группировал множество битов в одной команде...
Ну то есть чтобы вместо восьми битовых команд для одного, скажем, порта I/O формировал сразу общую байтовую маску.
Но это надо какое-то расширение языка в сторону HDL, например, объединить группу операторов в некий "квант", который можно выполнять одновременно
demiurg_spb
Цитата(zltigo @ Jun 19 2010, 16:00) *
Ну и зря, в тех-же 99 случаях флаги не используются отдельно, а "кучкуются" и лазить за каждым флагом в память, вместо работы с этими флагами в единожды загруженном одном регистре это уже не только растраты памяти, но и производительности. Естественно, случаи бывают разными. И железо бывает разным.

Конечно, они могут и кучковаться, а могут и нет. Это меня даже не сильно заботит.
Меня во всей этой ситуации всегда напрягала необходимость использования критической секции.
И даже если они (флаги) обрабатываются пачками по 3-5 штук ещё не известно что будет оптимальнее прочитать 3-5 байт из ОЗУ или вкрячить критичекую секцию, добавив при этом лишнюю латентность (пусть даже и копеечную).
Мне всегда ближе наиболее простой вариант. И код не засорён лишними временными промежуточными переменными.
zltigo
QUOTE (demiurg_spb @ Jun 20 2010, 12:30) *
И даже если они (флаги) обрабатываются пачками по 3-5 штук ещё не известно что будет оптимальнее прочитать 3-5 байт из ОЗУ или вкрячить критичекую секцию, добавив при этом лишнюю латентность (пусть даже и копеечную).

А зачем приплетать всуе слова "критическая секция". Эта сущность в общем случае совершенно отдельная. Если Вы не задумываясь щедрой рукой разбрасываете volatile да critical, и знаете только одну систему команд, то это не значит, что все должны следовать Вашему "примеру" и разбрасываться ресурсами sad.gif.

MALLOY2
Цитата
Я при переносе проекта на STM32 с avr решил не извращаться и все флаги просто байтовые сделал. Правда их не много - 30шт всего.


Совершенно зря, у Cortex есть фича упрощающая работу с битами называется она "Bit Banding"
Все ваши флаги можно было упаковать в одно слово, а там работай хоть через маски хоть через Bit Banding.
demiurg_spb
Цитата(zltigo @ Jun 20 2010, 14:49) *
А зачем приплетать всуе слова "критическая секция". Эта сущность в общем случае совершенно отдельная. Если Вы не задумываясь щедрой рукой разбрасываете volatile да critical, и знаете только одну систему команд, то это не значит, что все должны следовать Вашему "примеру" и разбрасываться ресурсами sad.gif.
Пусть хоть один флаг волатилен, он и всех собратьев (из одного байта) сделает таковыми.
Оно надо? Да я даю реально упрощающий жизнь пример. Когда не надо помнить ни про волатильность ни про то что особо умный и жадный программист разделил волатильные флаги от неволатильных, а потом забыл об этом ненароком он сам или наследники его таланта.
Зачем закладывать грабли когда можно и нужно без них обходиться.
Просто. Надёжно. Без геморроя. Быстро и не требует лишней писанины (я об описании через дефайны мути в виде масок, что вообще применимо лишь для описании периферии). Хочется воскликнуть: Ау! мы пишем на Си а не на я языке препроцессора в конце то концов...

А Вы всё о какой-то мифической экономии ресурсов печётесь.
Не здесь блох ловить стоит 20 байт озу и 5-20 тиков тактовой.
Не мне Вам объяснять где. Вы сами прекрасно знаете про вынесение из цикла всякой чуши, про их разворачивание, про правильный (нативный) выбор типов данных и про уместное использование volatile да и вообще о культуре программирования.

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

Цитата(MALLOY2 @ Jun 20 2010, 20:34) *
Совершенно зря, у Cortex есть фича упрощающая работу с битами называется она "Bit Banding"
Все ваши флаги можно было упаковать в одно слово, а там работай хоть через маски хоть через Bit Banding.
Это отлично! Через пару месяцев ему потребуется портировать проект под процессор XXX с адресным пространством чуть меньшим чем 4Gb без Bit Banding... "О сколько нам открытий чудных готовит просвещения дух!" - это я не к тому чтобы не использовать новую полезную фичу, а к тому что и старая даёт сопоставимый результат.

Ну нет в Си полноценного типа данных меньшего чем uint_fast8_t!
MALLOY2
Цитата
Это отлично! Через пару месяцев ему потребуется портировать проект под процессор XXX

и какие проблемы ? Все зависит как вы опишете Bit Banding, так вы его и портируете. Использовать 8-битный тип для флагов это двойной геморой, первое это расход памяти, второе это компилятор всегда расширяет 8 бит до 32 бит, а это для кортекса 1 лишняя команда.
zltigo
QUOTE (demiurg_spb @ Jun 21 2010, 00:44) *
Да я даю реально упрощающий жизнь пример. Когда не надо помнить ни....

Если не хочется помнить, знать, отвечать, то надо идти в дворники, ну или программисты 1C - там всякие бездумные действия порядке вещей.
QUOTE
и про уместное использование volatile да и вообще о культуре программирования.

Вот именно по этой причине меня и задевает пропаганда "реально упрощающий жизнь пример. Когда не надо помнить" подход к программированию sad.gif.
MrYuran
Цитата(MrYuran @ Jun 20 2010, 12:11) *
Компилятор сам не дурак, решит, где удобнее маску наложить, где подвигать, а где битовые команды (если они есть) использовать.
Таким образом, надо писать так, как удобнее.

Поэтому предлагаю описать так:
Код
struct
{
    FLAG( D0 );
    FLAG( D1 );
    ...
}stFlags;

, где FLAG можно описать макросом
#define FLAG(FlagName) unsigned char FlagName : 1
либо
#define FLAG(FlagName) unsigned char FlagName
либо
#define FLAG(FlagName) FlagType FlagName
demiurg_spb
Цитата(zltigo @ Jun 21 2010, 10:09) *
Если не хочется помнить, знать, отвечать, то надо идти в дворники, ну или программисты 1C - там всякие бездумные действия порядке вещей.
Опять 25... Обобщаем обобщаемое... Еще забыли сказать, что всю Россию пропили...
А моих доводов ЗА так и не увидели. Я ваш единственный довод об увеличении производительности парировал своими доводами. А Вы всё юлите и в общемировые проблемы уходите и проблемы частного индивида.
Цитата
Вот именно по этой причине меня и задевает пропаганда "реально упрощающий жизнь пример. Когда не надо помнить" подход к программированию sad.gif.
Ну не хотите Вы понять что прозрачно написанная программа это благо как ни крути. А любое привнесённое - это муть в чистой воде. Все я с Вами в такой манере больше не желаю общаться. И на том спасибо!



Цитата(MALLOY2 @ Jun 21 2010, 09:49) *
и какие проблемы ? Все зависит как вы опишете Bit Banding, так вы его и портируете.
Никаких проблем нет. Также как и явных преимуществ перед нативным типом. И тем что надо портировать и описывать.
Цитата
Использовать 8-битный тип для флагов это двойной геморой, первое это расход памяти, второе это компилятор всегда расширяет 8 бит до 32 бит, а это для кортекса 1 лишняя команда.
Где вы увидели что я предлагал использовать "жёсткий" 8-ми битный тип?
Да будет перерасход памяти. Это действительно плохо и ужасно. Сколько сейчас в среднем ставят на кортексах 8, 16К?
Для ликбеза: как там в кортексе устроен механизм записи 32-битного регистра в ОЗУ атомарно? И бывает ли иначе?
zltigo
QUOTE (demiurg_spb @ Jun 21 2010, 10:09) *
Ну не хотите Вы понять что прозрачно написанная программа...

Оценка степени прозрачности программ прежде всего зависит от количества мути в голове оценивающего sad.gif.

Tanya
А я вот... делаю и так и эдак. Если быстро флаги (семафоры) не нужны, пакую, а если быстро - то не экономлю.
Спор этот напоминает... тупоконечников и остроконечников...
demiurg_spb
Цитата(MrYuran @ Jun 21 2010, 10:25) *
Поэтому предлагаю описать так:
, где FLAG можно описать макросом
Много букв:-)
Но для мсп430 с его "огромным" ОЗУ иногда и так может сгодиться
или "даже хуже": просто битовое поле или просто байты с масками.

Цитата(Tanya @ Jun 21 2010, 12:37) *
А я вот... делаю и так и эдак. Если быстро флаги (семафоры) не нужны, пакую, а если быстро - то не экономлю.

И правильно делаете.
Цитата
Спор этот напоминает... тупоконечников и остроконечников...
Не будем уточнять кто есть ктоsmile.gif

Цитата(zltigo @ Jun 21 2010, 12:19) *
Оценка степени прозрачности программ прежде всего зависит от количества мути в голове оценивающего sad.gif.
Критерий один - отсутствие мути.
Муть в данном случае буковки. Много буковок. ООООчень много буковок и макросов и разделений на своих и чужих.
Herz
Цитата(demiurg_spb @ Jun 21 2010, 01:44) *
Ну нет в Си полноценного типа данных меньшего чем uint_fast8_t!

Простите, что влезаю в интеллигентный разговор, но я в С не видел такого типа. Наверное, речь не об ANSI C?
demiurg_spb
stdint.h часть С99

http://en.wikipedia.org/wiki/C_library
ViKo
Если определить несколько переменных типа bool, компилятор не объединит их в один байт/слово... ?
rezident
Цитата(ViKo @ Jun 21 2010, 19:20) *
Если определить несколько переменных типа bool, компилятор не объединит их в один байт/слово... ?
Сам по себе - нет. Тип bool в C99 макросом преобразуется в _Bool, который в свою очередь имеет размерность int.
Herz
Цитата(demiurg_spb @ Jun 21 2010, 14:14) *

Нажмите для просмотра прикрепленного файла ?
rezident
Цитата(Herz @ Jun 21 2010, 21:03) *
?
Не читайте советских газет перед обедом не ориентируйтесь на Википедию как на истину в последней инстанции. Справляйтесь у оригинала стандарта ISO/IEC 9899:1999 (E).

Цитата
7.18.1.3 Fastest minimum-width integer types
1Each of the following types designates an integer type that is usually fastest
216)
to operate
with among all integer types that have atleast the specified width.
2The typedef name int_fastN_t designates the fastest signed integer type with a width
of at least N.The typedef name uint_fastN_t designates the fastest unsigned integer
type with a width of at least N.
3The following types are required:
int_fast8_t
int_fast16_t
int_fast32_t
int_fast64_t
uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t
All other types of this form are optional.
zltigo
QUOTE (rezident @ Jun 21 2010, 18:14) *
стандарта ISO/IEC 9899:1999 (E)

Ну свежие драфты не забывать ISO/IEC 9899:201x Крайний August 11, 2008. В них тоже уже изменений накопилось.
Herz
Ясно, спасибо. Но вроде как и int8_t, и uint8_t гарантированно имеют размерность в 8 бит?
Serj78
Цитата(MALLOY2 @ Jun 21 2010, 09:49) *
и какие проблемы ? Все зависит как вы опишете Bit Banding, так вы его и портируете. Использовать 8-битный тип для флагов это двойной геморой, первое это расход памяти, второе это компилятор всегда расширяет 8 бит до 32 бит, а это для кортекса 1 лишняя команда.


А можно по подробнее, КАК он расширяет? ( я пользуюсь Кейлом uVision 3.85) Если у меня массив из 100 значений unsigned char ( u8 как в кейловской библиотеке переименовано), ведь не выделяется под них 400 байт?

При математических действиях разве эти 8 бит не записываются в младшие разряды 32- битного числа ( АЛУ 32-х битное) ? Я думал что только для знаковых типов преобразование требуется...
romez777
QUOTE (Serj78 @ Jun 21 2010, 21:39) *
А можно по подробнее, КАК он расширяет? ( я пользуюсь Кейлом uVision 3.85) Если у меня массив из 100 значений unsigned char ( u8 как в кейловской библиотеке переименовано), ведь не выделяется под них 400 байт?


Может быть имелось в виду integer promotion?

В С99, 6.3.1.1p2:

If an int can represent all values of the original type, the value is converted to an int;
otherwise, it is converted to an unsigned int.
MALLOY2
Цитата
А можно по подробнее, КАК он расширяет?


Когда загружается 8 битная переменная в 32 битный регистр, неиспользуемые биты принудительно обнуляются, или если это знаковый 8 бит, тогда заполняются значением знака, тоже самое и с 16 битами
demiurg_spb
Цитата(Herz @ Jun 21 2010, 21:02) *
Ясно, спасибо. Но вроде как и int8_t, и uint8_t гарантированно имеют размерность в 8 бит?
Да.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.