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

Да, это особенность портов для Cortex-M3. Специальный таймер в ядре - грех было не использовать.

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

Идея с WEAK мне кажется более подходящей. Постараюсь на днях опробовать этот вариант.

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


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

Да, это особенность портов для Cortex-M3. Специальный таймер в ядре - грех было не использовать.

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

Идея с WEAK мне кажется более подходящей. Постараюсь на днях опробовать этот вариант.

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

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


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

Всё ещё проще! :)

Для переопределения источника прерывания надо всего лишь передвинуть обработчик 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() инициализируем этот таймер (не забываем назначить ему наименьший приоритет!).

 

Вроде всё:)

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


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

Вроде всё:)
«Та не»™

Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

 

Так что таки надо какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h.

Поскольку это касается исключительно этого порта, стоит ли в scmRTOS_defs.h вносить проверку?

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


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

«Та не»™

Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

 

Так что таки надо какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h.

Поскольку это касается исключительно этого порта, стоит ли в scmRTOS_defs.h вносить проверку?

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

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


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

В том-то и дело, что в main() не получится — инициализация проходит в os_start(), которая вызывается из OS::run().

 

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


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

В том-то и дело, что в main() не получится — инициализация проходит в os_start(), которая вызывается из OS::run().

Действительно, затупил я. :) Да, тогда без вмешательства в os_start() красиво, по ходу, не сделать.

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


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

инициализация проходит в os_start()
Так может быть вынести ее оттуда, как и в остальных портах? Я предпочитаю всю инициализацию делать в одном месте, это имеет свои плюсы - только в это мето нужно "донести" #define с частотами. А с этим обрывком инициализации в os_start() стройная картина рушится. Да и дополнительные определения констант там совсем не красят код, в то время как их же можно красиво написать с символическими именами в любом месте C++ -исходника.

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


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

«Та не»™

Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

Да пусть молотит, он нам не мешает, поскольку мы переименовали обработчик его прерывания.

Если не нужен - потом в наиболее приоритетной задаче при старте отрубить, и всё. В общем, корявенько, но возможно:)

Так может быть вынести ее оттуда, как и в остальных портах?

Вот этого делать очень неохота - придётся дописывать эту инициализацию в кучу проектов.

Надо как-то придумать, чтоб по умолчанию было поведение как сейчас. Какой-нибудь

WEAK start_systimer(), что ли. Ну или

какой-то #define scmRTOS_CM3_PORT_USER_SYSTICK в scmRTOS_TARGET_CFG.h.

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


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

Да пусть молотит, он нам не мешает, поскольку мы переименовали обработчик его прерывания.
Что-то я не понял. Прерывание-то разрешено в регистрах 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

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


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

Надо еще выключить инициализацию SYSTICK (включение таймера и разрешение его прерываний) в os_start, которая в OS_Target_asm.S сидит.

Во как!

А я его зачем-то в main-е инициализирую до вызова OS::run(). По аналогии с АВР наверное.

А он потом ещё раз инициализируется.

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


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

 

Пришла такая мысль:

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

private:
    enabled_level_t  EnabledLevels;
};

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


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

Что-то я не понял. Прерывание-то разрешено в регистрах NVIC.

Без обработчика влетит в Default_Handler()

Не без обработчика, а с другим обработчиком :)

То есть, если пользователю нужен SysTick, то он уже есть и инициализирован. А если не нужен - то пустой обработчик. Или

состоит из функции, запрещающей назад прерывание, сбрасывая NVIC_ST_CTRL_INTEN.

 

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


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

Пришла такая мысль:

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

private:
    enabled_level_t  EnabledLevels;
};

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

 

По поводу таймера. Мне казалось, что самым правильным решением было бы не завязываться на аппаратуру таймера в коде ОС и вынести всю инициализацию на уровень проекта. Там реально несколько строчек. Зато никаких вопросов не возникает. Я так и делал в порте для Blackfin'а, хотя там тоже есть специальный таймер в ядре. Как сейчас правильнее поступить, даже не знаю.

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


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

#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: ).

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


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

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

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

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

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

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

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

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

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

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