Перейти к содержанию
    

Как отучить IAR использовать регистры FPU где не нужно?

А какая разница?...
Есть разница. У некоторых МК РОНы отображаются на память. И если в Вашем случае это так, то я хотел предложить создать по этому адресу volatile переменную, тогда компилятор не посягнул бы на эту область памяти - регистр.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Между тем в uCOS для портов на ARM под IAR повсеместно используется запрет на сохранение контекста FP.

Ошибся.

В uCOS-III опция OS_OPT_TASK_SAVE_FP есть , но для порта под Cortex-M4 не применяется.

Т.е. если компилятор объявил макрос __ARMVFP__ , то все задачи без исключения сохраняют контекст fpu.

Другое дело, что в startup файлах из bsp может случайно не взводится флаг FPCA в регистре CONTROL, допустим проигнорен вызов __iar_program_start, и прерывания по умолчанию не сохраняют контекст fpu.

 

Эт в MQX версии community большая проблема, там такая опция работает и реально блокирует сохранение контекста fpu при переключении задач, а FPCA сознательно не взводится.

Так они ускоряют переключение контекста.

 

Экспериментировал как-то насколько сохранение контекста fpu увеличивает расход процессорного времени в обычном режиме. Не обнаружил существенной разницы.

Однако на быстрых прерываниях ядра обслуживающих сэмплирование в токовой цепи моторов менее чем за 1 мкс все становится критичней.

И тут MQX работает умнее чем uCOS и прочие FreeRTOS-ы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что, флажок который говорит что FPU поюзали и его надо сохранить - отменили?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что, флажок который говорит что FPU поюзали и его надо сохранить - отменили?

Беда в том, что флажок не говорит. :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А какая разница? Контекст то ведь будет сохранять та же функция ОС, которая сохраняет и при вытеснении в тот же формат.
Пожалуй, вы правы. Тогда источником проблем остается только такой сценарий - задача, не сохраняющая регистры сопроцессора в момент копирования структуры через эти регистры прерывается другой задачей - либо законно использующей сопроцессор, либо такой же, которая в это время тоже решит скопировать структуру. Действительно, трудноотлавливаемый момент.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть разница. У некоторых МК РОНы отображаются на память. И если в Вашем случае это так, то я хотел предложить создать по этому адресу volatile переменную, тогда компилятор не посягнул бы на эту область памяти - регистр.

Я писал выше - у меня Cortex-M4. У него регистры никуда не отображаются.

 

Т.е. если компилятор объявил макрос __ARMVFP__ , то все задачи без исключения сохраняют контекст fpu.

Другое дело, что в startup файлах из bsp может случайно не взводится флаг FPCA в регистре CONTROL, допустим проигнорен вызов __iar_program_start, и прерывания по умолчанию не сохраняют контекст fpu.

И FPCA и ASPEN и LSPEN (в FPCCR) у меня сброшены. И сброшены не случайно, поверьте про них я знаю. Сброшены потому что в ISR-ах в этом проекте плавучку не использую.

Я не знаю как там дела обстоят в uCOS-III, у меня uCOS-II. И читать и понимать исходники я думаю что умею. Эта функция в uCOS-II вызывается при переключении активной задачи:

#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u)
void  OSTaskSwHook (void)
{

#if (OS_CPU_ARM_FP_EN > 0u)
   if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
       OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr);
   }

   if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
       OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr);
   }
#endif

#if OS_APP_HOOKS_EN > 0u
   App_TaskSwHook();
#endif
}
#endif

OS_CPU_HOOKS_EN, OS_TASK_SW_HOOK_EN, OS_CPU_ARM_FP_EN - все равны 1.

OS_CPU_FP_Reg_Push и OS_CPU_FP_Reg_Pop - тоже не пустые и делают то, что и полагается.

Обратите внимание на OS_TASK_OPT_SAVE_FP - именно этот флаг передаётся в аргументе prio (6-й бит) и говорит ОСи что задача юзает FPU и что нужно в сохраняемый/восстанавливаемый контекст для данной задачи включить регистры FPU.

Более того - одна из задач (Idle-задача) у меня имеет размер стека == 64 байта, т.е. - только-только чтобы сохранить регистры CPU, и если-бы туда сохранялись ещё и регистры FPU, то данные выше этого стека были бы снесены, а там весьма важные данные и они не портятся.

Да и отладчиком я пользоваться умею всё-таки... :laughing:

 

А что, флажок который говорит что FPU поюзали и его надо сохранить - отменили?

Когда FPU поюзала процедура копирования, то сохранять уже поздно.

 

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

Да, Вы правы, именно в таком случае. Когда задача копирует через FPU, то значит она в этот момент активная, а все остальные задачи выгружены в память (все их копии регистров FPU все находятся в памяти). И естественно в этом случае она не может эти данные попортить. Но вот её данные - попортить могут.

 

PS: Кстати - Ваше замечание навело меня на мысль, что в качестве костыля можно на время копирования структур запрещать прерывания (критическая секция).

Правда нет гарантии, что при копировании просто нескольких переменных, расположенных рядом, оптимизатор не захочет также прибегнуть к FPU. Или не копировании, а заполнении их константой. :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не знаю как там дела обстоят в uCOS-III, у меня uCOS-II. И читать и понимать исходники я думаю что умею.

За uCOS-II я не писал, как раз чтобы вам предоставить возможность высказаться.

 

Все идет к тому что надо переходить на mbed. Самая нативная RTOS.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все идет к тому что надо переходить на mbed. Самая нативная RTOS.

А толку? как это поможет? IAR, узрев её исходники, сразу поостерегётся своевольничать? B)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

PS: Кстати - Ваше замечание навело меня на мысль, что в качестве костыля можно на время копирования структур запрещать прерывания (критическая секция).

А я сразу подумал о таком решении, но постеснялся предлагать очевидное.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

PS: Кстати - Ваше замечание навело меня на мысль, что в качестве костыля можно на время копирования структур запрещать прерывания (критическая секция).

Именно так и пришлось делать в одном из проектов под ZYNQ, поскольку там компилятор в memcpy() использует FPU-регистры.

А где-то на сайте FreeRTOS даже читал, что действительно есть такой косяк. Вызываю в начале задачи vPortTaskUsesFPU() (даже забыл, что и во FreeRTOS можно указать задаче, использует ли она FPU или нет), и все равно все memcpy() защищаю критической секцией.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А толку? как это поможет? IAR, узрев её исходники, сразу поостерегётся своевольничать? B)

Да нет, просто в IAR 8.30 появился неплохой плагин под mbed. Можно уже нормально юзать. А там самый короткий переключатель контекста.

 

Кстати, в версии 8.30 у меня не получилось заставить использовать fpu при копировании структур.

Так что тревога отменяется.

 

 

А я сразу подумал о таком решении, но постеснялся предлагать очевидное.

Если речь идет об ISR уровня ядра длительностью в 0.5 мкс и джитером 0.1 мкс , то такой путь неприемлем.

Хотя кому в голову придет в таких ISR копировать структуры!?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И зачем их копировать? Для малых структур я копирую поэлементно. А большие копирую через указатели на int, приведя к ним адреса структур исходной и назначения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И зачем их копировать? Для малых структур я копирую поэлементно. А большие копирую через указатели на int, приведя к ним адреса структур исходной и назначения.

Это еще зачем?

Ведь структурные типы можно присваивать друг другу. Например

typedef struct
{...}TMyStruct;

TMyStruct s1, s2;
...
s1 = s2;

Наглядно, читабельно и понятно. Без всяких приведений на int и поэлементных копирований...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И зачем их копировать? Для малых структур я копирую поэлементно. А большие копирую через указатели на int, приведя к ним адреса структур исходной и назначения.

Умный оптимизатор может объединить ваши соседние копирования в более крупное одно. И получится то же самое. И не только структуры, можно предположить что любые рядом расположенные копирования смежных переменных: оптимизатору ведь по-барабану - единая это структура или просто несколько переменных, если адреса в памяти расположены смежно и нет volatile.

Здесь ключевой момент (как я показывал вначале): чтобы размер структуры был кратен 32 байтам - тогда видимо и используется FPU.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...