AHTOXA 15 1 мая, 2012 Опубликовано 1 мая, 2012 · Жалоба Да, это особенность портов для Cortex-M3. Специальный таймер в ядре - грех было не использовать. Теперь понимаю, что это не всегда удобно. Совсем выносить настройку прерывания на уровень проекта очень неохота - придётся дописывать инициализацию во все имеющиеся проекты. Идея с WEAK мне кажется более подходящей. Постараюсь на днях опробовать этот вариант. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 53 2 мая, 2012 Опубликовано 2 мая, 2012 · Жалоба Да, это особенность портов для Cortex-M3. Специальный таймер в ядре - грех было не использовать. Теперь понимаю, что это не всегда удобно. Совсем выносить настройку прерывания на уровень проекта очень неохота - придётся дописывать инициализацию во все имеющиеся проекты. Идея с WEAK мне кажется более подходящей. Постараюсь на днях опробовать этот вариант. Для того, чтобы подменить таймер, достаточно, как я понимаю, указать другой ISR. Т.е. даже в имеющейся реализации можно написать просто свой обработчик прерываний по образу и подобию в проекте, а ISR таймера ядра залочить. Ничего в сорцах ОС править не надо. Поправь, если ошибаюсь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 2 мая, 2012 Опубликовано 2 мая, 2012 · Жалоба Всё ещё проще! :) Для переопределения источника прерывания надо всего лишь передвинуть обработчик 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() инициализируем этот таймер (не забываем назначить ему наименьший приоритет!). Вроде всё:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба Вроде всё:)«Та не»™ Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит. Так что таки надо какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h. Поскольку это касается исключительно этого порта, стоит ли в scmRTOS_defs.h вносить проверку? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 53 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба «Та не»™ Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит. Так что таки надо какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h. Поскольку это касается исключительно этого порта, стоит ли в scmRTOS_defs.h вносить проверку? А можно и не выносить, а просто вырубить в main. Пара инструкций никому плохо не сделает. Мне кажется, что нормальное решение - для подавляющего большинства проектов годится вариант, который по умолчанию в порте, а для тех редких случаев, где хочется заменить системный таймер на другой, это решается несколькими командами на уровне проекта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба В том-то и дело, что в main() не получится — инициализация проходит в os_start(), которая вызывается из OS::run(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 53 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба В том-то и дело, что в main() не получится — инициализация проходит в os_start(), которая вызывается из OS::run(). Действительно, затупил я. :) Да, тогда без вмешательства в os_start() красиво, по ходу, не сделать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 132 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба инициализация проходит в os_start() Так может быть вынести ее оттуда, как и в остальных портах? Я предпочитаю всю инициализацию делать в одном месте, это имеет свои плюсы - только в это мето нужно "донести" #define с частотами. А с этим обрывком инициализации в os_start() стройная картина рушится. Да и дополнительные определения констант там совсем не красят код, в то время как их же можно красиво написать с символическими именами в любом месте C++ -исходника. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба «Та не»™ Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит. Да пусть молотит, он нам не мешает, поскольку мы переименовали обработчик его прерывания. Если не нужен - потом в наиболее приоритетной задаче при старте отрубить, и всё. В общем, корявенько, но возможно:) Так может быть вынести ее оттуда, как и в остальных портах? Вот этого делать очень неохота - придётся дописывать эту инициализацию в кучу проектов. Надо как-то придумать, чтоб по умолчанию было поведение как сейчас. Какой-нибудь WEAK start_systimer(), что ли. Ну или какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба Да пусть молотит, он нам не мешает, поскольку мы переименовали обработчик его прерывания.Что-то я не понял. Прерывание-то разрешено в регистрах NVIC. 1. В таблице векторов прерываний переименовываем SystemTimer_ISR во что-то другое (чтобы не вызывался штатный осёвый обработчик); Без обработчика влетит в Default_Handler() Тут разве что это «что-то другое» состоит из функции, запрещающей назад прерывание, сбрасывая NVIC_ST_CTRL_INTEN. ------------------------------------- Все прерывания с приоритетом выше configKERNEL_INTERRUPT_PRIORITY не запрещаются никогда, но работают без использования ОСи. NVIC CM3 позволяет сделать подобное. Но есть ли в этом смысл? Или оно не надо никому? https://groups.google.com/group/scmrtos-ru/...c21f94515?hl=ru Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 3 мая, 2012 Опубликовано 3 мая, 2012 · Жалоба Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит. Во как! А я его зачем-то в main-е инициализирую до вызова OS::run(). По аналогии с АВР наверное. А он потом ещё раз инициализируется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 4 мая, 2012 Опубликовано 4 мая, 2012 · Жалоба https://groups.google.com/group/scmrtos-ru/...c21f94515?hl=ru Пришла такая мысль: class TCritSect { public: TCritSect () { // запрет всех прерываний } #if (scmRTOS_USER_DEFINED_CRITSECT_ENABLE==1) TCritSect(enum INT_PRIORITY level) { // запрет всех кроме указанных }; #endif ~TCritSect() { // восстановление в изначальное состояние } private: enabled_level_t EnabledLevels; }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 4 мая, 2012 Опубликовано 4 мая, 2012 · Жалоба Что-то я не понял. Прерывание-то разрешено в регистрах NVIC. Без обработчика влетит в Default_Handler() Не без обработчика, а с другим обработчиком :) То есть, если пользователю нужен SysTick, то он уже есть и инициализирован. А если не нужен - то пустой обработчик. Или состоит из функции, запрещающей назад прерывание, сбрасывая NVIC_ST_CTRL_INTEN. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 53 4 мая, 2012 Опубликовано 4 мая, 2012 · Жалоба Пришла такая мысль: 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 0 4 мая, 2012 Опубликовано 4 мая, 2012 · Жалоба #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: ). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться