Jump to content

    

FreeRTOS - минимальное время тика?

Дык, тогда и не пишите тут то, что вызывает такую реакцию, кстати, вполне естественную реакцию

 

Так вот...

Упростил как мог, все выкинул никаких тачлибов и всего остального, только 2 задачи.

xSemaphoreHandle xSem1ms;    
volatile uint32_t ctim100us;    
uint8_t FlagCreateTask;
void TIM10_IRQHandler(void)
{
    static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    
    if(TIM_GetFlagStatus(TIM10, TIM_FLAG_Update) != RESET)
    {
        TIM_ClearFlag(TIM10, TIM_FLAG_Update);
        if(ctim100us) ctim100us--;
        else 
        {
            xSemaphoreGiveFromISR(xSem1ms, &xHigherPriorityTaskWoken);
            portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
        }
    }
}
int main(void)
{    
    xTaskCreate(Task2, "Task2-handler", configMINIMAL_STACK_SIZE, NULL, 1, NULL);    
    vTaskStartScheduler();
}
void Task2(void *pParams)
{

    FlagCreateTask = 0;
    vSemaphoreCreateBinary(xSem1ms);

    xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    while(1)
    {
        if(FlagCreateTask != 0) continue;
        xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    }
}
void Task1(void *pParams)
{
    uint16_t count = 3;

    xSemaphoreTake(xSem1ms, 0);
    FlagCreateTask = 1;

    ctim100us = count;
    Tx_Init();

    while(1)
    {
        if(xSemaphoreTake(xSem1ms, 10) != pdTRUE) continue;
        count++;
        if(count > 9) break;
    taskENTER_CRITICAL();
        ctim100us = count;
    taskEXIT_CRITICAL();
        GPIO_ToggleBits(GPIOB, GPIO_Pin_5);//пин контроля работы программы
    }
    TIM_DeInit(TIM10);
    FlagCreateTask = 0;
    vTaskDelete(NULL);
}

 

После выхода из обработчика прерывания TIM10 в случае выполнения portEND_SWITCHING_ISR(xHigherPriorityTaskWoken) программа попадает в Task2.

О Боже, за что?

Даже таймер настроен на 100мкс

Edited by maxntf

Share this post


Link to post
Share on other sites
Так вот...

Судя по всему, у обеих задач одинаковые приоритеты.

А Task2 вообще ВСЕГДА готова к выполнения.

Т.е. всегда что-то делает...

Более того, честно говоря, я чуть моск не сломал, пока попытался понять логику работы "флажка" FlagCreateTask :wacko:

Так нифига и не понял, что вы задумали (((

 

А вообще, прочитайте, наконец, нормальный мануал, как писать проекты под RTOS, посмотрите видео на ютубе, примеры из мануала и т. п.

Посмотрите примеры применения, конкретные рабочие примеры. Желательно это делать перед тем, как плодить франкешнейнов самодеятельность, и уж тем более тут это публиковать ;)

 

FreeRTOS запускается с полпинка и работает как и любая друга RTOS, но необходимы хотя бы базовые знания. Решите сначала этот вопрос!

Уверяю, ничего сверхсложного тут нет, все через это прошли ))

 

Немного упрощу задачу. Вот яркий пример откровенной самодеятельности:

    while(1)
    {
        if(FlagCreateTask != 0) continue;
        xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    }

 

Share this post


Link to post
Share on other sites
Судя по всему, у обеих задач одинаковые приоритеты.

 

Судя по чему конкретно?

xTaskCreate(Task2, "Task2-handler", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

 

А вообще, прочитайте, наконец, нормальный мануал, как писать проекты под RTOS...

 

Какие проекты, я про конкретный случай спрашиваю.

Убрал то, что моск ломает.

void Task2(void *pParams)
{
    vSemaphoreCreateBinary(xSem1ms);
    xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    while(1);
}
void Task1(void *pParams)
{
    xSemaphoreTake(xSem1ms, 0);
    ctim100us = 10;
    Tx_Init();
    xSemaphoreTake(xSem1ms, 10);    
    TIM_DeInit(TIM10);
    vTaskDelete(NULL);
}

 

Если задачи с одинаковым приоритетом, почему? Может где то настройки FreeRTOS?

Если Task2 всегда готова к выполнению, то когда срабатывает portEND_SWITCHING_ISR(xHigherPriorityTaskWoken) разве после выхода из прерывания контекст не должен переключится с Task2 на Task1?

Edited by maxntf

Share this post


Link to post
Share on other sites
xTaskCreate(Task2, "Task2-handler", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

Исходя из мануала

Task1 имеет приоритет выше, чем Task2. Признаю, тут я не доглядел (( .... Ненавижу функции с числом параметров больше одного-двух - невозможно разобраться без мануала :(

 

Убрал то, что моск ломает.
Уже проще ;)

 

Может где то настройки FreeRTOS?
Еще раз на всякий случай приведите настройки (в теге CODEBOX).

Share this post


Link to post
Share on other sites
Еще раз на всякий случай приведите настройки (в теге CODEBOX).

Для проверки работы приоритетов поменял приоритеты задач - программа в Task1 вообще не попадает, значит приоритеты работают.


#define configTICK_RATE_HZ						( ( TickType_t ) 1000 )
#define configCPU_CLOCK_HZ						( SystemCoreClock )
#define configUSE_PREEMPTION					1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION	1
#define configUSE_IDLE_HOOK						1
#define configUSE_TICK_HOOK						1
#define configMAX_PRIORITIES					( 5 )
#define configMINIMAL_STACK_SIZE				( ( unsigned short ) 120 )
#define configTOTAL_HEAP_SIZE					( ( size_t ) ( 12 * 1024 ) )
#define configMAX_TASK_NAME_LEN					( 16 )
#define configUSE_TRACE_FACILITY				1
#define configUSE_16_BIT_TICKS					0
#define configIDLE_SHOULD_YIELD					1
#define configUSE_MUTEXES						1
#define configQUEUE_REGISTRY_SIZE				5
#define configCHECK_FOR_STACK_OVERFLOW			2
#define configUSE_RECURSIVE_MUTEXES				1
#define configUSE_MALLOC_FAILED_HOOK			1
#define configUSE_APPLICATION_TASK_TAG			0
#define configUSE_COUNTING_SEMAPHORES			1

/* Software timer related definitions. */
#define configUSE_TIMERS						1
#define configTIMER_TASK_PRIORITY				( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH				10
#define configTIMER_TASK_STACK_DEPTH			configMINIMAL_STACK_SIZE

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 			0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet		1
#define INCLUDE_uxTaskPriorityGet		1
#define INCLUDE_vTaskDelete				1
#define INCLUDE_vTaskCleanUpResources	0
#define INCLUDE_vTaskSuspend			1
#define INCLUDE_vTaskDelayUntil			1
#define INCLUDE_vTaskDelay				1

/* Standard assert semantics. */
//#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }	

/* Use the system definition, if there is one */
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS       __NVIC_PRIO_BITS
#else
#define configPRIO_BITS       4        /* 15 priority levels */
#endif

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5

/* The lowest priority. */
#define configKERNEL_INTERRUPT_PRIORITY 	( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Priority 5, or 95 as only the top four bits are implemented. */
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/* Run time stats related macros. */
#define configGENERATE_RUN_TIME_STATS	0

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */

Edited by maxntf

Share this post


Link to post
Share on other sites

Создайте сразу две задачи (можно с разными приоритетами),

воткните в бесконечный цикл каждой задачи что-нибудь для постановки ее в очередь ожидания, например sleep(1) (или что там используется у freertos).

 

Поставьте по одному бряку внутри задач 1 и 2 и см. как идет процесс переключения задач.

 

Они должны переключаться по очереди.

 

Далее добавляйте свой код по чуть-чуть и смотрите, что сыпется от него.

 

Share this post


Link to post
Share on other sites

Похоже отладчик всему беда.

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

Share this post


Link to post
Share on other sites
Похоже отладчик всему беда.

Что же за отладчик такой, если не секрет?

 

Share this post


Link to post
Share on other sites
Что же за отладчик такой, если не секрет?

Тот что в Keil.

Причем только в пошаговом режиме кнопками Step или Step Over при выходе из обработчика прерываний.

А если поставить брекпоинты в задачах, и выйти из прерывания Step Out или Run тогда попадаем куда нужно, то есть в Task2.

Share this post


Link to post
Share on other sites
Тот что в Keil.

Причем только в пошаговом режиме кнопками Step или Step Over при выходе из обработчика прерываний.

А если поставить брекпоинты в задачах, и выйти из прерывания Step Out или Run тогда попадаем куда нужно, то есть в Task2.

Оптимизацию отключите, хотя бы для debug сборки. При пошаговой отладке она только вредит.

Или как вариант - ходить не по C/C++ исходникам, а в по командам в окне disasm.

 

И вообще, изучайте инструмент, а то вон 8 страниц наплодили по сути на пустом месте :)

Share this post


Link to post
Share on other sites
Оптимизацию отключите, хотя бы для debug сборки. При пошаговой отладке она только вредит.

Или как вариант - ходить не по C/C++ исходникам, а в по командам в окне disasm.

Оптимизация стоит Level 0, и сделал я это сразу после установки кейла. Никогда оптимизацию не использую.

Да хоть по Cи, хоть по disasm. Был бы disbasic :) думаю так же работал.

 

Эта реплика к чему?

И вообще, изучайте инструмент, а то вон 8 страниц наплодили по сути на пустом месте :)

Где про это сказано?

Share this post


Link to post
Share on other sites
Оптимизация стоит Level 0, и сделал я это сразу после установки кейла. Никогда оптимизацию не использую.

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

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

Я с таким "багом" столкнулся в старой TNKernel, что, кстати, заставило ее поменять на другую ртос - как раз на freeRTOS

В ней такого "бага" нет. Это я сразу проверил, как только освоил. В ней все работает как надо. Но с настройками повозился, к слову, отключил нафик динамическую память (у freeRTOS есть свой типа диспетчер дин. памяти)

 

Если весь код состоит из макросов (define), то старый компилятор кейла (v5) не умеет ходить по макросам. Новый v6 умеет.

Возможно, тут есть проблемы.

 

К проекту подключены исходники freeRTOS или заранее собранная библиотека (lib)?

Share this post


Link to post
Share on other sites
Вангую, что переключение задачи на активную происходит лишь при отработке прерывания системного таймера.

Нет.

Поставил 3 брекпоинта. Task1, Task2 и в xPortSysTickHandler.

Сразу попадаем в Task1.

 

P.S.

Возможно я ошибаюсь, но что то мне подсказывает, что по функции Step и Step Over отладчик не может попасть в прерывание, а собственно это и должно произойти после выход из обработчика прерывания TIM10, программа должна попасть в PendSV Handler.

Edited by maxntf

Share this post


Link to post
Share on other sites
Нет.

Поставил 3 брекпоинта. Task1, Task2 и в xPortSysTickHandler.

Сразу попадаем в Task2.

 

P.S.

Возможно я ошибаюсь, но что то мне подсказывает, что по функции Step и Step Over отладчик не может попасть в прерывание, а собственно это и должно произойти после выход из обработчика прерывания TIM10.

Ну значит задача просто закончила свою работу и сама вызвала диспетчер. Никакой мистики.

Так все операционки устроены

Share this post


Link to post
Share on other sites
Нет.

Поставил 3 брекпоинта. Task1, Task2 и в xPortSysTickHandler.

Сразу попадаем в Task2.

Пройдите под отладчиком по окну дизасма, анализирую содержимое стека. В частности при выходе из прерывания.

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

 

И приведите код этого "проекта" (в теге CODEBOX)

 

Ну значит задача просто закончила свою работу и сама вызвала диспетчер. Никакой мистики. Так все операционки устроены

© "Слышу звон, да не знаю, где он" :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now