Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум разработчиков электроники ELECTRONIX.ru _ FreeRTOS _ FreeRtos и его таски

Автор: Jenya7 Jun 6 2018, 08:55

Есть два таска - главный и логер с одинаковым приоритетом.В логере я записываю во флеш память большой кусок данных 4096 байт по SPI.

Код
do
{
     spi_rw_flash(0x00, &flash_data);
    *buff_in++ = flash_data;    /* read data to buffer */                
     leng--;
}while( leng > 0);
время записи 20 милисекунд. время переключения между тасками 2 милисекунды. по идее за эти 20 милисекунд должно быть 10 переключений между тасками.на деле я вижу что во время записи в логер главный таск застревает.Вопрос почему? И второй вопрос - если пришло время переключения таска - скедюлер даст SPI дозаписать текущий байт или выйдет посередине?

Автор: Lagman Jun 6 2018, 11:36

Все зависит от того в каком режиме RTOS работает, preemptive RTOS scheduler, or cooperative RTOS scheduler.

Автор: Jenya7 Jun 6 2018, 11:44

Цитата(Lagman @ Jun 6 2018, 16:36) *
Все зависит от того в каком режиме RTOS работает, preemptive RTOS scheduler, or cooperative RTOS scheduler.


у меня preemptive RTOS scheduler. может стоит перейти на cooperative?

Автор: Lagman Jun 6 2018, 12:41

Цитата(Jenya7 @ Jun 6 2018, 14:44) *
у меня preemptive RTOS scheduler. может стоит перейти на cooperative?

Наоборот, поведение похоже на cooperative.

Как работает в FreeRTOS
Any number of tasks can share the same priority. If configUSE_TIME_SLICING is not defined, or if configUSE_TIME_SLICING is set to 1, then Ready state tasks of equal priority will share the available processing time using a time sliced round robin scheduling scheme.

http://electronix.ru/redirect.php?https://freertos.org/RTOS-task-priority.html

Еще http://electronix.ru/redirect.php?https://freertos.org/a00110.html#configUSE_TIME_SLICING
configUSE_TIME_SLICING
By default (if configUSE_TIME_SLICING is not defined, or if configUSE_TIME_SLICING is defined as 1) FreeRTOS uses prioritised preemptive scheduling with time slicing. That means the RTOS scheduler will always run the highest priority task that is in the Ready state, and will switch between tasks of equal priority on every RTOS tick interrupt. If configUSE_TIME_SLICING is set to 0 then the RTOS scheduler will still run the highest priority task that is in the Ready state, but will not switch between tasks of equal priority just because a tick interrupt has occurred.

Автор: haker_fox Jun 6 2018, 14:49

QUOTE (Jenya7 @ Jun 6 2018, 16:55) *
Есть два таска - главный и логер с одинаковым приоритетом.В логере я записываю во флеш память большой кусок данных 4096 байт по SPI.
CODE
do
{
     spi_rw_flash(0x00, &flash_data);
    *buff_in++ = flash_data;    /* read data to buffer */                
     leng--;
}while( leng > 0);
время записи 20 милисекунд. время переключения между тасками 2 милисекунды. по идее за эти 20 милисекунд должно быть 10 переключений между тасками.на деле я вижу что во время записи в логер главный таск застревает.Вопрос почему? И второй вопрос - если пришло время переключения таска - скедюлер даст SPI дозаписать текущий байт или выйдет посередине?

Я надеюсь, у вас spi_rw_flash отдаёт управление шедулеру при первом удобном случае (работает только по прерываниям, используя средства межпроцессного взаимодействия.

Автор: aaarrr Jun 6 2018, 18:54

Цитата(Jenya7 @ Jun 6 2018, 11:55) *
...с одинаковым приоритетом

Вот и ответ - нет причин переключаться.

Цитата(Jenya7 @ Jun 6 2018, 11:55) *
И второй вопрос - если пришло время переключения таска - скедюлер даст SPI дозаписать текущий байт или выйдет посередине?

А что шедулер знает про SPI? Если SPI аппаратный, то пересылку слова закончит железка. Если нужно использовать SPI в разных задачах, то в любом случае придется разделять ресурс самостоятельно.

Автор: Jenya7 Jun 7 2018, 04:42

Цитата(haker_fox @ Jun 6 2018, 19:49) *
Я надеюсь, у вас spi_rw_flash отдаёт управление шедулеру при первом удобном случае (работает только по прерываниям, используя средства межпроцессного взаимодействия.

функция без прерываний
Код
uint8_t spi_rw_flash(uint8_t tx, uint8_t* rx)
{
    uint16_t counter_retry = 0;
    uint8_t err = 0;

      g_uiRecFlag_SFL = 0;

    // send byte
      err |= SFL_SPI_SendChar(tx);

    // wait until event of receive occurred
     while(!g_uiRecFlag_SFL){
         counter_retry++;
         if (counter_retry > SPI_TIMEOUT_RETRY)
             return 1;
     };

     // receive and save data in .
     err |= SFL_SPI_RecvChar(rx);

     g_uiRecFlag_SFL = 0;

     return err;
}

а как нужно отдавать управление шедулеру? по идее он сам знает когда переключиться на другой таск.

Автор: haker_fox Jun 7 2018, 08:20

QUOTE (Jenya7 @ Jun 7 2018, 12:42) *
функция без прерываний[code]uint8_t spi_rw_flash(uint8_t tx, uint8_t* rx)

Вот не делал бы я поллинг в системе, которая является событийно-ориентированный. Вы просто угробляете время проца, вместо того, чтобы отдать его более важной задачи. Я понимаю, что сейчас этой задачи нет. Но всё равно, так лучше не делать.
QUOTE (Jenya7 @ Jun 7 2018, 12:42) *
а как нужно отдавать управление шедулеру? по идее он сам знает когда переключиться на другой таск.

Да, если это ос вытесняющая, то таймер переключит вас с одного процесса на другой. Ну, а если вы молотите поллингом в задаче, у которой приоритет наивысший, то задачи с меньшим приоритетом никогда не получат управление. Нужно использовать прерывания, и ждать в задаче событий (используя семафоры, очереди, уведомления). Вот тогда, пока благородная железка занимается своим делом, вы ждёте прерывание, а процессор отдаёт это ожидание задаче, которая хочет что-то поделать, пусть она даже и низкоприоритетная. Когда железка закончит, она вызывает прерывание, а в прерывании вы сигналите задаче: "задача, для тебя есть работа". И если нет других, более приоритетных задач, то она получает управление. Обратите внимание, что в обоих случаях (по поллингу и с исопльзованием средств ос) задача ждёт, но время тратиться по-разному.

Почитать об этом вы можете в руководство на любую ос. Я рекомендую на scmRTOS. Там всё доходчиво разъяснено. Также почитайте http://electronix.ru/redirect.php?https://electronix.ru/forum/index.php?showtopic=24798 более, чем десятилетней давности. Там я задавал такие же вопросы)))


Автор: MrYuran Jun 7 2018, 10:57

Цитата(Jenya7 @ Jun 7 2018, 07:42) *
функция без прерываний

Переделайте на DMA.
Кинул ссылку на буфер - запустил - забыл.
По окончанию можно прерывание выставить, а если на хале - прописать колбэк.

Автор: datiqor Jun 8 2018, 14:03

Вот эта настройка : configUSE_TIME_SLICING, установлена в 1 ?

Автор: Lagman Jun 8 2018, 14:24

Цитата(datiqor @ Jun 8 2018, 17:03) *
Вот эта настройка : configUSE_TIME_SLICING, установлена в 1 ?


главное что бы она не была установлена в 0.

Автор: datiqor Jun 10 2018, 19:16

Цитата(Lagman @ Jun 8 2018, 17:24) *
главное что бы она не была установлена в 0.

Неа!
В исходниках ОС вот так проверяется : #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) ....

Автор: Lagman Jun 13 2018, 15:52

Цитата(datiqor @ Jun 10 2018, 22:16) *
Неа!
В исходниках ОС вот так проверяется : #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) ....

А если дальше поискать то можно найти в FreeRTOS\Source\include\FreeRTOS.h такие строчки:
Код
#ifndef configUSE_TIME_SLICING
    #define configUSE_TIME_SLICING 1
#endif

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)