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

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

Никакой конкретики. Отлично.

Ещё раз. Пожалуйста, расскажите своё видение отличий очереди и семафора.

Что вижу я: макрос vSemaphoreCreateBinary вызывает xQueueGenericCreate, макрос xSemaphoreGive вызывает функцию xQueueGenericSend.

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

 

А теперь расскажите, почему эту очередь maxntf ни в коем случае использовать не должен.

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


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

...

"Разжевать и положить в рот"? Нет, я пас. Извините, но мы не в ясельной группе!

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

В качестве "домашнего задания": подумайте, зачем в RTOS существует такое разноообразие сервисов?

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


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

Никакой конкретики. Отлично.

Ещё раз. Пожалуйста, расскажите своё видение отличий очереди и семафора...

А теперь расскажите, почему эту очередь maxntf ни в коем случае использовать не должен.

Опыта с freertos мало, точнее нет. Работал только с кооперативной ОС OSA, под pic_и, там все проще. По этому не смог сделать нужное мне на семафорах, в частности мне нужно было задачу разблокировать , а семафор забрать уже так, чтоб посреди этой функции снова не влететь в прерывание. А вот с очередями получилось, так как там можно прочитать сообщение не забирая его тем самым разблокировать задачу, а потом забрать когда задача будет к этому готова.

 

В качестве "домашнего задания": подумайте, зачем в RTOS существует такое разноообразие сервисов?

Чтоб народ с ума сводить :). Чем дальше углубляюсь, тем больше вижу, что там куча всего через дефайны дублируется.

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

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


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

Чтоб народ с ума сводить :). Чем дальше углубляюсь, тем больше вижу, что там куча всего через дефайны дублируется.

Это во FreeRTOS они все сделаны можно сказать "через одну щель", потому и не славится эта RTOS особой производительностью и малым размером. Но зато под нее существует порт практически под любой проц.

Увы, такова плата за универсальность и поддержку немереного числа платформ.

 

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

Но потом все равно придется делать как надо ))

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


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

Взял отладку на STM32F429, повторил код автора топика.

int main(void)
{
    HW_MCUInit();
    
    SampleSemaphoreHandle = xSemaphoreCreateBinary();
    
    xTaskCreate(&SampleHandlingTask, "SampleHandlingTask", 512, NULL, SAMPLE_HANLING_TASK_PRIORITY, &SampleHandlingTaskHandle);
    
    vTaskStartScheduler();
    
    return 0;
}

void SampleHandlingTask(void *Parameters)
{
    HW_TIMER_START();
    
    while(1)
    {
        xSemaphoreTake(SampleSemaphoreHandle, 10);
        
        unsigned int ReshedulingTime = DWT_CYCCNT - CYCCNT_ISR_Vale;

        ctim10ms = 10;
        
        GPIOG->ODR ^= GPIO_Pin_13;
    }
}

volatile unsigned int ctim10ms = 10000;
volatile unsigned int CYCCNT_ISR_Vale = 0;

void TIM1_UP_TIM10_IRQHandler(void)
{
    static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    
    if(TIM1->SR & TIM_IT_Update)
    {
        if(ctim10ms)
            ctim10ms--;
        else 
        {
            xSemaphoreGiveFromISR(SampleSemaphoreHandle, &xHigherPriorityTaskWoken);
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
            
            CYCCNT_ISR_Vale = DWT_CYCCNT;
        }
        TIM1->SR = (uint16_t)~TIM_IT_Update;
    }
}

Не работает (вернее работает через ж*пу - светодиод еле видно - но, видимо, переключается).

Ставлю таймер на 100мкс, все работает. Отлично - открываю отладчик, запускаю код в нем. Отключаю работу таймера при отладке, чтобы не поломалась система и результаты были честными.

 

В теле задачи ставлю точку останова на

ctim10ms = 10;

и результат 256 тактов CPU тратит на работу переключателя контекста.

 

256/16000000Гц = 16мкс.

 

Далее точно также посчитаем, сколько выполняется тело цикла прерывания: 40 тактов в случае, если ctim10ms отличен от 0 и вызовов xSemaphoreGiveFromISR() не производится, и 356 тактов в случае, если ctim10ms достигло 0 и были вызваны сервисы RTOS выдачи семафора. Добавим ко всему этому по 12 тактов на вход/выход в прерывание (предполагаем, что tail-chaining и late-arriving не запускаются в связи с непериодичностью): итого 64 и 380 тактов соответственно. В микросекундах это 4 и 23.75 соответственно при синхронизации CPU от 16МГц. О какой нафиг тут периодичности прерываний 10мкс может идти речь - не пойму. У Вас за 23.75мкс сформируется еще 2 прерывания, которые Вы пропустите и обработаете как одно.

 

P.S. Поднял частоту работы системы - и теперь 10мкс прерывания работают отлично, что и требовалось доказать.

А Ваши старания с очередью... Ну не уверен я, что оно работает действительно так, как задумано.

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

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


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

Взял отладку на STM32F429, повторил код автора топика.

...

О какой нафиг тут периодичности прерываний 10мкс может идти речь - не пойму. У Вас за 23.75мкс сформируется еще 2 прерывания, которые Вы пропустите и обработаете как одно.

Пролистайте тему выше. Ещё в 47-м, 49-м и 75-м сообщениях тут я писал об этом. Тут даже отладка не нужна - и так всё очевидно. Но "чукча не читатель, чукча писатель"...... :laughing:

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


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

Пролистайте тему выше. Ещё в 47-м, 49-м и 75-м сообщениях тут я писал об этом. Тут даже отладка не нужна - и так всё очевидно. Но "чукча не читатель, чукча писатель"...... :laughing:

Мне просто было интересно поковырять, пока еда готовится :biggrin:

Но где-то внутри тоже предполагал, что времени не хватает просто...

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


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

Всем участникам спасибо за помощь и в некоторых случаях за "мат". Кое как вроде разобрался, что то может не до понял, в дальнейшем процессе освоения дойдет.

Остался один не решенный момент, а именно макрос

portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);

 

В начале я думал, что он работает следующим образом:

Task1 имеет более высокий приоритет чем Task2, но она заблокирована, а работает Task2.

Вдруг в каком то месте Task2 возникает прерывание, в котором происходит разблокировка Task1 (установили семафор например, который ждет Task1).

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

После выхода из функции обработки прерывания уже попадаем в Task1, а не возвращаемся в Task2.

 

Но судя по отладке это не так.

Кто может без нервов разжевать, как оно работает?

 

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


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

В начале я думал, что он работает следующим образом.

Вы все правильно думаете. Прерывания - это асинхронные события, и всегда нужно стараться сократить время реакции системы на них.

Ваши домыслы, очевидно, верны.

Ну а при отладке Вы что-то делаете не так...

Еще раз прошу, скиньте файл FreeRTOSConfig.h, там много интересных настроек, и без включения некоторых из них действительно можно наблюдать чудеса.

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


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

Еще раз прошу, скиньте файл FreeRTOSConfig.h

Вот пожалуйста.

#define configTICK_RATE_HZ                        ( ( TickType_t ) 1000 )
#define configCPU_CLOCK_HZ                        ( SystemCoreClock )
#define configUSE_PREEMPTION                    1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
#define configUSE_IDLE_HOOK                        1
#define configUSE_TICK_HOOK                        1
#define configMAX_PRIORITIES                    ( 5 )
#define configMINIMAL_STACK_SIZE                ( ( unsigned short ) 170 )
#define configTOTAL_HEAP_SIZE                    ( ( size_t ) ( 14 * 1024 ) )
#define configMAX_TASK_NAME_LEN                    ( 16 )
#define configUSE_TRACE_FACILITY                1
#define configUSE_16_BIT_TICKS                    0
#define configIDLE_SHOULD_YIELD                    1
#define configUSE_MUTEXES                        1
#define configQUEUE_REGISTRY_SIZE                5
#define configCHECK_FOR_STACK_OVERFLOW            2
#define configUSE_RECURSIVE_MUTEXES                1
#define configUSE_MALLOC_FAILED_HOOK            1
#define configUSE_APPLICATION_TASK_TAG            0
#define configUSE_COUNTING_SEMAPHORES            1

/* Software timer related definitions. */
#define configUSE_TIMERS                        1
#define configTIMER_TASK_PRIORITY                ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH                10
#define configTIMER_TASK_STACK_DEPTH            configMINIMAL_STACK_SIZE

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES             0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet        1
#define INCLUDE_uxTaskPriorityGet        1
#define INCLUDE_vTaskDelete                1
#define INCLUDE_vTaskCleanUpResources    0
#define INCLUDE_vTaskSuspend            1
#define INCLUDE_vTaskDelayUntil            1
#define INCLUDE_vTaskDelay                1

/* Standard assert semantics. */
//#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for(;; ); }    

/* Use the system definition, if there is one */
#ifdef __NVIC_PRIO_BITS
    #define configPRIO_BITS       __NVIC_PRIO_BITS
#else
    #define configPRIO_BITS       4        /* 15 priority levels */
#endif

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY            15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5

/* The lowest priority. */
#define configKERNEL_INTERRUPT_PRIORITY     ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Priority 5, or 95 as only the top four bits are implemented. */
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/* Run time stats related macros. */
#define configGENERATE_RUN_TIME_STATS    0

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

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


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

Ну вроде в порядке все, только определены ли у Вас функции-ловушки всех установленных опций? Я про IdleHook, TickHook и т.д.

Как проверяете, что RTOS не переключается на задачу с самым высоким приоритетом?

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


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

Ну вроде в порядке все, только определены ли у Вас функции-ловушки всех установленных опций? Я про IdleHook, TickHook и т.д.

void vApplicationIdleHook(void)
{
    //HOOK_PULSE;
}
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{
    for(;;);
}
void vApplicationTickHook(void)
{
    
}
void vApplicationMallocFailedHook(void)
{
    for(;;);
}

#define HOOK_PULSE GPIO_ToggleBits(GPIOB, GPIO_Pin_5) - это вывод пина на осциллограф, когда нужно что то проверить. А так они IdleHook, TickHook пока у меня пустые.

Как проверяете, что RTOS не переключается на задачу с самым высоким приоритетом?

Шагаю по прерыванию, а после выхода из обработчика прерывания вываливаюсь в Task2 (точнее в тело функции которую она периодически вызывает) с низким приоритетом (приоритет 1) а Task1 который ждет семафор (только у меня событие из очереди) приоритет 2.

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

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


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

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);

А зачем два раза подряд вызывать ожидающие функции xQueuePeek() и xQueueReceive() причем подряд?

Как-то не корректно Вы с очередью работаете...

xQueuePeek() считает значение из очереди, но не удалит его оттуда.

xQueueReceive() тоже считает, но удалит (FIFO).

Почему просто не вызывать xQueueReceive()?

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

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


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

А зачем два раза подряд вызывать ожидающие функции xQueuePeek() и xQueueReceive() причем подряд?

Как-то не корректно Вы с очередью работаете...

xQueuePeek() считает значение из очереди, но не удалит его оттуда.

xQueueReceive() тоже считает, но удалит (FIFO).

Почему просто не вызывать xQueueReceive()?

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

 

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

По этому просьба больше не писать что я туплю и делаю не так, это не проект а тесты.

 

В частности сейчас у меня проблема, что не работает portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);

Докопался portYIELD(), понял что он устанавливает флаг прерывания PendSV, в котором ОС выполняет переключение контекста.

 

А теперь о моих баранах. В Task2(с низким приоритетом) у меня вызывается функция F1() с той самой тачлиб что фигурировала в начале темы. Так вот после выхода из обработчика прерывания в котором вызывался portEND_SWITCHING_ISR(xHigherPriorityTaskWoken), программа попадает в место из картинки. Получается что флаг прерывания PendSV был установлен когда судя по записи __disable_irq() все прерывания били отключены.

img.jpg

 

 

Убрал нафиг эти __disable_irq() и __enable_irq(). Но все равно не работает.

 

Как бы в отладчике узнать включено ли прерывание для PendSV?

 

P.S.

Кстати у меня с калибровкой на 10мкс все работало четко, только потому, что не переключается контекст и время на это не тратится и все успевает. Вот так бывает :)

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

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


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

По этому просьба больше не писать что я туплю и делаю не так.

Дык, тогда и не пишите тут то, что вызывает такую реакцию, кстати, вполне естественную реакцию :laughing:

 

зы. "По этому" в данном случае пишется слитно :biggrin:

 

 

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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