Перейти к содержанию
    

Кто тестировал IAR ARM 8.50, отзовитесь

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

во что это скомпилировалось.

В LDM и скомпилировалось. На O3 (или Os не помню).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, VladislavS said:

Адрес src на вход функции подаётся в общем случае невыровненный. По этому адресу читается 4 байта. Если бы это был Cortex-M0 какой-нибудь, то компилятор в несколько присестов как-нибудь собрал прочитал эти байты из памяти. Но тут он видит, что у него Cortex-M4 и можно с понтами сразу 32-битное чтение применить и выбирает неправильную инструкцию.

Нет. Вы явно преобразовали тип, тем самым взяв на себя ответственность за выравнивание. На CM0 будет то же самое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 minutes ago, one_eight_seven said:

Там у вас проблема не в переменной, а в адресе, т.е. значении, которое хранится в переменной. Адрес, по которому вы пытаетесь считать 32-разрядную переменную может быть выровнен по 8 байт.

Пример - вы хотите взять второй байт в 32-разрядном слове (интерпретировать его как массив байт [0:3], и обратиться ко второму элементу. Адрес второго элемента не будет выровнен по границе 32 бита. Это аргумент (функции uint8_t * src). И это не должно быть запрещено компилятором. Оно не запрещено.

А далее вы по этому адресу берёте не 1 байт, а 4, которые уже должны бы быть выровнены по границе 32 бита, а оно не так (см. предыдущий параграф)

 

Я в курсе :smile:

Считаю такое поведение компилятора неадекватным.  Любой указатель по умолчанию должен быть выровнен на 4 байта как минимум.  Даже если он указывает на char или short.  GCC к примеру выравнивает на 8 байт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, __inline__ сказал:

Да какая фиг разница?  Если это указатель, то он уже обязан быть выровнен на 4 байта как минимум, если он аргумент функции.  Для остальных случаев есть packed и всё с ним связанное.  То что вы привели, это - костыли для компилятора чтобы избежать случая, описанного VladislavS

Поясните как в коде:

uint8_t arr[] = {1,2,3,4,5};
WriteFIFO(&arr[1]);

как указатель внутри WriteFIFO() может быть "выровнен на 4 байта как минимум" ??? :shok:

Как Вы это себе физически представляете?

 

PS: А то что я привёл - это не костыли, а корректное описание типа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 minutes ago, __inline__ said:

Да какая фиг разница?  Если это указатель, то он уже обязан быть выровнен на 4 байта как минимум, если он аргумент функции.  Для остальных случаев есть packed и всё с ним связанное.

Само расположение указателя uint_8t*, конечно, должно быть выровнено. Но не значение, которое хранится в этом указателе.
Попробуйте до того, как делать запись
 

*fifo = *(uint32_t *)src;

поставить:
 

assert( (*src & 0x3) == 0 );

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, VladislavS сказал:

В LDM и скомпилировалось. На O3 (или Os не помню).

Тогда это просто отличный компилятор! Я на IAR о таком только мечтаю.  :wink:

Сколько уже раз, глядя на листинги, думал: "И почему бы здесь компилятору не использовать одну LDM вместо кучи последовательных LDR"? Но IAR пока такого не умеет. К сожалению...  :sad:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ещё раз. Я осознанно иду на невыровненное чтение, воспользовавшись тем что Cortex-M4 это умеет делать. Вот так же я имею право сделать?

GPIOA->IDR = *(uint32_t*)0x2000'0001;

То что мне компилятор вставит тут LDM в мои планы не входило.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, VladislavS сказал:

Ещё раз. Я осознанно иду на невыровненное чтение, воспользовавшись тем что Cortex-M4 это умеет делать. Вот так же я имею право сделать?

Вправе. Указав __packed.  :wink2:

1 минуту назад, VladislavS сказал:

GPIOA->IDR = *(uint32_t*)0x2000'0001;

То что мне компилятор вставит тут LDM в мои планы не входило.

Попробуйте добавить __packed (или её аналог). Команда стала LDR после этого?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, VladislavS said:

Вот так же я имею право сделать?

Это зависит от шины, которую ядро использует для доступа к памяти. Некоторые шины при этом дадут "испорченные" данные, потому, такой доступ, выданный напрямую в шину должен сделать одно из двух - либо вернуть недостовеные данные, либо HF.
Другое дело, что есть обходной путь. Если компилятор умеет его делать, то хорошо, если не умеет, то я бы выбрал HF, а не испорченные данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, one_eight_seven сказал:

Это зависит от шины, которую ядро использует для доступа к памяти.

Я говорю за конкретное ядро Cortex-M4, конкретный адрес в SRAM (0x2000'0001). Я точно знаю что так МОЖНО и хочу воспользоваться этим.

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

Попробуйте добавить __packed (или её аналог)

Это IAR-овская приблуда. Я не знаю как её в других компиляторах, работающих по стандарту, в данную операцию вставить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 minutes ago, VladislavS said:

Я не знаю как её в других компиляторах, работающих по стандарту, в данную операцию вставить.

Так доку почитать, нет? Если нужна сборка на разных компиляторах, оформить дефайном.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, VladislavS said:

Я говорю за конкретное ядро Cortex-M4, конкретный адрес в SRAM (0x2000'0001). Я точно знаю что так МОЖНО.

В Cortex-M4 используется AHB-Lite. В ней нет невыровненного доступа. Поэтому, для такого доступа нужно использовать обходные пути. Собственно, поддержка этого в ядре появилась с ARMv6, M4 - это ARMv7, значит, там это есть. Как конкретно это делается, я сказать не могу - у меня нет этого ядра, чтобы посмотреть, что там именно творится на шине. Но также есть и бит в регистрах конфигурации, который вызовет исключение при невыровненном доступе. Не знаю, надо это включать, или это включено по умолчанию. Не исключено даже, что в разных микроконтроллерах эта настройка будет выполнена по-разному.

Бит, если что CCR.UNALIGN_TRP.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 minutes ago, jcxz said:

Поясните как в коде:


uint8_t arr[] = {1,2,3,4,5};
WriteFIFO(&arr[1]);

как указатель внутри WriteFIFO() может быть "выровнен на 4 байта как минимум" ???

 

20 minutes ago, one_eight_seven said:

Само расположение указателя uint_8t*, конечно, должно быть выровнено. Но не значение, которое хранится в этом указателе.
Попробуйте до того, как делать запись
 


*fifo = *(uint32_t *)src;

поставить:
 


assert( (*src & 0x3) == 0 );

 

Вы перевираете.  Изначально пример выглядел вот так и я говорю про него: 

void WriteFIFO(uint8_t *src)
{
  uit32_t *fifo = CONST;
  *fifo = *(uint32_t *)src;
}

 

Здесь  uint8_t *src - указатель, адрес которого должен быть выровнен как минимум на 4 байта.

Далее идёт второй указатель в стеке: uint32_t *fifo - его адрес тоже должен быть выровнен как минимум на 4.

И наконец, копирование 4-х байт из src в fifo:  так как src и fifo  выровнены,  то будет сгенерирована инструкция без учёта выравнивания, всё ОК, должно работать.

 

Но если вдруг адреса src или адрес fifo   не кратны 4 как минимум, то будет ошибка выравнивания.  Но это возможно только если компилятор неадекватен или включен режим THUMB, а не ARM.  В тумбочке адреса могут быть кратны 2, и там принудительно надо задавать выравнивание массива и указателей:

Quote

 --pointer_alignment=4 --min_array_alignment=4

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, __inline__ said:

Вы перевираете.  Изначально пример выглядел вот так и я говорю про него: 

Согласен, у меня в assert лишнее разыменование.

assert( (src & 0x3) == 0 );

Вот когда оно проходит, тогда всё и выровнено. А когда не проходит - происходит невыровненный доступ. А поведение при невыровненном доступе - отдельный разговор. Чуть ниже мы с VladislavS это обсуждаем.

5 minutes ago, __inline__ said:

Но это возможно только если компилятор неадекватен или включен режим THUMB, а не ARM

Нет.
 

char * p = "aligned"; // assume address is 0x30000000
char * not_necessary_aligned = aligned_p; // 0x30000000
++not_necessary_aligned; // 0x30000001
char my_char = *not_necessary_aligned; // my_char == 'l'
uint_32t my_word = *( (uint_32t*)not_necessary_aligned ); // unaligned access. May cause HF, if core is set to do so

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 минут назад, one_eight_seven сказал:

Как конкретно это делается, я сказать не могу

Вестимо несколькими чтениями. Но это происходит прозрачно для кода. Если использовать правильные инструкции.

m4.thumb.jpg.06ed0e2ffda095f2057ac3f4b2da7da6.jpg

 

18 минут назад, aaarrr сказал:

Так доку почитать, нет?

А носом в доку ткнуть, нет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...