программа улетает в hard fault на stm32f103rb при работе с указателями на uint64_t. Код на Си простой: берется указатель на uint64_t и загружается в переменную с таким же типом значение с произвольного адреса (ну получается нужно 2 регистра). Если смотреть по ассемблеру, то не идут команды LDMIA (или LDRD если компилить в другой версии GNU), но собственно сценарий примерно один, берется адрес, который по условиям ассемблерной команды должен быть кратен 4 (кто б подсказал зачем), а у меня он в принципе произвольный и выравнивание мне там не сделать, как быть?
Невыровненный доступ поддерживают только простые инструкции LDR/STR, а LDRD уже требует выравнивания. Когда-то мне помогало в подобном случае указатель объявлять как volatile, тогда gcc вместо LDRD генерил LDR, но никаких гарантий... Если не сработает, то пиши на инлайн ассме используя инструкции не требующие выравнивания или указатель приводи к 32-х битному.
Заголовок сообщения: Re: hard fault на stm32f103rb при работе с указателями на ui
Добавлено: Сб сен 25, 2021 15:59:20
Открыл глаза
Зарегистрирован: Вс мар 21, 2021 11:06:04 Сообщений: 41
Рейтинг сообщения:0
auric писал(а):
у меня он в принципе произвольный и выравнивание мне там не сделать, как быть?
Написать функцию типа uint64_t GetUint64(void* p) и использовать её. Внутри неё будете считывать 8 байт по указателю и формировать из них возвращаемое значение. Это распата за невыровненный доступ. Зато работать будет всегда и везде.
А не пробовали написать свой обработчик hard fault, может не страшно. Win-да в такие ситуации попадает по 20 раз в секунду и, ничего, никто не журчит....
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Порешал, обработка теперь интом, потом склейка, как и писали дольше, зато гарантировано. Просто странно, что мешало сделать инструкции без выравнивания и что мешало сделать в компиляторе проверки и не генерить падающий на асме код.
Порешал, обработка теперь интом, потом склейка, как и писали дольше, зато гарантировано. Просто странно, что мешало сделать инструкции без выравнивания и что мешало сделать в компиляторе проверки и не генерить падающий на асме код.
Напишите обработчик HardFault, который исправляет ситуацию на лету.
А можно минимальный пример для воспроизведения? Похоже на баг в компиляторе
Как-то неопределенно выразились. Это и есть БАГ компилятора. Только его исправлять никто не хочет. Сейчас модно писать на Java. Следуя этой моде как раз я и предлагаю поправить компилятор написав обработчик HardFault, исправляющий ситуацию "на лету". И вообще, нужно для всех без исключения HardFault иметь свои обработчики. Это не трудно, без них Вы делаете вывод о необходимости править исходники, а с ними этого можно не делать. Т.е. исходники не править. Компилятор считает, что это проблема процессора и не собирается под него подстраиваться. Это, своего рода традиция.
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
В таком виде gcc 10.2 генерит четыре STR, а если убрать volatile, то получим STR+STRD+STR. Заменив чтение IDR константой компилятор будет знать во время компиляции точный адрес и даже без volatile подставит STRD только если адрес выровненный.
Если заранее неизвестно, то компилятор генерирует максимально быстрый код, не допускающий невыровненные адреса Это достаточно разумный подход, но приводящий к хардфаулту у программистов, которые ещё не знают от такой особенности ))
что мешало сделать в компиляторе проверки и не генерить падающий на асме код.
А что мешало вам прочитать доку на компилятор и узнать, что всё уже давно имеется?: если объявить указатель на пакованный тип, то компилятор вместо LDRD/STRD генерит пару LDR/STR. IAR: typedef __packed unsigned long long u64p; и все обращения к u64p будут только инструкциями, умеющими невыровненный доступ.
Последнюю строку gcc-arm-none-eabi-10.3-2021.07 при -O3 компилирует в
А какое это имеет отношение к теме? Такое сгенерилось видимо для какого-то младшего ядра (M0, etc.). А у ТС - Cortex-M3. Для него вменяемый компилятор, в случае невыровненного доступа, должен генерить пару LDR/STR, а не ворох LDRB/STRB.
Может у вас там для компилятора какая-то опция выставлена, говорящая, что на CPU принудительно запрещён невыровненный доступ? Ведь и на >=Cortex-M3 можно запретить невыровненный доступ установкой бита UNALIGN_TRP в CCR.
Так "всё уже давно имеется" говорил или все-же "странно"?
Так обработчик HardFault писать будем?
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Так "всё уже давно имеется" говорил или все-же "странно"?
Может сначала научимся читать сообщения? Я это говорил про пакованные данные. Где пример для GCC с пакованными 64-битными данными? Не вижу - никто не попробовал видимо. Для IAR я привёл.
jcxz, если не веришь, можешь просто поиграться онлайн: https://gcc.godbolt.org/z/ex1e5dcah Там налету и компилируется и дизасемблер отображается. Опции компиляции тоже можно менять
jcxz, если не веришь, можешь просто поиграться онлайн: https://gcc.godbolt.org/z/ex1e5dcah Там налету и компилируется и дизасемблер отображается
Понял. Компилит он так, потому что пример ваш некорректный. Вы объявили байтовый массив, а не 64-битную переменную (о чём вообще-то эта тема). Видимо, так как GCC видит, что это именно массив байт, потому его оптимизатор и генерит такой код. Достаточно ему написать корректный пример:
Сейчас этот форум просматривают: Bing [Bot] и гости: 23
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения