Jump to content

    
Sign in to follow this  
AHTOXA

Выпущена scmRTOS 4.0.

Recommended Posts

Запустил на F205, настройки такие же (72 МГц, 2 waitstate на флеши), IAR 6.30, получилось 2.38 мкс.

Наконец запустил свою плату на F207, IAR 6.30 + TNКernel

72МНz, 2WS, IAR6.30 - 2.16 мкс

120МНz, 3WS, IAR6.30 - 1.30 мкс

Да, еще измерил обратное переключение при засыпании приоритетной задачи на ожидании объекта - 1.63 мкс (для 120МГц).

 

 

Продолжим замеры? :)

Замерил скорость переключения контекста на STM32F4DISCOVERY.

168 МГц, 5ws.

Получилось 964 нс. Это просто ракета! :)

STM32F4DISCOVERY у меня тоже есть - в столе лежит :), но руки дойдут не скоро :(. И не думаю что TNKernel на нем на 168МГц из микросекунды "выбежит", поэтому в целом согласен - новая версия SCM чуточку быстрее.

 

Share this post


Link to post
Share on other sites
Вопрос скорее по порту GCC ARM, навеян этим. Из каких соображений не используется структура .init секций?
Такой механизм я реализовывал в своем первом стартапе для ARM7. И после просмотра результатов первой же сборки исходника удалил, ибо конкретно для ARM использовать их так, как это сделано в AVR, невозможно - ассемблер после функции размещает константы для команд типа LDR R0, =main. Поэтому закончив выполнение кода функции процессор должен выполнить команду перехода чтобы не начать исполнять эти константы как код. А переход надо делать на метку, расположенную в начале следующей функции. И летит к чертям вся красота получения линейного кода путем размещения __naked__ функций в .init - секциях, ибо первая функция должна начинаться меткой на которую делался переход из предыдущей секции, а заканчиваться переходом на метку, с которой начинается следующая функция и т.д. В общем случае раздельной компиляции имя метки начала следующей функции неизвестно.

 

А в секции .ctors или .init_array хранится просто массив указателей на конструкторы, с ним никаких подобных проблем нет. Можно, конечно, и .init-секции сделать массивами указателей, но есть ли в этом смысл? Сейчас можно всю необходимую инициализацию разместить в __low_level_init().

Share this post


Link to post
Share on other sites

Наблюдаю непонятное поведение проекта 1-EventFlag для AVR\IAR (компилировал в IAR6.10, поменял выходной формат на ubrof8, запускал в AVRStudio 4).

Поставил точки прерывания на строчках:

DRIVER(PROC1,OUT); (1)


DRIVER(PROC2,OUT); (2)


DRIVER(PROC3,OUT); (3)

 

Странность в том что после старта программа проходит по точкам не 1-2-3, а 1-3-2, что при Kernel.ReadyProcessMap равном 0x0E быть вроде как не должно.

И шо це таке?

 

Mega168.7z

Share this post


Link to post
Share on other sites
Системный таймер (работающий от часового кварца например) может быть источником пробуждения.

А system_timer_user_hook можно бы использовать как функцию где включается периферия и кварц после сна. И чем раньше system_timer_user_hook будет вызван, тем лучше, так как после пробуждения МК работает от медленного RC.

 

 

Это не столько связано с включением/отключением кварца, сколько с переключением источника тактирования. Например я при idle переключаю основной CLK с 48MHz на 32kHz/1kHz (не могу я уснуть полностью - кое что делать приходится), по таймеру получаю управление в функцию хука, которая производит обратное действие, но перепланировка rtos при этом выполняется раньше, еще при работе от низкочастотного источника синхронизации. Получаем лишние задержки.

 

_Артём_ все правильно написал.

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

Share this post


Link to post
Share on other sites
Зарегистрируйтесь здесь, скачайте, установите и сравните.

Не вижу смысла. Я уже парой постов выше показал, что arm-gcc этого не поддерживает и не поддерживал никогда (.ctors, затем сразу .init_array). И Сергей Борщ далее написал, что просто не получается нормально это сделать. А вы продолжаете упорствовать (причём даже не попробовав!).

Share this post


Link to post
Share on other sites
Не вижу смысла. Я уже парой постов выше показал, что arm-gcc этого не поддерживает и не поддерживал никогда (.ctors, затем сразу .init_array). И Сергей Борщ далее написал, что просто не получается нормально это сделать. А вы продолжаете упорствовать (причём даже не попробовав!).

Вы правы! Только init.

Я принял за .init секции это

extern const struct __cs3_region __cs3_regions[];

и

/* Initialize memory */

for (regions = __cs3_region_num, rptr = __cs3_regions; regions--; rptr++)

{

long long *src = (long long *)rptr->init;

long long *dst = (long long *)rptr->data;

.......

.....

}

из файлов cs3.h и start_c.c . Которых нет в lite версии CodeSourcery.

В lite нет и файлов по таким маскам *.cs3 и *17*.*

 

Share this post


Link to post
Share on other sites
Наконец запустил свою плату на F207, IAR 6.30 + TNКernel

72МНz, 2WS, IAR6.30 - 2.16 мкс

120МНz, 3WS, IAR6.30 - 1.30 мкс

Да, еще измерил обратное переключение при засыпании приоритетной задачи на ожидании объекта - 1.63 мкс (для 120МГц).

 

STM32F4DISCOVERY у меня тоже есть - в столе лежит :), но руки дойдут не скоро :(. И не думаю что TNKernel на нем на 168МГц из микросекунды "выбежит", поэтому в целом согласен - новая версия SCM чуточку быстрее.

Где ж быстрее. У меня на 205-ом при 72МГц получается 2.25 мкс, а у вас 2.16. TNKernel в вашей редакции - чемпион! :)

 

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

Перенёс в портах Blackfin и MSP430/IAR. В остальные порты без спросу лезть не стал.

Share this post


Link to post
Share on other sites
Странность в том что после старта программа проходит по точкам не 1-2-3, а 1-3-2, что при Kernel.ReadyProcessMap равном 0x0E быть вроде как не должно. И шо це таке?
Пример 1-EventFlag в примерх для AVR/IAR/MEGA немного усложнён по сравнению с 3.10 и приведён в соответствие с примером для AVR/GCC/MEGA (и для CortexM3/GCC/LPC17XX сразу сделан так). Краткое описание вариантов компиляции находится в комментарии в начале файла main.cpp:

59     //---------------------------------------------------------------------------
60     // Sample compilation options
61     //
62     // PROC2_HIGHER_THAN_PROC3
63     // 1 - Proc2 ef.signal() wakes up Proc3, but Proc3 becomes active after Proc2 sleep().
64     // Execution path:
65     // IdleProcess -> Proc2 -> Proc3 -> IdleProcess
66     // 0 - Proc2 ef.signal() wakes up Proc3 and switches execution from Proc2 to Proc3.
67     // Execution path:
68     // IdleProcess -> Proc2 -> Proc3 -> Proc2 -> IdleProcess
69     //
70     // PROC2_LONG_PULSE
71     // 1 - PROC2 pulse long. Good scope waveforms for 5-ms timebase (PROC2-PROC3 "generator" overview)
72     // 0 - PROC2 pulse short, defined by ef.Signal() execution time and PROC2-PROC3 task switching.
73     
74     #define PROC2_HIGHER_THAN_PROC3 0
75     #define PROC2_LONG_PULSE 0

При #define PROC2_HIGHER_THAN_PROC3 0 процессы и должны получить управление в первый раз в порядке 1-3-2.

И вообще — Вам сюда http://real.kiev.ua/scmrtos/1-eventflag/ (этот линк есть в файле readme.txt в архиве).

Share this post


Link to post
Share on other sites
Пример 1-EventFlag в примерх для AVR/IAR/MEGA немного усложнён по сравнению с 3.10 и приведён в соответствие с примером для AVR/GCC/MEGA (и для CortexM3/GCC/LPC17XX сразу сделан так). Краткое описание вариантов компиляции находится в комментарии в начале файла

 

При #define PROC2_HIGHER_THAN_PROC3 0 процессы и должны получить управление в первый раз в порядке 1-3-2.

И вообще — Вам сюда http://real.kiev.ua/scmrtos/1-eventflag/ (этот линк есть в файле readme.txt в архиве).

 

Спасибо за линк и пояснение.

 

Share this post


Link to post
Share on other sites
Перенёс в портах Blackfin и MSP430/IAR. В остальные порты без спросу лезть не стал.
Несколько странно начинает выглядеть ENABLE_NESTED_INTERRUPTS(); перед самым выходом из прерывания. Конечно, оно и ожидающее прерывание не будет ждать перепланирования. Может оказаться и так, что не будет лишнего перепланирования делаться , так как то ожидающее прерывание что-то более приоритетное разбудит.

Но всё равно выглядит странно :-) Тогда уж надо вложенные прерывания разрешить до того, как Kernel.system_timer(); будет обрабатывать поля таймаутов процессов.

 

Пока просто переставляю, так как это разрешение всё равно конфигурируется пользователем. Но тут есть о чём подумать.

Share this post


Link to post
Share on other sites
Несколько странно начинает выглядеть ENABLE_NESTED_INTERRUPTS(); перед самым выходом из прерывания. Конечно, оно и ожидающее прерывание не будет ждать перепланирования. Может оказаться и так, что не будет лишнего перепланирования делаться , так как то ожидающее прерывание что-то более приоритетное разбудит.

Но всё равно выглядит странно :-) Тогда уж надо вложенные прерывания разрешить до того, как Kernel.system_timer(); будет обрабатывать поля таймаутов процессов.

 

Пока просто переставляю, так как это разрешение всё равно конфигурируется пользователем. Но тут есть о чём подумать.

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

 

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

 

С третьей стороны, это вообще порт, тут на усмотрение автора порта.

 

С четвёртой стороны, учитывая всё вышесказанное, просится вообще этот ISR вытащить на уровень проекта - там кода три строчки. Раз выбор и настройка таймера отданы на откуп пользователю, то и реализация его ISR тоже логически должна быть на этом уровне. Хотя это не везде красиво - на некоторых платформах выбора таймера как такового вовсе и нет - он встроен в ядро (Blackfin, Cortex-M).

 

В общем, надо обсуждать, взвешивать. Все мнения приветствуются.

Share this post


Link to post
Share on other sites

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

 

Вариант убрать разрешение (а в случае CortexM и STM8 — так и запрещения, если не разрешены) вложенных прерываний из обработчика и переложить на хук вроде нормальный. Есть только там один момент...

В OS_Target.h настраивается

#define SYS_TIMER_CRIT_SECT() TCritSect cs

Но если прерывания во время обработчика не_разрешены (для, к примеру, AVR) или запрещены (по отсутствию разрешения — для имеющих автоматически разрешённые вложенные), то эта крит. секция не нужна и только зря занимает код и время.

 

Это уже залазим на территорию (лишних) запретов прерываний, которая сама по себе требует особого внимания. Некоторые идеи есть, но это позже.

 

Так что здесь и сейчас можно оставить как есть, так как для не имеющих вложенность прерываний они обычно и не разрешаются в таймерном прерівании (SYS_TIMER_CRIT_SECT() пустой).

 

А для имеющих — не запрещаются (и SYS_TIMER_CRIT_SECT() не пустой, но она такой и нужен). И где там стоит ENABLE NESTED — всё равно, так как теперь пустой он.

 

И пока подумать.

Share this post


Link to post
Share on other sites
Да, тоже обратил внимание на это.

Выглядит действительно как-то странно.

 

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

На процах не поддерживающих вложенных прерываний конечно трудно организовать их вложенность, да ещё если Ось используется, это да.

Но не менее странно видеть запрет прерываний на процессорах с реализованным NVIC (например Cortex-M3): низкопроритетное прерывание PendSVC_ISR запрещает все прерывания на ~80 тактов.

Логично было бы запретить только прерывания работающие в контексте ОСи (там где это нетрудно сделать: например в CM3 это возможно в CM0 нет).

Может быть от такого частичного запрета толку и мало, но иначе остаётся некоторый осадок - в Cortex-е полезную фичу реализовали, а мы её взяли и похерили.

 

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

Можно добавить ещё один макрос в scmRTOS_CONFIG.h:

#define scmRTOS_USER_DEFINED_SYSTICK_ENABLE 0//1

 

Если он 0 - используется обработчик и функция инициализации из OS_Target_cpp.cpp. Это - стандарный случай для ~80% проектов.

Иначе - пусть пользователь сам решает, что делать с системным таймером.

 

Хотя это не везде красиво - на некоторых платформах выбора таймера как такового вовсе и нет - он встроен в ядро (Blackfin, Cortex-M).

 

Выбор есть в большинстве случаях, но выбирать не нужно, так как и так всё устраивает: у какого-нибудь CM3/CM0 таймеров как правило несколько и любой годится на роль Systick-а, но в большинстве случаев и Systick годится.

А вот в меньшинстве случаев Systick не годится: например нужно увести процессор не в idle, а в "deep sleep" с выключением тактирования всего что можно. Тут Systick работать не сможет, а нестандарный таймер можно запустить от часового кварца и сделать системным таймером.

Share this post


Link to post
Share on other sites

Согласен с _Артём_ - например для случая с CM3 от energymicro - поскольку SysTick для кортексов внесен в ядро, то он с отключением тактирования ядра он тоже вырубается, а специфический маложрущий таймер LETIMER отлично работает от внутреннего килогерца. Для такого случая нужно давать возможность пользователю делать системный таймер как ему захочется. Понятно, что можно всегда допилить ручками до любый своих требований.

Для сравнения - в TNKernel системный таймер вообще вынесен за операционку. Это дает некоторую свободу в реализации системного прерывания (тут тебе и хуки и вложенный прерывания и т.п)

Share this post


Link to post
Share on other sites
Согласен с _Артём_ - например для случая с CM3 от energymicro - поскольку SysTick для кортексов внесен в ядро, то он с отключением тактирования ядра он тоже вырубается, а специфический маложрущий таймер LETIMER отлично работает от внутреннего килогерца. Для такого случая нужно давать возможность пользователю делать системный таймер как ему захочется. Понятно, что можно всегда допилить ручками до любый своих требований.

Для сравнения - в TNKernel системный таймер вообще вынесен за операционку. Это дает некоторую свободу в реализации системного прерывания (тут тебе и хуки и вложенный прерывания и т.п)

Вообще-то, в scmRTOS к потрохам ОСи привязана только функция TKernel::system_timer(), реализацию которой на откуп пользователю не отдают. Сам же таймер может быть любым, никаких завязок на него нет, о чём прямо сказано в документации. Если посмотреть внимательно на порты AVR, MSP430, то можно заметить, что и выбор, и код обслуживания (настройка, запуск) таймера полностью вынесены на уровень проекта - пользователь сам должен позаботиться об этом.

 

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

 

Что касается собственной реализации обработчика системного таймера, то можно применить стандартный финт для подмены функции на этапе линковки. Вариант, идущий в составе порта, объявить с атрибутом weak, тогда в случае появления в проекте функции с таким же именем, последняя и будет прилинкована в финальном исполняемом.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this