ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
13 июля
476048
VVB (24.12.2013 10:22, просмотров: 8303)
Как заставить GCC корректно работать в соответствии с AAPCS и инструкцией SVC, если обработчик прерывания должен возвращать значение? http://www.ethernut.de/en/documents/arm-inline-asm.html
В кейле всё просто и красиво. __svc(1) extern portBASE_TYPE prvRaisePrivilege( void ); signed portBASE_TYPE MPU_xTaskGenericCreate( pdTASK_CODE pvTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) { signed portBASE_TYPE xReturn; portBASE_TYPE xRunningPrivileged = prvRaisePrivilege(); xReturn = xTaskGenericCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, puxStackBuffer, xRegions ); portRESET_PRIVILEGE( xRunningPrivileged ); return xReturn; } Для реализации того же в GCC приходится знатно извращаться: #define SVC_par1(code) asm volatile ("svc %[call]" : : [call] "I" (code) : "r0") static portBASE_TYPE prvRaisePrivilege(void) __attribute__((always_inline)); static portBASE_TYPE prvRaisePrivilege(void) { register portBASE_TYPE rc asm("r0"); SVC_par1(1); return rc; } signed portBASE_TYPE MPU_xTaskGenericCreate( pdTASK_CODE pvTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) { signed portBASE_TYPE xReturn; portBASE_TYPE xRunningPrivileged = prvRaisePrivilege(); xReturn = xTaskGenericCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, puxStackBuffer, xRegions ); portRESET_PRIVILEGE( xRunningPrivileged ); return xReturn; } Мало того, что я грязным хаком указываю регистр R0 в качестве результата операции SVC, так ещё и всякие опции GCC типа -mabi=aapcs или атрибуты функций типа __attribute__((pcs("aapcs"))) не влияют на генерирование кода (по умолчанию GCC думает, что SVC это вызов функции, а не прерывания, и после инструкции SVC достаёт результат из стека, что неправильно). Что я делаю не так? Должно же быть корректное и красивое решение.