Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Косяк в компиляторе KEIL по части автоинкремента?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
KnightIgor
Привет, коллеги.

Столкнулся с "интересным" поведением программы под KEIL 4.23, процессор EFM32G210F128:
Код
void func(void *p)
{
   long *ptr = p;
   ...
   *ptr++ = variable;
   ...
}

приводит к исключению. В ассемблере это инструкция STM R5!, {R0}.
Код
void func(void *p)
{
   long *ptr = p;
   ...
   *ptr = variable;
    ptr++;
   ...
}

работает нормально. Там генерируется:
Код
  STR R0, [R5, #0x00]
  ADDS R5,R5,#4

В описании инструкции STM я не нашел упоминания, что регистр-указатель приемника должен быть выровнен на слово, а похоже именно это требуется. У меня же через void *p передается указатель на некий буфер обмена, который может содержать различные данные, а сам буфер в итоге где-то в стеке как локальная переменная внутри функции, которая и вызывает мою. Очевидно, что локальные переменные там не выровнены.

Что скажете? Мой недосмотр или грабли, подложенные KEIL?
esaulenka
поиск по arm.com "cortex-m3 unaligned access"

Цитата
The Cortex-M3 processor supports unaligned access only for the following instructions:
LDR, LDRT
LDRH, LDRHT
LDRSH, LDRSHT
STR, STRT
STRH, STRHT.
All other load and store instructions generate a UsageFault exception if they perform an unaligned access, and therefore their accesses must be address aligned.


Так что контроллер работает согласно спецификации :-)

К кейлу тоже никаких претензий - он же не знает, что этот указатель не выравнивается.


PS. Вот так должно работать.
KnightIgor
Цитата(esaulenka @ Dec 19 2012, 14:07) *
PS. Вот так должно работать.

Понял, спасибо.

Дополню.
Цитата
К кейлу тоже никаких претензий - он же не знает, что этот указатель не выравнивается.

Ну... здесь можно поспорить. С точки зрения C оба кода вполне равноценны и должны быть переносимы. А получается, что кусок кода c *p++ шустрил успешно на каком-нибудь 8-ми битнике, а тут на Cortex вдруг раз, и исключение! И только потому, что платформа себя так ведет, что к C никакого отношения не имеет. Некрасиво.
ar__systems
Цитата(KnightIgor @ Dec 19 2012, 09:22) *
Понял, спасибо.

Дополню.

Ну... здесь можно поспорить. С точки зрения C оба кода вполне равноценны и должны быть переносимы. А получается, что кусок кода c *p++ шустрил успешно на каком-нибудь 8-ми битнике, а тут на Cortex вдруг раз, и исключение! И только потому, что платформа себя так ведет, что к C никакого отношения не имеет. Некрасиво.
Тут дело не в *p++, а в том, чтовы указатель конвертируете из войд в лонг. На 8ми битнике понятное дело будет работать, на то он и 8ми битник чтобы про выравнивание не знать. Вы не получили warning при компиляции, что assignment increases alignment requirements? Компилятор ведет себя правильно. Вы же в курсе, что невыровненый доступ занимает больше времени?
KnightIgor
Цитата(ar__systems @ Dec 19 2012, 17:12) *
Вы не получили warning при компиляции, что assignment increases alignment requirements?

Нет.
Цитата
Вы же в курсе, что невыровненый доступ занимает больше времени?

Да. Но здесь я бы ожидал, что компилятор в угоду совместимости будет исходить из НЕвыровненных данных. А программист, который хочет быстро, может указать потом, какие данные выровнены, и если ошибется - пусть пеняет на себя же. То есть, не __packed нужно, что для меня выглядит как work around, а противоположный описатель типа __aligned. Тогда совместимость на уровне исходника будет, а оптимизацией под платформу можно будет заняться, если припечёт.
scifi
Цитата(KnightIgor @ Dec 19 2012, 20:25) *
Но здесь я бы ожидал, что компилятор в угоду совместимости будет исходить из НЕвыровненных данных. А программист, который хочет быстро, может указать потом, какие данные выровнены, и если ошибется - пусть пеняет на себя же.

В стандарте языка закреплено обратное: по умолчанию предполагается, что все объекты выровнены должным образом.
Что касается конкретно этого случая, то тут надо в деталях разбирать происхождение указателя на void. Тогда будет видно, где именно возникает невыровненный объект. Ну а работать с ним можно, используя packed (непереносимая фича компилятора), или делать перепаковку руками (переносимо).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.