SergNK 0 7 февраля, 2017 Опубликовано 7 февраля, 2017 · Жалоба Спасибо за доверие! Первый вариант. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 7 февраля, 2017 Опубликовано 7 февраля, 2017 · Жалоба Спасибо за доверие! Первый вариант. Написал в личку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 19 марта, 2020 Опубликовано 19 марта, 2020 · Жалоба Добрый день! простите за поднятие старющей темы, но ответа не нашёл. Да и с scmRTOS давно не работал. Но чем закончилось дело? Уважаемый @SergNK предоставил порт для IAR? Дело в том, что я его не нашёл в репозитарии. Смутило также, что, что у него используются макросы от GCC, например в обработчике PendSV #if defined __ARM_ARCH_6M__ // Cortex-M0(+)/Cortex-M1 При этом в документации на IAR таких макросов нет. Есть __CORE__ и сопутствующие значения, которые позволяют определить архитектуру процессора. Сейчас ваяю свой порт. Мой обработчик (не претендую на авторство!!!!!), например, выглядит так PendSV_Handler #if (__CORE__ == __ARM6M__) // Cortex-M0(+)/Cortex-M1 CPSID I // Prevent interruption during context switch MRS R0, PSP // Load process stack pointer to R0 SUBS R0, #32 // Adjust R0 to point to top of saved context in stack MOV R1, R0 // Preserve R0 (needed for os_context_switch_hook() call) STMIA R1!, {R4-R7} // Save low portion of remaining registers (r4-7) on process stack MOV R4, R8 // Move high portion of remaining registers (r8-11) to low registers MOV R5, R9 MOV R6, R10 MOV R7, R11 STMIA R1!, {R4-R7} // Save high portion of remaining registers (r8-11) on process stack // At this point, entire context of process has been saved PUSH {LR} // we must save LR (exc_return value) until exception return LDR R1, =os_context_switch_hook // call os_context_switch_hook(); BLX R1 // R0 is new process SP; ADDS R0, #16 // Adjust R0 to point to high registers (r8-11) LDMIA R0!, {R4-R7} // Restore r8-11 from new process stack MOV R8, R4 // Move restored values to high registers (r8-11) MOV R9, R5 MOV R10, R6 MOV R11, R7 MSR PSP, R0 // R0 at this point is new process SP SUBS R0, #32 // Adjust R0 to point to low registers LDMIA R0!, {R4-R7} // Restore r4-7 CPSIE I POP {PC} // Return to saved exc_return. Exception return will restore remaining context #elif (__CORE__ == __ARM7M__ || !defined(__ARMVFP__) ) // M3/M4 cores without FPU CPSID I // Prevent interruption during context switch MRS R0, PSP // PSP is process stack pointer STMDB R0!, {R4-R11} // Save remaining regs r4-11 on process stack // At this point, entire context of process has been saved PUSH {LR} // we must save LR (exc_return value) until exception return LDR R1, =os_context_switch_hook // call os_context_switch_hook(); BLX R1 // R0 is new process SP; LDMIA R0!, {R4-R11} // Restore r4-11 from new process stack MSR PSP, R0 // Load PSP with new process SP CPSIE I POP {PC} // Return to saved exc_return. Exception return will restore remaining context #else // Core with FPU (cortex-M4F) CPSID I // Prevent interruption during context switch MRS R0, PSP // PSP is process stack pointer TST LR, #0x10 // exc_return[4]=0? (it means that current process IT EQ // has active floating point context) VSTMDBEQ R0!, {S16-S31} // if so - save it. STMDB R0!, {R4-R11, LR} // save remaining regs r4-11 and LR on process stack // At this point, entire context of process has been saved LDR R1, =os_context_switch_hook // call os_context_switch_hook(); BLX R1 // R0 is new process SP; LDMIA R0!, {R4-R11, LR} // Restore r4-11 and LR from new process stack TST LR, #0x10 // exc_return[4]=0? (it means that new process IT EQ // has active floating point context) VLDMIAEQ R0!, {S16-S31} // if so - restore it. MSR PSP, R0 // Load PSP with new process SP CPSIE I BX LR // Return to saved exc_return. Exception return will restore remaining context #endif Также пришлось поменять кучу макросов в других файлов с GCC на IAR. Простенький тестовый пример (мигание двух светодиодов на платке дискавери) работает))) Мне интересно самому повозиться с портированием, но всё же интересно и знать, есть ли официальный универсальный порт для всех кортексов под IAR. Спасибо) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 19 марта, 2020 Опубликовано 19 марта, 2020 · Жалоба Насколько я помню, универсального порта для IAR нет. Последние коммиты в порт Cortex-M3 под IAR датированы летом 2012 года. Так что, если есть желание и силы, то предложение актуально :-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 19 марта, 2020 Опубликовано 19 марта, 2020 · Жалоба 1 hour ago, AHTOXA said: Так что, если есть желание и силы, то предложение актуально :-) Отлично! Возможно, приму участие. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 19 марта, 2020 Опубликовано 19 марта, 2020 · Жалоба Узкое место с этой функцией extern "C" NORETURN void os_start(stack_item_t *sp) { // Set PendSV lowest priority value #if (defined SHP3_WORD_ACCESS) SHPR3 |= (0xFF << 16); #else PendSvPriority = 0xFF; #endif #if (defined __ARMVFP__) FPCCR |= ASPEN | LSPEN; #endif asm volatile ( #if (!defined __ARMVFP__) // code without FPU " LDR R4, [%[stack], #(4 * 14)] \n" // Load process entry point into R4 " ADDS %[stack], #(4 * 16) \n" // emulate context restore #else " LDR R4, [%[stack], #(4 * 15)] \n" // Load process entry point into R4 " ADD %[stack], #(4 * 17) \n" // emulate context restore #endif " MSR PSP, %[stack] \n" // store process SP to PSP " MOVS R0, #2 \n" // set up the current (thread) mode: use PSP as stack pointer, privileged level " MSR CONTROL, R0 \n" " ISB \n" // Insert a barrier " LDR R1, =__init_system_timer \n" // " BLX R1 \n" // " CPSIE I \n" // Enable interrupts at processor level " BX R4 \n" // Jump to process exec() function : [stack]"+r" (sp) // output ); while(1); // suppress compiler warning "'noreturn' func does return" } Я её маленько поправил для IAR. В режиме полной оптимизации всё работает, но без оптимизации валится в хардфолт. Дело в том, что параметр sp, переданный в R0, перед вызовом функции записи в регистр SHPR3, компилятор сохраняет точненько в R4, который затем "портится" командой LDR. Следовательно, указатель стека первого процесса оказывается совершенно левым((( Когда оптимизация влкючена, вызова функции записи в регистр просто не проиходит, она инлайнится. Вот скрин дизассемблера с оптимизацией А вот без оптимизации Я не особо знаком с синтаксисом инлайн-ассемблера iar, но, полагаю, тут проблема написания кода. Буду думать, как решить красиво. Мне не очень нравится что без оптимизации код ломается(((( Сорри, за качество скринов, пишу не с рабочей машины( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 19 марта, 2020 Опубликовано 19 марта, 2020 · Жалоба Да, косяк. GCC таких трюков не делал, поэтому никто до сих пор не натыкался. Ну или по крайней мере никто не сообщал :-) Тут два выхода. Первый, простой - указать компилятору, что ассемблерная вставка портит регистры R0, R1 и R4: " BX R4 \n" // Jump to process exec() function : [stack]"+r" (sp) // output : // no input : "r0", "r1", "r4" // clobbers (На самом деле достаточно указать только R4, потому что остальные уже не важны). И второй, посложнее, избавиться от явного использования регистра R4 во вставке, заменив всё на параметры. Типа так: asm volatile ( #if (defined __SOFTFP__) // code without FPU " LDR %[tmp], [%[stack], #(4 * 14)] \n" // Load process entry point into R4 " ADD %[stack], #(4 * 16) \n" // emulate context restore #else " LDR %[tmp], [%[stack], #(4 * 15)] \n" // Load process entry point into R4 " ADD %[stack], #(4 * 17) \n" // emulate context restore #endif " MSR PSP, %[stack] \n" // store process SP to PSP " MOV R0, #2 \n" // set up the current (thread) mode: use PSP as stack pointer, privileged level " MSR CONTROL, R0 \n" " ISB \n" // Insert a barrier " LDR R1, =__init_system_timer \n" // " BLX R1 \n" // " CPSIE I \n" // Enable interrupts at processor level " BX %[tmp] \n" // Jump to process exec() function : [stack]"+r" (sp) // output : [tmp]"r" (0) // dummy param ); Мой GCC сделал из этого код на одну инструкцию длиннее (обнулил временный регистр). Но, думаю, ради надёжности и аккуратности кода можно это потерпеть. Надо будет исправить и в gcc-порте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба Странноватый этот IAR))) Сделал, как вы предложили, плюс избавился от явного использования остальных регистров (но также безуспешно пробовал и первоначальный вариант с избавлением только от R4), но всё равно не работает. asm volatile ( #if (!defined __ARMVFP__) // code without FPU " LDR %[tmp], [%[stack], #(4 * 14)] \n" // Load process entry point into R4 " ADDS %[stack], #(4 * 16) \n" // emulate context restore #else " LDR %[tmp], [%[stack], #(4 * 15)] \n" // Load process entry point into R4 " ADD %[stack], #(4 * 17) \n" // emulate context restore #endif " MSR PSP, %[stack] \n" // store process SP to PSP " MOVS %[ctrl], #2 \n" // set up the current (thread) mode: use PSP as stack pointer, privileged level " MSR CONTROL, %[ctrl] \n" " ISB \n" // Insert a barrier " LDR %[tmr], =__init_system_timer \n" // " BLX %[tmr] \n" // " CPSIE I \n" // Enable interrupts at processor level " BX %[tmp] \n" // Jump to process exec() function : [stack]"+r" (sp) // output : [tmp]"r" (0) // dummy value , [ctrl]"r" (0) // control register value , [tmr]"r" (0) // init timer procedure address ); Вот, что в дизассемблере со включенной оптимизацией. Компилятор использует R1 для сохранения адреса первой задачи. По условиям AAPCS функция не обязана сохранять этот регистр. И успешно его портит))) Уф. Либо работает только с оптимизацией, либо только без неё((( Что-то я пока запутался. Подумать надо. Пока видится вариант только переписать os_start всю на инлайн-ассемблере, либо в отдельном модуле. Но, главное, указать компилятору какие регистры использовать и сохранять в стеке в лоб. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба Ой, вы же первый вариант ещё предложили. Как-то я его сразу не испробовал) Чуть позже проверю! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба А, теперь вспоминаю. Я ведь не зря использовал R4, а не переменную в ассемблере. Именно потому, что вызываемая функция инициализации таймера имеет право портить R0-R3. Надо такие вещи записывать в комментариях. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба 1 hour ago, AHTOXA said: Я ведь не зря использовал R4, Я тоже к этому выводу в ходе экспериментов пришёл) @AHTOXA, предложенный вами вариант №1 заработал. Я проверил только на оптимизации "Balanced" и без оптимизации. Вот полный вариант функции extern "C" NORETURN void os_start(stack_item_t *sp) { // Set PendSV lowest priority value #if (defined SHP3_WORD_ACCESS) SHPR3 |= (0xFF << 16); #else PendSvPriority = 0xFF; #endif #if (defined __ARMVFP__) FPCCR |= ASPEN | LSPEN; #endif asm volatile ( #if (!defined __ARMVFP__) // code without FPU " LDR R4, [%[stack], #(4 * 14)] \n" // Load process entry point into R4 " ADDS %[stack], #(4 * 16) \n" // emulate context restore #else " LDR R4, [%[stack], #(4 * 15)] \n" // Load process entry point into R4 " ADD %[stack], #(4 * 17) \n" // emulate context restore #endif " MSR PSP, %[stack] \n" // store process SP to PSP " MOVS R0, #2 \n" // set up the current (thread) mode: use PSP as stack pointer, privileged level " MSR CONTROL, R0 \n" " ISB \n" // Insert a barrier " LDR R1, =__init_system_timer \n" // " BLX R1 \n" // " CPSIE I \n" // Enable interrupts at processor level " BX R4 \n" // Jump to process exec() function : [stack]"+r" (sp) // output : // no input : "r0", "r1", "r4" // clobbers ); while(1); // suppress compiler warning "'noreturn' func does return" } Спасибо вам! Я же думал, что проще уже вынести os_start в файл os_target_asm.S, переписав её полностью на ассемблере. Кстати, а ваш компилятор позволяет команды компилировать для Cortex-M0 без префикса S? Например, " MOVS R0, #2 \n" // set up the current (thread) mode: use PSP as stack pointer, privileged level у меня только так. Т.е. на MOV R0, #2 ругается. По мурзилке всё правильно со стороны IAR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба Ну и ладненько. Надо и в порте gcc тоже на всякий случай R4 внести в список clobbers. 54 минуты назад, haker_fox сказал: Кстати, а ваш компилятор позволяет команды компилировать для Cortex-M0 без префикса S? Например, В inline-ассемблерных вставках, судя по всему, разрешает. В ассемблерных файлах - нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба 56 minutes ago, AHTOXA said: В inline-ассемблерных вставках, судя по всему, разрешает. В ассемблерных файлах - нет. Ясно) Но, если быть откровенным, что-то мне инлайн-ассемблер всё равно не нравится) Субъективно, естественно. Модули на ассемблере вроде как-то серьезно выглядят. 57 minutes ago, AHTOXA said: Ну и ладненько. Надо и в порте gcc тоже на всякий случай R4 внести в список clobbers. Рад, что смог поспособствовать поиску бага. Сейчас текущий вариант оськи попробую на реальном проекте, котоырй по-маленьку растёт. Потом, можно будет думать о заливке в репозитаорий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба Уважаемый @AHTOXA, правильно ли я понимаю, что могу свою ветку fb-feature-iar-mx-port загрузить в репозитарий? Я сейчас только Cortex-M0 протестировал, и то на простой задаче. Возможно скоро смогу проверить на Cortex-M4F. Старался максимально придерживаться документа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 20 марта, 2020 Опубликовано 20 марта, 2020 · Жалоба Надеюсь, вы свою ветку ответвили от ветки develop? (Хотя в плане именно порта IAR ветки develop и master не отличаются, так что это не очень важно). Насколько я понимаю, загрузить напрямую не получится - нужно быть членом организации scmrtos Можете прислать pull request, мы его рассмотрим, и, если всё будет нормально, примем. Или напишите @dxp в личку, как вы называетесь на гитхабе, и он вас добавит в организацию. Тогда будете вести ветку прямо в репозитории. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться