GCC 4.6 и CMSIS: исправляем ошибку компиляции

В процессе изучения STM32 решил я обновить компилятор. Сказано — сделано. Свеженький Sourcery G++ Lite с GCC 4.6.1 на борту был скачен и установлен. Вот только проекты, использующие CMSIS дружно перестали компилироваться выдавая ошибки:

Error: registers may not be the same -- `strexh r0,r0,[r1]'
Error: registers may not be the same -- `strexb r0,r0,[r1]'

Гугление быстро выявило наличие данного бага в баг-трекере GCC. Впрочем, как оказалось, это вовсе не баг, а фича текущей версии. Все дело в том, что использование одного и того же регистра в качестве первого и второго операндов данных команд приводит, согласно спецификации ARMv7m, к неопределенному поведению. Кстати, в документации от STM32 об этом не говорится, и работает, насколько я понимаю, правильно. Тем не менее, спеку надо чтить, поэтому поищем, как исправить это досадное недоразумение.
На просторах интернета встречаются два решения:

uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
   uint32_t result=0;
   __ASM volatile ("strexh r2, %2, [%1] \n" \
       "    mov %0, r2" : "=r" (result) : "r" (addr), "r" (value) : "r2" );
   return(result);
}

и

uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
   register uint32_t result asm("r2");
   __ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
   return(result);
}

Очевидным минусом является явное использование регистра r2. Все же задачу выбора свободного регистра лучше было бы поручить компилятору. Попробуем сделать это!
Итак, мы хотим, чтобы в качестве выходного параметра использовался регистр, отличный от входных. В GCC мы можем использовать знак амперсанда, чтобы указать, что регистр должен использоваться исключительно как выходной. Таким образом, просто добавим знак амперсанда после символа =

uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
   uint32_t result=0;
   __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value));
   return(result);
}

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

Комментарии (14)

RSS свернуть / развернуть
Действительно красивое решение, зачет.
+1
  • avatar
  • evsi
  • 13 марта 2012, 08:54
собранный самостоятельно 4.6.1 ошибку не выдает, cmsis 1.30 из поставки 3.5.0. или я специфическое чтото не использовал?
0
CMSIS у меня тоже версии 1.30, из STM32 Periph library.
Надо полагать в вашей версии исходников отсутствовал патч, добавляющий эту проверку. Судя по описанию бага, ошибка возникает в GAS версии 2.21.53 и выше.
Попробую, кстати, еще проверить на последнем Yagarto с GCC 4.6.2.
0
у меня binutils 2.20.1a, наверное поэтому.
0
Почему нельзя обновить CMSIS? Последняя версия 3.0. Или есть какие-то подводные камни? А то Вы переизобрели то, что уже есть в CMSIS :)
+1
  • avatar
  • John
  • 15 марта 2012, 00:01
Пользовался той версией, что была в библиотеке от STM32. CoIDE также эту версию подсовывает. Но вы правы, нужно попробовать обновиться.
В 3.0 действительно все исправлено + прописано принудительное встраивание функции, что в данном случае очень правильно.
0
Подскажите, как именно подключать CMSIS 3.0 в сборку демки?
0
Вот так. А вообще по-моему пора бы уже ST-шникам обновить SPL. В SPL для F4 уже новая CMSIS, а для STM32F1 все по-прежнему пока(
0
Спасибо, хорошее решение
0
Не будет ли кто любезен сказать, куда этот кусок кода вставить? Попытка замигать на stm32vldiscovery уперлась в эту ошибку.
0
Воспользуемся поиском строк «STREXB» и «STREXH» в исходниках. Эти функции спрятаны в файлах core_cmInstr.h либо core_cm3.c в зависимости от версии библиотеки.
0
Спасибо тебе, добрый человек! Так и сделал.
Ё-мое, две недели с STM, да на эклипсе (хоть и под Windows)… Замигал!
0
Неужели спустя 4 года проблема всё ещё актуальна? Или Вы каким-то древним SDK пользуетесь? Сам я под STM давно ничего не собирал, по-этому не в курсе.
0
SPL на STM32F10x от STMicroelectronics давно не обновлялась. А свежие сборки для других ядер уже поправлены приведенным выше элегантным способом
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.