Beispiel #1
0
/*******************************************************************************
 * vTraceStoreKernelCallWithNumericParamOnly
 *
 * Used for storing kernel calls with numeric parameters only. This is
 * only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment.
 ******************************************************************************/
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint16_t param)
{
    KernelCallWithParam16 * kse;
    uint8_t dts6;

    if (RecorderDataPtr->recorderActive && handle_of_last_logged_task 
        && (! inExcludedTask || nISRactive))
    {
        /* Check if the event code is excluded */
        if (!GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
        {
            trcCRITICAL_SECTION_BEGIN();
            dts6 = (uint8_t)prvTraceGetDTS(0xFF);

            if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
            {                
                kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();
                if (kse != NULL)
                {
                    kse->dts = dts6;
                    kse->type = (uint8_t)evtcode;
                    kse->param = param;
                    prvTraceUpdateCounters();    
                }
            }
            trcCRITICAL_SECTION_END();
        }
    }
}
Beispiel #2
0
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, 
                                             traceObjectClass objectclass)
{
    ObjClosePropEvent * pe;

    if (objectclass == TRACE_CLASS_ISR)
    {        
        /* ISR handles should not be closed - never called for ISR */
        return;
    }

    // Interrupt disable not necessary, already done in trcHooks.h macro
    pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();
    if (pe != NULL)
    {
        if (objectclass == TRACE_CLASS_TASK)
        {
            pe->arg1 = PROPERTY_ACTOR_PRIORITY(objectclass, handle);
            pe->arg2 = PROPERTY_TASK_IFE_SERVICECODE(handle);
            pe->arg3 = PROPERTY_TASK_IFE_OBJHANDLE(handle);
            PROPERTY_TASK_IFE_SERVICECODE(handle) = 0;
            PROPERTY_TASK_IFE_OBJHANDLE(handle) = 0;
        }else{
            pe->arg1 = PROPERTY_OBJECT_STATE(objectclass, handle);
        }
        pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass;    
        prvTraceUpdateCounters();
    }
}
Beispiel #3
0
/*******************************************************************************
 * vTraceStoreKernelCallWithParam
 *
 * Used for storing kernel calls with a handle and a numeric parameter. This is
 * only used for traceTASK_PRIORITY_SET at the moment.
 ******************************************************************************/
void vTraceStoreKernelCallWithParam(uint32_t evtcode,
                                    traceObjectClass objectClass,
                                    uint32_t objectNumber,
                                    uint8_t param)
{
    KernelCallWithParamAndHandle * kse;
    uint8_t dts2;

    if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && 
        (! inExcludedTask || nISRactive))
    {
        /* Check if the referenced object or the event code is excluded */
        if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
        {
            trcCRITICAL_SECTION_BEGIN();
            dts2 = (uint8_t)prvTraceGetDTS(0xFF);

            if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
            {                
                kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();
                if (kse != NULL)
                {
                    kse->dts = dts2;
                    kse->type = (uint8_t)evtcode;
                    kse->objHandle = (uint8_t)objectNumber;
                    kse->param = param;
                    prvTraceUpdateCounters();    
                }
            }
            trcCRITICAL_SECTION_END();
        }
    }
}
Beispiel #4
0
/*******************************************************************************
 * vTraceStoreKernelCall
 *
 * This is the main integration point for storing FreeRTOS kernel calls, and
 * is called by the hooks in FreeRTOS.h (see trcKernel.h for event codes).
 ******************************************************************************/
void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)
{
    KernelCall * kse;
    uint16_t dts1;

    if (handle_of_last_logged_task == 0)
    {
        return;
    }
    
    if (RecorderDataPtr->recorderActive)
    {
        
        /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
        if (nISRactive || !inExcludedTask)
        {
            /* Make sure ISRs never change the IFE flags of tasks */
            if (!nISRactive)
            {
                /* This checks if this is the first kernel call after a call to
                vTraceTaskInstanceIsFinished. In that case, calls to this kernel service 
                with this specific kernel object become the "instance finish event"
                (IFE) of the calling task.*/
                if (GET_TASK_FLAG_MARKIFE(handle_of_last_logged_task))
                {
                    /* Reset the flag - this has been handled now */
                    CLEAR_TASK_FLAG_MARKIFE(handle_of_last_logged_task);

                    /* Store the kernel service tagged as instance finished event */
                    PROPERTY_TASK_IFE_SERVICECODE(handle_of_last_logged_task) = 
                      (uint8_t)ecode;                

                    /* Store the handle of the specific kernel object */
                    PROPERTY_TASK_IFE_OBJHANDLE(handle_of_last_logged_task) =
                      (objectHandleType)objectNumber;    
                }
            }
            
            /* Check if the referenced object or the event code is excluded */
            if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))
            {
                trcCRITICAL_SECTION_BEGIN();
                dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);

                if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
                {           
                    kse = (KernelCall*) xTraceNextFreeEventBufferSlot();
                    if (kse != NULL)
                    {
                        kse->dts = dts1;
                        kse->type = (uint8_t)ecode;
                        kse->objHandle = (uint8_t)objectNumber;
                        prvTraceUpdateCounters();
                    }
                }
                trcCRITICAL_SECTION_END();
            }
        }
    }
}
Beispiel #5
0
/*******************************************************************************
 * prvTraceGetParam
 *
 * Used for storing extra bytes for kernel calls with numeric parameters.
 ******************************************************************************/
static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
{
	XPSEvent* xps;
	if (param <= param_max)
	{
		return param;
	}
	else
	{
		xps = (XPSEvent*) xTraceNextFreeEventBufferSlot();
		if (xps != NULL)
		{
			xps->type = DIV_XPS;
			xps->xps_8 = (param & (0xFF00 & ~param_max)) >> 8;
			xps->xps_16 = (param & (0xFFFF0000 & ~param_max)) >> 16;
			prvTraceUpdateCounters();
		}
		
		return param & param_max;
	}
Beispiel #6
0
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle, 
                                       traceObjectClass objectclass)
{    
    ObjCloseNameEvent * ce;
    const char * name;
    traceLabel idx;

    name = PROPERTY_NAME_GET(objectclass, handle);

    idx = prvTraceOpenSymbol(name, 0);
    
    // Interrupt disable not necessary, already done in trcHooks.h macro
    ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot(); 
    if (ce != NULL)
    {
        ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;
        ce->objHandle = handle;
        ce->symbolIndex = idx;
        prvTraceUpdateCounters();
    }
    
}
Beispiel #7
0
/*******************************************************************************
 * vTraceStoreTaskReady
 *
 * This function stores a ready state for the task handle sent in as parameter.
 ******************************************************************************/
void vTraceStoreTaskReady(objectHandleType handle)
{
    uint16_t dts3;
    TREvent* tr;

    if (!GET_TASK_FLAG_ISEXCLUDED(handle))
    {
        dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
        if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
        {
            tr = (TREvent*)xTraceNextFreeEventBufferSlot();

            if (tr != NULL)
            {
                tr->type = TR_TASK_READY;
                tr->dts = dts3;
                tr->objHandle = handle;

                prvTraceUpdateCounters();    
            }
        }
    }
}
Beispiel #8
0
/*******************************************************************************
 * vTraceStoreTaskswitch
 * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart.
 * At this point interrupts are assumed to be disabled!
 ******************************************************************************/
void vTraceStoreTaskswitch(void)
{
    uint16_t dts3;
    TSEvent* ts;        
    int8_t skipEvent = 0;
    uint32_t schedulerState = 0;
    
    /*************************************************************************** 
    This is used to detect if a high-priority ISRs is illegally using the 
    recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the 
    recorder is busy with a task-level event or lower priority ISR event.
    
    If this is detected, it triggers a call to vTraceError with the error 
    "Illegal call to vTraceStoreISRBegin/End". If you get this error, it means
    that the macro taskENTER_CRITICAL does not disable this ISR, as required.
    You can solve this by adjusting the value of the FreeRTOS constant
    configMAX_SYSCALL_INTERRUPT_PRIORITY, which is defined in FreeRTOSConfig.h

    Note: Setting recorder_busy is normally handled in our macros
    trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this 
    function since critical sections should not be used in the context switch 
    event...)    
    ***************************************************************************/
    recorder_busy++; 
    
    schedulerState = xTaskGetSchedulerState();

    if (schedulerState == 0)
    {
        /* This occurs on the very first taskswitch event, generated by 
        vTraceStart and uiTraceStart if the scheduler is not yet started.
        This creates a dummy "(startup)" task entry internally in the
        recorder */
        if (handle_of_running_task == 0)
        {
            handle_of_running_task = xTraceGetObjectHandle(TRACE_CLASS_TASK);

            vTraceSetObjectName(TRACE_CLASS_TASK, 
                handle_of_running_task,
                "(startup)");

            vTraceSetPriorityProperty(TRACE_CLASS_TASK,
                handle_of_running_task,
                0);
        }        
    }
    else
    {    
        handle_of_running_task = 
        (objectHandleType)uxTaskGetTaskNumber(xTaskGetCurrentTaskHandle());
    }
    
    /* Skip the event if the task has been excluded, using vTraceExcludeTask */
    if (GET_TASK_FLAG_ISEXCLUDED(handle_of_running_task))
    {    
        skipEvent = 1;
        inExcludedTask = 1;            
    }
    else
        inExcludedTask = 0;
        

    /* Skip the event if the same task is scheduled */
    if (handle_of_running_task == handle_of_last_logged_task)
    {
        skipEvent = 1;
    }
  
    if (! RecorderDataPtr->recorderActive)
    {
        skipEvent = 1;
    }

    /* If this event should be logged, log it! */
    if (skipEvent == 0)    
    {    
        dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
        
        if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
        {
            handle_of_last_logged_task = handle_of_running_task;            
            ts = (TSEvent*)xTraceNextFreeEventBufferSlot();

            if (ts != NULL)
            {
                if (uiTraceGetObjectState(TRACE_CLASS_TASK,
                    handle_of_last_logged_task) == TASK_STATE_INSTANCE_ACTIVE)
                {
                    ts->type = TS_TASK_RESUME;
                }
                else
                {
                    ts->type = TS_TASK_BEGIN;
                }

                ts->dts = dts3;
                ts->objHandle = handle_of_last_logged_task;

                vTraceSetObjectState(TRACE_CLASS_TASK, 
                                     handle_of_last_logged_task, 
                                     TASK_STATE_INSTANCE_ACTIVE);

                prvTraceUpdateCounters();    
            }
        }
    }    

    /* See comment on recorder_busy++ above. */
    recorder_busy--; 
}
/******************************************************************************
 * prvTraceGetDTS
 *
 * Returns a differential timestamp (DTS), i.e., the time since
 * last event, and creates an XTS event if the DTS does not fit in the
 * number of bits given. The XTS event holds the MSB bytes of the DTS.
 *
 * The parameter param_maxDTS should be 0xFF for 8-bit dts or 0xFFFF for
 * events with 16-bit dts fields.
 *****************************************************************************/
uint32_t prvTraceGetDTS(uint32_t param_maxDTS)
{
    XTSEvent* xts;    
    int32_t dts = 0;
    uint32_t old_ts = RecorderDataPtr->absTimeLastEvent;

    if (RecorderDataPtr->frequency == 0)
    {
        /* If HWTC_PERIOD is mapped to the timer reload register,
        such as in the Cortex M port, it is not initialized before
        FreeRTOS has been started. We therefore store the frequency
        of the timer at the first timestamped event after the 
        scheduler has started. (Note that this function is called
        also by vTraceStart and uiTraceStart, which might be
        called before the scheduler has been started.) */

#if (SELECTED_PORT == PORT_Win32)    
        RecorderDataPtr->frequency = 100000;
#elif (SELECTED_PORT == PORT_HWIndependent)    
        RecorderDataPtr->frequency = configTICK_RATE_HZ;
#else        
        if (xTaskGetSchedulerState() != 0) /* Has the scheduler started? */
        {            
            RecorderDataPtr->frequency = 
                 HWTC_PERIOD * configTICK_RATE_HZ / HWTC_DIVISOR; 
        }
#endif
    }

    /**************************************************************************
    * The below statement reads the timestamp from the timer port module. Note 
    * the modulo operation on RecorderDataPtr->frequency, which makes the overflow 
    * case (if (dts < 0)) occur every 1 sec.
    * This is to make it easier to test. The overflow will happen sooner
    * or later anyway.
    **************************************************************************/

    if (RecorderDataPtr->frequency > 0)
    {
        RecorderDataPtr->absTimeLastEvent = 
            uiTracePortGetTimeStamp() % RecorderDataPtr->frequency;
    }
    else
    {
        /* Special case if the recorder has not yet started (frequency may be uninitialized, i.e., zero)
        The modulo operation is not necessary on the first events, since it is surely much less than 
        one second since startup. */
        RecorderDataPtr->absTimeLastEvent = uiTracePortGetTimeStamp(); 
    }

    dts = (int32_t)(RecorderDataPtr->absTimeLastEvent - old_ts);

    if (dts < 0) /* when the modulo operation wraps around (after 1 second) */
    {
        if (RecorderDataPtr->frequency == 0)
        {
            /* Frequency should normally be initialized on the first logged event after
            the FreeRTOS scheduler has started. In this case, it has not yet been 
            initialized (frequency is 0) and the dts (time since last event) was 
            negative. This is an illegal combination that indicates a problem in 
            uiTracePortGetTimeStamp, probably due to incorrect HWTC macros in trcPort.h.

            The dts variable normally becomes negative when the modulo operation wraps
            around, but since the modulo operation is not used in this case (only used 
            if frequency has been set), dts only becomes negative if
            uiTracePortGetTimeStamp returned a smaller value than last time.
            This is an error. The values returned by uiTracePortGetTimeStamp should be
            monotonically incresing (since it is a timestamp). */

            vTraceError("Timestamping error, see comment in prvTraceGetDTS (trcBase.c)");
            return 0;
        }
        dts = (int32_t)(RecorderDataPtr->frequency - old_ts + RecorderDataPtr->absTimeLastEvent);

        /* This is good for 136 years (incremented every 1 second) */
        RecorderDataPtr->absTimeLastEventSecond++; 
    }

    /* If the dts (time since last event) does not fit in event->dts (only 8 or 16 bits) */
    if (dts > (int32_t)param_maxDTS)
    {
        /* Create an XTS event (eXtended TimeStamp) containing the higher dts bits*/
        xts = (XTSEvent*) xTraceNextFreeEventBufferSlot();

        if (xts != NULL)
        {
            if (param_maxDTS == 0xFFFF)
            {
                xts->type = XTS16;
                xts->xts_16 = (uint16_t)((dts / 0x10000) & 0xFFFF);
                xts->xts_8 = 0;
            }
            else if (param_maxDTS == 0xFF)
            {
                xts->type = XTS8;
                xts->xts_16 = (uint16_t)((dts / 0x100) & 0xFFFF);
                xts->xts_8 = (uint8_t)((dts / 0x1000000) & 0xFF);
            }
            else
            {
                vTraceError("Bad param_maxDTS in prvTraceGetDTS");
            }
            prvTraceUpdateCounters();
        }
    }

    return dts % (param_maxDTS + 1);
}