Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Выпущена scmRTOS 4.0.
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
Страницы: 1, 2, 3, 4, 5, 6
mdmitry
Цитата(AHTOXA @ Apr 28 2012, 07:37) *
Не вижу смысла. Я уже парой постов выше показал, что 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*.*
dxp
QUOTE (VslavX @ Apr 28 2012, 02:46) *
Наконец запустил свою плату на F207, IAR 6.30 + TNКernel
72МНz, 2WS, IAR6.30 - 2.16 мкс
120МНz, 3WS, IAR6.30 - 1.30 мкс
Да, еще измерил обратное переключение при засыпании приоритетной задачи на ожидании объекта - 1.63 мкс (для 120МГц).

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

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

QUOTE (dxp @ Apr 28 2012, 10:18) *
Уважительная причина и внятное объяснение, спасибо. Если у участников проекта нет возражений, будем переносить.

Перенёс в портах Blackfin и MSP430/IAR. В остальные порты без спросу лезть не стал.
ReAl
Цитата(_Артём_ @ Apr 28 2012, 00:48) *
Странность в том что после старта программа проходит по точкам не 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 в архиве).
_Артём_
Цитата(ReAl @ Apr 28 2012, 19:15) *
Пример 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 в архиве).


Спасибо за линк и пояснение.
ReAl
Цитата(dxp @ Apr 28 2012, 12:43) *
Перенёс в портах Blackfin и MSP430/IAR. В остальные порты без спросу лезть не стал.
Несколько странно начинает выглядеть ENABLE_NESTED_INTERRUPTS(); перед самым выходом из прерывания. Конечно, оно и ожидающее прерывание не будет ждать перепланирования. Может оказаться и так, что не будет лишнего перепланирования делаться , так как то ожидающее прерывание что-то более приоритетное разбудит.
Но всё равно выглядит странно :-) Тогда уж надо вложенные прерывания разрешить до того, как Kernel.system_timer(); будет обрабатывать поля таймаутов процессов.

Пока просто переставляю, так как это разрешение всё равно конфигурируется пользователем. Но тут есть о чём подумать.
dxp
QUOTE (ReAl @ Apr 29 2012, 21:47) *
Несколько странно начинает выглядеть ENABLE_NESTED_INTERRUPTS(); перед самым выходом из прерывания. Конечно, оно и ожидающее прерывание не будет ждать перепланирования. Может оказаться и так, что не будет лишнего перепланирования делаться , так как то ожидающее прерывание что-то более приоритетное разбудит.
Но всё равно выглядит странно :-) Тогда уж надо вложенные прерывания разрешить до того, как Kernel.system_timer(); будет обрабатывать поля таймаутов процессов.

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

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

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

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

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

В общем, надо обсуждать, взвешивать. Все мнения приветствуются.
ReAl
Порт-то порт, но унификация желательна. Тем более не считаю нужным выносить обработчик на уровень проекта — в подавляющем большинстве случаев он просто будет копироваться из проекта в проект без изменений. Оставшиеся вполне покрываются настройкой вектора в 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 — всё равно, так как теперь пустой он.

И пока подумать.
_Артём_
Цитата(dxp @ Apr 30 2012, 08:27) *
Да, тоже обратил внимание на это.

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

Цитата(dxp @ Apr 30 2012, 08:27) *
Другой стороны, я вообще противник вложенных прерываний на процах, которые не поддерживают такую возможность аппаратно - как показывает практика, толку он неё чуть, а гемора может создать прилично.

На процах не поддерживающих вложенных прерываний конечно трудно организовать их вложенность, да ещё если Ось используется, это да.
Но не менее странно видеть запрет прерываний на процессорах с реализованным NVIC (например Cortex-M3): низкопроритетное прерывание PendSVC_ISR запрещает все прерывания на ~80 тактов.
Логично было бы запретить только прерывания работающие в контексте ОСи (там где это нетрудно сделать: например в CM3 это возможно в CM0 нет).
Может быть от такого частичного запрета толку и мало, но иначе остаётся некоторый осадок - в Cortex-е полезную фичу реализовали, а мы её взяли и похерили.

Цитата(dxp @ Apr 30 2012, 08:27) *
С четвёртой стороны, учитывая всё вышесказанное, просится вообще этот ISR вытащить на уровень проекта - там кода три строчки. Раз выбор и настройка таймера отданы на откуп пользователю, то и реализация его ISR тоже логически должна быть на этом уровне.

Можно добавить ещё один макрос в scmRTOS_CONFIG.h:
Код
#define scmRTOS_USER_DEFINED_SYSTICK_ENABLE 0//1


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

Цитата(dxp @ Apr 30 2012, 08:27) *
Хотя это не везде красиво - на некоторых платформах выбора таймера как такового вовсе и нет - он встроен в ядро (Blackfin, Cortex-M).


Выбор есть в большинстве случаях, но выбирать не нужно, так как и так всё устраивает: у какого-нибудь CM3/CM0 таймеров как правило несколько и любой годится на роль Systick-а, но в большинстве случаев и Systick годится.
А вот в меньшинстве случаев Systick не годится: например нужно увести процессор не в idle, а в "deep sleep" с выключением тактирования всего что можно. Тут Systick работать не сможет, а нестандарный таймер можно запустить от часового кварца и сделать системным таймером.
Nixon
Согласен с _Артём_ - например для случая с CM3 от energymicro - поскольку SysTick для кортексов внесен в ядро, то он с отключением тактирования ядра он тоже вырубается, а специфический маложрущий таймер LETIMER отлично работает от внутреннего килогерца. Для такого случая нужно давать возможность пользователю делать системный таймер как ему захочется. Понятно, что можно всегда допилить ручками до любый своих требований.
Для сравнения - в TNKernel системный таймер вообще вынесен за операционку. Это дает некоторую свободу в реализации системного прерывания (тут тебе и хуки и вложенный прерывания и т.п)
dxp
QUOTE (Nixon @ May 1 2012, 16:13) *
Согласен с _Артём_ - например для случая с CM3 от energymicro - поскольку SysTick для кортексов внесен в ядро, то он с отключением тактирования ядра он тоже вырубается, а специфический маложрущий таймер LETIMER отлично работает от внутреннего килогерца. Для такого случая нужно давать возможность пользователю делать системный таймер как ему захочется. Понятно, что можно всегда допилить ручками до любый своих требований.
Для сравнения - в TNKernel системный таймер вообще вынесен за операционку. Это дает некоторую свободу в реализации системного прерывания (тут тебе и хуки и вложенный прерывания и т.п)

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

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

Что касается собственной реализации обработчика системного таймера, то можно применить стандартный финт для подмены функции на этапе линковки. Вариант, идущий в составе порта, объявить с атрибутом weak, тогда в случае появления в проекте функции с таким же именем, последняя и будет прилинкована в финальном исполняемом.
AHTOXA
Да, это особенность портов для Cortex-M3. Специальный таймер в ядре - грех было не использовать.
Теперь понимаю, что это не всегда удобно. Совсем выносить настройку прерывания на уровень проекта очень неохота - придётся дописывать инициализацию во все имеющиеся проекты.
Идея с WEAK мне кажется более подходящей. Постараюсь на днях опробовать этот вариант.
dxp
QUOTE (AHTOXA @ May 2 2012, 01:33) *
Да, это особенность портов для Cortex-M3. Специальный таймер в ядре - грех было не использовать.
Теперь понимаю, что это не всегда удобно. Совсем выносить настройку прерывания на уровень проекта очень неохота - придётся дописывать инициализацию во все имеющиеся проекты.
Идея с WEAK мне кажется более подходящей. Постараюсь на днях опробовать этот вариант.

Для того, чтобы подменить таймер, достаточно, как я понимаю, указать другой ISR. Т.е. даже в имеющейся реализации можно написать просто свой обработчик прерываний по образу и подобию в проекте, а ISR таймера ядра залочить. Ничего в сорцах ОС править не надо. Поправь, если ошибаюсь.
AHTOXA
Всё ещё проще! sm.gif
Для переопределения источника прерывания надо всего лишь передвинуть обработчик SystemTimer_ISR в таблице векторов и дописать инициализацию.
Это в случае, если устраивает имеющийся обработчик. Если не устраивает (например, надо в обработчике сбрасывать флаг прерывания), то делаем так (пример для TIM2 в STM32):

1. В таблице векторов прерываний переименовываем SystemTimer_ISR во что-то другое (чтобы не вызывался штатный осёвый обработчик);
2. В scmRTOS_TARGET_CFG.h дописываем:
Код
namespace OS
{
    extern "C" void TIM2_IRQHandler();
}


3. Где-то в проекте вписываем новый обработчик:
Код
extern "C" void OS::TIM2_IRQHandler()
{
    if (TIM2->SR & TIM_SR_UIF)
    {
        scmRTOS_ISRW_TYPE ISR;
        TIM2->SR = ~TIM_SR_UIF;

        Kernel.system_timer();

#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
        system_timer_user_hook();
#endif
    }
}


4. Где-то до запуска run() инициализируем этот таймер (не забываем назначить ему наименьший приоритет!).

Вроде всёsm.gif
ReAl
Цитата(AHTOXA @ May 2 2012, 11:40) *
Вроде всёsm.gif
«Та не»™
Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

Так что таки надо какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h.
Поскольку это касается исключительно этого порта, стоит ли в scmRTOS_defs.h вносить проверку?
dxp
QUOTE (ReAl @ May 3 2012, 19:35) *
«Та не»™
Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

Так что таки надо какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h.
Поскольку это касается исключительно этого порта, стоит ли в scmRTOS_defs.h вносить проверку?

А можно и не выносить, а просто вырубить в main. Пара инструкций никому плохо не сделает. Мне кажется, что нормальное решение - для подавляющего большинства проектов годится вариант, который по умолчанию в порте, а для тех редких случаев, где хочется заменить системный таймер на другой, это решается несколькими командами на уровне проекта.
ReAl
В том-то и дело, что в main() не получится — инициализация проходит в os_start(), которая вызывается из OS::run().
dxp
QUOTE (ReAl @ May 3 2012, 20:08) *
В том-то и дело, что в main() не получится — инициализация проходит в os_start(), которая вызывается из OS::run().

Действительно, затупил я. sm.gif Да, тогда без вмешательства в os_start() красиво, по ходу, не сделать.
Сергей Борщ
QUOTE (ReAl @ May 3 2012, 16:08) *
инициализация проходит в os_start()
Так может быть вынести ее оттуда, как и в остальных портах? Я предпочитаю всю инициализацию делать в одном месте, это имеет свои плюсы - только в это мето нужно "донести" #define с частотами. А с этим обрывком инициализации в os_start() стройная картина рушится. Да и дополнительные определения констант там совсем не красят код, в то время как их же можно красиво написать с символическими именами в любом месте C++ -исходника.
AHTOXA
Цитата(ReAl @ May 3 2012, 18:35) *
«Та не»™
Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

Да пусть молотит, он нам не мешает, поскольку мы переименовали обработчик его прерывания.
Если не нужен - потом в наиболее приоритетной задаче при старте отрубить, и всё. В общем, корявенько, но возможноsm.gif
Цитата(Сергей Борщ @ May 3 2012, 23:27) *
Так может быть вынести ее оттуда, как и в остальных портах?

Вот этого делать очень неохота - придётся дописывать эту инициализацию в кучу проектов.
Надо как-то придумать, чтоб по умолчанию было поведение как сейчас. Какой-нибудь
WEAK start_systimer(), что ли. Ну или
Цитата(ReAl @ May 3 2012, 18:35) *
какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h.
ReAl
Цитата(AHTOXA @ May 3 2012, 21:18) *
Да пусть молотит, он нам не мешает, поскольку мы переименовали обработчик его прерывания.
Что-то я не понял. Прерывание-то разрешено в регистрах NVIC.
Цитата
1. В таблице векторов прерываний переименовываем SystemTimer_ISR во что-то другое (чтобы не вызывался штатный осёвый обработчик);
Без обработчика влетит в Default_Handler()

Тут разве что это «что-то другое» состоит из функции, запрещающей назад прерывание, сбрасывая NVIC_ST_CTRL_INTEN.

-------------------------------------
Цитата(_Артём_ @ Apr 10 2012, 17:11) *
Все прерывания с приоритетом выше configKERNEL_INTERRUPT_PRIORITY не запрещаются никогда, но работают без использования ОСи. NVIC CM3 позволяет сделать подобное.
Но есть ли в этом смысл? Или оно не надо никому?
https://groups.google.com/group/scmrtos-ru/...c21f94515?hl=ru
_Артём_
Цитата(ReAl @ May 3 2012, 15:35) *
Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

Во как!
А я его зачем-то в main-е инициализирую до вызова OS::run(). По аналогии с АВР наверное.
А он потом ещё раз инициализируется.
_Артём_
Цитата(ReAl @ May 3 2012, 22:27) *


Пришла такая мысль:
Код
class TCritSect
{
public:
    TCritSect () {
    // запрет всех прерываний
    }
#if (scmRTOS_USER_DEFINED_CRITSECT_ENABLE==1)
    TCritSect(enum INT_PRIORITY level) {
        // запрет всех кроме указанных
    };
#endif    
    ~TCritSect() {
        // восстановление в изначальное состояние
    }

private:
    enabled_level_t  EnabledLevels;
};
AHTOXA
Цитата(ReAl @ May 4 2012, 01:27) *
Что-то я не понял. Прерывание-то разрешено в регистрах NVIC.
Без обработчика влетит в Default_Handler()

Не без обработчика, а с другим обработчиком sm.gif
То есть, если пользователю нужен SysTick, то он уже есть и инициализирован. А если не нужен - то пустой обработчик. Или
Цитата(ReAl @ May 4 2012, 01:27) *
состоит из функции, запрещающей назад прерывание, сбрасывая NVIC_ST_CTRL_INTEN.

dxp
QUOTE (_Артём_ @ May 4 2012, 08:10) *
Пришла такая мысль:
CODE
class TCritSect
{
public:
    TCritSect () {
    // запрет всех прерываний
    }
#if (scmRTOS_USER_DEFINED_CRITSECT_ENABLE==1)
    TCritSect(enum INT_PRIORITY level) {
        // запрет всех кроме указанных
    };
#endif    
    ~TCritSect() {
        // восстановление в изначальное состояние
    }

private:
    enabled_level_t  EnabledLevels;
};

И как это поможет? Этим можно пилотировать в своём коде, который пишется в данный момент. Но критические секции в коде ОС останутся без изменений.

По поводу таймера. Мне казалось, что самым правильным решением было бы не завязываться на аппаратуру таймера в коде ОС и вынести всю инициализацию на уровень проекта. Там реально несколько строчек. Зато никаких вопросов не возникает. Я так и делал в порте для Blackfin'а, хотя там тоже есть специальный таймер в ядре. Как сейчас правильнее поступить, даже не знаю.
ReAl
Цитата(_Артём_ @ May 4 2012, 04:10) *
Код
#if (scmRTOS_USER_DEFINED_CRITSECT_ENABLE==1)
    TCritSect(enum INT_PRIORITY level) {
        // запрет всех кроме указанных
    };
#endif
Во-первых, как уже написал Гарри, запрещающий все конструктор без аргументов ничего не поменяет в работе ОС, а это была цель. Во-вторых, этот enum у всех будет свой (у Cortex оно вообще от проекта к проекту реально плавать будет). Где-то там в обсуждениях в группе я об этом писал — «стандартизовать» можно максимум имя для этого enum. Так что сейчас надо просто в scmRTOS_TARGET_CFG.h написать:
Код
#define scmRTOS_USER_DEFINED_CRITSECT_ENABLE 1
// как нужно автору проекта в данном проекте
enum TIsrPriority {     ipNone = ..., ipXXX = ..., ipYYY = ..., ipAll = ... };

const TIsrPriority  ipOsLevel = ipXXX;

class TCritSect {
public:
    // и TCritSect cs в ОС отработает с этим уровнем.
    TCritSect(TIsrPriority level = ipOsLevel) {
        // запрет всех кроме указанных
    };
...
};

Для STM8, к примеру, можно и сразу в порте так сделать, там число уровней фиксировано. Только
  • enum нужно в OS_Target.h определить выше включения scmRTOS_TARGET_CFG.h
  • Дабы не плодить #define/#ifdef — константу const TIsrPriority ipOsLevel обязать задавать в scmRTOS_TARGET_CFG.h
  • Сам такой «приоритетный» класс задать в OS_Target.h определить ниже включения scmRTOS_TARGET_CFG.h.

Но пока это не сделано, каждый может подсунуть своё (у меня с портом STM8 вообще пауза — и у меня времени нет, и тот, кто попросил порт сделать — свою дискавери-платку забрал назад laughing.gif ).
AHTOXA
Про пользовательский системный таймер. Сделал так:
Инициализацию таймера вынес в WEAK-функцию init_system_timer().
Переименовал SystemTimer_ISR() в Default_SystemTimer_ISR(), а SystemTimer_ISR() объявил WEAK-алиасом для неё.
То есть, если ничего не трогать, то всё работает как было.
Теперь, чтобы перейти на свой альтернативный системный таймер, надо:
  • написать свою функцию init_system_timer() (extern "C");
  • (опционально) написать свой обработчик прерывания таймера SystemTimer_ISR();
  • перенести в таблице векторов SystemTimer_ISR() на место нужного вектора.

Мне кажется, что это достаточно удобно. Если не будет замечаний, то я запилю это в транк.
ReAl
На мой взгляд — нормально. Лучше очередного #define.
AHTOXA
Окей, запилил (rev 539) sm.gif

Пример использования будет на днях.
ReAl
Думаю, отдельный пример не нужен, просто в каком-то из существующих реализовать на другом таймере и описать это в комментариях к примерам. Как прерывание SPM либо компаратора для переключения контекстов в примерах AVR.
AHTOXA
Да, я так и хотел. Просто как раз сейчас готовлю примеры для F2xx, вот заодно и приурочу.
AHTOXA
Залил в репозиторий примеры для STM32F2XX (пока три штуки). Пример 2-Message сделан на альтернативном таймере.
(функцию init_system_timer() я, подумав немного, переименовал в __init_system_timer(), ибо она в какой-то мере системная).

Заодно замерил скорость.
Цитата(VslavX @ Apr 28 2012, 01:46) *
Наконец запустил свою плату на F207, IAR 6.30 + TNКernel
72МНz, 2WS, IAR6.30 - 2.16 мкс
120МНz, 3WS, IAR6.30 - 1.30 мкс

Платка TE-STM32F217, arm-kgp-eabi-gcc, 120 МГц, 3WS - 1.192 мкс. Правда, для достижения такого результата пришлось задействовать LTO, без него получалось 1.4 мкс. Но всё равно, scmRTOS побеждает! sm.gif
_Артём_
Цитата(AHTOXA @ May 5 2012, 23:52) *
для достижения такого результата пришлось задействовать LTO


LTO - это плохо?

В папке 2-Message\prj ничего нет. Скрипт из 1-EventFlag\prj будет работать с USE_LTO=YES?
AHTOXA
LTO - это тяжёлая артиллерия sm.gif
Скрипт везде одинаковый.

---
А если использовать svn, то ничего руками копировать не надо:
Заходим в нужную папку, командуем:
Код
svn co http://scmrtos.svn.sourceforge.net/svnroot/scmrtos/trunk/Samples/CortexM3/GCC/STM32F2XX STM32F2XX

Создаётся папка STM32F2XX с примерами. Заходим в неё, командуем:
Код
switch.bat

, или
Код
sh ./switch.sh

, и всё появляется само sm.gif
_Артём_
Цитата(AHTOXA @ May 6 2012, 08:30) *
Код
svn co http://scmrtos.svn.sourceforge.net/svnroot/scmrtos/trunk/Samples/CortexM3/GCC/STM32F2XX STM32F2XX

Я где-то уже спрашивал, но не помню где...
Какой лучше клиент взять под WinXp?
svn ведь не идёт в комплекте к windows.
VslavX
Цитата(_Артём_ @ May 6 2012, 18:41) *
Я где-то уже спрашивал, но не помню где...
Какой лучше клиент взять под WinXp?
svn ведь не идёт в комплекте к windows.

Мне нравится TortoiseSVN - удобно интегрируется прямо в Explorer.
AHTOXA
Для команд, которые я привёл, достаточно собственно svn. А если нужно что-то графическое - то tortoise svn. Есть ещё RapidSVN, он слабоват, но зато работает и под виндой и под линуксом.
_Артём_
Не разъяснит ли кто-нибудь такой момент (интересуюсь для углубления понимания):
В Оси есть функции disable_context_switch/enable_context_switch, которые реализованы через запрет/разрешение прерываний.
А как они должны реализовываться, если делать без запрета прерываний (через маскировку Осевых уровней)?
И как должен быть сконфигурён ContextSwitcher_ISR? Должен "сидеть" один на самом низшем уровне прерываний?
Спасибо.
AHTOXA
Залил недостающий пример 4-Debug для CortexM3/GCC/STM32F2XX.

Цитата(_Артём_ @ May 7 2012, 00:18) *
В Оси есть функции disable_context_switch/enable_context_switch, которые реализованы через запрет/разрешение прерываний.
А как они должны реализовываться, если делать без запрета прерываний (через маскировку Осевых уровней)?

Да. Только там ещё много чего надо будет учесть.
Цитата(_Артём_ @ May 7 2012, 00:18) *
И как должен быть сконфигурён ContextSwitcher_ISR? Должен "сидеть" один на самом низшем уровне прерываний?

Да. Он работает исходя из предположения, что он прерывает основной поток выполнения.
_Артём_
Цитата(AHTOXA @ May 8 2012, 14:59) *
Да. Он работает исходя из предположения, что он прерывает основной поток выполнения.

Расточительно как-то выглядит, если у проца уровней мало (stm8, xmega): низший исключительно для ContextSwitcher, средний - OS_SystemTimer_ISR и остальные ОСевые прерывания, высший - для вне ОСевых. Тесно.
AHTOXA
SystemTimer тоже можно на низший. И другие малоприоритетные. Смысл в том, чтобы ContextSwitcher не прерывал какое-либо другое прерывание.
_Артём_
Цитата(AHTOXA @ May 8 2012, 23:30) *
SystemTimer тоже можно на низший. И другие малоприоритетные. Смысл в том, чтобы ContextSwitcher не прерывал какое-либо другое прерывание.

Понял, спасибо.
Получается есть всё-таки несколько вариантов: загнать все ОСевые прерывания на один уровень (как сейчас по сути в тех же АВР), использовать для ОСи два или три уровня с ContextSwitcher настроенным на низший уровень.
_Артём_
Глянул в репозитории в папку /trunk/Ports/AVR/IAR, увидел
Код
#if scmRTOS_USER_DEFINED_CRITSECT_ENABLE == 0

Какой в этом смысл на АВР? У него же Interrupt conrtoller не nested.
И как тогда может выглядеть TCritSect при scmRTOS_USER_DEFINED_CRITSECT_ENABLE=1?
ReAl
«пусть и безобразно, зато единообразно»
Оно-то (пользовательские крит. секции) проходит транзитом от scmRTOS_TARGET_CFG.h к OS_Target.h и не используется в потрохах собсвтенно ОС (кроме проверки и значения по умолчанию в scmRTOS_defs.h), но всё равно проще иметь это однотипным во всех портах.

(там где-то на горизонте болтается xmega, у нее три уровня приоритетов, брать за основу этот порт тоже будет проще, когда все заготовки на месте)
_Артём_
Цитата(ReAl @ May 13 2012, 13:11) *
«пусть и безобразно, зато единообразно»
Оно-то (пользовательские крит. секции) проходит транзитом от scmRTOS_TARGET_CFG.h к OS_Target.h и не используется в потрохах собсвтенно ОС (кроме проверки и значения по умолчанию в scmRTOS_defs.h), но всё равно проще иметь это однотипным во всех портах.

Для MegaAVR ещё добавить надо что-то такое в OS_Target_asm.s90:
Код
ContextSwitcher_ISR, Например так:
     save_SREG
     save_SP
#if scmRTOS_USER_DEFINED_CRITSECT_ENABLE == 1
     sei
#endif


Будет ли после такого изменения работать - вопрос. И при каких условиях, если будет.

Цитата(ReAl @ May 13 2012, 13:11) *
(там где-то на горизонте болтается xmega, у нее три уровня приоритетов, брать за основу этот порт тоже будет проще, когда все заготовки на месте)

Да у хмеги отличий не много видимо.
Прикидывал как может быть сделано на xmega:

Код
В scmRTOS_CONFIG.h задал макрос scmRTOS_OS_INTERRUPT_MAX_PRIORITY
// 0 - Ос используют все уровни
// 1 - средний и низший
// 2 - низший
#define scmRTOS_OS_INTERRUPT_MAX_PRIORITY 1


В OS_Target_asm.s90:
Код
#if (scmRTOS_OS_INTERRUPT_MAX_PRIORITY == 0)
#define scmRTOS_OS_INT_STATUS_MASK ~((PMIC_HILVLEN_bm)|(PMIC_MEDLVLEN_bm)|(PMIC_LOLVLEN_bm))

#elif (scmRTOS_OS_INTERRUPT_MAX_PRIORITY == 1)
#define scmRTOS_OS_INT_STATUS_MASK ~((PMIC_MEDLVLEN_bm)|(PMIC_LOLVLEN_bm))

#elif (scmRTOS_OS_INTERRUPT_MAX_PRIORITY == 2)
#define scmRTOS_OS_INT_STATUS_MASK ~(PMIC_LOLVLEN_bm)

#else
#error "OS interrupt level not defined."
#endif

class TCritSect
{
public:
    TCritSect () {
        StatusReg=PMIC.CTRL;
        PMIC.CTRL&=scmRTOS_OS_INT_STATUS_MASK;
    }


    ~TCritSect() {
        PMIC.CTRL=StatusReg;
    }

private:
    uint8_t StatusReg;

};

Но так наверное однобразия не выйдет.
Aprox
Не желаете продолжить абортированную дискуссию? Меня по-прежнему очень интересует вопрос - как практически написать на С++ так, чтобы один из методов статического класса вызывался по прерыванию, и адрес точки входа в эту ISR был бы помещен компилятором+линкером в .intvect ? Если нетрудно, то конкретный листинг для STM32 Cortex.
IgorKossak
Aprox
Создайте отдельную тему в разделе "Программирование" и там обсуждайте сколько влезет.
Встревать в чужую тему не этично.
Проявитесь подобным образом ещё раз - получите отпуск на месяц.
Модератор.
brag
Возможность запуска задач с одинаковым приоритетом имеет смысл. На пример нужно принимать данные допустим с 4х портов, делать сложную тяжелую обработку для каждого канала и выводить результат на дисплей. На пример:
Есть 4 порта uart. Над каждым больпим блоком данных по каждому порту надо выполнять FFT и выводить на дисплей результат по каждому каналу отдельно. Все каналы асинхронные по отношению друг к другу.
Задача легко решается созданием 4х процессов с одинаковым приоритетом для каждого порта, которые принимают данные,обрабатывают и передают 5-му процессу, который это дело оформляет в виде картинки.
Если будут разные приоритеты - обрабатываться будет самый приоритетный канал при большой его загрузке, а остальные будут спать и рано или поздно их очереди переполнятся.
Тут какраз карусель хорошо идет либо возможность вытеснения друг другом процессов с одинаковым приоритетом.

Сама реализация очереди на базе двусвязных списков и карусели всего на несколько инструкций сложнее реализации на bitmap (при наличии инструкции а-ля clz, конечно), тут проблем нету.
Проблема в поиске самого приоритетного процесса в очереди мютекса и др. синхр.примитив. Иначе просыпаться будет не самый приоритетный процесс, а тот, который первый в очереди. Мне пока известно 3 реализации - либо просмотр всего списка(как в TNKernel), либо очередь в виде бинарного дерева - оба варианта тормознутые, каждый в своем случаи. Либо держать массив голов списков - очень быстро, зато каждый обьект ядра будет весить минимум по 33 слова для 32х уровней приоритета.
dxp
По результатам прошедшей дискуссии ситуация была обдумана - по всей видимости возможно реализовать карусель между процессами в виде расширения (т.е. без модификации сорцов оси). К сожалению, текущая загрузка основной работой не позволяет плотно заняться этой темой.
basil__
Окажите пожалуйста любезность, Вы не могли бы привести примеры применения функций terminate() и start() , а то в мануале самый минимум миниморум) - буквально пара слов. И мне как начинающему поклоннику scm )) не очень понятно как их применять. Спасибо.
MBR
Цитата(brag @ Jul 19 2012, 15:53) *
Сама реализация очереди на базе двусвязных списков и карусели всего на несколько инструкций сложнее реализации на bitmap (при наличии инструкции а-ля clz, конечно), тут проблем нету.
Проблема в поиске самого приоритетного процесса в очереди мютекса и др. синхр.примитив. Иначе просыпаться будет не самый приоритетный процесс, а тот, который первый в очереди. Мне пока известно 3 реализации - либо просмотр всего списка(как в TNKernel), либо очередь в виде бинарного дерева - оба варианта тормознутые, каждый в своем случаи. Либо держать массив голов списков - очень быстро, зато каждый обьект ядра будет весить минимум по 33 слова для 32х уровней приоритета.

На правах оффтопа к оффтопу, отпишу как я реализовал диспетчер в mkernel. У меня есть упорядоченный вектор с уникальными приоритетами. Каждый элемент вектора - это приоритет элемента и указатель на список активных процессов с этим приоритетом. Поиск - простой бинарный. Да, на вставление и удаление уникального элемента (сдвиг вектора) нужно время, но время это не столь критично. Зато нет никаких программных ограничений.

Сейчас переделываю диспетчер с вектора на красно-черные деревья. К концу октября должен управиться.

Естественно, речь о списке активных задач, а не ожидающих. Активных задач при грамотном проектировании крайне мало. К тому же, система у меня без тиков, поэтому не нужно дергать супервизора 100 раз в секунду (а в это время можно спать и экономить батарейку sm.gif ). Ну и вдобавок, отзывчивость на тайм-ауты от 1 микросекунды, а не 1 тик.

Поэтому, небольшая дополнительная нагрузка на диспетчер с большим перевесом компенсируется архитектурой ОС и гибкостью возможностей.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.