реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Команда "STM r0!, {r1}" на Cortex M3, При невыровненном адресе возникает Hard Fault.
ISK2010
сообщение Sep 6 2011, 13:37
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Добрый день!

Железо - STM32F105VC rev.Z.

ПО - Keil 4.21, компилятор armcc 4.1.0.644

Случилось вот что. Понадобилось мне одну 32битную сохранить в буфер, и адрес поменять на следующую ячейку буфера:

Код
*((u32*)pPDU) = __REV16_W(*((u32*)( MB_HoldRegs + Address))); //да хоть просто число туда записывать
  
             pPDU += 4;


Ситуация стандартная. Но на мою голову компилятор засовывает инструкцию "STM":

Код
0x080018A0 F7FEFC70  BL.W     __REV16_W (0x08000184)
  0x080018A4 C601      STM      r6!,{r0}
тем самым пытаясь выполнить запись+инкремент за раз, но при выполнении которой происходит ошибка (HardFault).

Пока выяснял почему, начитался всякого. Вплоть до того, что вставленная 16битная инструкция STM является устаревшей и не используется для ядер ARMv6 и выше. А в другом месте (в ссылке про STM) вообще написано, что 16битная STM не поддерживается в Thumb-2EE, который для ARMv7, т.е. нашего Cortex-M3.

Но тогда почему именно эта инструкция была вставлена? Неужели косяк компилятора? Или же все-таки эта инструкция поддерживается Cortex-M3, но есть ограничения для ревизиии Z?

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

Результат экспериментов: инструкция работает, но если адрес массива не кратен 4, то вылетаем в Hard Fault.

Люди добрые, прокомментируйте случившееся. Помогите подвести итог.

Сообщение отредактировал ISK2010 - Sep 6 2011, 13:39
Go to the top of the page
 
+Quote Post
ViKo
сообщение Sep 6 2011, 14:06
Сообщение #2


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



А почему вы не определили pPDU как указатель на 32-битовую переменную, а увеличиваете его на 4?
По состоянию битов в xxx Fault Status регистрах можно определить причину вылета. Их можно увидеть в Keil - посмотреть соответствующий диапазон памяти (0xE000ED28 и др.).
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 6 2011, 14:25
Сообщение #3


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(ISK2010 @ Sep 6 2011, 17:37) *
Пока выяснял почему, начитался всякого. Вплоть до того, что вставленная 16битная инструкция STM является устаревшей и не используется для ядер ARMv6 и выше. А в другом месте (в ссылке про STM) вообще написано, что 16битная STM не поддерживается в Thumb-2EE, который для ARMv7, т.е. нашего Cortex-M3.

Есть 16 битное кодирование, в ARMv7M reference manual называется Encoding T1 - тут все ок!

А в Hard Fault скорее всего вылетает из-за не выравненного доступа! STM нельзя так использовать. Если это так то в исходнике некорректное приведение типов, надо приводить к не выравненному типу или писать макрос.
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Sep 6 2011, 15:55
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



To ViKo:

pPDU - указатель на байт, поэтому прибавляю 4. Fault Status завтра гляну, все железо на работе.

To KRS:

Да, ошибка возникала при не выровненном доступе. Но я не нашел где написано, что нельзя с не выровненными использовать. Подскажите в каком доке? Кто знает, может там для меня еще что-нибудь найдется.

Да, приведение корректно до некорректности. Как бы это обойти. Есть буфер, и в него пишутся разные вещи, в том числе 32битные. А структуры этих вещей выровнять не могу, т.к. этот буфер для связи с внешним устройством. Тут точно надо избавляться от "STM", но как бы это компилятору объяснить.




Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 6 2011, 16:56
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ISK2010 @ Sep 6 2011, 19:55) *
как бы это компилятору объяснить.

__packed
Go to the top of the page
 
+Quote Post
ViKo
сообщение Sep 6 2011, 17:32
Сообщение #6


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Процитирую помощь к Кейлу, правда, не уверен, что если указатель определен на байтовую переменную, а потом приводится к указателю на целое, то будет работать.

Unaligned pointers
By default, the ARM compiler expects conventional C pointers to point to an aligned word in memory, because this enables the compiler to generate more efficient code.

If you want to define a pointer that can point to a word at any address, then you must specify this using the __packed qualifier when defining the pointer. For example:

__packed int *pi; // pointer to unaligned int
When a pointer is declared as __packed, the ARM compiler generates code that correctly accesses the dereferenced value of the pointer, regardless of its alignment. The generated code consists of a sequence of byte accesses, or variable alignment-dependent shifting and masking instructions, rather than a simple LDR instruction. Consequently, declaring a pointer as __packed incurs a performance and code size penalty.
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 6 2011, 18:08
Сообщение #7


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(ISK2010 @ Sep 6 2011, 19:55) *
Подскажите в каком доке? Кто знает, может там для меня еще что-нибудь найдется.

arm architecture v7m reference manual
так же полезно будет
Cortex™-M3 Technical Reference Manual
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Sep 6 2011, 19:15
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Огромное СПАСИБО! Использовал _packed для структур, а применительно к указателям не знал)
И мануальчики почитаю.


Наверное, топик надо в раздел "помощь начинающим/программирование". Скандалы, интриги, расследования закончены. Их просто нет, все банально просто.

Сообщение отредактировал ISK2010 - Sep 6 2011, 19:18
Go to the top of the page
 
+Quote Post
777777
сообщение Sep 7 2011, 05:53
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(ISK2010 @ Sep 6 2011, 17:37) *
Код
*((u32*)pPDU) = __REV16_W(*((u32*)( MB_HoldRegs + Address))); //да хоть просто число туда записывать

А что это за макрос __REV16_W?
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Sep 7 2011, 06:21
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Цитата
А что это за макрос __REV16_W?


Эта функция меняет местами байты в каждом полуслове и выдает результат. В CMSIS есть такое:
Код
__ASM uint32_t __REV16(uint16_t value)
{
     rev16 r0, r0
     bx lr
}
Но,как видите, они зачем-то аргумент сделали 16-битным. Поэтому я сделал тоже, только с 32-битным:
Код
__ASM u32 __REV16_W(u32 value)
{
     rev16 r0, r0
     bx lr
  }


Go to the top of the page
 
+Quote Post
ViKo
сообщение Sep 7 2011, 06:41
Сообщение #11


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(ISK2010 @ Sep 7 2011, 09:21) *
Но,как видите, они зачем-то аргумент сделали 16-битным.

Похоже на косяк в CMSIS?
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Sep 7 2011, 06:51
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Может у них так и было задумано)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Sep 7 2011, 07:02
Сообщение #13


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(ISK2010 @ Sep 7 2011, 09:51) *
Может у них так и было задумано)

Реверсируется-то порядок байтов в обоих полусловах, и в младшем, и в старшем. wacko.gif
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 7 2011, 08:04
Сообщение #14


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Получается, что фолт на cm3 может произойти лишь при адресации не выравненных объектов больших байта?
А указатели на байт в принципе не нуждаются в атрибуте packed.
Я правильно мыслю?

Цитата(ViKo @ Sep 7 2011, 11:02) *
Реверсируется-то порядок байтов в обоих полусловах, и в младшем, и в старшем. wacko.gif
Поэтому аргумент и 16-ти битный в старшем полуслове будут всегда нули. Баги в CMSIS я не вижу.

Кстати, в литературе есть мнение, что
Код
b = ((a & 0x00ff) << 8) | ((a & 0xff00) >> 8); // This should generate the REV16 instruction.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Sep 7 2011, 08:57
Сообщение #15


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(demiurg_spb @ Sep 7 2011, 11:04) *
Поэтому аргумент и 16-ти битный в старшем полуслове будут всегда нули. Баги в CMSIS я не вижу.

Кстати, в литературе есть мнение, что
Код
b = ((a & 0x00ff) << 8) | ((a & 0xff00) >> 8); // This should generate the REV16 instruction.

Понятно, что при 16-битовом аргументе будет работать. А если нужно проинвертировать порядок в обоих полусловах, придется писать свою функцию, как сделал ISK2010. Хотя команда та же.
А можно было задать в функции REV16 32-битовый аргумент. Если кому-то нужно было проинвертировать порядок байтов в 16-битовой переменной, то эту 32-битовую функцию можно было бы использовать без переделок.

Кстати, в приведенной вами литературе есть пример, показывающий неэффективность использования в функциях переменныхс размерностью, меньше, чем int32. То же относится и к аргументам функций и возвращаемому результату.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 07:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01503 секунд с 7
ELECTRONIX ©2004-2016