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

TN-kernel: поддержка critical section для CM3

собтсвенно сабж. Интересует правильная реализация.

 

Кстати, сообщество не созрело создать подфорум по этой RTOS ?!

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


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

собтсвенно сабж. Интересует правильная реализация.

Что именно понимается под critical sections?

tn_disable_interrupt() и tn_enable_interrupt() недостаточно?

 

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


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

Что именно понимается под critical sections?

tn_disable_interrupt() и tn_enable_interrupt() недостаточно?

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

 

Правильней так (пример от IAR-а)

oldState = __save_interrupt();
__disable_interrupt();
/* Critical section goes here */


__restore_interrupt(oldState);

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


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

Правильней так (пример от IAR-а)

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

 

 

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


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

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

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


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

чой та не понимаю.

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

 

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

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


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

чой та не понимаю.

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

 

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

 

Так как переключение контекста происходит в прерывании с наименьшим возможным приоритетом (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);
}

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

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


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

По крайней мере внутри системных вызовов ОСи используется именно запрещение прерываний, для исключения проблем с реентерабельностью, судя по всему.

А реентерабельность тут причём?

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


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

А реентерабельность тут причём?

Реентерабельность системных вызовов конечно. Ведь они могут вызываться как из задач, так и из прерываний, и работа в них ведётся с одними и теми же внутренними структурами ОС.

 

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


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

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

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

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().

 

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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