(c) valessiobrito, "Open clipart" |
Ввімкнувши її у простому проектику для STM32 (в CoIDE), теж зіткнувся з проблемами. Компілятор видав наступне:
[cc] C:\Users\indrekis\AppData\Local\Temp\ccaX3kx8.s:1162: Error: registers may not be the same -- `strexb r0,r0,[r1]'
[cc] C:\Users\indrekis\AppData\Local\Temp\ccaX3kx8.s:1187: Error: registers may not be the same -- `strexh r0,r0,[r1]'
[cc] C:\Users\indrekis\AppData\Local\Temp\ccaX3kx8.s:1187: Error: registers may not be the same -- `strexh r0,r0,[r1]'
З допомогою Гугла зразу знайшов пояснення: "Error: registers may not be the same -- `strexb r0,r0,[r1]'". Машинні команди ARM strexb і strexh не можуть мати в ролі аргументів однакові регістри, а компілятор двічі підсовує їм r0. Справді, у файлі cmsis/core_cm3.c є наступні оголошення:
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ /* --------- SKIPPED --------- */ uint32_t __STREXB(uint8_t value, uint8_t *addr) { uint32_t result=0; __ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) ); return(result); } /* --------- SKIPPED --------- */ 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); } /* --------- SKIPPED --------- */ #elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ /* --------- SKIPPED --------- */ uint32_t __STREXB(uint8_t value, uint8_t *addr) { __ASM("strexb r0, r0, [r1]"); __ASM("bx lr"); } /* --------- SKIPPED --------- */ uint32_t __STREXH(uint16_t value, uint16_t *addr) { __ASM("strexh r0, r0, [r1]"); __ASM("bx lr"); }
Як виправити
для IAR iccarm не знаю -- невірні регістри там прописані явно, мало що ABI очікуватиме, але
для актуального мені GCC все відносно просто. Слід в обох асемблерних
вставках "=r" (result), замість "=r" написати "=&r", це змусить компілятор підібрати інший регістр:
Детальніше про такі асемблерні вставки, як їх писати, як вони функціонують і т.д., див. "Ассемблерные вставки в AVR-GCC".
Ймовірно, помилка проявляється лише за ввімкненої оптимізації через те, що компілятор починає хитрувати із використанням регістрів, і вирішує, що двічі використати один і той же буде вигідніше...
Стосовно CoIDE, яка є моєю основною оболонкою для STM32 -- на жаль, таку модифікацію може довестися робити в кожному проекті. Спробувати вирішити проблему раз і назавжди можна наступним чином. Файл, який копіюється в проекти, лежить в деяких піддиректоріях <CoIDE_Path>\CoIDE\repo\Components, головний, здається, в "<CoIDE_Path>\CoIDE\repo\Components\50_CMSIS core\src\cmsis". Однак, повної впевненості, як оболонка їх тасує, в мене немає... (Увага, свій core_cm.c є і в репозиторії CoSmart, але останній не підтримує STM32, тому поки не користувався).
Для тих, хто забув, core_cm3.c є частиною CMSIS, стандартної бібліотеки для всіх Cortex-ів, основа якої розроблена ARM Holdings, допилюється виробниками мікроконтролерів під їх периферію. Детальніше див. розділ "CMSIS i SPL (Standard Peripherals Library)" в одному із попередніх постів, "Огляд STM32 (ARM Cortex-M від STMicroelectronics)", та посилання там.
UPD: Зрозуміло, що помилка ця -- відома, не є чимось новим. Ось ще декілька посилань: 1, 2, 3. Просто ілюстрація, що буває, коли відважуєшся на оптимізацію. :-) Якщо орієнтуватися -- дрібниця, для початківця -- непідйомне.
В новіших CMSIS вже виправлено, але CoIDE використовує доволі стару. Обіцяють оновлення.
__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
Детальніше про такі асемблерні вставки, як їх писати, як вони функціонують і т.д., див. "Ассемблерные вставки в AVR-GCC".
Ймовірно, помилка проявляється лише за ввімкненої оптимізації через те, що компілятор починає хитрувати із використанням регістрів, і вирішує, що двічі використати один і той же буде вигідніше...
Стосовно CoIDE, яка є моєю основною оболонкою для STM32 -- на жаль, таку модифікацію може довестися робити в кожному проекті. Спробувати вирішити проблему раз і назавжди можна наступним чином. Файл, який копіюється в проекти, лежить в деяких піддиректоріях <CoIDE_Path>\CoIDE\repo\Components, головний, здається, в "<CoIDE_Path>\CoIDE\repo\Components\50_CMSIS core\src\cmsis". Однак, повної впевненості, як оболонка їх тасує, в мене немає... (Увага, свій core_cm.c є і в репозиторії CoSmart, але останній не підтримує STM32, тому поки не користувався).
Для тих, хто забув, core_cm3.c є частиною CMSIS, стандартної бібліотеки для всіх Cortex-ів, основа якої розроблена ARM Holdings, допилюється виробниками мікроконтролерів під їх периферію. Детальніше див. розділ "CMSIS i SPL (Standard Peripherals Library)" в одному із попередніх постів, "Огляд STM32 (ARM Cortex-M від STMicroelectronics)", та посилання там.
UPD: Зрозуміло, що помилка ця -- відома, не є чимось новим. Ось ще декілька посилань: 1, 2, 3. Просто ілюстрація, що буває, коли відважуєшся на оптимізацію. :-) Якщо орієнтуватися -- дрібниця, для початківця -- непідйомне.
В новіших CMSIS вже виправлено, але CoIDE використовує доволі стару. Обіцяють оновлення.
Автору честь і слава
ВідповістиВидалитиДякую! Хоча, особливо за що хвалити тут і немає --- просто зарисова про відомі факти, з якими зіткнувся. :-)
ВідповістиВидалити