AVR-GCC обращение к пинам в стиле CWAVR

Да все просто, в стандарте С у полей структуры можно указывать размер (в битах), при работе с микроконтроллерами, да и прочим железом — бывает чертовски удобно.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <avr/io.h>
#include <util/delay.h>
#define PACKED __attribute__((__packed__))
struct PACKED bit_struct {
    unsigned int bit_0: 1;
    unsigned int bit_1: 1;
    unsigned int bit_2: 1;
    unsigned int bit_3: 1;
    unsigned int bit_4: 1;
    unsigned int bit_5: 1;
    unsigned int bit_6: 1;
    unsigned int bit_7: 1;
};
 
int main() {
    struct bit_struct * portb = (void*)&PORTB;
    struct bit_struct * ddrb = (void*)&DDRB;
    ddrb->bit_5 = 1;
    while (1) {
        portb->bit_5 = !portb->bit_5;
        _delay_ms(25);
    }
    return 0;
}

По-поводу:

__attribute__((__packed__))

это расширение GCC, позволяет минимизировать размер структуры, иначе компилятор может выравнять поля. Для 8-битной структуры это ничем не грозит, кроме небольшого перерасхода памяти. А вот если структура сложная, и подразумевается, что поля (в памяти) следуют друг за другом — тут может получится сюрприз.
Подробней об атрибутах: https://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Type-Attributes.html