реклама на сайте
подробности

 
 
> Вопросы по TNKernel, порт для PIC32
Ruslan1
сообщение Jan 27 2011, 11:55
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025



Здравствуйте!

Поставил, скомпилировал, подредактировал проект примера, идущий в комплекте, под себя, все компилируется и работает. Пока что экспериментирую на кошках (встроенный в 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 системных тиков." На малую долю этого тика, но ведь меньше.... И кто мне гарантирует что эта доля не увеличится до почти целого тика при каких-то условиях.

Оговорюсь, это все на основе симулятора, попробую позже на железе посмотреть.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 07:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.01367 секунд с 7
ELECTRONIX ©2004-2016