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

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

Я смотрю Ваш код, по поиску (CTRL-F) вижу enableInterruptTIM10 только в одном месте ((

Да так и есть. Включаем, когда готовы принимать семафор.

 

При частоте таймера ==100кГц и частоте ядра==16МГц, у Вас как только обнуляется ctim10ms, то в каждом прерывании вызывается xSemaphoreGiveFromISR(), а так как она наверняка длительная (и следующая за ней функция - скорей всего ещё более длительная, так как скорей всего делается решедулинг задач), то к моменту выхода из ISR успевает пройти >= 160 тактов ядра. А значит - ждёт уже новое прерывание таймера и сразу снова входит в ISR и всё повторяется. Естественно, что всё блокируется на постоянных входах в ISR.

 

Ага. Но только если я долблю таймером xSemaphoreGiveFromISR без обработки переменной каждые 10мкс все работает. xSemaphoreGiveFromISR() не должна повторно устанавливать семафор пока задача его не заберет, соответственно возвращает FALSE и portEND_SWITCHING_ISR ничего не переключает.

#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()

 

 

 

Я как бы увидел что происходит.

В неработающем варианте

xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken);

всегда возвращается pdTREU - соответственно постоянно перевызывается планировщик - почему так?

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

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


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

Да так и есть. Включаем, когда готовы принимать семафор.

Я как бы увидел что происходит.

В неработающем варианте

xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken);

всегда возвращается pdTREU - соответственно постоянно перевызывается планировщик - почему так?

Потому что задача находится в состоянии READY и готова к выполнению.

Приведите пожалуйста файл настройки FreeRTOSConfig.h.

 

xSemaphoreGiveFromISR() не должна повторно устанавливать семафор пока задача его не заберет, соответственно возвращает FALSE и portEND_SWITCHING_ISR ничего не переключает.

Нет. Это означает, что после выдачи семафора планировщик не видит задач, готовых к выполнению, находящихся в состоянии READY, поэтому решедулинга задач не производится.

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

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


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

Все разобрался, не верно обрабатывал семафор.

Нужно было так:

void TIM10_IRQHandler(void)
{
    static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    
    if(TIM_GetFlagStatus(TIM10, TIM_FLAG_Update) != RESET)
    {
        TIM_ClearFlag(TIM10, TIM_FLAG_Update);
        if(ctim10ms) ctim10ms--;
        else 
        {
            if(xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken) != pdFAIL) portEND_SWITCHING_ISR(1);
        }
    }
}

 

Осталось понять нафиг xHigherPriorityTaskWoken.

И почему во всех примерах так

            xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken);
            portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);

А у меня не работает?

 

P.S.

Все понял.

У меня задача всегда READY. Но в нее не успеваем попасть, и все время выполняем решедулинг!

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

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


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

if(xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken) != pdFAIL) portEND_SWITCHING_ISR(1);

Да не правильно так делать!

 

Проверять на возвращаемое значение выдачи семафора - зачем? Да и portEND_SWITCHING_ISR(1) не с 1 должно быть, а с xHigherPriorityTaskWoken.

Семафор Вы можете выдавать всегда сколько раз угодно - другое дело, что пока задача его не заберет, выдать его Вы не сможете.

Повысьте тактовую частоту CPU и проверьте еще раз свой нерабочий вариант. У меня на F4 приблизительно похожая задача, и все прекрасно успевает и обрабатывается как нужно.

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

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


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

if(xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken) != pdFAIL) portEND_SWITCHING_ISR(1);

Да не правильно так делать!

 

Проверять на возвращаемое значение выдачи семафора - зачем? Да и portEND_SWITCHING_ISR(1) не с 1 должно быть, а с xHigherPriorityTaskWoken.

Семафор Вы можете выдавать всегда сколько раз угодно - другое дело, что пока задача его не заберет, выдать его Вы не сможете.

Повысьте тактовую частоту CPU и проверьте еще раз свой нерабочий вариант. У меня на F4 приблизительно похожая задача, и все прекрасно успевает и обрабатывается как нужно.

В моем случае не совсем так.

у меня запускается планировщик, где то по середине прерывается, и запускается снова и так бесконечно. Так как задача всегда READY, но семафор обработать не успевает.

Конкретно в моем варианте нужно так:

void TIM10_IRQHandler(void)
{
    static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, fGiveResult = pdFALSE;
    
    if(TIM_GetFlagStatus(TIM10, TIM_FLAG_Update) != RESET)
    {
        TIM_ClearFlag(TIM10, TIM_FLAG_Update);
        if(ctim10ms) ctim10ms--;
        else 
        {
            fGiveResult = xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken);
            portEND_SWITCHING_ISR(xHigherPriorityTaskWoken & fGiveResult);
        }
    }
}

 

P.S.

На своей плате поднять частоту я не могу (на данный момент), а пропустить несколько отсчетов по 10мкс. в данном случае не критично и всегда можно подкорректировать.

Задача в первую очередь была понять почему так, а путей решения всегда бывает больше чем один!

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

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


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

На своей плате поднять частоту я не могу (на данный момент), а пропустить несколько отсчетов по 10мкс. в данном случае не критично и всегда можно подкорректировать.

Задача в первую очередь была понять почему так, а путей решения всегда бывает больше чем один!

Я вам уже несколько раз объяснил и пример дал, но вы так и не поняли.... и опять всё то же самое накатали. Да ещё какой-то бред добавили с ПОБИТОВЫМ ИЛИ между логическими (видимо) типами...

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


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

На семафоре полностью развязать задачу я не смог, а вот с очередями получилось.

Реальная задача динамически запускается и удаляется примерно на сотню миллисекунд - передает команду через ИК диод.

В общем сделал так, все работает без проблем на любой частоте таймера.

void TIM10_IRQHandler(void)
{
    static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, fGiveResult = pdFALSE;
    
    if(TIM_GetFlagStatus(TIM10, TIM_FLAG_Update) != RESET)
    {
        TIM_ClearFlag(TIM10, TIM_FLAG_Update);
        if(ctim10ms) ctim10ms--;
        else 
        {
            fGiveResult = xQueueSendToBackFromISR(xQueue, (const void *)0, &xHigherPriorityTaskWoken);
            if(xHigherPriorityTaskWoken & fGiveResult) 
            {
                portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
            }
                else cal_ctim10ms++;
        }
    }
}
void Task_temp(void *pParams)
{
    uint32_t newValue = 100;
    uint32_t q_buf;
    
    xQueue = xQueueCreate(1, sizeof(uint32_t));


    ctim10ms = newValue;
    Tx_Init();

    while(1)
    {
        xQueuePeek(xQueue, &q_buf, 10);
    taskENTER_CRITICAL();
        ctim10ms = newValue - cal_ctim10ms;
        cal_ctim10ms = 0;
    taskEXIT_CRITICAL();
        GPIO_ToggleBits(GPIOB, GPIO_Pin_5);//пин контроля работы программы
        xQueueReceive(xQueue, &q_buf, 0);
    }
}

Если кто объяснит почему так нельзя приведя реальный пример как нужно - респект!

 

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


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

Если кто объяснит почему так нельзя приведя реальный пример как нужно - респект!

Очередь (Queue) в данном случае - как из пушки по воробьям.

 

 

Чтобы избежать таких детских граблей:

 if(xHigherPriorityTaskWoken & fGiveResult)

это следует писать хотя бы так:

 if( (xHigherPriorityTaskWoken != 0) && (fGiveResult != 0))

Вы вообще понимаете разницу между операторами & и && ?

 

Самый главный косяк, разрешать себе делать так: if(some) { ... }.

Это допустимо только для одного случая some есть bool, но в таких случаях эту some лучше называть иначе, чтобы было проще читать, например: bool isRxDone = что_то_что_возвращает true/false;

Тогда всякие условия читаются в разы проще: if (isRxDone) { ... }

 

Если же речь идет про все остальные типы, которые анализируются в блоке if {} else, то их сравнение следует указывать явно (number != 0), и обязательно брать в скобки, если в одном блоке if проверяются более одного значения.

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


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

Очередь (Queue) в данном случае - как из пушки по воробьям.

Я спроси конкретный пример! А то все пишете плохо да плохо.

 

Вы вообще понимаете разницу между операторами & и && ?

Самый главный косяк, разрешать себе делать так: if(some) { ... }.

Отлично понимаю и вообще косяка не вижу. Поразрядное И с однотипными данными в условии, что тут такого!

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


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

Я спроси конкретный пример!

Конкретные примеры скачивайте с сайта freeRTOS.

 

А то все пишете плохо да плохо.
Все просто - так оно и есть ;)

 

Отлично понимаю и вообще косяка не вижу. Поразрядное И с однотипными данными в условии, что тут такого!
Вот с этого бреда и нужно было начинать тему. Дальше можно не продолжать, все ясно.

 

Напоследок. Вот так будет работать правильно:

if ( (xHigherPriorityTaskWoken != pdFALSE) && (fGiveResult != pdFALSE) )

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


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

Напоследок. Вот так будет работать правильно:

if ( (xHigherPriorityTaskWoken != pdFALSE) && (fGiveResult != pdFALSE) )

 

#define pdFALSE ( ( BaseType_t ) 0 )

#define pdTRUE ( ( BaseType_t ) 1 )

typedef long BaseType_t;

 

xHigherPriorityTaskWoken и fGiveResult могут быть только 0x00000000 или 0x00000001

 

(xHigherPriorityTaskWoken & fGiveResult) в результате даст либо 0 либо 1

if(0) нет

if(1) да

 

P.S.

Ваш вариант с точки зрения читабельности, верный.

Фактически в данном случае мой вариант рабочий и перед тем чтоб такое написать я проверил что там за типы данных и какие значения принимают. Так пишу потому что последнее время писал только под pic с очень малым flash и приходилось очень много вот так подтачивать чтоб все влезло. Ваш код займет больше места, особенно если таких сравнений будет много.

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

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


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

xHigherPriorityTaskWoken и fGiveResult могут быть только 0x00000000 или 0x00000001
Ну-ну ...

Мануалы читать - не Ваше.

Вот: https://www.freertos.org/xQueueSendToBackFromISR.html

Цитирую строчку для особе упертых: "pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL"

 

Ваш код займет больше места, особенно если таких сравнений будет много.

Мля, что за идиотская привычка пошла у начинающих программеров экономить на спичках, плодя потенциальны места для будущих багов!!! :cranky:

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

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


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

Очередь (Queue) в данном случае - как из пушки по воробьям.

Расскажите пожалуйста, чем отличается очередь и семафор.

Напомню (и это важно!) мы по прежнему про FreeRTOS, а не о сферическом коне, как тут принято.

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


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

Расскажите пожалуйста, чем отличается очередь и семафор.

Напомню (и это важно!) мы по прежнему про FreeRTOS, а не о сферическом коне, как тут принято.

RTFM

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


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

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

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

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

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

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

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

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

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

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