From: Jeroen Domburg Date: Thu, 27 Oct 2016 08:18:55 +0000 (+0800) Subject: Merge latest master in X-Git-Tag: v1.0~95^2~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b14faabfdabb3b11ec19d666ebb40540eea90543;p=esp-idf Merge latest master in --- b14faabfdabb3b11ec19d666ebb40540eea90543 diff --cc components/freertos/Kconfig index 881c7616f3,1a65e1eeb7..e821d7445b --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@@ -172,6 -172,6 +172,14 @@@ menuconfig ENABLE_MEMORY_DEBU help Enable this option to show malloc heap block and memory crash detect ++config FREERTOS_ISR_STACKSIZE ++ int "ISR stack size" ++ range 1536 32768 ++ default 1536 ++ help ++ The interrupt handlers have their own stack. The size of the stack can be defined here. ++ Each processor has its own stack, so the total size occupied will be twice this. ++ menuconfig FREERTOS_DEBUG_INTERNALS bool "Debug FreeRTOS internals" default n @@@ -197,15 -197,6 +205,8 @@@ config FREERTOS_PORTMUX_DEBUG_RECURSIV If enabled, additional debug information will be printed for recursive portMUX usage. - config FREERTOS_ISR_STACKSIZE - int "ISR stack size" - range 1536 32768 - default 1536 - help - The interrupt handlers have their own stack. The size of the stack can be defined here. - Each processor has its own stack, so the total size occupied will be twice this. + + endif # FREERTOS_DEBUG_INTERNALS endmenu diff --cc components/freertos/tasks.c index 82b97fe268,386401904a..3cdca4d433 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@@ -584,70 -613,160 +616,188 @@@ static void prvAddNewTaskToReadyList( T /*-----------------------------------------------------------*/ +/* + * This routine tries to send an interrupt to another core if needed to make it execute a task + * of higher priority. We try to figure out if needed first by inspecting the pxTCB of the + * other CPU first. Specifically for Xtensa, we can do this because pxTCB is an atomic pointer. It + * is possible that it is inaccurate because the other CPU just did a task switch, but in that case + * at most a superfluous interrupt is generated. +*/ +void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) +{ + BaseType_t i; + if (xCoreID != tskNO_AFFINITY) { + if ( pxCurrentTCB[ xCoreID ]->uxPriority < uxPriority ) { + vPortYieldOtherCore( xCoreID ); + } + } + else + { + /* The task has no affinity. See if we can find a CPU to put it on.*/ + for (i=0; iuxPriority < uxPriority) + { + vPortYieldOtherCore( i ); + break; + } + } + } +} + + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - { - BaseType_t xReturn; - TCB_t * pxNewTCB; - StackType_t *pxTopOfStack; - BaseType_t i; - configASSERT( pxTaskCode ); - configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) ); - configASSERT( (xCoreID>=0 && xCoreID=0 && xCoreIDpxStack = ( StackType_t * ) puxStackBuffer; + + #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note this + task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL, xCoreID ); + prvAddNewTaskToReadyList( pxNewTCB, pxTaskCode, xCoreID ); + } + else + { + xReturn = NULL; + } + + return xReturn; + } + + #endif /* SUPPORT_STATIC_ALLOCATION */ + /*-----------------------------------------------------------*/ + + #if( portUSING_MPU_WRAPPERS == 1 ) + + BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) { - #if( portUSING_MPU_WRAPPERS == 1 ) - /* Should the task be created in privileged mode? */ - BaseType_t xRunPrivileged; - if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) + TCB_t *pxNewTCB; + BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + + configASSERT( pxTaskDefinition->puxStackBuffer ); + + if( pxTaskDefinition->puxStackBuffer != NULL ) + { + /* Allocate space for the TCB. Where the memory comes from depends + on the implementation of the port malloc function and whether or + not static allocation is being used. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) { - xRunPrivileged = pdTRUE; + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; + + /* Tasks can be created statically or dynamically, so note + this task had a statically allocated stack in case it is + later deleted. The TCB was allocated dynamically. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; + + prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, + pxTaskDefinition->pcName, + ( uint32_t ) pxTaskDefinition->usStackDepth, + pxTaskDefinition->pvParameters, + pxTaskDefinition->uxPriority, + pxCreatedTask, pxNewTCB, + pxTaskDefinition->xRegions, + tskNO_AFFINITY ); + + prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY ); + xReturn = pdPASS; } - else + } + + return xReturn; + } + + #endif /* portUSING_MPU_WRAPPERS */ + /*-----------------------------------------------------------*/ + + #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask, + const BaseType_t xCoreID ) + { + TCB_t *pxNewTCB; + BaseType_t xReturn; + + /* If the stack grows down then allocate the stack then the TCB so the stack + does not grow into the TCB. Likewise if the stack grows up then allocate + the TCB then the stack. */ + #if( portSTACK_GROWTH > 0 ) + { + /* Allocate space for the TCB. Where the memory comes from depends on + the implementation of the port malloc function and whether or not static + allocation is being used. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) { - xRunPrivileged = pdFALSE; + /* Allocate space for the stack used by the task being created. + The base of the stack memory stored in the TCB so the task can + be deleted later if required. */ + pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } } - uxPriority &= ~portPRIVILEGE_BIT; + } + #else /* portSTACK_GROWTH */ + { + StackType_t *pxStack; + + /* Allocate space for the stack used by the task being created. */ + pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - if( puxStackBuffer != NULL ) + if( pxStack != NULL ) { - /* The application provided its own stack. Note this so no - attempt is made to delete the stack should that task be - deleted. */ - pxNewTCB->xUsingStaticallyAllocatedStack = pdTRUE; + /* Allocate space for the TCB. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */ + + if( pxNewTCB != NULL ) + { + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxStack; + } + else + { + /* The stack cannot be used as the TCB was not created. Free + it again. */ + vPortFree( pxStack ); + } } else { @@@ -751,49 -1059,35 +1090,49 @@@ static void prvAddNewTaskToReadyList( T { mtCOVERAGE_TEST_MARKER(); } + } - uxTaskNumber++; + uxTaskNumber++; - #if ( configUSE_TRACE_FACILITY == 1 ) - { - /* Add a counter into the TCB for tracing only. */ - pxNewTCB->uxTCBNumber = uxTaskNumber; - } - #endif /* configUSE_TRACE_FACILITY */ - traceTASK_CREATE( pxNewTCB ); + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); - prvAddTaskToReadyList( pxNewTCB ); + prvAddTaskToReadyList( pxNewTCB ); - xReturn = pdPASS; - portSETUP_TCB( pxNewTCB ); - } - taskEXIT_CRITICAL(&xTaskQueueMutex); - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - traceTASK_CREATE_FAILED(); + portSETUP_TCB( pxNewTCB ); } + taskEXIT_CRITICAL(&xTaskQueueMutex); - if( xReturn == pdPASS ) + if( xSchedulerRunning != pdFALSE ) { - if( xSchedulerRunning != pdFALSE ) + /* Scheduler is running. If the created task is of a higher priority than an executing task + then it should run now. + ToDo: This only works for the current core. If a task is scheduled on an other processor, + the other processor will keep running the task it's working on, and only switch to the newer + task on a timer interrupt. */ + //No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires. + if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < pxNewTCB->uxPriority ) { - taskYIELD_IF_USING_PREEMPTION(); + /* Scheduler is running. If the created task is of a higher priority than an executing task + then it should run now. + No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires. + */ - if( tskCAN_RUN_HERE( xCoreID ) && pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < uxPriority ) ++ if( tskCAN_RUN_HERE( xCoreID ) && pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < pxNewTCB->uxPriority ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else if( xCoreID != xPortGetCoreID() ) { - taskYIELD_OTHER_CORE(xCoreID, uxPriority); ++ taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else {