|
|
  |
Вопросы по scmRTOS |
|
|
|
Mar 24 2010, 10:18
|
Группа: Участник
Сообщений: 10
Регистрация: 8-02-10
Пользователь №: 55 367

|
Начал разбираться с scmRTOS.3.10. Ответьте, плз. на несколько вопросов. 1) смотрю пример 1-EventFlag, описание процесса: typedef OS::process<OS::pr0, 120, 32> TProc1; Что означает 32? В доке на V2.0 такого параметра нет.
2) Существует ли проблема локальных переменных, объявленных в разных процессах? Когда происходит прерывание текущего процесса более приоритетным, тогда есть опасность порчи локальных переменных, ведь они формируются компилятором из кучи. Как быть? Объявлять их static? Чего-то я недопонимаю. Сильно не пинайте.
|
|
|
|
|
Mar 25 2010, 08:37
|
Группа: Участник
Сообщений: 10
Регистрация: 8-02-10
Пользователь №: 55 367

|
Цитата(jorikdima @ Mar 24 2010, 14:14)  из стека, если вы не пользуетесь динамическим выделением. А стек у каждой задачи свой, следовательно проблемы нет. В стеке задачи сохраняются только регистры, при этом не факт, что компилятор назначит регистр какой-либо локальной переменной. Например, если в подпрограмме определяются несколько float - локальных переменных, то скорее всего они создадутся из кучи, т.е из ОЗУ. Вы никогда не пробовали (в программе без ОСи) в прерываниях определить несколько локальных переменных (не static)? И что из этого вышло? Цитата(jorikdima @ Mar 24 2010, 14:14)  из стека, если вы не пользуетесь динамическим выделением. А что, разве существует какой-то другой тип распределения памяти компилятором? Как в IARe я могу изменить этот тип? Научите меня, плз.
|
|
|
|
|
Mar 25 2010, 09:01
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Embedder74 @ Mar 25 2010, 10:37)  Например, если в подпрограмме определяются несколько float - локальных переменных, то скорее всего они создадутся из кучи, т.е из ОЗУ. Локальные переменные выделяются на стеке. Всегда. Память из кучи выделяется функцией malloc() и подобными. В плюсах - оператором new. И никак иначе. Куча находится в ОЗУ точно так же, как и стек находится в ОЗУ. ОЗУ (RAM) != куча (heap). Цитата(Embedder74 @ Mar 25 2010, 10:37)  Вы никогда не пробовали (в программе без ОСи) в прерываниях определить несколько локальных переменных (не static)? И что из этого вышло? Пробовали. Вышло именно то, что и должно было. Цитата(Embedder74 @ Mar 25 2010, 10:37)  А что, разве существует какой-то другой тип распределения памяти компилятором? Как в IARe я могу изменить этот тип? Сначала опишите, что вы понимаете под "этим" способом. Это поможет определить, какие способы являются "другими".
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 9 2010, 17:34
|
Местный
  
Группа: Участник
Сообщений: 312
Регистрация: 9-04-10
Пользователь №: 56 532

|
atmega8 scmRTOS_SYSTIMER_NEST_INTS_ENABLE 1 scmRTOS_PROCESS_COUNT 2 Начал изучать эту ОС. Документацию прочитал. Но не пойму. Почему в моем коде никогда не выполняется TProc2? TProc1 ждет байт. Если пришел то отправить. TProc2 постоянно шлет 'b'. SystemTimerUserHook. постоянно отсылает 'v'. На выводе постоянно фижу 'v' но никогда 'b'. Если отсылаю байт то он тут же возвращается. Вывод TProc2 никогда не передается управление. Код int main() { MyUart.init(); // Start System Timer TCCR0 = (1 << CS01) | (1 << CS00); // clk/64 TIMSK |= (1 << TOIE0);
//Запускаем ОС OS::Run();
return 0; }
//--------------------------------------------------------------------------- namespace OS {
template<> OS_PROCESS void TProc1::Exec() { unsigned char c;
for(;;) { c=MyUart.receiveByte(); MyUart.sendByte(c); } } // TProc1::Exec()
template<> OS_PROCESS void TProc2::Exec() { for(;;) { MyUart.sendByte('b'); Sleep(50); } } // TProc2::Exec()
} // namespace OS
void OS::SystemTimerUserHook() { #if scmRTOS_SYSTIMER_NEST_INTS_ENABLE && !PORT_TOGGLE_BY_PIN_WRITE TCritSect cs; #endif MyUart.sendByte('v'); }
|
|
|
|
|
Apr 9 2010, 18:26
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
А всё потому, что TProc1 имеет наивысший приоритет, и не отдаёт никому управление. Вставьте в TProc1 Код MyUart.sendByte('b'); Sleep(10); и всё заработает. А если всё делать по уму, то надо чтобы функция MyUart.receiveByte(); сама вгоняла вызвавший её процесс в спячку до прихода символа.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 9 2010, 19:04
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(a9d @ Apr 10 2010, 01:06)  Т.е. я должен должен явно указывать какой процесс может отдать управление? Конечно. Это не виндоуз, где все процессы получают время, только более приоритетные побольше. Здесь, пока более приоритетный процесс не отдаст управление, менее приоритетный его не получит. А вот наоборот - запросто. Цитата Если вставить в первый процесс Sleep(10) то ничего не изменится. Ну значит надо вызывать какую-то другую, неблокирующую функцию, типа MyUart.rx_count(). Тут уж вам виднее. И кстати, если вы работаете с MyUart из разных потоков, то надо обернуть обращения к нему блокировками. Например, завести мьютекс MyUartMutex, и при начале работы его захватывать, а по окончании - отдавать.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 9 2010, 19:13
|
Местный
  
Группа: Участник
Сообщений: 312
Регистрация: 9-04-10
Пользователь №: 56 532

|
Мда. Не удобно. Модифицировал Код void OS::SystemTimerUserHook() { #if scmRTOS_SYSTIMER_NEST_INTS_ENABLE && !PORT_TOGGLE_BY_PIN_WRITE TCritSect cs; #endif //MyUart.sendByte('v'); OS::Sleep(1); } И все заработало. Но походу это очень плохая идея. Вот код получения байта. Код unsigned char CUart::receiveByte() { while((UCSRA&(1<<RXC))==0); return UDR; }
Сообщение отредактировал a9d - Apr 9 2010, 19:15
|
|
|
|
|
Apr 9 2010, 21:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Вы четко должны понять, в RTOS реализуется "псевдопараллельное" выполнение задач, ведь процессор то один. Если вы в своей функции, которая вызывается из самого приоритетного процесса, висите в while(), то никогда этот процесс не передаст управление другим процессам. Вставлять Sleep в функцию, вызываемую по прерыванию, на мой взгляд, тоже не лучший вариант. Не очень понятно, как оно у вас заработало
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|