alux 0 18 марта, 2008 Опубликовано 18 марта, 2008 · Жалоба Как узнать точное использование стека процессами? А то я все делаю вслепую: выставил 100 - работает. Добавил ф-цию - зависает... Использую AVR (Mega324P). JTAG исключен из-за отсутствия свободных выводов. В симуляторе тоже проблематично (как получить ответ от перефирии I2C, SPI, ?..). Было бы совсем неплохо, если бы средствами ОС была возможность в отладочном режиме посмотреть размер неиспользуемого стека каждой задачи через терминал. Такую возможность я увидел в ОС нашего соотечественника uOS. Там для этой цели используется ф-ция task_stack_avail(). И второе. По поводу ф-ции Blink в режиме редактирования времени. Я это реализовал с использованием очереди сообщений, как в примере 3- Channel. Создал от базового класса TMsg объект Blink с методом InvertRect(...); Вопрос, собственно, заключается в следующем : Как обеспечить периодический MsgQueue.push(&Blink) ? Конечно, можно для этой цели использовать отдельный таймер, но хотелось бы обойтись системным таймером. Но не хочу использовать SystemTimerUserHook() по понятным причинам. Может воспользоваться OS::GetTickCount(); которая, на сколько я понял, возвращает общее количество тиков с момента запуска ОС ? Тогда при входе в п. меню "Редактирование" сохранить T = OS::GetTickCount(), а в низкоприоритетном процессе LCDProc отсчитывать от значения T 500 тиков (500*2=1сек) и тогда класть сообщение Blink в очередь. Также нужно учитывать переполнение счетчика. Что скажете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 18 марта, 2008 Опубликовано 18 марта, 2008 · Жалоба Как узнать точное использование стека процессами? Сергей Борщ советовал добавить в конструктор процесса memset, которая заполнит стековую память указанным значением. Стек для эксперимента надо взять с запасом. После этого делается прогон программы и анализируется глубина потребления стека. Вопрос, собственно, заключается в следующем : Как обеспечить периодический MsgQueue.push(&Blink) ? Конечно, можно для этой цели использовать отдельный таймер, но хотелось бы обойтись системным таймером. Но не хочу использовать SystemTimerUserHook() по понятным причинам. Может воспользоваться OS::GetTickCount(); которая, на сколько я понял, возвращает общее количество тиков с момента запуска ОС ? Тогда при входе в п. меню "Редактирование" сохранить T = OS::GetTickCount(), а в низкоприоритетном процессе LCDProc отсчитывать от значения T 500 тиков (500*2=1сек) и тогда класть сообщение Blink в очередь. Также нужно учитывать переполнение счетчика. Что скажете? А что является инициатором (источником события) этого блинка? Вот оно и должно пихать в очередь сообщение. Если надо просто периодически мигать, то запуск по счетчику тиков, имхо, не самое плохое решение (если в отдельный процесс не выносить, а запускать из имеющегося, выполняющиегося с заданной периодичностью). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 18 марта, 2008 Опубликовано 18 марта, 2008 · Жалоба Сергей Борщ советовал добавить в конструктор процесса memset, которая заполнит стековую память указанным значением. Стек для эксперимента надо взять с запасом. После этого делается прогон программы и анализируется глубина потребления стека.Что такое memset ? Можно поподробней? А что является инициатором (источником события) этого блинка? Вот оно и должно пихать в очередь сообщение.Инициатором Blink является вход в п. меню "Настройка", в котором меняется режим работы клавиатуры (вернее процесса ScanKey): .............................. CurrentMode = &EditTime; } если в отдельный процесс не выносить, а запускать из имеющегося, выполняющееся с заданной периодичностью).Т.е. есть необходимо, чтобы был отдельный процесс, который запускается с заданной периодичностью? Я думал для этой цели использовать низкоприоритетный процесс LCDProc, а заданную периодичность в нем же осуществлять проверкой OS::GetTickCount()? и каждые 500 тиков в этом же процессе делать MsgQueue.push(&Blink). Но почему-то это не сработало: OS_PROCESS void TProcLCD::Exec() //TProc5 { for(;;) { CurrentTick = OS::GetTickCount(); if(((CurrentTick-T) > 500)&&(CurrentMode == &EditTime)) { MsgQueue.push(&Blink); T = CurrentTick; } TMsg* msg; MsgQueue.pop(msg); msg->run(); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 18 марта, 2008 Опубликовано 18 марта, 2008 · Жалоба Что такое memset ? Можно поподробней? Функция такая. :) Инициатором Blink является вход в п. меню "Настройка", в котором меняется режим работы клавиатуры (вернее процесса ScanKey): Ну, вот из этого места и надо метать сообщение в очередь. Я имел в виду нечто иное. Когда запускается Blink, то это самостоятельный процесс (просто запускаемый в качестве job), который сам отмеряет все времена и управляет требуемой периферией. Т.е. метнули сообщение в очередь, на том конце очереди сообщение извлекается и вызывается соответствующая функция, которая весь процесс мигания и осуществляет. Отработала, закончилась. Обработчик очереди готов к обработке следующего сообщения. Т.е. вся низкоуровневая работа по формированию времен возложена на виртуальную функцию объекта Blink. А код входа в меню только лишь мечет команду сделать это (путем помещения указателя на объект: &Blink). Удобнее всего формировать времянки с помощью системных средств - той же функции Sleep(), например. Но для этого надо выделить целый процесс, что жалко, т.к. само по себе действие нечастое. Так вот делегирование выполнения операции позволяет совместить приятное с полезным - выполнять код в отдельном процессе (с использованием слипов и прочего) и в то же время не выделять индивидуально процесс под одну операцию, а зашарить его между всеми "желающими" - естественно, все их "желания" будут выполняться по очереди. Если все успевает, то все хорошо. Т.е. если, скажем, во время блинка срочно надо еще что-то сделать, то тогда ой. А если нет, то и пусть себе мигает отведенное ему время. Т.е. насколько этот вариант подходит под ваши требования, вам виднее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 18 марта, 2008 Опубликовано 18 марта, 2008 · Жалоба После этого делается прогон программы и анализируется глубина потребления стека.Уж извините за назойливость. А каким образом проанализировать глубину потребления стека? Вернее, как просмотреть содержимое стека? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 19 марта, 2008 Опубликовано 19 марта, 2008 · Жалоба Уж извините за назойливость. А каким образом проанализировать глубину потребления стека? Вернее, как просмотреть содержимое стека? В данном случае руками либо написав функцию, которая будет анализировать область памяти, занятую под стек - адреса-то все известны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 19 марта, 2008 Опубликовано 19 марта, 2008 · Жалоба В данном случае руками либо написав функцию, которая будет анализировать область памяти, занятую под стек - адреса-то все известны. Что значит "руками" ? Или приведите, пожалуйста, пример функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 19 марта, 2008 Опубликовано 19 марта, 2008 · Жалоба Что значит "руками" ? Руками - значит, остановить эмулятором прогон программы и посмотреть до куда стек заполнился. Или приведите, пожалуйста, пример функции. Предлагаете написать мне для вас функцию? :) Там все это совсем не сложно - адрес объекта известен, размер его полей до стека тоже известен, отсюда можно вычислить адрес, где начинается стек. Размер стека тоже известен. По сути надо просто от начала стека пройти до первого значения, которое отличается от значения по умолчанию (того, которым заполнен стек сначала). Это и будет размер свободного пространства в стеке. Далее, можно это опять же эмулятором смотреть, а можно вываливать хоть на терминал или куда удобно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 19 марта, 2008 Опубликовано 19 марта, 2008 · Жалоба Обнаружил такую проблему. Если два процесса ждут один и тот же Signal от третьего процесса, то почему-то программа виснет. Если ef.Wait() в одном из процессов убрать, то все работает. Размеры стеков увеличивал. Не помогло. OS_PROCESS void TMeasure::Exec() //TProc1 { for(;;) { monitoring.Wait(); while(Flags & MEASURE) { PCInt1.Wait(); // Ждем окончания преобразования АЦП (RDY => 0) measure(); } } } OS_PROCESS void TProcFOSP::Exec() //TProc2 { for(;;) { monitoring.Wait(); // <<<<<<< Если этот убрать, то работает Sleep(); } } ........... При входе в п. меню: Flags |= MEASURE; ENABLE_PCINT1; // Разрешить прерывание от RDY monitoring.Signal(); } Второй процесс вообще ничего не делает, только ждет и спит. В чем может быть проблема? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Обнаружил такую проблему. Если два процесса ждут один и тот же Signal от третьего процесса, то почему-то программа виснет. Если ef.Wait() в одном из процессов убрать, то все работает. Возможное решение есть тут. Файлы OS_Services.h и OS_Services.cpp. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 21 марта, 2008 Опубликовано 21 марта, 2008 · Жалоба Возможное решение есть тут. Файлы OS_Services.h и OS_Services.cpp. Заменил эти файлы. Проблема осталась. Плюс перестала работать очередь сообщений. А есть ли смысл пробовать /branches/b1/Common_b2 Rev138 ? PS. Прпробовал заменить файлы из /branches/b1/Common_b2 Rev138 . Обнаружил, что в файле scmRTOS_def.h отсутствует #include "scmRTOS_config.h" со всеми вытекающими ошибками. При подключении scmRTOS_config.h компилятор выдает ошибку: Error[Pe144]: a value of type "byte" cannot be used to initialize an entity of type "OS::TPriority" D:\...\device\scmRTOS\Common\OS_Kernel.h 355 . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 21 марта, 2008 Опубликовано 21 марта, 2008 · Жалоба Заменил эти файлы. Проблема осталась. Плюс перестала работать очередь сообщений. На данный момент ничего сказать не могу. У меня тоже есть проблемы с этим вариантом реализации в текущем проекте, поэтому я пока использую штатный вариант из trunk. Скоро доберусь до этого. Автор варианта правки бага в этой ветке Сергей Борщ, возможно, он сможет прокомментировать. А есть ли смысл пробовать /branches/b1/Common_b2 Rev138 ? Это тоже Сергей тренировался (Common_b2), но вся эта ветка (b1) - это полигон для отработки других вещей, никак не связанных с фиксом bug_1878045_fix. Т.ч. тут не ищите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 21 марта, 2008 Опубликовано 21 марта, 2008 · Жалоба Попробовал создать отдельный ef2 для TProc2 и ........... при входе в п. меню: Flags |= MEASURE; ENABLE_PCINT1; // Разрешить прерывание от RDY monitoring.Signal(); ef2.Signal(); Не помогло. Программа виснет и все тут... :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 21 марта, 2008 Опубликовано 21 марта, 2008 · Жалоба Попробовал создать отдельный ef2 для TProc2 и ........... при входе в п. меню: Flags |= MEASURE; ENABLE_PCINT1; // Разрешить прерывание от RDY monitoring.Signal(); ef2.Signal(); Не помогло. Программа виснет и все тут... :( Т.е. два разных флага для разных процессов? Ну, тогда не в них дело. А чем смотрите? В смысле, какие отладочные средства есть? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 21 марта, 2008 Опубликовано 21 марта, 2008 · Жалоба Отладчиком (JTAG) не пользуюсь по причине отсутствия свободных выводов. Наблюдаю визуально по программе: перестает реагировать на кнопки и не выводит результат на экран через очередь сообщений. Ну, тогда не в них дело.А в чем же дело? Два процесса ждут Signal, каждый от своего EventFlag. В процессах после Wait() идет Sleep(). Когда из третьего процесса (из п. меню) даю ef1.Signal() и ef2.Signal() для процессов, то все виснет. В смысле остальные процессы не работают. Что я делаю не так ? :05: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться