Jump to content

    
nanorobot

А может быть Holtek?

Recommended Posts

1 час назад, jcxz сказал:

Если IAR, то достаточно в таких местах приводить не к u64, а к __packed u64 - и всё наладится.  :wink:

Это gcc и структуры, помогает __attribute__((packed)), но в некачественном исходнике нужно искать все места с потенциальной проблемой.

Сейчас включил UsageFault для невыровненных данных и ключем "-mno-unaligned-access" попросил компилятор не использовать фичу Cortex-M по работе с невыровнеными данными. Отключил сторожевой таймер. Гоняю -  жду дампов от UsageFault.

Share this post


Link to post
Share on other sites
1 час назад, jcxz сказал:

...я обычно всегда ставил инструкцию DMB. Но на STM32 она не помогает почему-то в таких случаях...

Тут дело в том, где архитектурно заложен так называемый буфер записи. CPU своими инструкциями барьеров может повлиять только на буфер записи, реализованный на его шинном интерфейсе. Если, например, буфер записи есть еще и на самих мостах AHB/APB - то все эти DSB/DMB бесполезны. Об этом вкратце можно глянуть тут. Несколько сложнее обстоят дела в Cortex-M7 с его AXI, который умеет переупорядочивать доступы и параллелить ожидающие передачи. Во где красота:prankster2:

P.S. Кстати, их пример (что в приведенной мною ссылке)

Цитата

void Timer_IRQHandler (void) {
  PortD->PTOR |= 1<<0;              /* Toggle output on port D0         */
  Timer->MSR |= TIMER_MASK;         /* Clear timer interrupt            */
  Timeout_counter++;                /* Count timeout & insure IRQ clear */
}

может не помочь, если Timeout_counter не volatile (но кем надо быть, чтобы так делать, я не знаю).

Share this post


Link to post
Share on other sites
41 минуту назад, adnega сказал:

Сейчас включил UsageFault для невыровненных данных и ключем "-mno-unaligned-access" попросил компилятор не использовать фичу Cortex-M по работе с невыровнеными данными. Отключил сторожевой таймер. Гоняю -  жду дампов от UsageFault.

Так можно долго ждать и никогда не дождаться. Если оно происходит только при определённых условиях.

Разумнее (имхо) - по листингу отыскивать все LDRD/STRD, LDM/STM, LDREX/STREX и т.п. и смотреть - возможен ли там невыровненный адрес или нет?

Сложнее будет с PUSH/POP - ведь их будет дофига, глазами не просмотришь, и если накосячено и с указателями стека.....  :dash2:

 

12 минут назад, Arlleex сказал:

Тут дело в том, где архитектурно заложен так называемый буфер записи. CPU своими инструкциями барьеров может повлиять только на буфер записи, реализованный на его шинном интерфейсе

Я знаю про буфер записи. Именно поэтому и борюсь с ним обратным чтением.

Share this post


Link to post
Share on other sites
2 минуты назад, jcxz сказал:

Я знаю про буфер записи. Именно поэтому и борюсь с ним обратным чтением.

Не понятно только, почему STM-щики не могут указать в RM на свои контроллеры некоторые сведения system-level design, где и описали бы, мол так и так, тут есть буфер записи, будьте осторожны, не наступите на грабли. Нет же - все только опытным путем. Самому тоже приходилось наступать:smile:

Share this post


Link to post
Share on other sites
21 минуту назад, jcxz сказал:

Разумнее (имхо) - по листингу отыскивать все LDRD/STRD, LDM/STM, LDREX/STREX и т.п. и смотреть - возможен ли там невыровненный адрес или нет?

Это не гарантирует, что при следующей сборке не появятся новые LDRD и компания.

Проще в исходнике искать приведение к типу "(some_type *)".

Share this post


Link to post
Share on other sites
9 minutes ago, adnega said:

Проще в исходнике искать приведение к типу "(some_type *)".

Еще проще в исходника вообще избегать приведений типа в С-стиле :dirol:

В плюсовом стиле проще искать такие места в коде. Вот и вот про это.

Share this post


Link to post
Share on other sites
53 минуты назад, adnega сказал:

Это не гарантирует, что при следующей сборке не появятся новые LDRD и компания.

Проще в исходнике искать приведение к типу "(some_type *)".

Какой-то странный у вас метод - вместо отыскания наличия определённых команд (приводящих к проблеме), сидеть и пытаться по исходнику угадать в каком месте они могут возникнуть и ещё и привести к проблеме.

Примерно то же самое, что если б для определения достаточно ли горячие дома батареи отопления, вместо того чтобы просто их потрогать, бежать в котельную и смотреть сколько угля кочегары бросают в топку и угадывать температуру у себя в батарее.  :crazy:

Предположу, что никогда не угадаете все возможные случаи возникновения LDRD/STRD/LDM/STM по исходнику. Да даже те, что можно угадать - и то по исходнику намного сложнее будет сделать, чем по листингу.

Share this post


Link to post
Share on other sites
11 минут назад, jcxz сказал:

Какой-то странный у вас метод

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

Точнее, если выравнивание не гарантируется, то ставить packed. Дальше уже дело компилятора это правильно трактовать, и с этим проблем не замечено.

В подавляющем большинстве случаев в данном исходнике к какой-то части пакета некого протокола осуществляется доступ через указатель на структуру.

У всех этих структур просто нужно добавить packed. В другом наборе случаев данные организованы так, что они принципиально выровненные и тут править ничего не надо.

Я отлавливаю какие-то промежуточные варианты: например, структура с настройками выровнена и сами настройки хранятся выровненными, но по протоколу могут прилететь настройки уже не выровненные в памяти. Как поступать в таких случаях?

Share this post


Link to post
Share on other sites
1 час назад, adnega сказал:

Я отлавливаю какие-то промежуточные варианты: например, структура с настройками выровнена и сами настройки хранятся выровненными, но по протоколу могут прилететь настройки уже не выровненные в памяти. Как поступать в таких случаях?

Ну так если к этим "настройкам прилетевшим по протоколу" обращение идёт через указатель на структуру, то эту структуру и сделать __packed. Сами же это сказали.

Share this post


Link to post
Share on other sites
5 минут назад, jcxz сказал:

Ну так если к этим "настройкам прилетевшим по протоколу" обращение идёт через указатель на структуру, то эту структуру и сделать __packed. Сами же это сказали.

По протоколу настройки прилетают крайне редко. А с самими настройками работа очень интенсивная. Если я тупо добавлю packed, то все многобайтные типы будут побайтово собираться - а мне так не надо (на самом деле для Cortex-M3 и выше можно сборки избежать в расчете на лишний такт при обращении к невыровненным данным). Я могу в протокол добавить фиктивных байтиков перед структурой настройки, чтобы они уже получались выровненными. Я могу для протокола выделить тип-близнец настроек, но с packed. Могу просто memcpy устроить или присвоение структуры. Вариантов много и не все так очевидно. Очевидно одно, что исходник плохой и его нужно править. Собственно, я весь этот разговор затеял в контексте того, что исходник нужно писать так, чтобы от уровня оптимизации, компилятора, слишком быстрого или медленного исполнения - результат не зависел и всегда был корректным. Кста, исходник мой, но 10-летней давности. Все это время биарник работал без нареканий в большом количестве изделий 24/7 и вообще считался отлаженным (светодиодные информационные остановочные табло). Собирал когда-то сборкой от klen. Сейчас пользуюсь ланчпадовской сборкой, lto и прочими плюшками - вот и повылезало при переносе на новое железо.

Share this post


Link to post
Share on other sites
3 минуты назад, adnega сказал:

По протоколу настройки прилетают крайне редко. А с самими настройками работа очень интенсивная. Если я тупо добавлю packed, то все многобайтные типы будут побайтово собираться

С чего бы это? Какой компилятор так компилит??? :umnik2: IAR точно такой глупости не делает. Он знает что CPU умеет невыровненный доступ для LDR\STR\LDRH\STRH, поэтому применяет их и для обращений к __packed типам 16- и 32-разрядным. А уж сколько получится тактов при этом обращении - зависит от того как реально лежит: реально лежит ровно? -> значит и будет минимально возможное число тактов.

3 минуты назад, adnega сказал:

Я могу в протокол добавить фиктивных байтиков перед структурой настройки, чтобы они уже получались выровненными. Я могу для протокола выделить тип-близнец настроек, но с packed. Могу просто memcpy устроить или присвоение структуры.

Имхо - Вы всё излишне усложняете. __packed помогает избежать LDRD/STRD/LDM/STM/..., а больше ничего и не нужно.

Share this post


Link to post
Share on other sites
13 минут назад, jcxz сказал:

С чего бы это? Какой компилятор так компилит???

gcc с ключем "-mno-unaligned-access" (принуждает packed собирать побайтово). По-умолчанию, для Cortex-M3 он использует невыровненый доступ и для него использует ldr вместо побайтовой сборки. Но я ручками в МК включил исключение для невыровненого доступа, чтобы знать потенциально опасные места. Разумеется, начал спотыкаться на всех невыровненных данных, даже на содержащих атрибут packed. После этого добавил packed, где нужно, чтобы не словить там ldrd. После этого можно генерацию исключения отключать как и ключ "-mno-unaligned-access".

13 минут назад, jcxz сказал:

Имхо - Вы всё излишне усложняете. __packed помогает избежать LDRD/STRD/LDM/STM/..., а больше ничего и не нужно.

Согласен. Тут я больше из-за академического интереса переборщил. Столкнулся с этим первый раз и решил в дебри погрузиться.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.