Здравствуйте!
Поставил, скомпилировал, подредактировал проект примера, идущий в комплекте, под себя, все компилируется и работает. Пока что экспериментирую на кошках (встроенный в MPLAB симулятор), железо через неделю только будет. Но уже есть некоторые вопросы. Я не знаю пока вызвано ли это некорректным симулированием, попробую проверить на железе.
Вопрос первый, по работе системного таймера. Проблема: от прерывания до следующего прерывания проходит меньше машинных циклов (МЦ), чем задано. Было бы больше- я б слова не сказал, но меньше.... В качестве таймера TNKernel пользует Core timer ядра MIPS32. Этот таймер инкрементируется каждые два МЦ, то есть в bsp.c вижу логичную конструкцию (это я уже под свои 40МГЦ переделал, в оригинале было под 80):
#define CORE_TIMER_PERIOD 20000UL /* 1 ms @ 40 MHz */
ну и есть прерывание:
void Sys_Tmr_Int_Handler (void) { INTClearFlag(INT_CT); // clear the interrupt flag UpdateCoreTimer(CORE_TIMER_PERIOD); // update the period }
результат по симулятору: 39991 МЦ. Хотя согласно таймеру должно быть 40000.
Изменив величину инициализации таймера на #define CORE_TIMER_PERIOD (20000L + 5) /* 1 ms @ 40 MHz */
получил ровно 40000 МЦ, причем никакой погрешности не набегает при любом количестве прерываний.
То же самое с выдержками больше чем 1мс, скажем 1 секунда: #define CORE_TIMER_PERIOD (20000000UL + 5) /* 1 s @ 40 MHz */
получаю ровно 40 миллионов МЦ. То есть ошибка аддитивная. Но почему таймер считает быстрее чем машинные циклы идут- не понимаю. Или лыжи не едут (симулятор врет) или реализация функции UpdateCoreTimer() хромает.
Вопрос второй. Ну добился я что системный таймер в TNKernel идет как мне хочется (то есть с периодом 1мс), а не быстрее указанного. дальше перешел к проверке пауз в задачах. такая простенькая задача, чтобы светодиод поморгал
#define LED_PERIOD 500 //ms
//task void TN_TASK LED_CPU_Task (void *par) { for (;;) { LED_CPU_ON; tn_task_sleep(LED_PERIOD/2); LED_CPU_OFF; tn_task_sleep(LED_PERIOD/2); } }
Результат удивил: на строку включения светодиода (LED_CPU_ON) я должен попадать каждые 500мс или реже, если другие задачи работают. Реально время меньше требуемого примерно на 20 МЦ. Почему меньше?????????? Причем дельта явно меньше одного системного тика. Я хочу быть уверенным, что прошел период не меньше указанного мной, это очень часто используется при выпиливании времянок: больше пожалуйста, а меньше нельзя. Вероятно, разработчики считают таймаут от текущего системного тика который уже начался, тогда это понятно и нужно просто увеличивать нужные юзерские зазоры на единицу при вызове tn_task_sleep() (проблема юзера, а не кернела), но это где-то отображено? В документации вижу обратное: tn_task_sleep() : Функция переводит текущую задачу в ожидание на время не меньше чем timeout системных тиков. Я согласен с этим и это нормально, но реально вижу "меньше чем timeout системных тиков." На малую долю этого тика, но ведь меньше.... И кто мне гарантирует что эта доля не увеличится до почти целого тика при каких-то условиях.
Оговорюсь, это все на основе симулятора, попробую позже на железе посмотреть.
|