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

FreeRTOS проба семафора.

В 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 версии операционки так.

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


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

3) Макрос configKERNEL_INTERRUPT_PRIORITY - это макрос, который определяет приоритет прерывания, используемого для тиков FreeRTOS. Т.е. это приоритет прерывания SysTick микроконтроллера равный 14. Так или не так?

4) Макрос configMAX_SYSCALL_INTERRUPT_PRIORITY - это макрос, который устанавливает наивысший приоритет ЧЕГО?, из которого могут быть вызваны защищенные для прерываний функции FreeRTOS API, т.е. функции в названии которых есть FromISR (например xSemaphoreGiveFromISR). Так или не так? Тока приоритет чего? прерываний или задач

 

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


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

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(). В остальных (более приоритетных) прерываниях использовать эти функции уже нельзя.

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


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

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

В контроллере прерывания настроил так:

1.thumb.JPG.86318f4e9fd24ba053f03a4b6691c453.JPG2.thumb.JPG.9bca263e48044ec6e9f27b4953bbab2e.JPG

При запуске отладки, до нажатия кнопки (прерывания) всё вроде норм. После нажатия случается один раз прерывание и всё виснет тут:

    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 ); // <-------------------------------------------------------ВОТ ТУТ
        }

 

Что не верно?

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

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


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

32 минуты назад, LAS9891 сказал:

Наверно имелось в виду: ((250 & 0xF0) >> 4) = 10...

Нет, Вы тоже не правы оказались, как и я (я подзабыл, что приоритет еще и в старших битах):wink:

Правильно будет все-таки 175, а не 250. Тогда (175 & 0xF0) >> 4 == 10.

Цитата

Согласны ли Вы с...

Да.

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


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

34 минуты назад, LAS9891 сказал:

Что не верно?

configMAX_SYSCALL_INTERRUPT_PRIORITY установите в 192.

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


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

12 minutes ago, Arlleex said:

configMAX_SYSCALL_INTERRUPT_PRIORITY установите в 192.

Почему? Хотя и так тоже работает

 

Всё заработало когда сделал так:

#define configKERNEL_INTERRUPT_PRIORITY       255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY  175

 

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

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


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

5 минут назад, LAS9891 сказал:

Почему?

175 - это число для получения приоритета 10 в Cortex-Mx. Взял с потолка в качестве примера.

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

Работает со 175 - логично, потому что будет работать со всеми NVIC_SetPriority(IRQn, x), где x == 15...10 (включительно).

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


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

1 minute ago, Arlleex said:

должно быть 192.

Почему именно должно? Если приоритет кнопки будет находиться в интервале между 10 и 15 (приоритеты 11, 12, 13, 14) это будет неправильно? Приоритет кнопки и configMAX_SYSCALL_INTERRUPT_PRIORITY обязательно должны быть равны? Или это рекомендация из соображений экономии памяти и т. д. ?

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


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

6 минут назад, LAS9891 сказал:

Почему именно должно?

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

Разумеется, может быть 192 и далее только в меньшую сторону.

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


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

7 minutes ago, Arlleex said:

 

954844252_.jpg.438115c001a944482250c8dbfb6be3f0.jpg

Сохранили пару дней жизни мне

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

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


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

Но мое мнение - вешать кнопку на внешнее прерывание, в той реализации, которую Вы привели на первой странице - плохое решение.

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


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

1 minute ago, Arlleex said:

Но мое мнение - вешать кнопку на внешнее прерывание, в той реализации, которую Вы привели на первой странице - плохое решение.

А как лучше? в main.c в while(1){} её ждать ?

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


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

2 минуты назад, LAS9891 сказал:

А как лучше? в main.c в while(1){} её ждать ?

В любом достаточно периодичном процессе опрашивать. Хоть даже в прерывании таймера.

Можно даже Ваш вариант подпилить напильником до нормальной работы, добавив антидребезг.

Погуглите, что такое дребезг кнопки и сопоставьте скорость работы МК с его проявлением:wink:

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


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

1. По коду.
Кажется, выполнять taskYIELD() внутри прерывания - не есть хорошо.

2. Полностью согласен с Arlleex - используйте задачу для опроса кнопки. Это позволит работать на одном уровне приоритета и не лезть в прерывания. Опрос, естественно, подобным образом:

task1 () {
 xSemaphoreTake( xSemaphore, portMAX_DELAY );
 do_something();
};

task2 () {
 if (button_pressed()) {
  xSemaphoreGive(xSemaphore);
 };
 vTaskDelay(10); // 10 тиков планировщика. Не самый идеальный вариант ожидания, зато системный.

};

3. А если будет больше одной кнопки, можете взять очередь. Работать будет аналогичным образом. Основной поток пытается получить из очереди значение (бесконечно ожидая его), а поток-поллер проверяет кнопки и в зависимости от того, какая (какие) нажата (-ы) - кладёт в очередь соответствующее значение.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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