-
- Использую структуры, где чередуются char и long и выравнивание "pragma pack(1)". Полет нормальный. Компилятор IAR. Ale3000(296 знак., 05.02.2015 07:28 - 07:33)
- За обращение к невыровненным данным методом отличным от memcpy нужно сжигать. fk0(189 знак., 04.02.2015 12:20)
- memcpy использует ldrd иногда, что так же приводит к hardfault - Mikla(04.02.2015 12:35)
- А расскажите пожалуйста поподробнее для малознакомого с CortexM3, как оно пришло к hardfault. Сам принцип и путь к ошибке. Очень интересно, но непонятно что там творится) - Олдфаг(04.02.2015 21:18, )
- в memcpy использовались указатели на long, компилятор считает что они всегда выравнены на границу 4 байт и заюзал команды LDRD STRD которые не умеют обращаться по невыровненному адресу. указатель был невыровненный, что и привело к hardfault. Mikla(212 знак., 05.02.2015 11:09)
- Спасибо за разъяснения. - Олдфаг(05.02.2015 15:46, )
- о! Это очень увлекательная история, у меня после АВРок и ПИКов было чувство глубокого когнитивного диссонанса :) - Nikolay801_(05.02.2015 10:02)
- в memcpy использовались указатели на long, компилятор считает что они всегда выравнены на границу 4 байт и заюзал команды LDRD STRD которые не умеют обращаться по невыровненному адресу. указатель был невыровненный, что и привело к hardfault. Mikla(212 знак., 05.02.2015 11:09)
- ААА! Теперь не использовать memcpy??? Или может просто не подсовывать неправильные аргументы в memcpy. Вообще её компилятор инлайнит и код может нагенерить какой больше подходит в данной ситуации. - fk0(04.02.2015 12:39)
- пример неправильных аргументов приведите, может быть указатели должны быть выравнены только на границу 8байт или на 4 в худшем случае по вашему? а если не так, то это неправильные аргументы? - Mikla(04.02.2015 15:41)
- Просто не надо извращаться с приведением типов указателя. Тады компайлер и memcpy сделают все правильно. - LightElf(04.02.2015 18:51)
- не знаю какие там были указатели, не у меня было когда memcpy вывалился в hardfault. знаю что длина строки была 8 и компилер подставил ldrd. при изменении длины строки на любое другое число все было нормально. а если бы другой тип указателя был, Mikla(247 знак., 04.02.2015 19:26)
- Надо смотреть что в конкретном случае сгенерил кейл. Я с кейлом не знаком. В общем случае компилятор выберет интринсик, основываясь в том числе и на типах указателей. И ежели указатели имеют тип int *, то компилер разумно предположит что они LightElf(55 знак., 04.02.2015 19:52)
- да, счас экспериментировал, вы правы. реализация memcpy зависит от типа указателей. Mikla(463 знак., 04.02.2015 20:44)
- А вот не надо в указателях на long хранить неровные адреса. Стандарт языка так и говорит: undefined behavior. - SciFi(05.02.2015 00:56)
- А вот не надо в функции ожидать, что указатель void* куда-то выровнен. - LightElf(08.02.2015 17:13)
- Это он зря, конечно, но закон на его стороне. - SciFi(08.02.2015 17:15, ссылка)
- А вот не надо в функции ожидать, что указатель void* куда-то выровнен. - LightElf(08.02.2015 17:13)
- Компиляторная магия, фуле! Из-за подобных непоняток выкинул стандартные либы и использую свой велосипед,
с квадратными колесамиLightElf(153 знак., 04.02.2015 22:27)- а я наоборот, использую мемкопи только библиотечную. это с тех пор, как меня кроссворк на тесте скорости этой самой мемкопи уделал в раза три по скорости. в общем я перестал считать себя умнее компилятора. Mahagam(138 знак., 04.02.2015 23:03)
- В описываемом случае двусмысленность. memcpy объявлена, как принимающая указатели void*. Логично предположить, что параметры должны рассматриваться как нетипизированные и выравнивание должно проверяться/фикситься в рантайме. Но компиляторная LightElf(24 знак., 05.02.2015 14:37)
- Логично предположить, что если неровный адрес приведён к типу (long*), то возможны неприятности. Что и произошло. Стандарт не нарушен: SciFi(217 знак., 05.02.2015 15:11)
- не компиляторная! библиотечная. насколько я понял из либы, там сначала копировались байты чтобы выровнять адреса приёмника и источника (если это было возможно), а потом запускался цикл с LDM/STM на все регистры. ну и под конец копировался Mahagam(186 знак., 05.02.2015 14:52)
- В описываемом случае двусмысленность. memcpy объявлена, как принимающая указатели void*. Логично предположить, что параметры должны рассматриваться как нетипизированные и выравнивание должно проверяться/фикситься в рантайме. Но компиляторная LightElf(24 знак., 05.02.2015 14:37)
- а я наоборот, использую мемкопи только библиотечную. это с тех пор, как меня кроссворк на тесте скорости этой самой мемкопи уделал в раза три по скорости. в общем я перестал считать себя умнее компилятора. Mahagam(138 знак., 04.02.2015 23:03)
- А вот не надо в указателях на long хранить неровные адреса. Стандарт языка так и говорит: undefined behavior. - SciFi(05.02.2015 00:56)
- Кофейная гуща не есть кошерная пища :-) - SciFi(04.02.2015 19:54, ссылка)
- да, счас экспериментировал, вы правы. реализация memcpy зависит от типа указателей. Mikla(463 знак., 04.02.2015 20:44)
- Код - в студию. Гадание на кофейной гуще кого-то увлекает, но нуевонафик. - SciFi(04.02.2015 19:35)
- Надо смотреть что в конкретном случае сгенерил кейл. Я с кейлом не знаком. В общем случае компилятор выберет интринсик, основываясь в том числе и на типах указателей. И ежели указатели имеют тип int *, то компилер разумно предположит что они LightElf(55 знак., 04.02.2015 19:52)
- Там нужно разбираться. Не тот МК, не та библиотека, кривой тулчейн, кривые руки. Тысяча возможных причин. - SciFi(04.02.2015 19:23)
- не знаю какие там были указатели, не у меня было когда memcpy вывалился в hardfault. знаю что длина строки была 8 и компилер подставил ldrd. при изменении длины строки на любое другое число все было нормально. а если бы другой тип указателя был, Mikla(247 знак., 04.02.2015 19:26)
- Просто не надо извращаться с приведением типов указателя. Тады компайлер и memcpy сделают все правильно. - LightElf(04.02.2015 18:51)
- пример неправильных аргументов приведите, может быть указатели должны быть выравнены только на границу 8байт или на 4 в худшем случае по вашему? а если не так, то это неправильные аргументы? - Mikla(04.02.2015 15:41)
- А расскажите пожалуйста поподробнее для малознакомого с CortexM3, как оно пришло к hardfault. Сам принцип и путь к ошибке. Очень интересно, но непонятно что там творится) - Олдфаг(04.02.2015 21:18, )
- Процессоростроители из арма дурачки, зачем-то сделали невыровненный доступ :-))) - SciFi(04.02.2015 12:30)
- memcpy использует ldrd иногда, что так же приводит к hardfault - Mikla(04.02.2015 12:35)
- у кортексов еще есть фича позволяющая реализовать атомарный доступ без запрета на прерывания. - Nikolay801_(04.02.2015 11:54, ссылка)
- Если обращение одной инструкцией, то всё атомарно. Кроме инструкций LDM, STM, конечно. - SciFi(04.02.2015 11:15)
- То есть зависит от левой ноги компилятора? Вот и думай: если ему взбредет в голову что оптимально взять сразу 2 регистра то он может применить LDM? И volatile не поможет? Тогда что, все-таки запрещать прерывания? - Petrovich(04.02.2015 11:30, )
- volatile тут вообще ни с какого бока. Кстати, видел у компиляторов ключики, запрещающие LDM, STM. Ну и по большому счёту компилятор никому не обещает, что не разобьёт доступ к объекту на несколько инструкций. Гарантировать может только ассемблер. - SciFi(04.02.2015 11:35)
- Компилятор так же не обещает, что он не закеширует объект в регистрах, что он не будет считывать из памяти два раза подряд и ещё всякое странное. Для компилятора лишь главное -- чтоб результат вычислений на выходе сходился с ожиданиями fk0(378 знак., 04.02.2015 12:27)
- Думал, что volatile даст указание работать с переменной индивидуально, не привязывая ее загрузку к загрузке другой переменной, даже если они лежали в памяти рядом и должны быть сравнены/сложены/умножены. Спасибо, понял. Буду пока понуждать к Petrovich(13 знак., 04.02.2015 11:52, )
- вообще volatile указывает чтобы компилятор каждый раз когда в исходнике встретится обращение к этой переменной (константе) каждый раз лазил бы в память по её адресу, а не работал через регистры. - Mahagam(04.02.2015 11:55)
- :) Тогда бы у МК, не умеющих делать операции память-память не было бы шансов. Для работы компилятор все равно достает volatile из памяти и кладет в регистры. Обработает и как паинька положит назад. Вот и вопрос - может ли умница компилятор Petrovich(189 знак., 04.02.2015 12:11, )
- почему это не было бы шансов? - Mahagam(04.02.2015 12:32)
- Ну как бы они сделали volatileVal++, если они не умеют ADD Memo,Memo; а брать в регистры Вы им запретили? - Petrovich(04.02.2015 12:47, )
- Ну ё-маё. Он имел в виду кэширование значения переменной в регистре - именно это запрещено. Знаете, что такое кэширование? - SciFi(04.02.2015 12:50)
- Не было там слов про кэширование. Был запрет "работать через регистры". Вот я и спросил - а как быть с МК, которые обрабатывают данные ТОЛЬКО через регистры. - Petrovich(04.02.2015 12:52, )
- а в таких МК количество переменных в коде не может превышать количество регистров у МК, да? )))) - Mahagam(04.02.2015 13:10)
- Не было там слов про кэширование. Был запрет "работать через регистры". Вот я и спросил - а как быть с МК, которые обрабатывают данные ТОЛЬКО через регистры. - Petrovich(04.02.2015 12:52, )
- Ну ё-маё. Он имел в виду кэширование значения переменной в регистре - именно это запрещено. Знаете, что такое кэширование? - SciFi(04.02.2015 12:50)
- Ну как бы они сделали volatileVal++, если они не умеют ADD Memo,Memo; а брать в регистры Вы им запретили? - Petrovich(04.02.2015 12:47, )
- почему это не было бы шансов? - Mahagam(04.02.2015 12:32)
- :) Тогда бы у МК, не умеющих делать операции память-память не было бы шансов. Для работы компилятор все равно достает volatile из памяти и кладет в регистры. Обработает и как паинька положит назад. Вот и вопрос - может ли умница компилятор Petrovich(189 знак., 04.02.2015 12:11, )
- вообще volatile указывает чтобы компилятор каждый раз когда в исходнике встретится обращение к этой переменной (константе) каждый раз лазил бы в память по её адресу, а не работал через регистры. - Mahagam(04.02.2015 11:55)
- volatile тут вообще ни с какого бока. Кстати, видел у компиляторов ключики, запрещающие LDM, STM. Ну и по большому счёту компилятор никому не обещает, что не разобьёт доступ к объекту на несколько инструкций. Гарантировать может только ассемблер. - SciFi(04.02.2015 11:35)
- То есть зависит от левой ноги компилятора? Вот и думай: если ему взбредет в голову что оптимально взять сразу 2 регистра то он может применить LDM? И volatile не поможет? Тогда что, все-таки запрещать прерывания? - Petrovich(04.02.2015 11:30, )