Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: отладка scmrtos
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
сарматъ
добрый день

подскажите кто пользуется эклипсом возможно ли нормально отлаживать задачку с scmrtos

у меня в коде на с++ точки остановки криво устанавливаются - остановка происходит не в тех местах где где в эклипсе установлены брекпойнты, при пошаговом исполнении какие то непонятные скачки по коду, при этом в частях написанных на чистом с в этой же задачке отладка проходит нормально

черезназад отлаживать конечно можно но вдруг есть нормальное решение этой проблемы
dxp
Так проблема в поддержке клипсой плюсов при отладке или в оси?
Сергей Борщ
Полагаю, проблема в оптимизации. Ось компилируется с достаточно высокой степенью оптимизации и связь между исходником и ассемблерным кодом становится далеко не однозначной. Сишный же код наверняка компилится вообще без оптимизации, поэтому никаких неоднозначностей не возникает. Остается выбрать: если мы хотим писать большие медленные программы, то надо отключить оптимизацию и при компиляции C++. Если же мы хотим писать маленькие быстрые программы, то надо открывать рядом окно дизассемблера и отлаживаться в нем. Вариант "отключать оптимизацию на время отладки" - это вообще не вариант, ибо
а) будет отлаживаться фактически другая программа
б) не факт что она вообще соберется (без оптимизациии отключается встраивание)
в) после включения оптимизации в якобы отлаженной программе она может перестать работать и горе-программист окажется в той же ситуации, что и в начале - программа не работает, а отлаживать оптимизированный код он не умеет.
сарматъ
проблема не в оси а в системе отладки еклипса плюсов похоже

никто не знает в кокосе дело точно так же обстоит?
Сергей Борщ
Не вижу у себя таких проблем с отладкой. Да, он скачет по сишным/плюсплюсным строкам, но только лишь потому, что благодаря объединению одинаковых участков кода один и тот же код ассемблера соответствует нескольким разным строкам исходника. Поставьте оптимизацию -O1 и увидите прекрасную отладку.
сарматъ
да я посмотрел код дизасемблера, там все перемешано из-за оптимизации, потому видимо так все скачет
сарматъ
добрый день, подскажите как правильно использовать 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);
}
}
сарматъ
продолжаю тему начатую тут

платка работает под управлением ос, через несколько дней работы ос перестает переключать задачки, при этом сама ос продолжает работать

в одной из задач есть мигание светодиодом, эта задачка никого не ждет никаких ресурсов, вот ее код

Код
template <>
OS_PROCESS void TProc4::exec()
{//init_stack_frame();
    for(;;)
        {res_table.uregs[104]=stack_slack();
            GreenLED::On();
            sleep(50);
            GreenLED::Off();
            sleep(950);
        }
}

но светодиодик моргать перестает

подскажите какие места в ос посмотреть отладчиком какие переменные чтобы понять отчего перестали переключаться задачки?
Сергей Борщ
Здесь я вижу только три возможные проблемы:
1) Перестают генериться прерывания системного таймера. Это можно проверить, останавливая и запуская программу и смотря на переменную Kernel.SysTickCount. Если она меняется - значит прерывания генерятся и обработчик вызывается.
2) Из-за переполнения стека в переменную Timeout этого процесса заносится ноль и ожидание этого процесса становится бесконечным, либо заносится какое-то огромное число и вы просто не дожидаетесь окончания задержки sleep(). Опять же отлавливается отладчиком наблюдая за этой переменной - тикает ли и дотикивает ли до нуля.
3) Какой-то из более высокоприоритетных процессов крутится в цикле не отдавая управление (не впадая в ожидание в каком-либо из системных сервисов). Или же более высокоприоритетные процессы не успевают выполнить свою работу и до низкоприоритетных очередь просто не доходит. Это отлавливается наблюдая за тем, где крутится программа - если в IdleTask, то все нормально, если в каком-то из процессов - разбираться, почему он не отдает управление.

Есть еще одна возможная причина -
4) во время выполнения этой задачи происходит перепланировка, которая по какой-то неведомой причине удаляет эту задачу из карты активных задач. Это можно проверить, поставив точку останова в IdleTask и посмотрев на переменную Timeout этого процесса и на карту активных процессов Kernel.ReadyProcessMap. Либо ReadyProcessMap должен содержать единичку в бите этого процесса, либо Timeout должен быть ненулевым.
Ни вторая, ни четвертая не объясняют, почему останавливаются и другие задачи тоже. Ну разве что кто-то обнуляет ReadyProcessMap, останавливая все процессы.
сарматъ
да в этом месте
Код
void OS::TKernel::system_timer()
{
    SYS_TIMER_CRIT_SECT();
#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
    SysTickCount++;
#endif
точки останова не срабатывают, Kernel.SysTickCount не увеличивается, но я не понимаю изза чего, подскажите куда копать дальше?

в задачке есть прерывания - они работают, в том смысле что прерывания разрешены... в TIdleProc::exec() тоже ос попадает
Сергей Борщ
QUOTE (сарматъ @ Oct 18 2013, 18:50) *
точки останова не срабатывают, Kernel.SysTickCount не увеличивается, но я не понимаю изза чего, подскажите куда копать дальше?
Смотреть, тикает ли таймер. Если тикает - то почему не вызываются прерывания - может кто-то их запретил. А может таймер кто-то остановил.
сарматъ
наехал телнетом на опеносд посмотрел значения регистров связанных с таймером систик

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, равно как и систик отложены поэтому прерывание систик больше не генерируется, так? и что с этим делать?
Сергей Борщ
QUOTE (сарматъ @ Oct 19 2013, 11:23) *
в работающей системе регистр 0xe000ed04 равен 0
когда система залипла то значение 1400e84d выходит что pendsv, равно как и систик отложены поэтому прерывание систик больше не генерируется, так? и что с этим делать?
Вот честно - совершенно не хочется лопатить документацию ST чтобы найти, что за регистр живет по адресу 0xe000ed04.
сарматъ
да,я погорячился, это ICSR, таблица 8.6 из книжки джозефа
Сергей Борщ
Тогда, если я ничего не путаю, 4D в младших битах указывает, что ваша программа осталась в прерывании OTG_FS. Вероятно, вы вызвали из этого прерывания какой-то сервис, который выполнил перепланировку.
сарматъ
сравнивая с работающей системой получил что 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 буфер модифицированный как обсуждалось тут (добавлены инлайн функции)

ну с другой стороны... разве можно повторно зайти в прерывание не выйдя из него? отладчик показывает что программа спокойно в него входит...
Сергей Борщ
Возможно вы списывали значение из регистра в тот момент, когда программа находилась в этом прерывании? Попробуйте поставить точку останова в Idle Task.
сарматъ
что то я совсем запутался, короче все сбросил жду опять когда повиснет
сарматъ
похоже, дело в кривой обработке мною прерываний сети, значение ETH_DMASR 0х80 - недоступен буфер приема и прога вечно висит в прерывании, как только запрещаю прерывания сети начинает работать ось - переключать задачки, как только прерывания разрешаю платка снова уходит в вечное прерывание
Сергей Борщ
Поздравляю с нахождением причины. Значит чудес не бывает sm.gif
сарматъ
спасибо wink.gif
AHTOXA
Ура! Я тоже за вас болелsm.gif
сарматъ
))
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.