Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: TN-kernel: поддержка critical section для CM3
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы
megajohn
собтсвенно сабж. Интересует правильная реализация.

Кстати, сообщество не созрело создать подфорум по этой RTOS ?!
VslavX
Цитата(megajohn @ Jul 25 2012, 14:33) *
собтсвенно сабж. Интересует правильная реализация.

Что именно понимается под critical sections?
tn_disable_interrupt() и tn_enable_interrupt() недостаточно?
_Артём_
Цитата(VslavX @ Jul 25 2012, 17:46) *
Что именно понимается под critical sections?
tn_disable_interrupt() и tn_enable_interrupt() недостаточно?

Странная секция какая-то: если она вложенная, то как тогда?

Правильней так (пример от IAR-а)
Код
oldState = __save_interrupt();
__disable_interrupt();
/* Critical section goes here */


__restore_interrupt(oldState);
VslavX
Цитата(_Артём_ @ Jul 25 2012, 18:18) *
Правильней так (пример от IAR-а)

Ну насколько я знаю - в оригинальном порте TNKernel так и сделано, только переменная OldState спрятана внутри макроса. В своей модификации RTOSе я использую идеологию IAR-овского примера - с явным сохранением состояния.

msalov
Код
TN_INTSAVE_DATA
tn_disable_interrupt();
...
{
  // Вложенная
  TN_INTSAVE_DATA
  tn_disable_interrupt();
  ...
  tn_enable_interrupt();
}
...
tn_enable_interrupt();

Всё потому что
Код
#define  TN_INTSAVE_DATA_INT     unsigned int tn_save_status_reg = 0;
#define  TN_INTSAVE_DATA         unsigned int tn_save_status_reg = 0;
#define  tn_disable_interrupt()  tn_save_status_reg = tn_cpu_save_sr()
#define  tn_enable_interrupt()   tn_cpu_restore_sr(tn_save_status_reg)

#define  tn_idisable_interrupt() tn_save_status_reg = tn_icpu_save_sr()
#define  tn_ienable_interrupt()  tn_icpu_restore_sr(tn_save_status_reg)

tn_cpu_save_sr() - запрещает прерывания и возвращает статус разрешения прерываний до запрещения
tn_cpu_restore_sr() - разрешает прерывания если параметр != 0 и запрещает, если == 0
megajohn
чой та не понимаю.
Зачем отключать вообще прерывания ? Нужно всего лишь дать знать шедуллеру чтобы покамест не переключал задачи. А блокировать ВСЕ - это уже блокировка и на уровне драйверов, которые входящие данные складывают в циклический буфер.

или мои представления о РТОС ошибочны ?!
msalov
Цитата(megajohn @ Jul 26 2012, 09:49) *
чой та не понимаю.
Зачем отключать вообще прерывания ? Нужно всего лишь дать знать шедуллеру чтобы покамест не переключал задачи. А блокировать ВСЕ - это уже блокировка и на уровне драйверов, которые входящие данные складывают в циклический буфер.

или мои представления о РТОС ошибочны ?!


Так как переключение контекста происходит в прерывании с наименьшим возможным приоритетом (PendSV с приоритетом 0xFF), то можно не запрещать прерывания, а поднять нижнюю границу обслуживаемых прерываний. Тем самым оставив прерывания включёнными, но запретив переключение контекста. Как это делается для Cortex-M3, увы не скажу.
Будет что-то типа:
Код
int tn_disable_context_switch(void)
{
  int state = get_priority_level();
  if (state == 0xFF) // all interrupt are accepted
  {
    set_priority_level(0xFF - 1); // accept all, except PendSV
  }
  // else - do nothing, since PendSV is not acceptable already
  return state;
}

void tn_enable_context_switch(int state)
{
  set_priority_level(state);
}

На счёт представлений ничего не скажу sad.gif Сам бы хотел получить ответ на этот вопрос. По крайней мере внутри системных вызовов ОСи используется именно запрещение прерываний, для исключения проблем с реентерабельностью, судя по всему.
_Артём_
Цитата(gotty @ Jul 26 2012, 10:36) *
По крайней мере внутри системных вызовов ОСи используется именно запрещение прерываний, для исключения проблем с реентерабельностью, судя по всему.

А реентерабельность тут причём?
msalov
Цитата(_Артём_ @ Jul 26 2012, 11:09) *
А реентерабельность тут причём?

Реентерабельность системных вызовов конечно. Ведь они могут вызываться как из задач, так и из прерываний, и работа в них ведётся с одними и теми же внутренними структурами ОС.
VslavX
Цитата(gotty @ Jul 26 2012, 10:36) *
Так как переключение контекста происходит в прерывании с наименьшим возможным приоритетом (PendSV с приоритетом 0xFF), то можно не запрещать прерывания, а поднять нижнюю границу обслуживаемых прерываний.

Дело в том что часто критическая секция именно организуется для защиты данных разделяемых с обработчиком прерываний - тут только запрет прерываний и поможет. Если данные в критической секции разделяются только между задачами - то лучше уже использовать синхрообъекты RTOS - мутексы, семафоры или события. Еще, иногда, если код в критической секции очень быстрый и короткий, то из соображений быстродействия вполне можно критическую секцию организовать на tn_interrupt_xxxx(). Пример (не самый удачный для Cortex с его ldrex/strex):
CODE

HAL_SYSTEM_CALL
DWORD
HAL_CALL_OPTION
hal_interlocked_inc(
PDWORD var)
{
DWORD lock, ret;
lock = hal_lock_interrupt();
ret = *var + 1;
*var = ret;
hal_unlock_interrupt(lock);
return ret;
}

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