|
|||||||
Установка битовых флагов через удобный макрос
Время создания: 30.12.2021 12:14
Текстовые метки: stm32, программирование, макрос, битовый флаг,
Раздел: Компьютер - Аппаратное обеспечение - Микроконтроллеры ARM
Запись: xintrea/mytetra_syncro/master/base/1640855691zk8uvdd691/text.html на raw.github.com
|
|||||||
|
|||||||
В одном проекте, понадобилось много битовых флагов Выделять на каждый флаг по байту — это роскошь. Имея в STM32 bit-band, написал макрос, может кому то пригодится. // Сама переменная, где будут наши флаги,можно заранее проинициализировать unsigned int BitBandArray=0; // SRAM_BASE начало памяти // SRAM_BB_BASE - где начинается битбанд алиас памяти // Объявлено тут stm32f10x.h // Сам макрос первый параметр - номер бита, второй имя перемененной, где биты хранятся #define BitBand(b,a) (*((char *)SRAM_BB_BASE+(((int)&a)SRAM_BASE )*32+b*4)) // Сами флаги #define AxelFlag BitBand(0,BitBandArray) #define PowerGood BitBand(1,BitBandArray) #define BatFlag BitBand(2,BitBandArray) // И так 32 раза //////////////// // Теперь можем к ним обращаться как к обычным переменным //////////////// // Присвоение AxelFlag =1; // Чтение if(PowerGood ==1) { } Примечание 1 В приведенном макросе есть ошибка, должно быть: #define BitBand(b, a) (*((char *)SRAM_BB_BASE + (((unsigned)&a) - SRAM_BASE )*32+b*4)) Попробовал скомпилить, посмотрел, что вышло. Оказалось битовые поля даже быстрее, на такт. Компилятор почему-то не смог вычилить адрес во время компиляции, может LTO поможет, мне лень пробовать. Но он все равно не атомарны, в отличии от bit-band. struct Foo { unsigned flag1:1; unsigned flag2:1; unsigned flag3:1; unsigned flag4:1; }foo; unsigned int BitBandArray=0; #define BitBand(b, a) (*((char *)SRAM_BB_BASE + (((unsigned)&a)-SRAM_BASE )*32+b*4)) #define AxelFlag BitBand(0,BitBandArray) #define PowerGood BitBand(1,BitBandArray) #define BatFlag BitBand(2,BitBandArray) void Bar() { AxelFlag = 1; 803e594: 4b05 ldr r3, [pc, #20] ; (803e5ac <Bar+0x18>) 803e596: 015b lsls r3, r3, #5 803e598: f103 5308 add.w r3, r3, #570425344 ; 0x22000000 803e59c: 2201 movs r2, #1 803e59e: 701a strb r2, [r3, #0] foo.flag2 = 1; 803e5a0: 4b03 ldr r3, [pc, #12] ; (803e5b0 <Bar+0x1c>) 803e5a2: 781a ldrb r2, [r3, #0] 803e5a4: f042 0202 orr.w r2, r2, #2 803e5a8: 701a strb r2, [r3, #0] 803e5aa: 4770 bx lr 803e5ac: 20000000 .word 0x20000000 803e5b0: 200008c8 .word 0x200008c8 } В случае bit-band идет вычисление адреса и запись, с битовым полем — чтение, модификация, запись. То есть, если нет потребности в атомарности, то битовые поля — норм? Ну, то есть других особых каких-то у них проблем нет? (я просто сам недавно о них узнал и начал применять, да и в Сях я очень новичок… А как увидел, подумал — «какая удобная штука!» Так что благодарю за информацию!) Примечание 2 #define BIT_SET(var,mask) { var |= (mask); } #define BIT_CLEAR(var,mask) { var &= ~(mask); } #define BIT_TOGGLE(var,mask) { var ^= (mask); } #define IS_BIT_SET(var,mask) ( (var) & (mask) ) #define IS_BIT_CLEARED(var,mask) (!( (var) & (mask) )) очень интересно, но стоит переписать так: #define BIT_SET(var,mask) do{ var |= (mask); }while(0) #define BIT_CLEAR(var,mask) do{ var &= ~(mask); }while(0) #define BIT_TOGGLE(var,mask) do{ var ^= (mask); }while(0) в этом случае не будет проблем в следующем построении: if(cond) BIT_SET(var,mask); else BIT_CLEAR(var,mask); |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|