-
Постов
322 -
Зарегистрирован
-
Посещение
Сообщения, опубликованные k000858
-
-
#pragma pack(push, 1) struct _input { uint32_t Value; }; #pragma pack(pop) struct _input * I = (struct _input *) ptr; printf("val = %lu\n", I->Value);
да, спасибо, такой способ вполне подойдет.
-
Опубликовано · Изменено пользователем k000858 · Пожаловаться
Нужно гарантировать, что uint32_t* указывает на переменную, расположенную по адресу, кратному 4.а, вот оно что. теперь более менее понимаю.
буфер в котором содержится нужное мне 32-битное значение uint8_t buf[100];
указатель на место, в котором содержится значением uint8_t* ptr = &buf[5];
на Cortex-M4 не заморачивался и делал вот так printf("val = %lu\n", *(uint32_t*)ptr);
на Cortex-M0+ такая запись приводит к HardFault'у. Причину теперь понимаю хорошо, и как не получать такой эффект тоже.
Пока сделал вот так:
uint8_t value[4]; value[0] = *ptr; value[1] = *(ptr + 1); value[2] = *(ptr + 2); value[3] = *(ptr+ 3); uint32_t val = (value[0]) | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); printf("val = %lu\n", val);
но чувствую, можно сделать это поизящнее. Подскажите красивый способ получения доступа к 32-битному значению
-
Потому что не поддерживает невыровненный доступ.
можно поподробнее?
пока все проблемы выравнивая обходил стороной, проектов на M0+ минимум
-
Опубликовано · Изменено пользователем k000858 · Пожаловаться
Есть какие то ограничения в ядре, приводящие к HardFault?
Пришлось в одной функции привести указатель типа uint8_t* к типу uint32_t* изза чего получил HardFault.
В STM32F4 камне тот же самый код работает нормально.
Почему же M0+ вылетает в HardFault?
-
все оказалось проще: в одной задаче действительно использовались данные, которые подготавливаются другой задачей, при этом в некоторых случаях происходила коллизия, при которой использовались недоподготовленные данные. Причем возможность такой ситуации я учитывал и, еще не приступив к глубокой отладке, несколько раз проверил наличие такой возможности. Говоря простым языком, пялился в конкретные строчки кода много раз, подозревая что дело в них, не знаю, почему не обнаружил, видимо "глаз замылил".
-
Очень очень давно разрабатывал модем. Появлялись сбои непонятные. Очень редкие... Примерно 1 сбой на 2 Мб передаваемых данных. Отладчика тогда не было как класса. По вероятности вычислил что ошибка возникает если приходит прерывание в каком-то месте головы. Осей тогда тоже не было. Сделал синхронный вывод инфы. Ну и обнаружил переменную. Дальнейшее было делом техники.
На вашем месте я попробовал бы
1. добиться повторяемости ошибки
2. Выводил бы отладочную инфу по прерываниям и задачам (для локализации)
3. дальше - глубже залазил.
В принципе именно такую методику и применяю
Выяснил что именно и при каких условиях портится: вот есть буфер со скопированной часть ПО, вот он же но уже битый. За время порчи молотил езернет (именно им провоцирую баг). Не удается пока выяснить почему происходит эта порча в буфере (а может происходит порча указателей на буферы ака указатели типа хедер?).
Пока кручусь вокруг одного места, добавляю отладочной инфы, меняю условия, проверяю адреса...но пока безрезультатно.
-
не соглашусь
темы подобного рода создаю в части случаев не для того, что бы получить готовый ответ "нажми А + Б и все заработает", а для того, что бы почитать размышления и опыт других программеров по теме.
можно кое что подчерпнуть.
проблема не простая, баг найти нелегко, пытаюсь зайти с разных сторон. проект вполне рабочий, содержит в себе ни мало функционала, все работает исправно, не считая описанного в посте-1 эффекта
дам немного конкретики: устройство помимо ethernet интерфейса имеет на борту радио-интерфейс, который обслуживает 6lowPAN протокол (само устройство - координатор, общается с конечными устройствами через ре-трансляторы). По радио-интерфейсу конечные устройства скидывают данные, а так же обновляются прошивки. Прошивка конечных устройств закачивается в координатор через вэб-интерфейс. Один из этапов обновления ПО конечных устройств - передача частей ПО по радио-интерфейсу, для этого каждая часть по очереди копируется с FLASH и упаковывается в DataPacket. эффект наступает именно на этом этапе. Спровоцировать эффект можно повысив нагрузку на ethernet-интерфейс. под штормом трафика подразумивал банальный UDP спам
-
где-то используется глобальная переменная, доступная на запись из нескольких задач. Туда ройте.
такое есть. чем это чревато?
-
В настройках поставлена галочка Use float with nano printf для включения опции -u _printf_float.
Эта опция не помогает.
Не знаю как настроить такое выравнивание.
в настройках адреса начала стека
-
спасибо за советы. определенный смысл в них конечно есть, но задача стоит несколько другая. необходимо в существующем проекте найти источник утечки памяти или другую причину такого поведения. явно проблемы на стеке.
-
Всем привет.
Кто изучал драйвер Ethernet'а, идущий с HAL библиотеками (вариант для FreeRTOS: ETHERNET прерывание релизит семафору, которая парсится в отдельной realtime задаче ОС)? Что будет при переполнении указанного количества приёмных буферов? Ошибка DMA обработается, но не будет ли DMA записывать данные дальше (портить память) или это исключено т.к. указывается в размер буферов в настройках DMA?
Имею следующую ситуацию: устройство с Ethernet в параллельной задаче (с меньшим приоритетом чем Ethernet) копирует данные (memcpy функцией) с внутренней FLASH контроллера. При шторме устройства Ethernet трафиком, в какой то раз данные копируются неправильно (временно нарушается адресация флэш - откуда копировать, но до конца процесса восстанавливается), в результате часть данных получается битыми.
Пока подозрения на ошибку в Ethernet драйверах либо LwIP стеке (v1.4.1).
То есть многократное срабатывание прерывания Ethernet + работа задачи по сохранению принятого по Ethernet пакету приводит к сбою работы memcpy
Нехватка памяти для RTOS и его задач контролируется соответствующими отладочными функция FreeRTOS
Может у кого то будут умные мысли, как можно сузить круг поиска бага?
Как еще подиагностировать. Повторить ситуацию непросто, получается ни каждый раз.
-
В других контроллерах (stm32f4 к примеру) дата меняется в 00:00:00 время
В STM32F2 наблюдаю другую картину: дата может измениться в 00:00:07 время или не изменяться вообще.
Кто то сталкивался с такой проблемой? куда капать?
-
Разрешите поинтересоваться, а как у вас получилось, что адрес стека оказался не выровнен? И в какой IDE вы работаете? У меня такого ни разу не было, ни в одном проекте.
Eclipse + GCC, адрес стека был 0x2001FFFF, стал 0x20020000
-
Это требование ARM EABI. На практике косяки вылазили только с плавучкой, но для порядка надо везде.
спасибо за разъяснения
-
спасибо. проблема решена.
причина озвучена выше: адрес стека не был выровнен
вопрос в тему: выравнивание адреса указателя стека к 8 должно быть обязательно на всех типах ядер (конкретно STM32L0, STM32F4) ?
во любых типах проектов или только в тех, что используют newlib для print/sprint ?
-
Опубликовано · Изменено пользователем k000858 · Пожаловаться
С выводом чисел с плавающей точкой была только одна проблема - адрес дна стека должен быть кратен 8. У вас оно пришет 0.00, то есть оно распознало модификатор %f и что-то вывело. Но вывело явно не то, вероятнее всего потому, что переменная оказалась не в том месте, где ее ожидал printf.никаких переменных
printf("%f\n", 1.0f); выводит 0.000000
а printf("%f\n", 1.1f); выводите -0.000000
-
Во всех своих проектах пользуюсь выводом отладочных сообщений, в том числе выводом значений переменных. Float переменные обычно вывожу printf("%.2f\n", val); - таким методом пользуюсь и на L0, и на F4 контроллерах, и через UART и через SWO интерфейс.
Однако на STM32F205 контроллере не работает, как надо, например printf("%.2f\n", 1.0f); выводит 0.00, при этом в настройках линкера включено
-specs=nano.specs -u _printf_float
Что ни так с этим контроллером?
-
я правильно понимаю, что ключ fno-strict-aliasing отключает эту самую оптимизацию по альязингу и снимает все эти негативные эффекты?
-
кстати вся инфа актуальна только на оптимизации -Os?
или на -Og так же актуально?
-
При выходе за границу массива компилятор генерирует код, который не то, чтобы просто за границу массива выходит, а лезет в совершенно левые адреса.
Вот как раз что то подобное в паре проектов у себя наблюдаю...
только вот выходы за границу массивов не наблюдаю...
-
ок. а в рамках обсуждаемого предмета (баг, я так понимаю в lwip который проявляется с GCC 5) можно разжевать что там к чему дабы не вдаваться в ассемблерный код?
-
Качество кода lwip во всей красе, UB на UB и UB погоняет.
въехать бы тебе в сакральный смысл данного поста
-
Опубликовано · Изменено пользователем k000858 · Пожаловаться
Опишите подробней плиз по-русски о чем речь (я так понимаю, какие то баги по части DHCP в lwip)
И что есть UB?
Сам пользую lwip 1.4.1 и GCC 5 с максимальной оптимизацией и как раз наблюдаю странное поведение ПО.
-
схема мне не нужна. главное что все построено на UART. a DMA у вас используется? по примеру как тут http://we.easyelectronics.ru/STM32/stm32-1...odolzhenie.html
планирую использовать эту библиотеку переписав ее под HAL
P.S.
дело в том, что это мой первый проект на STM32 да еще и такой сложный а тут еще этот HAL с минимальным набором готовых библиотек на нем и сроки поджимают. а в проекте не только датчики...
все так же делал: все написано на основе HAL:
DMA используется по RX линии, по TX линии использовать его не вижу смысла; в ТХ плюю байтики, а между тем они же (но с учетом влияния шины 1-wire и устройств на ней) складываются по DMA в RX.
STM32L0 HardFault: заморочки с выравниванием
в STM
Опубликовано · Пожаловаться
заработали оба способа
второй способ понравился даже больше. еще раз спасибо, теперь мне тема выравнивания еще более понятна.