Перейти к содержанию
    

FreeRTOS - минимальное время тика?

Потихоньку разбираюсь далее с FreeRTOS.

Возникла новая проблема, я ее решил но возможно не совсем правильно и не понимаю из за чего так получилось.

Сейчас системный тик 1мсек.

Может кто подскажет?

 

Есть таймер настроенный на 10мкс, на каждом прерывании он декрементирует глоб. переменную, значение которой задает Task2 (имеет самый высокий приоритет).

Когда переменная = 0, устанавливает семафор, чтоб разбудить задачу, которая установит новое значение переменной.

//Task2
...
        IrState.ctim10ms = IrState.bRxTx[pValue->nComm][0];
        ctx_bit = 1;
        xSemaphoreTake(IrState.xSemNx, 0);
        T10_Init();
        while(ctx_bit <= IrState.cRxTx[pValue->nComm])
        {        
            [b]enableInterruptTIM10();[/b]
            if(xSemaphoreTake(IrState.xSemNx, 25) != pdTRUE) break;
            SwitchPWM;
            IrState.ctim10ms = IrState.bRxTx[pValue->nComm][ctx_bit];
            ctx_bit++;
        }
        T10_DeInit();
...

void TIM10_IRQHandler(void)
{
    static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    
    if(TIM_GetFlagStatus(TIM10, TIM_FLAG_Update) != RESET)
    {
        TIM_ClearFlag(TIM10, TIM_FLAG_Update);
        if(IrState.ctim10ms) IrState.ctim10ms--;
        else 
        {
            [b]disableInterruptTIM10();[/b]
            xSemaphoreGiveFromISR(IrState.xSemNx, &xHigherPriorityTaskWoken);
            portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
        }
    }
}

В общем пока я не начал отключать прерывания таймера (в коде выделил), все висло в обработчике таймера и ни одна задача управление не получает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть таймер настроенный на 10мкс, на каждом прерывании он декрементирует глоб. переменную, значение которой задает Task2 (имеет самый высокий приоритет).

...

В общем пока я не начал отключать прерывания таймера (в коде выделил), все висло в обработчике таймера и ни одна задача управление не получает.

Чтобы на столь высоких частотах периодических прерываний работало и не висло, нужно вначале научиться обходиться без куба.

И потрудитесь хотя-бы посчитать каков период прерываний в тактах ядра.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтобы на столь высоких частотах периодических прерываний работало и не висло, нужно вначале научиться обходиться без куба.

И потрудитесь хотя-бы посчитать каков период прерываний в тактах ядра.

Где тут куб увидели?

Ядра чего ОС? Если да то я писал 1мсек.

 

P.S. На всякий случай, частота тактирования МК - 16МГц.

Изменено пользователем maxntf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. На всякий случай, частота тактирования МК - 16МГц.

Естественно тактах CPU.

Если не куб, то кубоподбный код: TIM_GetFlagStatus(), TIM_ClearFlag()

у Вас всего 160 тактов между прерываниями, за которые CPU должен успеть кучу всего (откройте листинг и вручную посчитайте такты или то же самое сделайте отладчиком).

Даже если писать нормально (с прямой работой с регистрами IO, без ненужных функций) при такой высокой частоте у Вас CPU только и будет заниматься входами/выходами в ISR - загрузка будет близка к 100%.

А при обнулении счётчика так вообще там у Вас таймер наверняка переполняется и что-то при этом происходит.

Вам надо кардинально пересматривать архитектуру проекта и или повышать частоту CPU или обходиться без таких ВЧ прерываний. И научиться работать с регистрами напрямую, без ненужных обёрток.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

у Вас всего 160 тактов между прерываниями, за которые CPU должен успеть кучу всего

1600

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Любого ждет анафема, кто замечен за подобными злодеяниями - изменение глобальных объектов в фоне задачи и в прерываниях.

Допустимо, если будет только чтение таких объектов и оно атомарно (8...32-битное слово).

Как минимум непредсказуемые баги будут на самом ровном месте, а симптомы ни разу не однозначные. Поэтому найти такие баги крайне сложно!

 

Вот наглядный пример в Вашем коде:

 

процедура записи нового значения (между знаком "=") прервана прерыванием

//Task2
...
        IrState.ctim10ms = IrState.bRxTx[pValue->nComm][0];
...

 

в котором будет выполнено это условие?

 

void TIM10_IRQHandler(void)
{
....
        if(IrState.ctim10ms) IrState.ctim10ms--;
....
}

 

Зы. ту не поможет ни какая volatile.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если подумать? :rolleyes:

10 кГц -> 100 мкс

100 мкс * 16 МГц = 1600 тактов

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 кГц -> 100 мкс

100 мкс * 16 МГц = 1600 тактов

Есть таймер настроенный на 10мкс,

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я думал, речь идет по-прежнему про частоту работы планировщика задач.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Любого ждет анафема, кто замечен за подобными злодеяниями - изменение глобальных объектов в фоне задачи и в прерываниях.

Ничего там криминального нет с IrState.ctim10ms, так как в задаче выполняется только запись в неё (хоть объявления IrState.ctim10ms не видно, но думаю что она - одного из встроенных типов), а запись встроенного типа 8/16/32/64 бита на Cortex-M - атомарна.

В ISR выполняется чтение-модификация-запись, приоритет ISR заведомо выше любого таска, так что таск не сможет прерывать ISR. А значит и операции внутри ISR для тасков - атомарны.

 

Допустимо, если будет только чтение таких объектов и оно атомарно (8...32-битное слово).

Для чтения/записи 64-битных переменных например IAR использует LDRD/STRD, а они тоже атомарны.

 

процедура записи нового значения (между знаком "=") прервана прерыванием

в котором будет выполнено это условие?

...

И что? Пускай прервана. Она не прервёт посередине операции записи (запись атомарна), а только перед или после.

К тому же как я понимаю: указанный участок внутри таска начнёт выполняться только когда IrState.ctim10ms == 0. А при этом в ISR никакого декремента не делается, только чтение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я же все объяснил на конкретном примере.

 

Еще раз, но на пальцах:

Пусть IrState.ctim10ms равно, скажем 10, но прерывание еще не возникло и в этот момент выполняется в задаче это кусок:

 

IrState.ctim10ms = IrState.bRxTx[pValue->nComm][0];

 

скажем нас прервали как раз перед записью нового значения в IrState.ctim10ms, собирались записать туда 100, которые тока что вычитали из IrState.bRxTx[pValue->nComm][0]

 

и тут вдруг возникает прерывание, где мы вполняем эту строчку:

if(IrState.ctim10ms) IrState.ctim10ms--;

 

логично, что после выхода из прерывания будет IrState.ctim10ms = 9,

а тут мы выходим из прерывания и тут же загоняем в IrState.ctim10ms = 100

 

Не знаю, как это скажется на логике работы прерывания, но явно, что в следующем вызове прерывания вместо 9 вдруг получить 100 - очень странно.

Как себя поведет прога в таком случае остается только гадать.... :smile3046:

 

 

К тому же как я понимаю: указанный участок внутри таска начнёт выполняться только когда IrState.ctim10ms == 0.

Ну-ну. Но чуть-чуть поменяли логику и привет? Ловим баги на ровном месте, через час/сутки/год? Тут кому как повезет.

 

Существуют неписанные правила: доступ к глобальным объектам при чтении-модификации-записи (из задачи) должен быть защищен от любых прерываний, которые могут этот объект изменить посреди этой цепочки.

Для таких случае в простейшем варианте можно использовать критическую секцию.

А в идеале - вообще избегать "дергать" один и тот же глобальный объект из задачи и прерываний. Есть решения.

К тому же нужно постоянно держать в голове - "а что будет, если ... ". Кому нужна доп. головная боль на ровном месте?

 

В той же MISRA вообще рекомендуют избегать или на край очень осторожно использовать глобальные объекты.

Разумеется, если используются прерывания. Но где их нынче не используют? ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а тут мы выходим из прерывания и тут же загоняем в IrState.ctim10ms = 100

И что???

 

Не знаю, как это скажется на логике работы прерывания, но явно, что в следующем вызове прерывания вместо 9 вдруг получить 100 - очень странно.

А сколько там должно быть после записи 100? 200 что-ли? :smile3046:

В чём проблема-то??

В программе написано "записать 100", код это делает? Делает. Никакие прерывания этому не мешают. Так в чём проблема, что Вас смущает?

 

Существуют неписанные правила: доступ к глобальным объектам при чтении-модификации-записи (из задачи) должен быть защищен от любых прерываний, которые могут этот объект изменить посреди этой цепочки.

Проблема тут только в том, что чтение-модификацию-запись (в задаче) переменной IrState.ctim10ms в указанном примере видите здесь похоже только Вы.... :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В программе написано "записать 100", код это делает? Делает. Никакие прерывания этому не мешают. Так в чём проблема, что Вас смущает?

Это мешает самим прерываниям, точнее, нарушает логику работы кода внутри этих самых прерываний.

 

Короче, я указал на потенциально опасное место в коде.

И связано оно именно с обращениям к одним и тем же глобальным объектам из фона задачи и прерываний БЕЗ соотв. защиты.

 

Даже, если в самом коде это в данный момент работает, ну, какое-то определенное время работает. Хотя бы в текущей версии.

Если игнорировать эти вещи, то все может стать только хуже, особенно, когда проект практически готов, но сбоит на ровном месте и в самый неожиданный момент.

К тому же, судя по всему, ТС только-только осваивает RTOS и поэтому много может просто не знать. Особенно про такие очень скверные грабли с глобальными объектами.

Или Вы считаете, что это - не грабли, и так делать нормально и безопасно? ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Или Вы считаете, что это - не грабли, и так делать нормально и безопасно? ;)

Ещё раз: грабли там видите только Вы.

Никаких проблем (по крайней мере с работой этой переменной) в указанном фрагменте нет.

Сериализация доступа необходима только в случае неатомарных операций с переменной в прерываемом коде. Операции записи базовых типов данных в Cortex-M - все атомарные. Т.е. - в Task2 нет неатомарных операций с IrState.ctim10ms. Критические секции (или подобное) там как собаке пятая нога.

 

PS: Кто-нить ещё, кроме Forger, видит проблему с работой IrState.ctim10ms ? :rolleyes:

 

PPS: ТСу можно разве что посоветовать объявить IrState.ctim10ms с модификатором volatile. Хотя возможно что он уже есть, так как объявления её не приведено.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...