sonycman 1 5 сентября, 2022 Опубликовано 5 сентября, 2022 · Жалоба В 05.09.2022 в 14:56, aaarrr сказал: Не нужно ничего менять: свой макрос и назвать по-своему. Так есть же "нормальный" макрос, который создаёт пустой семафор: xSemaphoreCreateBinary() И в доке по vSemaphoreCreateBinary() указывается: Цитата Mutexes and binary semaphores that were created using the old vSemaphoreCreateBinary() macro, as opposed to the preferred xSemaphoreCreateBinary() function, are both created such that the first call to xSemaphoreTake() on the semaphore or mutex will pass. Note vSemaphoreCreateBinary() is deprecated and must not be used in new applications. Binary semaphores created using the xSemaphoreCreateBinary() function are created ‘empty’, so the semaphore must first be given before the semaphore can be taken (obtained) using a call to xSemaphoreTake(). По крайней мере в 10 версии операционки так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LAS9891 0 5 сентября, 2022 Опубликовано 5 сентября, 2022 · Жалоба 3) Макрос configKERNEL_INTERRUPT_PRIORITY - это макрос, который определяет приоритет прерывания, используемого для тиков FreeRTOS. Т.е. это приоритет прерывания SysTick микроконтроллера равный 14. Так или не так? 4) Макрос configMAX_SYSCALL_INTERRUPT_PRIORITY - это макрос, который устанавливает наивысший приоритет ЧЕГО?, из которого могут быть вызваны защищенные для прерываний функции FreeRTOS API, т.е. функции в названии которых есть FromISR (например xSemaphoreGiveFromISR). Так или не так? Тока приоритет чего? прерываний или задач Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 187 5 сентября, 2022 Опубликовано 5 сентября, 2022 · Жалоба 1 час назад, LAS9891 сказал: Макрос configKERNEL_INTERRUPT_PRIORITY - это макрос, который определяет приоритет прерывания, используемого для тиков FreeRTOS. Т.е. это приоритет прерывания SysTick микроконтроллера равный 14. Так или не так? Почти. В дебрях FreeRTOS этот приоритет задается для PendSV и SysTick. configKERNEL_INTERRUPT_PRIORITY должен иметь минимальный логический приоритет для конкретной архитектуры. Для Cortex-Mx (в силу инверсии понятия "число <=> приоритет") должно быть 255. Это число 255 дальше обрежется по маске реализованного кол-ва прерываний конкретного МК прямо перед записью в регистр приоритетов, хоть это и не обязательно (МК все равно лишнее обрежет сам). Цитата Макрос configMAX_SYSCALL_INTERRUPT_PRIORITY - это макрос, который устанавливает наивысший приоритет ЧЕГО? Прерываний. Ведь даже из названия видно. Этот макрос задает верхний порог логического приоритета прерываний, которые могут пользоваться сервисными функциями RTOS x_fromISR(). Опять же, для Cortex-Mx счет приоритетов инверсный, т.е., например, задав configMAX_SYSCALL_INTERRUPT_PRIORITY равным 250, функциями x_fromISR() можно пользоваться в прерываниях с приоритетом 255...250 (включительно). Имея, например, аппаратное ограничение уровней приоритета в самом МК в 4 бита (приоритеты 0 (высший) ... 15 (низший)), получится, что (250 & 0xF) == 10. Т.е. приоритеты с 15 (низшего) до 10 включительно можно юзать для прерываний, которые вызывают всякие x_fromISR(). В остальных (более приоритетных) прерываниях использовать эти функции уже нельзя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LAS9891 0 6 сентября, 2022 Опубликовано 6 сентября, 2022 (изменено) · Жалоба 13 hours ago, Arlleex said: получится, что (250 & 0xF) == 10. Наверно имелось в виду: ((250 & 0xF0) >> 4) = 10 Согласны ли Вы с 15 hours ago, jcxz said: PendSV = 15 SysTick = 14 ... аппаратные прерывания ? Я сделал так: #define configKERNEL_INTERRUPT_PRIORITY 255 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 250 В контроллере прерывания настроил так: При запуске отладки, до нажатия кнопки (прерывания) всё вроде норм. После нажатия случается один раз прерывание и всё виснет тут: void vPortValidateInterruptPriority( void ) { uint32_t ulCurrentInterrupt; uint8_t ucCurrentPriority; /* Obtain the number of the currently executing interrupt. */ ulCurrentInterrupt = vPortGetIPSR(); /* Is the interrupt number a user defined interrupt? */ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) { /* Look up the interrupt's priority. */ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; /* The following assertion will fail if a service routine (ISR) for * an interrupt that has been assigned a priority above * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API * function. ISR safe FreeRTOS API functions must *only* be called * from interrupts that have been assigned a priority at or below * configMAX_SYSCALL_INTERRUPT_PRIORITY. * * Numerically low interrupt priority numbers represent logically high * interrupt priorities, therefore the priority of the interrupt must * be set to a value equal to or numerically *higher* than * configMAX_SYSCALL_INTERRUPT_PRIORITY. * * Interrupts that use the FreeRTOS API must not be left at their * default priority of zero as that is the highest possible priority, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * and therefore also guaranteed to be invalid. * * FreeRTOS maintains separate thread and ISR API functions to ensure * interrupt entry is as fast and simple as possible. * * The following links provide detailed information: * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html * https://www.FreeRTOS.org/FAQHelp.html */ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); // <-------------------------------------------------------ВОТ ТУТ } Что не верно? Изменено 6 сентября, 2022 пользователем LAS9891 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 187 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба 32 минуты назад, LAS9891 сказал: Наверно имелось в виду: ((250 & 0xF0) >> 4) = 10... Нет, Вы тоже не правы оказались, как и я (я подзабыл, что приоритет еще и в старших битах) Правильно будет все-таки 175, а не 250. Тогда (175 & 0xF0) >> 4 == 10. Цитата Согласны ли Вы с... Да. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 187 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба 34 минуты назад, LAS9891 сказал: Что не верно? configMAX_SYSCALL_INTERRUPT_PRIORITY установите в 192. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LAS9891 0 6 сентября, 2022 Опубликовано 6 сентября, 2022 (изменено) · Жалоба 12 minutes ago, Arlleex said: configMAX_SYSCALL_INTERRUPT_PRIORITY установите в 192. Почему? Хотя и так тоже работает Всё заработало когда сделал так: #define configKERNEL_INTERRUPT_PRIORITY 255 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 175 Изменено 6 сентября, 2022 пользователем LAS9891 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 187 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба 5 минут назад, LAS9891 сказал: Почему? 175 - это число для получения приоритета 10 в Cortex-Mx. Взял с потолка в качестве примера. У Вас же приоритет прерывания с кнопкой настроен на 192 (12). Поэтому и говорю, что в данном случае должно быть 192. Работает со 175 - логично, потому что будет работать со всеми NVIC_SetPriority(IRQn, x), где x == 15...10 (включительно). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LAS9891 0 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба 1 minute ago, Arlleex said: должно быть 192. Почему именно должно? Если приоритет кнопки будет находиться в интервале между 10 и 15 (приоритеты 11, 12, 13, 14) это будет неправильно? Приоритет кнопки и configMAX_SYSCALL_INTERRUPT_PRIORITY обязательно должны быть равны? Или это рекомендация из соображений экономии памяти и т. д. ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 187 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба 6 минут назад, LAS9891 сказал: Почему именно должно? В контексте Вашего прошлого вопроса было не понятно, разобрались Вы или нет. Поэтому написал, что в том случае должно было быть 192 (как минимум). Разумеется, может быть 192 и далее только в меньшую сторону. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LAS9891 0 6 сентября, 2022 Опубликовано 6 сентября, 2022 (изменено) · Жалоба 7 minutes ago, Arlleex said: Сохранили пару дней жизни мне Изменено 6 сентября, 2022 пользователем LAS9891 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 187 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба Но мое мнение - вешать кнопку на внешнее прерывание, в той реализации, которую Вы привели на первой странице - плохое решение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LAS9891 0 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба 1 minute ago, Arlleex said: Но мое мнение - вешать кнопку на внешнее прерывание, в той реализации, которую Вы привели на первой странице - плохое решение. А как лучше? в main.c в while(1){} её ждать ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 187 6 сентября, 2022 Опубликовано 6 сентября, 2022 · Жалоба 2 минуты назад, LAS9891 сказал: А как лучше? в main.c в while(1){} её ждать ? В любом достаточно периодичном процессе опрашивать. Хоть даже в прерывании таймера. Можно даже Ваш вариант подпилить напильником до нормальной работы, добавив антидребезг. Погуглите, что такое дребезг кнопки и сопоставьте скорость работы МК с его проявлением Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlanDrakes 1 11 сентября, 2022 Опубликовано 11 сентября, 2022 · Жалоба 1. По коду. Кажется, выполнять taskYIELD() внутри прерывания - не есть хорошо. 2. Полностью согласен с Arlleex - используйте задачу для опроса кнопки. Это позволит работать на одном уровне приоритета и не лезть в прерывания. Опрос, естественно, подобным образом: task1 () { xSemaphoreTake( xSemaphore, portMAX_DELAY ); do_something(); }; task2 () { if (button_pressed()) { xSemaphoreGive(xSemaphore); }; vTaskDelay(10); // 10 тиков планировщика. Не самый идеальный вариант ожидания, зато системный. }; 3. А если будет больше одной кнопки, можете взять очередь. Работать будет аналогичным образом. Основной поток пытается получить из очереди значение (бесконечно ожидая его), а поток-поллер проверяет кнопки и в зависимости от того, какая (какие) нажата (-ы) - кладёт в очередь соответствующее значение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться