|
|
|
FreeRTOS - минимальное время тика? |
|
|
|
May 30 2018, 17:31
|
Профессионал
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831
|
Цитата(esaulenka @ May 30 2018, 20:15) ... "Разжевать и положить в рот"? Нет, я пас. Извините, но мы не в ясельной группе! Если вы сами до сих пор еще не разобрались, где какой сервис RTOS нужно использовать, а где какой будет избыточен, то я ни как Вам не смогу помочь. В качестве "домашнего задания": подумайте, зачем в RTOS существует такое разноообразие сервисов?
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
May 30 2018, 17:58
|
Частый гость
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008
|
Цитата(esaulenka @ May 30 2018, 20:15) Никакой конкретики. Отлично. Ещё раз. Пожалуйста, расскажите своё видение отличий очереди и семафора... А теперь расскажите, почему эту очередь maxntf ни в коем случае использовать не должен. Опыта с freertos мало, точнее нет. Работал только с кооперативной ОС OSA, под pic_и, там все проще. По этому не смог сделать нужное мне на семафорах, в частности мне нужно было задачу разблокировать , а семафор забрать уже так, чтоб посреди этой функции снова не влететь в прерывание. А вот с очередями получилось, так как там можно прочитать сообщение не забирая его тем самым разблокировать задачу, а потом забрать когда задача будет к этому готова. Цитата(Forger @ May 30 2018, 20:31) В качестве "домашнего задания": подумайте, зачем в RTOS существует такое разноообразие сервисов? Чтоб народ с ума сводить . Чем дальше углубляюсь, тем больше вижу, что там куча всего через дефайны дублируется.
Сообщение отредактировал maxntf - May 30 2018, 17:59
|
|
|
|
|
May 30 2018, 18:27
|
Профессионал
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831
|
Цитата(maxntf @ May 30 2018, 20:58) Чтоб народ с ума сводить . Чем дальше углубляюсь, тем больше вижу, что там куча всего через дефайны дублируется. Это во FreeRTOS они все сделаны можно сказать "через одну щель", потому и не славится эта RTOS особой производительностью и малым размером. Но зато под нее существует порт практически под любой проц. Увы, такова плата за универсальность и поддержку немереного числа платформ. В самом начале пути можно делать как угодно: и через зад лечить зубы и через нос зашивать пятку. Но потом все равно придется делать как надо ))
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
May 30 2018, 19:41
|
Местный
Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264
|
Взял отладку на 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 - May 30 2018, 19:42
|
|
|
|
|
May 31 2018, 13:15
|
Частый гость
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008
|
Всем участникам спасибо за помощь и в некоторых случаях за "мат". Кое как вроде разобрался, что то может не до понял, в дальнейшем процессе освоения дойдет. Остался один не решенный момент, а именно макрос Код portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); В начале я думал, что он работает следующим образом: Task1 имеет более высокий приоритет чем Task2, но она заблокирована, а работает Task2. Вдруг в каком то месте Task2 возникает прерывание, в котором происходит разблокировка Task1 (установили семафор например, который ждет Task1). В макросе portYIELD() грубо говоря поменяли адрес (на задачу с большим приоритетом) куда нужно вернуться. После выхода из функции обработки прерывания уже попадаем в Task1, а не возвращаемся в Task2. Но судя по отладке это не так. Кто может без нервов разжевать, как оно работает?
|
|
|
|
|
May 31 2018, 13:44
|
Местный
Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264
|
Цитата(maxntf @ May 31 2018, 17:15) В начале я думал, что он работает следующим образом. Вы все правильно думаете. Прерывания - это асинхронные события, и всегда нужно стараться сократить время реакции системы на них. Ваши домыслы, очевидно, верны. Ну а при отладке Вы что-то делаете не так... Еще раз прошу, скиньте файл FreeRTOSConfig.h, там много интересных настроек, и без включения некоторых из них действительно можно наблюдать чудеса.
|
|
|
|
|
May 31 2018, 13:46
|
Частый гость
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008
|
Цитата(Arlleex @ May 31 2018, 16:44) Еще раз прошу, скиньте файл 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
|
|
|
|
|
May 31 2018, 14:13
|
Частый гость
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008
|
Цитата(Arlleex @ May 31 2018, 17:05) Ну вроде в порядке все, только определены ли у Вас функции-ловушки всех установленных опций? Я про 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 пока у меня пустые. Цитата(Arlleex @ May 31 2018, 17:05) Как проверяете, что RTOS не переключается на задачу с самым высоким приоритетом? Шагаю по прерыванию, а после выхода из обработчика прерывания вываливаюсь в Task2 (точнее в тело функции которую она периодически вызывает) с низким приоритетом (приоритет 1) а Task1 который ждет семафор (только у меня событие из очереди) приоритет 2.
Сообщение отредактировал maxntf - May 31 2018, 14:42
|
|
|
|
|
May 31 2018, 15:05
|
Местный
Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264
|
Код 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 - May 31 2018, 15:10
|
|
|
|
|
Jun 1 2018, 09:18
|
Частый гость
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008
|
Цитата(Arlleex @ May 31 2018, 18:05) А зачем два раза подряд вызывать ожидающие функции xQueuePeek() и xQueueReceive() причем подряд? Как-то не корректно Вы с очередью работаете... xQueuePeek() считает значение из очереди, но не удалит его оттуда. xQueueReceive() тоже считает, но удалит (FIFO). Почему просто не вызывать xQueueReceive()? Таймер тикает очень часто. Пока я в задаче после разблокировки дойду до установки счетчика (в примере не весь код, я его упростил) в новое значение, он может тикнуть еще несколько раз, по этому в это время (по не удается установить новое событие), наполняется счетчик калибровки, который я отнимаю от нового устанавливаемого значения. И вообще я как бы уже понял что и как нужно делать, вся моя затея была концептуально не верна. Но вылезло много глюков с которыми и разбираюсь, почему так получается, чтоб потом не наступать на подобные грабли. По этому просьба больше не писать что я туплю и делаю не так, это не проект а тесты. В частности сейчас у меня проблема, что не работает portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); Докопался portYIELD(), понял что он устанавливает флаг прерывания PendSV, в котором ОС выполняет переключение контекста. А теперь о моих баранах. В Task2(с низким приоритетом) у меня вызывается функция F1() с той самой тачлиб что фигурировала в начале темы. Так вот после выхода из обработчика прерывания в котором вызывался portEND_SWITCHING_ISR(xHigherPriorityTaskWoken), программа попадает в место из картинки. Получается что флаг прерывания PendSV был установлен когда судя по записи __disable_irq() все прерывания били отключены. Убрал нафиг эти __disable_irq() и __enable_irq(). Но все равно не работает. Как бы в отладчике узнать включено ли прерывание для PendSV?P.S. Кстати у меня с калибровкой на 10мкс все работало четко, только потому, что не переключается контекст и время на это не тратится и все успевает. Вот так бывает
Сообщение отредактировал maxntf - Jun 1 2018, 09:23
|
|
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|