maxntf 0 12 сентября, 2018 Опубликовано 12 сентября, 2018 · Жалоба Всем привет, наткнулся на такой баг - объявил буфер в глобальных переменных. Передаю его адрес в аргументе функции. И когда обращаюсь в функции к этой переменной через указатель сразу вылетаю в HardFault_Handler. Пол дня парился, и в конце концов выяснил, что линковщик расположил ее по адресу не кратному 4. Проверил, действительно если передать в функцию указатель не кратный 4, то при чтении по этому адресу вылетаем в HardFault_Handler. И теперь не могу добиться, чтоб этот буфер разместился по корректному адресу. Добавляю перед ним или после него новые переменные, адреса смещаются, и у него все равно адрес не корректный. Что делать? P.S Keil V5.23.0.0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 12 сентября, 2018 Опубликовано 12 сентября, 2018 · Жалоба линковщик расположил ее по адресу не кратному 4 Сейчас принято делать так: http://www.keil.com/support/man/docs/armcc...59124981436.htm но раньше делали так: http://www.keil.com/support/man/docs/armcc...59124966304.htm И укажите версию компилятора. Keil умеет работать с разными компиляторами, в комплекте к нему нынче идут ДВА встроенных РАЗНЫХ, и даже можно подключить внешний (GNU например) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 136 12 сентября, 2018 Опубликовано 12 сентября, 2018 · Жалоба Что делать? 1) Уменьшить картинку, чтобы страница форума не расползалась. 2) Показать объявление этого буфера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 13 сентября, 2018 Опубликовано 13 сентября, 2018 · Жалоба Скопировать значение в выравненную переменную с помощью memcpy. Вызвать функцию с этой локальной переменной. (опционально)Скопировать значение назад. Это и есть пуленепробиваемое решение которое работает везде, независимо от типов и версий компиляторов и языка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 13 сентября, 2018 Опубликовано 13 сентября, 2018 · Жалоба Скопировать значение в выравненную переменную с помощью memcpy. Вызвать функцию с этой локальной переменной. (опционально)Скопировать значение назад. Это и есть пуленепробиваемое решение которое работает везде, независимо от типов и версий компиляторов и языка. Ваш совет - один из лидеров среди самых вредных и опасных советов :cranky: Кстати, memcpy - очень коварный костыль! Любой компилятор умеет "говорить" о том, какой он и даже "назвать" свою версию. Ничто не мешает использовать эту информацию в своем коде для учета особенностей разных компиляторов, если есть нужда в поддержки разных компиляторов. Пример реально пуленепробиваемого решения: // Arm Compiler v5 #if defined ( __CC_ARM ) #pragma import(__use_no_heap) #pragma import(__ARM_use_no_argv) #pragma import(__use_two_region_memory) // Arm Compiler v6 #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) __asm(".global __use_no_heap \n\t"); __asm(".global __ARM_use_no_argv \n\t"); __asm(".global __use_two_region_memory \n\t"); #endif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxntf 0 13 сентября, 2018 Опубликовано 13 сентября, 2018 (изменено) · Жалоба Сейчас принято делать так: http://www.keil.com/support/man/docs/armcc...59124981436.htm Спасибо, понял в чем тут дело. Просто раньше работал только с 8 битными МК, там таких проблем нет. А у меня получилось, что буфер char - выравнивание у него по одному байту (без атрибута, начинаться может с любого адреса), а в качестве аргумента функции я передаю указатель на этот буфер с приведением типа до uint32. Изменено 13 сентября, 2018 пользователем maxntf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 13 сентября, 2018 Опубликовано 13 сентября, 2018 · Жалоба union спасает выравнивание при любых компиляторах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 13 сентября, 2018 Опубликовано 13 сентября, 2018 · Жалоба 2) Показать объявление этого буфера. +1. Сначала надо не костылями подпирать, а разобраться, в чём первопричина проблемы. А у меня получилось, что буфер char - выравнивание у него по одному байту (без атрибута, начинаться может с любого адреса), а в качестве аргумента функции я передаю указатель на этот буфер с приведением типа до uint32. Это ужасно. Костыль в виде aligned вылечит, но ужас никуда не денется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 13 сентября, 2018 Опубликовано 13 сентября, 2018 · Жалоба Костыль в виде aligned вылечит, но ужас никуда не денется. Ну-ну, попробуйте объявить массив для стека какой-нить задачи RTOS, НЕ применив к нему обязательный "костыль" aligned. ... "Ужас" убирается объявлением вместо банальных байтовых массивов с разношерстными данными ("протокольные" дела) объявлением полноценных структур с полями нужных размеров и названий, даже с применением union, где это нужно. Чтобы структура была одинакового размера на любых компиляторах, нужен атрибут packed. Это - норма. После чего в соотв. функцию передается ссылка (&) на структуру (или указатель, если нельзя писать на плюсах). В этом случае правильный доступ к полям структуры станет головной болью компилятора, а не кодера. Вот пример обяявления такой структуры (не самый лучший пример, но тем не менее): struct __PACKED Frame { uint8_t start; uint8_t command; uint8_t dataSize; union { uint8_t payload[COMMUNICATION_MAX_FRAME_DATA_SIZE_IN_BYTES]; MasterToSlave masterToSlave; SlaveToMaster slaveToMaster; } data; struct { union { struct { uint8_t low; uint8_t high; }; uint16_t value; }; } crc16; }; // SlaveToMaster и SlaveToMaster - структуры одинакового размера, но с разными полями ps. из-за необходимости применения телепатии к стартовому посту эта тема рискует перейти в очередной холивар :D Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 13 сентября, 2018 Опубликовано 13 сентября, 2018 · Жалоба Ваш совет - один из лидеров среди самых вредных и опасных советов :cranky: Кстати, memcpy - очень коварный костыль! Пруфов, я так понимаю, дождаться нереально? Пример реально пуленепробиваемого решения: Гы! :biggrin: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 13 сентября, 2018 Опубликовано 13 сентября, 2018 · Жалоба Пруфов, я так понимаю, дождаться нереально? Вы правы - это бесполезный пруф из разряда: почему нужно мыть руки перед едой или чистить зубы. Это знают даже дети :biggrin: Во многих уважающих себя конторах это "наследие" вообще давно запрещено к применению. Хотя в примитивном коде, который ни за что не отвечает или служит чисто образовательным целям (ардуины), memcpy в целом беды не несет, разве что кроме впустую потраченных нервов и времени :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 14 сентября, 2018 Опубликовано 14 сентября, 2018 · Жалоба Ну-ну, попробуйте объявить массив для стека какой-нить задачи RTOS, НЕ применив к нему обязательный "костыль" aligned. ... Скажем, lwip делает это легко и непринуждённо. Нужно выравнивать по 4 байта? Прибавь к размеру массива 3 байта, а указатель отрихтуй до ровного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 14 сентября, 2018 Опубликовано 14 сентября, 2018 · Жалоба Скажем, lwip делает это легко и непринуждённо. Не пойму, при чем тут lwip? Ядро ARM требуют выравнивание стеков по границе 8 байт, иначе вылетаем в HF. Не вижу никакой сложности использовать встроенное расширение компилятора, которое полностью устраняет эту "проблему". Тем более компилятор v6 от ARM практически полностью поддерживает расширения GCC (в отличие от v5, который в целом устарел и поэтому лишь частично умеет это делать). Нужно выравнивать по 4 байта? Прибавь к размеру массива 3 байта, а указатель отрихтуй до ровного. Соревнуетесь с Kabdim по вредности "советов"? ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 14 сентября, 2018 Опубликовано 14 сентября, 2018 · Жалоба Вы правы - это бесполезный пруф из разряда: почему нужно мыть руки перед едой или чистить зубы. Это знают даже дети :biggrin: Потому что пруфы для мытья рук есть и если не заниматься демагогией их несложно найти. Во многих уважающих себя конторах это "наследие" вообще давно запрещено к применению. И видимо что бы запретить совсем уж всю идею копирования памяти в другое место они придумали memcpy_s... :biggrin: Хотя в примитивном коде, который ни за что не отвечает или служит чисто образовательным целям (ардуины), memcpy в целом беды не несет, разве что кроме впустую потраченных нервов и времени :smile3046: Ну и к чему эти намеки, если вдруг вы не догадывались, то с Ардуиной я никогда не работал и к образованию кого-либо отношения не имею. Вы мешаете в один чан два разных применения. С буферами переменной длинны где для использования memcpy нужно много проверок и всё зло от того что индусы о ни забывают, а их отсутствие не обеспечивает падение сразу. А с другой стороны копирование переменной фиксированной длинны, где единственная задача убедится что на входе есть данные нужного размера. Если вы тратите на второй вариант использования memcpy нервы и время, могу только посочувствовать. Соревнуетесь с Kabdim по вредности "советов"? ;) Не переживайте, в этом вопросе вы непревзойденный идеал. :biggrin: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 14 сентября, 2018 Опубликовано 14 сентября, 2018 · Жалоба Потому что пруфы для мытья рук есть и если не заниматься демагогией их несложно найти. Пруф. Нельзя вызывать memcpy абы как. Ну и обратный пруф - memcpy спасает мир :biggrin: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться