Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

hard fault на stm32f103rb при работе с указателями на uint64

Пт сен 24, 2021 22:29:25

программа улетает в hard fault на stm32f103rb при работе с указателями на uint64_t. Код на Си простой: берется указатель на uint64_t и загружается в переменную с таким же типом значение с произвольного адреса (ну получается нужно 2 регистра). Если смотреть по ассемблеру, то не идут команды LDMIA (или LDRD если компилить в другой версии GNU), но собственно сценарий примерно один, берется адрес, который по условиям ассемблерной команды должен быть кратен 4 (кто б подсказал зачем), а у меня он в принципе произвольный и выравнивание мне там не сделать, как быть?

Re: hard fault на stm32f103rb при работе с указателями на ui

Пт сен 24, 2021 22:56:36

Невыровненный доступ поддерживают только простые инструкции LDR/STR, а LDRD уже требует выравнивания. Когда-то мне помогало в подобном случае указатель объявлять как volatile, тогда gcc вместо LDRD генерил LDR, но никаких гарантий... Если не сработает, то пиши на инлайн ассме используя инструкции не требующие выравнивания или указатель приводи к 32-х битному.

Re: hard fault на stm32f103rb при работе с указателями на ui

Сб сен 25, 2021 15:59:20

auric писал(а):у меня он в принципе произвольный и выравнивание мне там не сделать, как быть?

Написать функцию типа uint64_t GetUint64(void* p) и использовать её. Внутри неё будете считывать 8 байт по указателю и формировать из них возвращаемое значение. Это распата за невыровненный доступ. Зато работать будет всегда и везде.

Re: hard fault на stm32f103rb при работе с указателями на ui

Сб сен 25, 2021 16:07:56

А не пробовали написать свой обработчик hard fault, может не страшно. Win-да в такие ситуации попадает по 20 раз в секунду и, ничего, никто не журчит....

Re: hard fault на stm32f103rb при работе с указателями на ui

Сб сен 25, 2021 19:43:17

Порешал, обработка теперь интом, потом склейка, как и писали дольше, зато гарантировано. Просто странно, что мешало сделать инструкции без выравнивания и что мешало сделать в компиляторе проверки и не генерить падающий на асме код.

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 12:54:29

А можно минимальный пример для воспроизведения? Похоже на баг в компиляторе

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 15:06:27

Порешал, обработка теперь интом, потом склейка, как и писали дольше, зато гарантировано. Просто странно, что мешало сделать инструкции без выравнивания и что мешало сделать в компиляторе проверки и не генерить падающий на асме код.


Напишите обработчик HardFault, который исправляет ситуацию на лету.

Добавлено after 11 minutes 11 seconds:
А можно минимальный пример для воспроизведения? Похоже на баг в компиляторе

Как-то неопределенно выразились. Это и есть БАГ компилятора. Только его исправлять никто не хочет. Сейчас модно писать на Java. Следуя этой моде как раз я и предлагаю поправить компилятор написав обработчик HardFault, исправляющий ситуацию "на лету". И вообще, нужно для всех без исключения HardFault иметь свои обработчики. Это не трудно, без них Вы делаете вывод о необходимости править исходники, а с ними этого можно не делать. Т.е. исходники не править. Компилятор считает, что это проблема процессора и не собирается под него подстраиваться. Это, своего рода традиция.

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 16:22:44

А можно минимальный пример для воспроизведения? Похоже на баг в компиляторе

Код:
uint32_t arr[10];
volatile uint32_t* p = (uint32_t*)((uint8_t*)arr + (GPIOA->IDR & 7));
*p++ = 0x55;
*p++ = 0x55;
*p++ = 0x55;
*p++ = 0x55;

В таком виде gcc 10.2 генерит четыре STR, а если убрать volatile, то получим STR+STRD+STR. Заменив чтение IDR константой компилятор будет знать во время компиляции точный адрес и даже без volatile подставит STRD только если адрес выровненный.

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 18:15:56

В этом примере программист сам себе злобный буратино, т.к. код изначально допускает обращение по невыровненному адресу.

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 18:17:33

А ТС изначально написал, что адреса у него произвольные и выравнивание не сделать.

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 18:56:47

Если компилятор заранее знает, что будет идти доступ по невыровненному адресу, то он будет это делать побайтно.
Код:
char aaa[10] = {};
volatile uint64_t *ptr = (uint64_t*)(aaa+1);
*ptr = 0x1234567887654321;


Последнюю строку gcc-arm-none-eabi-10.3-2021.07 при -O3 компилирует в
Код:
ldrb.w   r3, [sp, #13]         
movs   r3, #33   ; 0x21       
strb.w   r3, [sp, #13]         
ldrb.w   r3, [sp, #14]         
movs   r3, #67   ; 0x43       
strb.w   r3, [sp, #14]         
ldrb.w   r3, [sp, #15]         
movs   r3, #101   ; 0x65
strb.w   r3, [sp, #15]         
ldrb.w   r3, [sp, #16]         
mvn.w   r3, #120   ; 0x78
strb.w   r3, [sp, #16]         
ldrb.w   r3, [sp, #17]         
movs   r3, #120   ; 0x78
strb.w   r3, [sp, #17]         
ldrb.w   r3, [sp, #18]         
movs   r3, #86   ; 0x56       
strb.w   r3, [sp, #18]         
ldrb.w   r3, [sp, #19]         
movs   r3, #52   ; 0x34       
strb.w   r3, [sp, #19]         
ldrb.w   r3, [sp, #20]         
movs   r3, #18               
strb.w   r3, [sp, #20]         


А если компилятор не знает, но программист допускает такое обращение - то повторюсь, он ССЗБ

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 22:15:12

ArtDen писал(а):Если компилятор заранее знает, что будет идти доступ по невыровненному адресу

А если неизвестно? Т.е. адрес может быть произвольным: как выровненным, так и нет. Что ДОЛЖЕН сделать компилятор?
Например:
Код:
uint64_t getUint64(void* buf_p) {
    return *((uint64_t*)buf_p));
}

Будет ли выровнен указатель buf_p заранее неизвестно. Может да, а может нет. И тот и другой случаи возможны и равновероятны.

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 22:30:04

Если заранее неизвестно, то компилятор генерирует максимально быстрый код, не допускающий невыровненные адреса Это достаточно разумный подход, но приводящий к хардфаулту у программистов, которые ещё не знают от такой особенности ))

Re: hard fault на stm32f103rb при работе с указателями на ui

Вс сен 26, 2021 23:33:50

что мешало сделать в компиляторе проверки и не генерить падающий на асме код.

А что мешало вам прочитать доку на компилятор и узнать, что всё уже давно имеется?: если объявить указатель на пакованный тип, то компилятор вместо LDRD/STRD генерит пару LDR/STR.
IAR:
typedef __packed unsigned long long u64p;
и все обращения к u64p будут только инструкциями, умеющими невыровненный доступ.

Добавлено after 7 minutes 38 seconds:
Последнюю строку gcc-arm-none-eabi-10.3-2021.07 при -O3 компилирует в

А какое это имеет отношение к теме? Такое сгенерилось видимо для какого-то младшего ядра (M0, etc.). А у ТС - Cortex-M3. Для него вменяемый компилятор, в случае невыровненного доступа, должен генерить пару LDR/STR, а не ворох LDRB/STRB.

Re: hard fault на stm32f103rb при работе с указателями на ui

Пн сен 27, 2021 08:58:04

А какое это имеет отношение к теме? Такое сгенерилось видимо для какого-то младшего ядра (M0, etc.)


Забыл указать. Компилировалось это с флагом -mcpu=cortex-m4 для STM32F401

Сейчас проверил. Для cortex-m3 генерируется точно такой-же код.

Re: hard fault на stm32f103rb при работе с указателями на ui

Пн сен 27, 2021 11:29:03

Забыл указать. Компилировалось это с флагом -mcpu=cortex-m4 для STM32F401

Сейчас проверил. Для cortex-m3 генерируется точно такой-же код.

Странно это... Так как не нужно там по-байтно.
IAR, например, код:
Код:
__packed unsigned long long volatile z = 0;
z++;
printf("%llu", z);
компилит в:
Код:
LDR.N    R5,??DataTable12_1
LDR      R0,[R5, #+72]
LDR      R1,[R5, #+76]
ADDS     R0,R0,#+1
SBC      R1,R1,#-1
STR      R0,[R5, #+72]
STR      R1,[R5, #+76]
LDR      R2,[R5, #+72]
LDR      R3,[R5, #+76]
ADR.W    R0,?_2
BL       _printf
т.е. - по паре LDR/STR на обращение.
Полная оптимизация вкл.
Убираем __packed и получаем:
Код:
LDR.N    R5,??DataTable12_1
LDRD     R0,R1,[R5, #+24]
ADDS     R0,R0,#+1
SBC      R1,R1,#-1
STRD     R0,R1,[R5, #+24]
LDRD     R2,R3,[R5, #+24]
ADR.W    R0,?_2
BL       _printf
что и ожидалось....

Может у вас там для компилятора какая-то опция выставлена, говорящая, что на CPU принудительно запрещён невыровненный доступ? Ведь и на >=Cortex-M3 можно запретить невыровненный доступ установкой бита UNALIGN_TRP в CCR.

Re: hard fault на stm32f103rb при работе с указателями на ui

Пн сен 27, 2021 11:39:57

Так "всё уже давно имеется" говорил или все-же "странно"?

Так обработчик HardFault писать будем?

Re: hard fault на stm32f103rb при работе с указателями на ui

Пн сен 27, 2021 11:44:19

Так "всё уже давно имеется" говорил или все-же "странно"?
Может сначала научимся читать сообщения?
Я это говорил про пакованные данные.
Где пример для GCC с пакованными 64-битными данными? Не вижу - никто не попробовал видимо. Для IAR я привёл.

Re: hard fault на stm32f103rb при работе с указателями на ui

Пн сен 27, 2021 11:52:52

jcxz, если не веришь, можешь просто поиграться онлайн:
https://gcc.godbolt.org/z/ex1e5dcah
Там налету и компилируется и дизасемблер отображается. Опции компиляции тоже можно менять

Re: hard fault на stm32f103rb при работе с указателями на ui

Пн сен 27, 2021 12:07:45

jcxz, если не веришь, можешь просто поиграться онлайн:
https://gcc.godbolt.org/z/ex1e5dcah
Там налету и компилируется и дизасемблер отображается

Понял. Компилит он так, потому что пример ваш некорректный. Вы объявили байтовый массив, а не 64-битную переменную (о чём вообще-то эта тема).
Видимо, так как GCC видит, что это именно массив байт, потому его оптимизатор и генерит такой код.
Достаточно ему написать корректный пример:
Код:
    extern volatile uint64_t aaa;
    volatile uint64_t *ptr = (uint64_t*)(&aaa+1);
    *ptr = 0x1234567887654321;

Как будут вполне ожидаемые LDRD/STRD.

Т.е. - volatile в случае GCC никак не спасает от исключения невыровненного доступа. Не поможет оно.
Последний раз редактировалось jcxz Пн сен 27, 2021 12:24:34, всего редактировалось 2 раз(а).
Ответить