maxntf 0 30 мая, 2018 Опубликовано 30 мая, 2018 (изменено) · Жалоба Я смотрю Ваш код, по поиску (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 - соответственно постоянно перевызывается планировщик - почему так? Изменено 30 мая, 2018 пользователем maxntf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 30 мая, 2018 Опубликовано 30 мая, 2018 (изменено) · Жалоба Да так и есть. Включаем, когда готовы принимать семафор. Я как бы увидел что происходит. В неработающем варианте xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken); всегда возвращается pdTREU - соответственно постоянно перевызывается планировщик - почему так? Потому что задача находится в состоянии READY и готова к выполнению. Приведите пожалуйста файл настройки FreeRTOSConfig.h. xSemaphoreGiveFromISR() не должна повторно устанавливать семафор пока задача его не заберет, соответственно возвращает FALSE и portEND_SWITCHING_ISR ничего не переключает. Нет. Это означает, что после выдачи семафора планировщик не видит задач, готовых к выполнению, находящихся в состоянии READY, поэтому решедулинга задач не производится. Изменено 30 мая, 2018 пользователем Arlleex Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxntf 0 30 мая, 2018 Опубликовано 30 мая, 2018 (изменено) · Жалоба Все разобрался, не верно обрабатывал семафор. Нужно было так: 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. Но в нее не успеваем попасть, и все время выполняем решедулинг! Изменено 30 мая, 2018 пользователем maxntf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 30 мая, 2018 Опубликовано 30 мая, 2018 (изменено) · Жалоба if(xSemaphoreGiveFromISR(xSemNx, &xHigherPriorityTaskWoken) != pdFAIL) portEND_SWITCHING_ISR(1); Да не правильно так делать! Проверять на возвращаемое значение выдачи семафора - зачем? Да и portEND_SWITCHING_ISR(1) не с 1 должно быть, а с xHigherPriorityTaskWoken. Семафор Вы можете выдавать всегда сколько раз угодно - другое дело, что пока задача его не заберет, выдать его Вы не сможете. Повысьте тактовую частоту CPU и проверьте еще раз свой нерабочий вариант. У меня на F4 приблизительно похожая задача, и все прекрасно успевает и обрабатывается как нужно. Изменено 30 мая, 2018 пользователем Arlleex Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxntf 0 30 мая, 2018 Опубликовано 30 мая, 2018 (изменено) · Жалоба 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мкс. в данном случае не критично и всегда можно подкорректировать. Задача в первую очередь была понять почему так, а путей решения всегда бывает больше чем один! Изменено 30 мая, 2018 пользователем maxntf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба На своей плате поднять частоту я не могу (на данный момент), а пропустить несколько отсчетов по 10мкс. в данном случае не критично и всегда можно подкорректировать. Задача в первую очередь была понять почему так, а путей решения всегда бывает больше чем один! Я вам уже несколько раз объяснил и пример дал, но вы так и не поняли.... и опять всё то же самое накатали. Да ещё какой-то бред добавили с ПОБИТОВЫМ ИЛИ между логическими (видимо) типами... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxntf 0 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба На семафоре полностью развязать задачу я не смог, а вот с очередями получилось. Реальная задача динамически запускается и удаляется примерно на сотню миллисекунд - передает команду через ИК диод. В общем сделал так, все работает без проблем на любой частоте таймера. 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); } } Если кто объяснит почему так нельзя приведя реальный пример как нужно - респект! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба Если кто объяснит почему так нельзя приведя реальный пример как нужно - респект! Очередь (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 проверяются более одного значения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxntf 0 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба Очередь (Queue) в данном случае - как из пушки по воробьям. Я спроси конкретный пример! А то все пишете плохо да плохо. Вы вообще понимаете разницу между операторами & и && ? Самый главный косяк, разрешать себе делать так: if(some) { ... }. Отлично понимаю и вообще косяка не вижу. Поразрядное И с однотипными данными в условии, что тут такого! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба Я спроси конкретный пример! Конкретные примеры скачивайте с сайта freeRTOS. А то все пишете плохо да плохо.Все просто - так оно и есть ;) Отлично понимаю и вообще косяка не вижу. Поразрядное И с однотипными данными в условии, что тут такого!Вот с этого бреда и нужно было начинать тему. Дальше можно не продолжать, все ясно. Напоследок. Вот так будет работать правильно: if ( (xHigherPriorityTaskWoken != pdFALSE) && (fGiveResult != pdFALSE) ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxntf 0 30 мая, 2018 Опубликовано 30 мая, 2018 (изменено) · Жалоба Напоследок. Вот так будет работать правильно: 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 и приходилось очень много вот так подтачивать чтоб все влезло. Ваш код займет больше места, особенно если таких сравнений будет много. Изменено 30 мая, 2018 пользователем maxntf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба xHigherPriorityTaskWoken и fGiveResult могут быть только 0x00000000 или 0x00000001Ну-ну ... Мануалы читать - не Ваше. Вот: https://www.freertos.org/xQueueSendToBackFromISR.html Цитирую строчку для особе упертых: "pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL" Ваш код займет больше места, особенно если таких сравнений будет много. Мля, что за идиотская привычка пошла у начинающих программеров экономить на спичках, плодя потенциальны места для будущих багов!!! :cranky: Забудьте про PIC и начинайте уже писать код так, как это делают остальные, без такой адской самодеятельности и оптимизаций! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxntf 0 30 мая, 2018 Опубликовано 30 мая, 2018 (изменено) · Жалоба Не тот пример был. Изменено 30 мая, 2018 пользователем maxntf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба Очередь (Queue) в данном случае - как из пушки по воробьям. Расскажите пожалуйста, чем отличается очередь и семафор. Напомню (и это важно!) мы по прежнему про FreeRTOS, а не о сферическом коне, как тут принято. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 30 мая, 2018 Опубликовано 30 мая, 2018 · Жалоба Расскажите пожалуйста, чем отличается очередь и семафор. Напомню (и это важно!) мы по прежнему про FreeRTOS, а не о сферическом коне, как тут принято. RTFM Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться