|
|
  |
Настройка GCC компилятора для CortexM4, Какой ключ указать, чтобы использовать DSP инструкции |
|
|
|
Jul 3 2013, 05:03
|
Местный
  
Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333

|
Сравнивал два компилятора GCC 4.7 и ARMCC 4.1.0 в Keil'e. Код вида i+=a*a эти компиляторы исполняют по разному. В ARMCC это выглядит следующим образом:
т.е. используется одна команда MLA ( Multiply with accumulate). А GCC делает этот код следующим образом:
сначала mul (умножение) потом adds (add with substract). Т.е. команд в GCC становится на 3 больше. Вопрос можно ли заставить gcc использовать такие же инструкции как и в ARMCC. (MLA не DSP инструкция). Уровни оптимизации одинаковые -O0
Сообщение отредактировал sidy - Jul 3 2013, 05:11
|
|
|
|
|
Jul 3 2013, 05:58
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (sidy @ Jul 3 2013, 07:03)  Уровни оптимизации одинаковые -O0 gcc сделал именно то, что вы просили - сначала умножил, потом прибавил. И без всякой самодеятельности, ибо оптимизацию вы ему запретили. Попробуйте -Os, -O3, тогда можно будет что-то сравнивать.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 6 2013, 20:16
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
GCC не умет??????????????? c-код Код NOP(); NOP(); NOP(); i+=a*b; NOP(); NOP(); NOP(); ключи -mcpu=cortex-m3 -mfloat-abi=soft -mthumb -Os -fomit-frame-pointer -finline-functions -ffunction-sections -fdata-sections -fgraphite -funroll-loops -flto=8 выход компиллера Код 80016d0: bf00 nop NOP(); 80016d2: bf00 nop NOP(); 80016d4: bf00 nop i+=a*b; 80016d6: 4f59 ldr r7, [pc, #356]; (800183c <ResetHandler.4045+0x880>) 80016d8: 4b59 ldr r3, [pc, #356]; (8001840 <ResetHandler.4045+0x884>) 80016da: 680e ldr r6, [r1, #0] 80016dc: 6818 ldr r0, [r3, #0] 80016de: 683a ldr r2, [r7, #0] 80016e0: fb00 2406 mla r4, r0, r6, r2 80016e4: 603c str r4, [r7, #0] NOP(); 80016e6: bf00 nop NOP(); 80016e8: bf00 nop NOP(); 80016ea: bf00 nop под четверку тем более....
|
|
|
|
|
Dec 6 2013, 21:33
|
Знающий
   
Группа: Свой
Сообщений: 549
Регистрация: 13-07-10
Из: Солнечногорск-7
Пользователь №: 58 414

|
Цитата(sidy @ Dec 6 2013, 09:25)  в LR содержится 0xFFFFFFF1, но прочитав документ Cortex M4 programming manual не нашел как по содержимому LR определить стек возврата MSP или PSP. Читать надо документацию на архитектуру в целом. Конкретно по прерывания можно на русском посмотреть здесь.
|
|
|
|
|
Dec 16 2013, 15:31
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(sidy @ Dec 16 2013, 09:55)  Как написано в ReferenceManual во время исключения в LR записывается значение EXC_RETURN. У меня в LR записано 0xFFFFFFF1. Как написано в RM такое значение появляется при: Return to Handler mode, exception return uses non-floating-point state from the MSP and execution uses MSP after return. Т.е. теперь мне необходимо в DefaultHandler прочитать MSP следующим образом: uint32_t i=__get_MSP(), и в i будет содержаться адрес с которого программа попадает в HardFault. Правильно ли я понял? Вот код стыбренный на просторах интернета (на форуме st) для Cortex M3: Код void hard_fault_handler_c(unsigned int * hardfault_args) { unsigned int stacked_r0; unsigned int stacked_r1; unsigned int stacked_r2; unsigned int stacked_r3; unsigned int stacked_r12; unsigned int stacked_lr; unsigned int stacked_pc; unsigned int stacked_psr;
stacked_r0 = ((unsigned long) hardfault_args[0]); stacked_r1 = ((unsigned long) hardfault_args[1]); stacked_r2 = ((unsigned long) hardfault_args[2]); stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]); stacked_lr = ((unsigned long) hardfault_args[5]); stacked_pc = ((unsigned long) hardfault_args[6]); stacked_psr = ((unsigned long) hardfault_args[7]);
printf ("[Hard fault handler]\n"); printf ("R0 = %x\n", stacked_r0); printf ("R1 = %x\n", stacked_r1); printf ("R2 = %x\n", stacked_r2); printf ("R3 = %x\n", stacked_r3); printf ("R12 = %x\n", stacked_r12); printf ("LR = %x\n", stacked_lr); printf ("PC = %x\n", stacked_pc); printf ("PSR = %x\n", stacked_psr); printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38)))); printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28)))); printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C)))); printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30)))); printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
while (1);
}
/******************************************************************************* * Description : This function handles Hard Fault exception. * Input : - * Return : - *******************************************************************************/ void HardFault_Handler(void) { // Go to infinite loop when Hard Fault exception occurs asm("TST LR, #4"); asm("ITE EQ"); asm("MRSEQ R0, MSP"); asm("MRSNE R0, PSP"); asm("B hard_fault_handler_c"); while (1); } Доработaть по вкусу. printf можно выбросить. Поставить брейкпойнт на месте первого printf. Сравнить пойманный аддресс с map файлом, найти из какой функции вылетает Может, memory corruption или stack маленький. Наиболее частые проблемы, мне кажется, особенно при таких странных LR
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
Dec 18 2013, 07:32
|
Местный
  
Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333

|
Я снова получил HardFault и использовал функцию, приведенную выше для определения адреса с которого перешли в HardFault. Значения переменных у меня получились следующие:  А значения регистров в отладчике такие:
Вопрос почему несовпадают значения r0, r1, r2, r3 и т.д. полученные в функции с тем что я вижу в регистрах? И как теперь мне определить адрес из которого попали в HardFault? И еще мысль переменные stacked_r0 и т.д. должны быть глобальными, чтобы не портить стэк? И еще в Reference Manual написано что нужно использовать функции __get_PSP() и __get_MSP(), но когда я их пытаюсь вызвать компилятор выдает следующую ошибку: [cc] C:\ARTRON_VER1.1\cmsis/core_cmFunc.h:410:61: error: expected '=', ',', ';', 'asm' or '__attribute__' before '__get_PSP' [cc] C:\ARTRON_VER1.1\cmsis/core_cmFunc.h:410:1: error: unknown type name '__STATIC_INLINE' Сама функция в core_cmFunc.h описана так: __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) { register uint32_t result; __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); return(result); } Что нужно сделать чтобы данные функции вызывались нормально. P.S. проверил в файле main.c функция __get_MSP(); вызывается, а вот в файле startup_stm32f4xx.c компилирует с ошибками, непонятно.
Сообщение отредактировал sidy - Dec 18 2013, 09:36
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|