• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

BLE SoC PHY6202

pvvx

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

cool2000

Member
После загрузки новой прошивки по OTA по адресам выше, оно и будет запускаться, но базовая останется
Может, чтобы не плодить прошивки, при старте грузить промежуточный загрузчик? Он смотрит, если есть корректный образ OTA в верхних адресах, то его переписывает, в противном случае запускает App.
 

cool2000

Member
Режим упаковки полей структур можно указать ключом -fpack-struct[=n] при компиляции.
Если нужно только упаковку менять, то можно проще:
C:
#pragma pack(1)
// Данные без выравнивания
...
// Возврат к упаковке по умолчанию.
#pragma pack()
 

pvvx

Активный участник сообщества
Чем отличается #pragma pack(1) от __attribute__((packed)) ?
При __attribute__((packed)) он uint32_t будет загружать побайтно, не смотря на выровненность адреса.
Почему то для других CPU этого не происходит - определяет что адрес выровнен...
 

pvvx

Активный участник сообщества
./SDK/components/ble/controller/ll_def.h:1280:1: warning: alignment 1 of 'struct <anonymous>' is less than 4 [-Wpacked-not-aligned]
на -fpack-struct
 

pvvx

Активный участник сообщества
Не обязательно. Зависит от архитектуры. Кажется M0 позволяет загружать невыровненные 4-х байтные слова.
Да пофиг на архитектуру - создавайте сами структуры только с выровненными адресами переменных. Это упрощает работу с ними в других системах. Но вот лишние байты в конце, если структура {uint32 x; uint8 b} тут всё нарушают. И вместо 5 байт выходит 8-мь.
 

cool2000

Member
Добавил невыровненную структуру и gcc сгенерировал побайтный код:
Код:
#pragma pack()
struct {
uint8_t  sz;
uint32_t val;
} aaa;
#pragma pack()

        aaa.sz = 1;
11020d6e:    2101          movs    r1, #1
11020d70:    4a0d          ldr    r2, [pc, #52]    @ (11020da8 <read_sensor+0x9c>)
11020d72:    7011          strb    r1, [r2, #0]
        aaa.val = _r32;
11020d74:    7053          strb    r3, [r2, #1]
11020d76:    1851          adds    r1, r2, r1
11020d78:    0a1a          lsrs    r2, r3, #8
11020d7a:    704a          strb    r2, [r1, #1]
11020d7c:    2200          movs    r2, #0
11020d7e:    0e1b          lsrs    r3, r3, #24
11020d80:    708a          strb    r2, [r1, #2]
11020d82:    70cb          strb    r3, [r1, #3]
Но везде пишут, что по скорости невыровненный доступ сильно проигрывает побайтному чтению, и кроме того в определённых случаях может сгененрировать hard fault
 

pvvx

Активный участник сообщества
-fpack-struct - text на 12 килобайт больше 🤪
Короче это опять "оптимизаторы" в gcc поигрались...
 

pvvx

Активный участник сообщества
Так делать не нужно:
struct {
uint8_t sz;
uint32_t val;
} aaa;

нужно так:
struct {
uint32_t val;
uint8_t sz;
} aaa;

И чтобы sizeof(aaa) был = 5.
Остальной маразм в gcc как нибудь обойду.
Это сделано, чтобы в случае массива из этих структур выравнивание не нарушалось.
Где тут не выровнено?
 

cool2000

Member

pvvx

Активный участник сообщества
Это сделано, чтобы в случае массива из этих структур выравнивание не нарушалось.
Я не Ардуинщик и не собираюсь составлять из нечетных по размеру структур массивы.
Гнать их всех погаными тряпками.. :)
Правда это уже началось - прогнозируют что ИИ в ближайшие 5 лет вычистит из "программистов" 99% на улицу собирать бутылки... О смерти любимых толпе языков программирования уже объявили.
Ныне соотношение бабок за строку кода у програмера (на либах и прочих API или группового кода) и ИИ уже 500:1 :p
 

pvvx

Активный участник сообщества
И при чем тут массивы?
При составлении массива берутся выровненные адреса для каждого элемента. Это никак не влияет на размер элемента.
Аналогично со структурами в структурах. Всегда начинаются с выровненного адреса, но размер может быть нечетным. Никому это не мешает.
И операция a = b со структурой не должна копировать лишние байты. И сравнение memcmp(a,b, sizeof(a)) отработает правильно. Иначе - нет.
 

pvvx

Активный участник сообщества
В общем приехали с gcc из за структурных программистов (коих точно вытеснит ИИ, т.к. всё их дело - это раздувание размера кода для понимания человеком, что нафиг не нужно машине) - Придется вручную считать размер структур и писать #define size_этой_стркутуры 5 .
 

pvvx

Активный участник сообщества
Какая тут логика?

struct {
uint8_t a;
}
Размер равен 1.

struct {
uint16_t a;
uint8_t b;
}
Размер равен 4.

struct {
uint32_t a;
uint8_t b;
}
Размер равен 8.
 

pvvx

Активный участник сообщества
C:
void test(void) {
    struct {
        uint32_t a;
        uint8_t b;
    }x1;
    struct {
        uint32_t a;
        uint8_t b;
    }x2;
    x1.a = 1;
    x1.b = 2;
    x2.a = 1;
    x2.b = 2;
    if (!memcmp(&x1, &x2, sizeof(x1)))
        return;
    LOG("BAG/BAD GCC! %u,%u != %u,%u\n", x1.a, x1.b, x2.a, x2.b);
}
Log:
Код:
BAG/BAD GCC! 1,2 != 1,2
Как жить?
 

pvvx

Активный участник сообщества
aaa[1].val окажется невыровненным.
Массивы значит?
C:
void test(void) {
    struct {
        uint32_t a;
        uint8_t b;
    }x[2];
    x[0].a = 1;
    x[0].b = 2;
    x[1].a = 1;
    x[1].b = 2;
    if (!memcmp(&x[0], &x[1], sizeof(x[0])))
        return;
    LOG("BAG/BAD GCC! %u,%u != %u,%u\n", x[0].a, x[0].b, x[1].a, x[1].b);
}
BAG/BAD GCC! 1,2 != 1,2
 

cool2000

Member
Массивы значит?
Ага ;)
C:
void test(void) {
    struct {
        uint32_t a;
        uint8_t b;
    }x[2];
    memset(x, 0, sizeof(x));
    x[0].a = 1;
    x[0].b = 2;
    x[1].a = 1;
    x[1].b = 2;
    if (!memcmp(&x[0], &x[1], sizeof(x[0])))
        return;
    LOG("BAG/BAD GCC! %u,%u != %u,%u\n", x[0].a, x[0].b, x[1].a, x[1].b);
}
Добавил -munaligned-access к ключам компиляции, gcc начал выдавать warning: target CPU does not support unaligned accesses.
 
Сверху Снизу