diff --git a/rtos/rtx/TARGET_CORTEX_A/cmsis_os.h b/rtos/rtx/TARGET_CORTEX_A/cmsis_os.h index d1449cc77c..5bd60ed23a 100644 --- a/rtos/rtx/TARGET_CORTEX_A/cmsis_os.h +++ b/rtos/rtx/TARGET_CORTEX_A/cmsis_os.h @@ -224,6 +224,16 @@ typedef enum { osTimerPeriodic = 1 ///< repeating timer } os_timer_type; +typedef enum { + osThreadInfoState, + osThreadInfoStackSize, + osThreadInfoStackMax, + osThreadInfoEntry, + osThreadInfoArg, + + osThreadInfo_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization. +} osThreadInfo; + /// Entry point of a thread. /// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS. typedef void (*os_pthread) (void const *argument); @@ -451,6 +461,13 @@ osPriority osThreadGetPriority (osThreadId thread_id); uint8_t osThreadGetState (osThreadId thread_id); #endif +/// Get into from an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] info information to read. +/// \return current state of the thread function. +/// \return requested info that includes the status code. +os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info); + // ==== Generic Wait Functions ==== /// Wait for Timeout (Time Delay). diff --git a/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c b/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c index 2a23d1958e..7f71b8e0ff 100644 --- a/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c +++ b/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c @@ -713,6 +713,7 @@ SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET SVC_0_1(svcThreadYield, osStatus, RET_osStatus) SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus) SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority) +SVC_2_3(svcThreadGetInfo, os_InRegs osEvent, osThreadId, osThreadInfo, RET_osEvent) // Thread Service Calls @@ -851,6 +852,80 @@ osPriority svcThreadGetPriority (osThreadId thread_id) { return (osPriority)(ptcb->prio - 1 + osPriorityIdle); } +/// Get info from an active thread +os_InRegs osEvent_type svcThreadGetInfo (osThreadId thread_id, osThreadInfo info) { + P_TCB ptcb; + osEvent ret; + ret.status = osOK; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) { + ret.status = osErrorValue; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_status; + return; +#else + return osEvent_ret_status; +#endif + } + + if (osThreadInfoStackSize == info) { + uint32_t size; + size = ptcb->priv_stack; + if (0 == size) { + // This is an OS task - always a fixed size + size = os_stackinfo & 0x3FFFF; + } + ret.value.v = size; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_value; + return; +#else + return osEvent_ret_value; +#endif + } + + if (osThreadInfoStackMax == info) { + // Cortex-A RTX does not have stack init so + // the maximum stack usage cannot be obtained. + ret.status = osErrorResource; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_status; + return; +#else + return osEvent_ret_status; +#endif + } + + if (osThreadInfoEntry == info) { + ret.value.p = (void*)ptcb->ptask; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_value; + return; +#else + return osEvent_ret_value; +#endif + } + + if (osThreadInfoArg == info) { + ret.value.p = (void*)ptcb->argv; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_value; + return; +#else + return osEvent_ret_value; +#endif + } + + // Unsupported option so return error + ret.status = osErrorParameter; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_status; + return; +#else + return osEvent_ret_status; +#endif +} // Thread Public API @@ -930,6 +1005,16 @@ uint8_t osThreadGetState (osThreadId thread_id) { } #endif +/// Get the requested info from the specified active thread +os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info) { + osEvent ret; + if (__exceptional_mode()) { + ret.status = osErrorISR; + return ret; // Not allowed in ISR + } + return __svcThreadGetInfo(thread_id, info); +} + osThreadEnumId osThreadsEnumStart() { static uint32_t thread_enum_index; osMutexWait(osMutexId_osThreadMutex, osWaitForever); diff --git a/rtos/rtx/TARGET_CORTEX_A/rt_TypeDef.h b/rtos/rtx/TARGET_CORTEX_A/rt_TypeDef.h index 832f9ad008..568c4389ef 100644 --- a/rtos/rtx/TARGET_CORTEX_A/rt_TypeDef.h +++ b/rtos/rtx/TARGET_CORTEX_A/rt_TypeDef.h @@ -85,6 +85,7 @@ typedef struct OS_TCB { /* Task entry point used for uVision debugger */ FUNCP ptask; /* Task entry address */ + void *argv; /* Task argument */ } *P_TCB; #define TCB_TID 3 /* 'task id' offset */ #define TCB_STACKF 37 /* 'stack_frame' offset */ diff --git a/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h b/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h index c59ff18994..44cc2ebf7a 100644 --- a/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h +++ b/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h @@ -160,6 +160,16 @@ typedef enum { osTimerPeriodic = 1 ///< repeating timer } os_timer_type; +typedef enum { + osThreadInfoState, + osThreadInfoStackSize, + osThreadInfoStackMax, + osThreadInfoEntry, + osThreadInfoArg, + + osThreadInfo_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization. +} osThreadInfo; + /// Entry point of a thread. typedef void (*os_pthread) (void const *argument); @@ -361,6 +371,13 @@ osPriority osThreadGetPriority (osThreadId thread_id); uint8_t osThreadGetState (osThreadId thread_id); #endif +/// Get into from an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] info information to read. +/// \return current state of the thread function. +/// \return requested info that includes the status code. +os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info); + // ==== Generic Wait Functions ==== /// Wait for Timeout (Time Delay). diff --git a/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c b/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c index dc259660bd..092539bb63 100644 --- a/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c +++ b/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c @@ -637,6 +637,7 @@ SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET SVC_0_1(svcThreadYield, osStatus, RET_osStatus) SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus) SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority) +SVC_2_3(svcThreadGetInfo, os_InRegs osEvent, osThreadId, osThreadInfo, RET_osEvent) // Thread Service Calls @@ -796,6 +797,67 @@ osPriority svcThreadGetPriority (osThreadId thread_id) { return (osPriority)(ptcb->prio - 1 + osPriorityIdle); } +/// Get info from an active thread +os_InRegs osEvent_type svcThreadGetInfo (osThreadId thread_id, osThreadInfo info) { + P_TCB ptcb; + osEvent ret; + ret.status = osOK; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) { + ret.status = osErrorValue; + return osEvent_ret_status; + } + + if (osThreadInfoStackSize == info) { + uint32_t size; + size = ptcb->priv_stack; + if (0 == size) { + // This is an OS task - always a fixed size + size = os_stackinfo & 0x3FFFF; + } + ret.value.v = size; + return osEvent_ret_value; + } + + if (osThreadInfoStackMax == info) { + uint32_t i; + uint32_t *stack_ptr; + uint32_t stack_size; + if (!(os_stackinfo & (1 << 28))) { + // Stack init must be turned on for max stack usage + ret.status = osErrorResource; + return osEvent_ret_status; + } + stack_ptr = (uint32_t*)ptcb->stack; + stack_size = ptcb->priv_stack; + if (0 == stack_size) { + // This is an OS task - always a fixed size + stack_size = os_stackinfo & 0x3FFFF; + } + for (i = 1; i ptask; + return osEvent_ret_value; + } + + if (osThreadInfoArg == info) { + ret.value.p = (void*)ptcb->argv; + return osEvent_ret_value; + } + + // Unsupported option so return error + ret.status = osErrorParameter; + return osEvent_ret_status; +} // Thread Public API @@ -890,6 +952,17 @@ uint8_t osThreadGetState (osThreadId thread_id) { } #endif +/// Get the requested info from the specified active thread +os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info) { + osEvent ret; + + if (__get_IPSR() != 0U) { // Not allowed in ISR + ret.status = osErrorISR; + return ret; + } + return __svcThreadGetInfo(thread_id, info); +} + osThreadEnumId osThreadsEnumStart() { static uint32_t thread_enum_index; osMutexWait(osMutexId_osThreadMutex, osWaitForever); diff --git a/rtos/rtx/TARGET_CORTEX_M/rt_Task.c b/rtos/rtx/TARGET_CORTEX_M/rt_Task.c index 3179a5192f..812978fdc6 100644 --- a/rtos/rtx/TARGET_CORTEX_M/rt_Task.c +++ b/rtos/rtx/TARGET_CORTEX_M/rt_Task.c @@ -247,6 +247,7 @@ OS_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv) { task_context->task_id = (U8)i; /* Pass parameter 'argv' to 'rt_init_context' */ task_context->msg = argv; + task_context->argv = argv; /* For 'size == 0' system allocates the user stack from the memory pool. */ rt_init_context (task_context, (U8)(prio_stksz & 0xFFU), task); diff --git a/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h b/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h index 39cb9d477e..f16b96ec20 100644 --- a/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h +++ b/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h @@ -79,6 +79,7 @@ typedef struct OS_TCB { /* Task entry point used for uVision debugger */ FUNCP ptask; /* Task entry address */ + void *argv; /* Task argument */ void *context; /* Pointer to thread context */ } *P_TCB; #define TCB_STACKF 37 /* 'stack_frame' offset */