Полная версия этой страницы:
отладка scmrtos
сарматъ
Aug 20 2013, 09:32
добрый день
подскажите кто пользуется эклипсом возможно ли нормально отлаживать задачку с scmrtos
у меня в коде на с++ точки остановки криво устанавливаются - остановка происходит не в тех местах где где в эклипсе установлены брекпойнты, при пошаговом исполнении какие то непонятные скачки по коду, при этом в частях написанных на чистом с в этой же задачке отладка проходит нормально
черезназад отлаживать конечно можно но вдруг есть нормальное решение этой проблемы
Так проблема в поддержке клипсой плюсов при отладке или в оси?
Сергей Борщ
Aug 21 2013, 05:32
Полагаю, проблема в оптимизации. Ось компилируется с достаточно высокой степенью оптимизации и связь между исходником и ассемблерным кодом становится далеко не однозначной. Сишный же код наверняка компилится вообще без оптимизации, поэтому никаких неоднозначностей не возникает. Остается выбрать: если мы хотим писать большие медленные программы, то надо отключить оптимизацию и при компиляции C++. Если же мы хотим писать маленькие быстрые программы, то надо открывать рядом окно дизассемблера и отлаживаться в нем. Вариант "отключать оптимизацию на время отладки" - это вообще не вариант, ибо
а) будет отлаживаться фактически другая программа
б) не факт что она вообще соберется (без оптимизациии отключается встраивание)
в) после включения оптимизации в якобы отлаженной программе она может перестать работать и горе-программист окажется в той же ситуации, что и в начале - программа не работает, а отлаживать оптимизированный код он не умеет.
сарматъ
Aug 21 2013, 06:54
проблема не в оси а в системе отладки еклипса плюсов похоже
никто не знает в кокосе дело точно так же обстоит?
Сергей Борщ
Aug 21 2013, 08:18
Не вижу у себя таких проблем с отладкой. Да, он скачет по сишным/плюсплюсным строкам, но только лишь потому, что благодаря объединению одинаковых участков кода один и тот же код ассемблера соответствует нескольким разным строкам исходника. Поставьте оптимизацию -O1 и увидите прекрасную отладку.
сарматъ
Aug 21 2013, 15:52
да я посмотрел код дизасемблера, там все перемешано из-за оптимизации, потому видимо так все скачет
сарматъ
Sep 22 2013, 06:34
добрый день, подскажите как правильно использовать init_stack_frame() и stack_slack(), если можно на примере, что то у меня не получается с этими функциями программу скомпилировать - ошибки такого плана
CODE
cannot call member function 'size_t OS::TBaseProcess::stack_slack() const' without object main.cpp
no matching function for call to 'OS::process<(OS::TPriority)1u, 300u>::init_stack_frame()' main.cpp
вот в таком вот коде
CODE
template <>
OS_PROCESS void TProc4::exec()
{init_stack_frame();
for(;;)
{res_table.uregs[104]=stack_slack();
GreenLED::On();
sleep(50);
GreenLED::Off();
sleep(950);
}
}
что я не так делаю?
кажется разобрался...
init_stack_frame(); вызывается самой ос
а stack_slack(); следует вызывать таким образом Proc4.stack_slack();
верно? то есть в итоге делать так
CODE
template <>
OS_PROCESS void TProc4::exec()
{//init_stack_frame();
for(;;)
{res_table.uregs[104]=Proc4.stack_slack();
GreenLED::On();
sleep(50);
GreenLED::Off();
sleep(950);
}
}
сарматъ
Oct 18 2013, 10:49
продолжаю тему начатую
тутплатка работает под управлением ос, через несколько дней работы ос перестает переключать задачки, при этом сама ос продолжает работать
в одной из задач есть мигание светодиодом, эта задачка никого не ждет никаких ресурсов, вот ее код
Код
template <>
OS_PROCESS void TProc4::exec()
{//init_stack_frame();
for(;;)
{res_table.uregs[104]=stack_slack();
GreenLED::On();
sleep(50);
GreenLED::Off();
sleep(950);
}
}
но светодиодик моргать перестает
подскажите какие места в ос посмотреть отладчиком какие переменные чтобы понять отчего перестали переключаться задачки?
Сергей Борщ
Oct 18 2013, 13:33
Здесь я вижу только три возможные проблемы:
1) Перестают генериться прерывания системного таймера. Это можно проверить, останавливая и запуская программу и смотря на переменную Kernel.SysTickCount. Если она меняется - значит прерывания генерятся и обработчик вызывается.
2) Из-за переполнения стека в переменную Timeout этого процесса заносится ноль и ожидание этого процесса становится бесконечным, либо заносится какое-то огромное число и вы просто не дожидаетесь окончания задержки sleep(). Опять же отлавливается отладчиком наблюдая за этой переменной - тикает ли и дотикивает ли до нуля.
3) Какой-то из более высокоприоритетных процессов крутится в цикле не отдавая управление (не впадая в ожидание в каком-либо из системных сервисов). Или же более высокоприоритетные процессы не успевают выполнить свою работу и до низкоприоритетных очередь просто не доходит. Это отлавливается наблюдая за тем, где крутится программа - если в IdleTask, то все нормально, если в каком-то из процессов - разбираться, почему он не отдает управление.
Есть еще одна возможная причина -
4) во время выполнения этой задачи происходит перепланировка, которая по какой-то неведомой причине удаляет эту задачу из карты активных задач. Это можно проверить, поставив точку останова в IdleTask и посмотрев на переменную Timeout этого процесса и на карту активных процессов Kernel.ReadyProcessMap. Либо ReadyProcessMap должен содержать единичку в бите этого процесса, либо Timeout должен быть ненулевым.
Ни вторая, ни четвертая не объясняют, почему останавливаются и другие задачи тоже. Ну разве что кто-то обнуляет ReadyProcessMap, останавливая все процессы.
сарматъ
Oct 18 2013, 15:50
да в этом месте
Код
void OS::TKernel::system_timer()
{
SYS_TIMER_CRIT_SECT();
#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
SysTickCount++;
#endif
точки останова не срабатывают, Kernel.SysTickCount не увеличивается, но я не понимаю изза чего, подскажите куда копать дальше?
в задачке есть прерывания - они работают, в том смысле что прерывания разрешены... в TIdleProc::exec() тоже ос попадает
Сергей Борщ
Oct 18 2013, 17:54
QUOTE (сарматъ @ Oct 18 2013, 18:50)

точки останова не срабатывают, Kernel.SysTickCount не увеличивается, но я не понимаю изза чего, подскажите куда копать дальше?
Смотреть, тикает ли таймер. Если тикает - то почему не вызываются прерывания - может кто-то их запретил. А может таймер кто-то остановил.
сарматъ
Oct 19 2013, 08:23
наехал телнетом на опеносд посмотрел значения регистров связанных с таймером систик
0xE000E010 - 0х00010007 - прерывания разрешены
(не понял пока назначение 16-го бита пробовал его сбрасывать с помощью mww команды, этот бит все равно устанавливается в единицу)0хЕ000Е014 - 0х0002903f - значение регистра перезагрузки
0хЕ000Е018 - все время разные значения - таймер тикает
это прерывание не вызывается
CODE
extern "C" OS_INTERRUPT void Default_SystemTimer_ISR()
{
scmRTOS_ISRW_TYPE ISR;
#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
system_timer_user_hook();
#endif
Kernel.system_timer();
#if scmRTOS_SYSTIMER_NEST_INTS_ENABLE == 0
DISABLE_NESTED_INTERRUPTS();
#endif
}
нашел разницу между работающей и нерабочей системой
в работающей системе регистр 0xe000ed04 равен 0
когда система залипла то значение 1400e84d выходит что pendsv, равно как и систик отложены поэтому прерывание систик больше не генерируется, так? и что с этим делать?
Сергей Борщ
Oct 19 2013, 20:43
QUOTE (сарматъ @ Oct 19 2013, 11:23)

в работающей системе регистр 0xe000ed04 равен 0
когда система залипла то значение 1400e84d выходит что pendsv, равно как и систик отложены поэтому прерывание систик больше не генерируется, так? и что с этим делать?
Вот честно - совершенно не хочется лопатить документацию ST чтобы найти, что за регистр живет по адресу 0xe000ed04.
сарматъ
Oct 19 2013, 22:41
да,я погорячился, это ICSR, таблица 8.6 из книжки джозефа
Сергей Борщ
Oct 19 2013, 23:27
Тогда, если я ничего не путаю, 4D в младших битах указывает, что ваша программа осталась в прерывании OTG_FS. Вероятно, вы вызвали из этого прерывания какой-то сервис, который выполнил перепланировку.
сарматъ
Oct 20 2013, 11:09
сравнивая с работающей системой получил что 4d это прерывание ETH
его код
Код
extern "C" void ETH_IRQHandler(void)
{
// снимаем флаг прерывания
ETH_DMAClearITPendingBit(ETH_DMA_IT_R | ETH_DMA_IT_T | ETH_DMA_IT_NIS | ETH_DMA_IT_AIS);
// прерывание Ethernet
OS::TISRW isrw;
JobQueue.push_isr_empty(&c_Eth);
}
оно вызывается порядка 5000 раз в секунду
JobQueue - очередь заданий как описано в руководстве по ос
OS::channel<TEth*, 20> JobQueue;
метод push_isr_empty
Код
template<typename T, uint16_t Size, typename S>
INLINE void OS::channel<T, Size, S>::push_isr_empty(const T& item)
{
TCritSect cs;
if(!pool.get_count_inline())
{;
pool.push_back_inline(item);
resume_all_isr(ConsumersProcessMap); }
}
осуществляет вставку объекта в очередь если очередь пустая, я криво этот метод написал?
класс channel буфер модифицированный как обсуждалось
тут (добавлены инлайн функции)
ну с другой стороны... разве можно повторно зайти в прерывание не выйдя из него? отладчик показывает что программа спокойно в него входит...
Сергей Борщ
Oct 20 2013, 16:39
Возможно вы списывали значение из регистра в тот момент, когда программа находилась в этом прерывании? Попробуйте поставить точку останова в Idle Task.
сарматъ
Oct 20 2013, 17:15
что то я совсем запутался, короче все сбросил жду опять когда повиснет
сарматъ
Oct 23 2013, 12:13
похоже, дело в кривой обработке мною прерываний сети, значение ETH_DMASR 0х80 - недоступен буфер приема и прога вечно висит в прерывании, как только запрещаю прерывания сети начинает работать ось - переключать задачки, как только прерывания разрешаю платка снова уходит в вечное прерывание
Сергей Борщ
Oct 23 2013, 13:52
Поздравляю с нахождением причины. Значит чудес не бывает
сарматъ
Oct 23 2013, 14:44
спасибо
AHTOXA
Oct 23 2013, 15:28
Ура! Я тоже за вас болел
сарматъ
Oct 23 2013, 15:32
))
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.