|
|
  |
FreeRTOS - минимальное время тика? |
|
|
|
May 30 2018, 07:51
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Цитата(Forger @ May 30 2018, 10:32)  Я смотрю Ваш код, по поиску (CTRL-F) вижу enableInterruptTIM10 только в одном месте (( Да так и есть. Включаем, когда готовы принимать семафор. Цитата(jcxz @ May 30 2018, 10:36)  При частоте таймера ==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 - May 30 2018, 07:50
|
|
|
|
|
May 30 2018, 08:05
|

Местный
  
Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264

|
Цитата(maxntf @ May 30 2018, 11:51)  Да так и есть. Включаем, когда готовы принимать семафор. Я как бы увидел что происходит. В неработающем варианте Код xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken); всегда возвращается pdTREU - соответственно постоянно перевызывается планировщик - почему так?Потому что задача находится в состоянии READY и готова к выполнению. Приведите пожалуйста файл настройки FreeRTOSConfig.h. Цитата(maxntf @ May 30 2018, 11:51)  xSemaphoreGiveFromISR() не должна повторно устанавливать семафор пока задача его не заберет, соответственно возвращает FALSE и portEND_SWITCHING_ISR ничего не переключает. Нет. Это означает, что после выдачи семафора планировщик не видит задач, готовых к выполнению, находящихся в состоянии READY, поэтому решедулинга задач не производится.
Сообщение отредактировал Arlleex - May 30 2018, 08:09
|
|
|
|
|
May 30 2018, 08:06
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Все разобрался, не верно обрабатывал семафор. Нужно было так: Код 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 - May 30 2018, 08:13
|
|
|
|
|
May 30 2018, 08:17
|

Местный
  
Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264

|
Код if(xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken) != pdFAIL) portEND_SWITCHING_ISR(1); Да не правильно так делать! Проверять на возвращаемое значение выдачи семафора - зачем? Да и portEND_SWITCHING_ISR(1) не с 1 должно быть, а с xHigherPriorityTaskWoken. Семафор Вы можете выдавать всегда сколько раз угодно - другое дело, что пока задача его не заберет, выдать его Вы не сможете. Повысьте тактовую частоту CPU и проверьте еще раз свой нерабочий вариант. У меня на F4 приблизительно похожая задача, и все прекрасно успевает и обрабатывается как нужно.
Сообщение отредактировал Arlleex - May 30 2018, 08:21
|
|
|
|
|
May 30 2018, 08:25
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Цитата(Arlleex @ May 30 2018, 11:17)  Код 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 - May 30 2018, 08:29
|
|
|
|
|
May 30 2018, 13:03
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
На семафоре полностью развязать задачу я не смог, а вот с очередями получилось. Реальная задача динамически запускается и удаляется примерно на сотню миллисекунд - передает команду через ИК диод. В общем сделал так, все работает без проблем на любой частоте таймера. Код 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); } } Если кто объяснит почему так нельзя приведя реальный пример как нужно - респект!
|
|
|
|
|
May 30 2018, 13:06
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(maxntf @ May 30 2018, 16:03)  Если кто объяснит почему так нельзя приведя реальный пример как нужно - респект! Очередь (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 проверяются более одного значения.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
May 30 2018, 13:29
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Цитата(Forger @ May 30 2018, 16:06)  Очередь (Queue) в данном случае - как из пушки по воробьям. Я спроси конкретный пример! А то все пишете плохо да плохо. Цитата(Forger @ May 30 2018, 16:06)  Вы вообще понимаете разницу между операторами & и && ? Самый главный косяк, разрешать себе делать так: if(some) { ... }. Отлично понимаю и вообще косяка не вижу. Поразрядное И с однотипными данными в условии, что тут такого!
|
|
|
|
|
May 30 2018, 13:33
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(maxntf @ May 30 2018, 16:29)  Я спроси конкретный пример! Конкретные примеры скачивайте с сайта freeRTOS. Цитата А то все пишете плохо да плохо. Все просто - так оно и есть  Цитата Отлично понимаю и вообще косяка не вижу. Поразрядное И с однотипными данными в условии, что тут такого! Вот с этого бреда и нужно было начинать тему. Дальше можно не продолжать, все ясно. Напоследок. Вот так будет работать правильно: Код if ( (xHigherPriorityTaskWoken != pdFALSE) && (fGiveResult != pdFALSE) )
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
May 30 2018, 13:50
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Цитата(Forger @ May 30 2018, 16:33)  Напоследок. Вот так будет работать правильно: Код 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 - May 30 2018, 13:57
|
|
|
|
|
May 30 2018, 14:14
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(maxntf @ May 30 2018, 16:50)  xHigherPriorityTaskWoken и fGiveResult могут быть только 0x00000000 или 0x00000001 Ну-ну ... Мануалы читать - не Ваше. Вот: https://www.freertos.org/xQueueSendToBackFromISR.htmlЦитирую строчку для особе упертых: " pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL" Цитата Ваш код займет больше места, особенно если таких сравнений будет много. Мля, что за идиотская привычка пошла у начинающих программеров экономить на спичках, плодя потенциальны места для будущих багов!!! Забудьте про PIC и начинайте уже писать код так, как это делают остальные, без такой адской самодеятельности и оптимизаций!
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
May 30 2018, 15:30
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(Forger @ May 30 2018, 16:06)  Очередь (Queue) в данном случае - как из пушки по воробьям. Расскажите пожалуйста, чем отличается очередь и семафор. Напомню (и это важно!) мы по прежнему про FreeRTOS, а не о сферическом коне, как тут принято.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|