STM32 task never gets ready

Odd thing. I have one task and one interrupt.
Task takes elements from queue, interrupt fills the queue. The problem is that the task is not woken if queue is empty and sleep time is grater than 1 if I do not use portYIELD_FROM_ISR() whithin ISR. Alternatively, all starts working if I create another doomy task that sleeps some time. But if another task uses vTaskSuspend(), problem is back again.

STM32 task never gets ready

Are you using the STM32 standard peripheral drivers?  If so, then read my first response here:
https://sourceforge.net/projects/freertos/forums/forum/382005/topic/8666292 Otherwise, do you have configUSE_PREEMPTION set to 1 in FreeRTOSConfig.h and are you sure the tick interrupt is executing (check the value of xTickCount in tasks.c)? Regards.

STM32 task never gets ready

Yes,  tick interrupt is executing but xTaskIncrementTick() only once returns pdTRUE (seen on de debbuger).
When I debug more the I get to the place in xQueueGenericSendFromISR() (marked)
....
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
    /* The task waiting has a higher priority so record that a
    context switch is required. */
    if( pxHigherPriorityTaskWoken != NULL ) // ## here
    {
        *pxHigherPriorityTaskWoken = pdTRUE;
    }
}
...
but in Idle task:
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
{
    taskYIELD(); // ## never get here
}
Here is my FreeRTOSConfig.h file.
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#ifdef __ICCARM__
    #include <stdint.h>
    uint32_t SystemCoreClock(void);
    //extern uint32_t SystemCoreClock;
#endif
#define configUSE_PREEMPTION            1
#define configUSE_IDLE_HOOK             1
#define configUSE_TICK_HOOK             1
#define configCPU_CLOCK_HZ              ( SystemCoreClock() )
#define configTICK_RATE_HZ              ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES            ( ( unsigned portBASE_TYPE ) 5 )
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 75 * 1024 ) )
#define configMAX_TASK_NAME_LEN         ( 10 )
#define configUSE_TRACE_FACILITY        1
#define configUSE_16_BIT_TICKS          0
#define configIDLE_SHOULD_YIELD         1
#define configUSE_MUTEXES               1
#define configQUEUE_REGISTRY_SIZE       8
#define configCHECK_FOR_STACK_OVERFLOW  2
#define configUSE_RECURSIVE_MUTEXES     1
#define configUSE_MALLOC_FAILED_HOOK    1
#define configUSE_APPLICATION_TASK_TAG  1
#define configUSE_NEWLIB_REENTRANT      1
#define configUSE_COUNTING_SEMAPHORES   1
#define configGENERATE_RUN_TIME_STATS   0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES       0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS                1
#define configTIMER_TASK_PRIORITY       ( 2 )
#define configTIMER_QUEUE_LENGTH        10
#define configTIMER_TASK_STACK_DEPTH    ( configMINIMAL_STACK_SIZE * 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   1
#define INCLUDE_vTaskSuspend            1
#define INCLUDE_vTaskDelayUntil         1
#define INCLUDE_vTaskDelay              1
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
    /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
    #define configPRIO_BITS             __NVIC_PRIO_BITS
#else
    #define configPRIO_BITS             4        /* 15 priority levels */
#endif
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         ( (1<<configPRIO_BITS) - 1)
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    1
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#include <assert.h>
#define configASSERT( x ) assert( x )
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */
Task Creation functionons
portTASK_FUNCTION(test, param)
{
    void __sinit( struct _reent *s );
    __sinit(_REENT);
    char stdout_buf[32];
    setbuf(stdin, NULL); // _IOLBF
    setvbuf(stdout, stdout_buf, _IOLBF, sizeof_array(stdout_buf));
    setbuf(stderr, NULL);
    int cnt = 0;
    char buf[32];
    while( 1 )
    {
        board_led_togle(LED3);
        board_led_togle(LED4);
        printf("%d:r", cnt++);
    }
}
portTASK_FUNCTION(test2, param)
{
    //vTaskSuspend
    while(1)
        vTaskDelay(portTICK_RATE_MS);
}
int main( void )
{
    extern void SystemInit();
    SystemInit();
    xTaskCreate(test, (signed char *)"Test", configMINIMAL_STACK_SIZE < 512 ? 512 : configMINIMAL_STACK_SIZE, NULL, 2, NULL);
//  xTaskCreate(test2, (signed char *)"Test2", 256, NULL, 2, NULL);
    vTaskStartScheduler();
    abort();
}
And Problematic code
int stm32f4_uart_dma_tc_isr( struct stm32f4_uart *u )
{
    assert(u->tx_dma->NDTR == 0);
    assert( (u->tx_dma->CR & DMA_SxCR_EN) == 0);
    assert( !xQueueIsQueueEmptyFromISR(u->tx_free_queue) || !xQueueIsQueueEmptyFromISR(u->tx_ready_queue) );
    signed portBASE_TYPE woken = 0;
    int res;
    DMA_ClearITPendingBit(u->tx_dma, DMA_IT_TCIFx);
    if( u->current_rx_buf_isr )
    {
        res = xQueueSendFromISR(u->tx_free_queue, &u->current_rx_buf_isr, &woken);
        assert(res == pdTRUE );
        u->current_rx_buf_isr = NULL;
    }
    struct stm32f4_uart_buffer * b = NULL;
    res = xQueueReceiveFromISR(u->tx_ready_queue, &b, NULL);
    u->current_rx_buf_isr = b;
    if( res == pdTRUE )
    {
        assert(b);
        u->tx_dma->M0AR = (uint32_t)b->data;
        u->tx_dma->NDTR = b->size;
        //DMA_ITConfig(u->tx_dma, DMA_IT_TC, ENABLE);
        DMA_Cmd(u->tx_dma, ENABLE);
    }
    else
    {
        assert(!b);
        //DMA_ITConfig(u->tx_dma, DMA_IT_TC, DISABLE);
    }
    return 0;
    return woken;
}
ssize_t stm32f4_uart_dma_write(void *__cookie, const char *__buf, size_t __n)
{
    size_t left = __n;
    struct stm32f4_uart *u = __cookie;
    struct stm32f4_uart_buffer *buf;
    while( left )
    {
        int res = xQueueReceive(u->tx_free_queue, &buf, portMAX_DELAY);
        assert(res == pdTRUE);
        buf->size = left > sizeof_array(buf->data) ? sizeof_array(buf->data) : left;
        memcpy(buf->data, __buf, buf->size);
        left -= buf->size;
        portENTER_CRITICAL();
        {
            res = xQueueSendToBackFromISR(u->tx_ready_queue, &buf, NULL);
            assert(res);
            if( u->tx_dma->NDTR == 0 )
            {
                stm32f4_uart_dma_tc_isr(u);
            }
        }
        portEXIT_CRITICAL();
    }
    return __n;
}

STM32 task never gets ready

For calification: code below is for testing and int stm32f4_uart_dma_tc_isr is also invoked from DMA handler.
return 0;
return woken;

STM32 task never gets ready

Are you using FreeRTOS V7.5.2? It is especially for STM32 users! If assert() of the stack overflow callback get called will you know by some means other than a printf()? Things I would try: Remove the printf() from your task, along with other stdio functions. You can add them back when it is working. What calls stm32f4_uart_dma_write()? If it is an interrupt then remove the critical section around the sendfromisr function. If it is not an interrupt then use the standard send function, again without the critical section (see http://www.freertos.org/FAQHelp.html)

STM32 task never gets ready

should be “If assert() or the stack overflow”

STM32 task never gets ready

@davedoors @richardbarry: yest, I am using FreeRTOS 7.5.2 @davedoors: assert() never calls printf like functions in my application. It call __assert_func which is
void __assert_func(const char *_file, int line, const char *func, const char *expr )
{
    while( 1 )
        asm volatile (" bkpt 1");
}
Remove the printf() from your task, along with other stdio functions. You can add them back when it is working.
Code tha was shown is for those functions 😛 I will try directly inwoke stm32f4_uart_dma_write() but doubt this will help.

STM32 task never gets ready

My fingers are faster than mind.
What calls stm32f4_uart_dma_write()? If it is an interrupt then remove the critical section around the sendfromisr function. If it is not an interrupt then use the standard send function, again without the critical section (see http://www.freertos.org/FAQHelp.html)
This is called by newlib IO (printf). It is not an interrupt.
Is it something wrong using portENTER_CRITICAL() and ..ISR() like functions? I whill have to call this leter to setup DMA stream so to save some ticks I used this constructions.

STM32 task never gets ready

The general rules are “don’t call API functions from critical sections”
“call the FromISR versions inside interrupts”
“call the standard (not the FromISR versions) from tasks” That keeps the rules simple and easy for people to follow.  In reality whether these rules matter or not depends on the situation and more importantly on the port being used.  On an STM32, doing what you are doing should be ok, I do similar things myself to optimise code, but with a bit of inside knowledge that you won’t get from the API.  It is however not a well tested usage scenario. The STM32 implements a nest-able critical section inside the xQueueSendToBackFromISR() function, so the critical section outside the function is obsolete, but provided this code is only executed from a task and not an interrupt, it should not be harmful.  I presume in this case the critical section is there to protect the ‘u’ variable, rather than the queue access. Going back to the original problem, am I correct in that the fundamental issue is that a task is blocked on a queue with a timeout, and if the timeout expires without any data arriving, then the task should unblock, but doesn’t? You also mention that, after the task should have unblocked (but didn’t), the tick interrupt is still executing, but xTaskIncrementTick() is returning false, hence no context switch is performed. Can you step through xTaskIncrementTick() when this situation has occurred?  We need to determine what it thinks the status of the system is.  Basically we need to determine what state the task is in, is it still blocked on the queue, and if not, where is it.  Maybe there just has been a data corruption within the kernel controlled data. I get nervous with printf() being used in tasks, especially if Newlib is being used (it is too big for small embedded systems, there is a new Newlib Nano now, but even so…), so I will also be interested to see if you notice a difference when you replace the printf() with a direct write to the serial port.  Start by writing to the serial port using a simple polling function to keep things as small as possible to start.  If that works, we can add back in the DMA, and if that works, build up to adding back printf(), until the problem occurs again. There is a very small and very limited printf() implementation that comes with FreeRTOS that just requires you to write a character output function.  You will find lots of copies of printf-stdarg.c in the FreeRTOS/Demo directory.  It is a third party file though. Regards.

STM32 task never gets ready

I got tired of trying to work with printf in tiny stuff and wrote a super tiny set of routines: PrintS, PrintI, PrintX, PrintB, and ScanI These allow some formatting of numbers.  If anyone is interested in them, let me know off-list.

STM32 task never gets ready

Ok after couple hours of debbuging I have something.
I have made an minimal test case that shows the error, see below (using stm32f4discovery & openOCD as debbuger). In this test case I am using heap_1.c as allocator. No NewLib call are made.
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "stm32f4xx_conf.h"
uint32_t SystemCoreClock( void )
{
    RCC_ClocksTypeDef clk;
    RCC_GetClocksFreq(&clk);
    return clk.SYSCLK_Frequency;
}
#define PLL_M      8
#define PLL_N      336
#define PLL_P      2
#define PLL_Q      7
#define BKPT(x) asm volatile ( "bkpt " # x );
// from STM32 library
static void SystemInit(void)
{
    RCC_DeInit();
    /******************************************************************************/
    /*            PLL (clocked by HSE) used as System clock source                */
    /******************************************************************************/
    /* Enable HSE */
    RCC_HSEConfig(RCC_HSE_ON);
    /* Wait till HSE is ready and if Time out is reached exit */
    if( RCC_WaitForHSEStartUp() == SUCCESS )
    {
        /* Enable high performance mode, System frequency up to 168 MHz */
        RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWREN, ENABLE);
        PWR_MainRegulatorModeConfig(PWR_Regulator_Voltage_Scale1);
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        RCC_PCLK2Config(RCC_HCLK_Div2);
        RCC_PCLK1Config(RCC_HCLK_Div4);
        RCC_PLLConfig( RCC_PLLSource_HSE, PLL_M, PLL_N, PLL_P, PLL_Q);
        RCC_PLLCmd(ENABLE);
        do { } while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != RESET );
        FLASH_SetLatency(FLASH_Latency_5); // FLASH_Latency_7
        FLASH_InstructionCacheCmd(ENABLE);
        FLASH_DataCacheCmd(ENABLE);
        FLASH_PrefetchBufferCmd(ENABLE);
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        do { } while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    }
    else
    { /* If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */
    }
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    GPIO_InitTypeDef GPIO_conf = { GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15, GPIO_Mode_OUT, GPIO_Speed_2MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL };
    GPIO_Init(GPIOD, &GPIO_conf);
}
xSemaphoreHandle xTestSemaphore;
portTASK_FUNCTION(test, param)
{
    GPIO_ResetBits(GPIOD, GPIO_Pin_12);
    for( int i = 0; i< 10; ++i )
    {
        int res = xSemaphoreTake(xTestSemaphore, portMAX_DELAY);
        if( !res )
        {
            while( 1 )
                BKPT(2);
        }
    }
    GPIO_SetBits(GPIOD, GPIO_Pin_12);
    do { BKPT(3); } while(1);
}
portTASK_FUNCTION(test2, param)
{
    while(1)
        vTaskDelay(configTICK_RATE_HZ);
}
int main( void )
{
    SystemInit();
    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
    xTaskCreate(test, (signed char *)"Test", 512, NULL, 3, NULL);
//  xTaskCreate(test2, (signed char *)"Test2", 256, NULL, 4, NULL);
    xTestSemaphore = xSemaphoreCreateCounting(4, 4);
    vTaskStartScheduler();
    while( 1 )
        BKPT(2);
}
void vApplicationIdleHook(void)
{ ; }
void vApplicationTickHook(void)
{
    static int i = 10;
    if( i != 0 )
    {
        i --;
        return;
    }
    xSemaphoreGiveFromISR(xTestSemaphore, NULL);
}
extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName )
{
    while(1)
        BKPT(1);
}
void vApplicationMallocFailedHook( void )
{
    while(1)
        BKPT(10);
}
void __assert_func(const char *_file, int line, const char *func, const char *expr )
{
    while( 1 )
        asm volatile (" bkpt 1");
}
void _exit( int i )
{
    while(1)
        BKPT(5);
}
The xSemaphoreGiveFromISR(xTestSemaphore, NULL);  seems to wort ok. It places test task in pxReadyTasksLists. What I have traced out is in xTaskIncrementTick(): the condition in if statement (task.c:1671) is always false since pxCurrentTCB points at IDLE task (priority 0) and there is only one task at this priority.
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 )
{
    xSwitchRequired = pdTRUE;
}
When I had uncommented code that creates task2, the task test is executing just after test2 delay expires (but before task2). It is because condition in task.c:1601 becomes true and xSwitchRequired variable is set to true, but still expression int task.c:1671 is false. Is there some issue in task.c:1671? I think, it should be checked also higher/(other/all?) priorities for readiness, not only current leve.

STM32 task never gets ready

I think I can see why this is happening now. In previous versions of FreeRTOS the tick interrupt performed a context switch on each tick.  Doing that meant tasks using
“FromISR” functions inside the tick hook didn’t need to pend a context switch from inside the tick hook function because a context switch was going to be performed anyway. V7.5.x changed that behaviour so a context switch is only performed when xTaskIncrementTick() returned pdTRUE – that is a major efficiency improvement but does have the effect that the tick hook function must now be treated like any other interrupt, with a context switch being pended if the “FromISR” function (xSemaphoreGiveFromISR() in this case) unblocks a task of equal or higher priority than the current Running state task.  In fact, the way it is, the last parameter to the “FromISR” functions is no longer really optional, especially if there are no other tasks in the system (which would only be the case is test code such as this, not real applications, although a user opting to set it to NULL is also opting to delay when the task will run, but the documents say it will be on the next tick). This needs to be highlighted and the documentation updated accordingly.  It might be that a check is inserted into the xTaskIncrementTick() function so it returns true if the highest priority ready state task is above the currently running task – but that would have a run time impact.  Instead, maybe an ASSERT() could be added to check this, with a comment above the assert noting the circumstances that can cause it to be hit.  That way the additional hit would only effect development builds. Regards.

STM32 task never gets ready

Ok, I understand your rationale about performance. But not every one need this “hard realtime” and even more, in example of my application I depend on old behaviour. When I unblock some higher priority task I do not want to switch context right now but wait for next tic to finish some lower priority jobs because there is still much buffered data do send. Doing a context switch is harmfull in this situation.
Your changed basic priciple on which someone depends. I made a quick and dirty patch for this, but problem stays open. Here is my patch
### Eclipse Workspace Patch 1.0
#P FreeRTOS
Index: Source/tasks.c
===================================================================
--- Source/tasks.c  (revision 5)
+++ Source/tasks.c  (working copy)
@@ -1666,14 +1666,47 @@
        /* Tasks of equal priority to the currently running task will share
        processing time (time slice) if preemption is on, and the application
        writer has not explicitly turned time slicing off. */
-       #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
+       #if ( configUSE_PREEMPTION == 1 )
        {
-           if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 )
+           if( xSwitchRequired == pdFALSE )
            {
-               xSwitchRequired = pdTRUE;
+               /* First check higher priority tasks */
+               unsigned portBASE_TYPE uxPriority = pxCurrentTCB->uxPriority + 1;
+               while( uxPriority < configMAX_PRIORITIES )
+               {
+                   if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 0 )
+                   {
+                       xSwitchRequired = pdTRUE;
+                   }
+
+                   ++uxPriority;
+               }
+
+               #if ( configUSE_TIME_SLICING == 1 )
+               /* then current priority */
+               if( xSwitchRequired == pdFALSE && listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 0 )
+               {
+                   if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 )
+                       xSwitchRequired = pdTRUE;
+               }
+               else
+               {
+                   /* at last lower priority tasks if no tasks at current priority */
+                   uxPriority = pxCurrentTCB->uxPriority;
+                   while( uxPriority )
+                   {
+                       uxPriority--;
+                       if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 0 )
+                       {
+                           xSwitchRequired = pdTRUE;
+                           break;
+                       }
+                   }
+               }
+               #endif /* ( configUSE_TIME_SLICING == 1 ) */
            }
        }
-       #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
+       #endif /*( configUSE_PREEMPTION == 1 ) */
    }
    else
    {

STM32 task never gets ready

In addition: your macros are hard to debug and very confusing. PS: can you enable last post editining option?

STM32 task never gets ready

I don’t get on well with patch files, but I think your solution won’t work when configPORT_OPTIMISED_TASK_SELECTION is set to 1. I have a small change that reverts to the previous behaviour using the xYieldPending variable.  If you write to me using the business contact link on http://www.freertos.org/contact I can send it to you to try. Regards.

STM32 task never gets ready

I turned on configUSE_PORT_OPTIMISED_TASK_SELECTION and at first run it worked but I will not argueue wiht you. I send an email on buisness contact address.

STM32 task never gets ready

richardbarry: file you send, seems to work.

STM32 task never gets ready

OK, I have the same problem on LPC1769 – when I use revision 1914 everything is fine, when I switch to 1927 – the TCP/IP becomes extremely unresponsive. The problem is that in all my interrupts I use proper return method – portENDSWITCHINGISR(higherprioritytask_woken). On the other hand the EMAC interrupt handler, which I took from some FreeRTOS example, does not use this function, as it does not use the FreeRTOS queue directly – the calls to FreeRTOS API is buried deep inside LwIP and there’s no good way to actually get the flag indicating that new task was woken up (I could use global variable, but does not seem pretty)… The problem is fixed in the most recent revision, but I wanted to know how should I proceed in the future – should I always find a way to end interrupt with portENDSWITCHINGISR() or maybe it’s handled automatically now? I guess it’s done automagically, as xTaskRemoveFromEventList() sets global variable xYieldPending to true, so using portENDSWITCHINGISR() gives only a speed gain that the switch will be done right after exit from ISR, right? Thx in advance.

STM32 task never gets ready

as xTaskRemoveFromEventList() sets global variable xYieldPending
[it’s not global, its file scope] That code is not released yet, but I’m actually just going through the release process now. It should be in SVN with the new version number very soon. If not tonight, then tomorrow. Regards.

STM32 task never gets ready

OK, file scope, true (; But that does not answer my question about “proper” interrupt handling with new FreeRTOS (; Regards, FCh

STM32 task never gets ready

I’m not sure what your question is. The setting of the pending yield does not remove the requirement to call portENDSWITCHINGISR / portYIELDFROMISR if you want the context switch to happen immediately that the interrupt exits. It just allows context switches requested from the tick hook to occur immediately, and ensure that context switches occur when there is only one task running (as per at the start of this thread). Regards.