📄 stclkrv.c
字号:
/****************************************************************************
File Name : stclkrv.c
Description : Clock Recovery API Routines
Copyright (C) 2006, STMicroelectronics
Revision History :
[...]
References :
$ClearCase (VOB: stclkrv)S
stclkrv.fm "Clock Recovery API" Reference DVD-API-072 Revision 5.0
****************************************************************************/
/* Includes --------------------------------------------------------------- */
#if defined(ST_OS20) || defined(ST_OS21) /* linux changes */
#include <string.h>
#include <stdlib.h>
#include "stlite.h" /* MUST be included BEFORE stpti.h */
#include "sttbx.h"
#include "stsys.h"
#endif
#include "stevt.h"
/* our own includes */
#include "stclkrv.h"
#include "clkrvreg.h"
#include "clkrvdat.h"
/* Private Constants ------------------------------------------------------ */
#ifndef STCLKRV_FILTER_TASK_PRIORITY
#ifdef ST_OSLINUX
#define STCLKRV_FILTER_TASK_PRIORITY 99
#else
#define STCLKRV_FILTER_TASK_PRIORITY MAX_USER_PRIORITY
#endif
#endif
/* Externs ---------------------------------------------------------------- */
extern stclkrv_Freqtable_t NominalFreqTable[MAX_NO_IN_FREQ_TABLE];
/* Clock recovery Filter & drift correction of slaves clocks Debug Array */
#ifdef CLKRV_FILTERDEBUG
#define CLKRV_MAX_SAMPLES 5000
extern U32 ClkrvDbg[13][CLKRV_MAX_SAMPLES];
extern U32 Clkrv_Slave_Dbg[13][CLKRV_MAX_SAMPLES];
extern U32 SampleCount;
#endif
/* Private Variables ------------------------------------------------------ */
/* Provides mutual exclusion on global data */
static semaphore_t *AccessSemaphore_p = NULL;
/* Initialization Context */
static stclkrv_Context_t InitContext =
{
TRUE, /* Reset */
0, /* PrevDiff */
0, /* PrevPcr*/
0, /* Out Standing Error */
0, /* ControlValue */
NULL, /* ErrorStore_p; */
0, /* ErrorStoreCount */
0, /* Head */
0, /* ErrorSum */
(PCRTIMEFACTOR * STCLKRV_PCR_DRIFT_THRES) /* Maximum error before a Glitch event is thrown*/
};
static stclkrv_ReferencePCR_t InitRefPcr =
{
TRUE, /* AwaitingPCR */
FALSE, /* Valid */
TRUE, /* PCRHandlingActive */
0, /* PcrBaseBit32 */
0, /* PcrBaseValue */
0, /* PcrExtension */
0, /* PcrArrivalBaseBit32 */
0, /* PcrArrvialBaseValue */
0, /* PcrArrivalExtension */
0, /* Total Value */
0, /* Time */
0, /* GlitchCount */
(U32) STCLKRV_STATE_PCR_UNKNOWN /* MachineState */
};
/* Initialise ptr to Control block list */
STCLKRV_ControlBlock_t *ClkrvList_p = NULL;
#ifdef WA_GNBvd44290
extern void stclkrv_GNBvd44290_ResetClkrvTracking(void);
#endif /* WA_GNBvd44290 */
/* Driver revision number */
static const ST_Revision_t stclkrv_DriverRev = "STCLKRV-REL_5.2.0A4";
/* Private Macros --------------------------------------------------------- */
#if defined (ST_5100)
#define AdjustHPTTicksToMicroSec(Value) \
{ \
/* With 64-bit arithmetic we can do the exact calculation:
Value' = (Value * 1000000) / ST_GetClocksPerSecondHigh() */ \
U32 HPTicksPerSec = ST_GetClocksPerSecondHigh(); \
__optasm \
{ \
ldabc Value, 1000000, 0; \
lmul; /* A*B + C (carry) -> A'B' */ \
/* should strictly add HPTicksPerSec/2 */ \
ldl HPTicksPerSec; /* NOT ld (might corrupt B, C */ \
ldiv; /* B'C' / A -> A remainder B */ \
st Value; \
} \
/* We might want to change and use this code on all chips */ \
}
#endif
/* Private Function prototypes -------------------------------------------- */
#ifndef STCLKRV_NO_PTI
/* Callback Registered with STPTI to notify PCR,STC values */
#ifdef ST_5188
extern void STCLKRV_ActionPCR(STEVT_CallReason_t EventReason,
ST_DeviceName_t RegistrantName,
STEVT_EventConstant_t EventOccured,
STDEMUX_EventData_t *PcrData_p,
STCLKRV_Handle_t *InstanceHandle_p);
#else
extern void STCLKRV_ActionPCR(STEVT_CallReason_t EventReason,
ST_DeviceName_t RegistrantName,
STEVT_EventConstant_t EventOccured,
STPTI_EventData_t *PcrData_p,
STCLKRV_Handle_t *InstanceHandle_p);
#endif
#if defined(ST_OS20) || defined(ST_OS21) /* linux changes */
extern void ClockRecoveryFilterTask(STCLKRV_ControlBlock_t *CB_p);
#else
extern int ClockRecoveryFilterTask(STCLKRV_ControlBlock_t *CB_p);
#endif
extern void UpdateStateMachine(STCLKRV_ControlBlock_t *Instance_p,BOOL DiscontinuousPCR);
static ST_ErrorCode_t SubscribePCR(STCLKRV_ControlBlock_t *Instance_p);
static ST_ErrorCode_t UnsubscribePCR(STCLKRV_ControlBlock_t *Instance_p);
/* STPTI */
#ifndef ST_5188
static BOOL GetExtendedPacketArrivalTime(STCLKRV_Handle_t Handle,
U32 *BaseBit32,
U32 *BaseValue,
U32 *Extension);
static BOOL GetPacketArrivalTime(STCLKRV_Handle_t Handle, U32 *ArrivalTime);
#endif
static void AddTwoExtSTCValues(STCLKRV_ExtendedSTC_t ExtSTCA,STCLKRV_ExtendedSTC_t ExtSTCB,
STCLKRV_ExtendedSTC_t *ReturnExtSTC_p);
static void SubtractTwoExtSTCValues(STCLKRV_ExtendedSTC_t ExtSTCA,STCLKRV_ExtendedSTC_t ExtSTCB,
STCLKRV_ExtendedSTC_t *ReturnExtSTC_p);
#if defined (ST_5100)
static BOOL ConvertMicroSecsToExtSTC(clock_t MicroSecVal, STCLKRV_ExtendedSTC_t *ExtSTC_p);
#endif
#endif
extern STOS_INTERRUPT_DECLARE(ClkrvTrackingInterruptHandler, Data);
/* EVT Related */
static ST_ErrorCode_t RegisterEvents(STCLKRV_ControlBlock_t *Instance_p);
static ST_ErrorCode_t UnregisterEvents(STCLKRV_ControlBlock_t *Instance_p);
/* Utility Functions */
static void AddToInstanceList(STCLKRV_ControlBlock_t *NewItem_p);
static BOOL DelFromInstanceList(ST_DeviceName_t DeviceName);
static STCLKRV_ControlBlock_t *FindInstanceByHandle(STCLKRV_Handle_t ClkHandle);
static STCLKRV_ControlBlock_t *FindInstanceByName(const ST_DeviceName_t DeviceName);
static BOOL IsClockValid(STCLKRV_ControlBlock_t *CB_p, STCLKRV_ClockSource_t ClockSource );
/* Functions -------------------------------------------------------------- */
#if defined(CLKRV_TESTING)
/****************************************************************************
Name : STCLKRV_GetClocksFrequency()
Description : Returns the current freq. of various FS clocks.
NOTE: This function is not documented in the
API and is not exported in stclkrv.h as it
is only needed by the test harness
Parameters : STCLKRV_Handle_t Handle - Valid clock recovery handle
U32 * - Pointer to returned FS0 freq.
U32 * - Pointer to returned FS1 freq.
U32 * - Pointer to returned FS2 freq.
Return Value : ST_ErrorCode_t
ST_NO_ERROR Successful completion
ST_ERROR_INVALID_HANDLE STCLKRV handle is not open
See Also :
****************************************************************************/
ST_ErrorCode_t STCLKRV_GetClocksFrequency( STCLKRV_Handle_t Handle,
U32 *pSTCFrequency,
U32 *pFS1Frequency,
U32 *pFS2Frequency,
U32 *pFS3Frequency,
U32 *pFS4Frequency,
U32 *pFS5Frequency)
{
/* Test handle validity */
STCLKRV_ControlBlock_t *TmpCB_p;
TmpCB_p = FindInstanceByHandle(Handle);
if(TmpCB_p == NULL)
{
return ST_ERROR_INVALID_HANDLE;
}
if (TmpCB_p->InitPars.DeviceType==STCLKRV_DEVICE_TYPE_BASELINE_ONLY)
{
return (ST_ERROR_FEATURE_NOT_SUPPORTED);
}
/* set to zero all first */
*pFS1Frequency = 0;
*pFS2Frequency = 0;
*pFS3Frequency = 0;
*pFS4Frequency = 0;
*pFS5Frequency = 0;
*pSTCFrequency = TmpCB_p->HWContext.Clocks[0].Frequency;
/* 5188 has only one slave until cut 1.0 */
*pFS1Frequency = TmpCB_p->HWContext.Clocks[1].Frequency;
#if defined (ST_5100) || defined (ST_5105) || defined (ST_5301) || defined (ST_5107)\
|| defined (ST_7710) || defined (ST_7100) || defined (ST_7109)
*pFS2Frequency = TmpCB_p->HWContext.Clocks[2].Frequency;
#endif
#if defined (ST_7710) || defined (ST_7100) || defined (ST_7109)
*pFS3Frequency = TmpCB_p->HWContext.Clocks[3].Frequency;
#endif
#if defined (ST_7100) || defined (ST_7109)
*pFS4Frequency = TmpCB_p->HWContext.Clocks[4].Frequency;
#endif
#if defined (ST_5525)
*pFS5Frequency = TmpCB_p->HWContext.Clocks[5].Frequency;
#endif
return ST_NO_ERROR; /* Success */
}
#ifndef STCLKRV_NO_PTI
#if CLKRV_TESTING==2
/****************************************************************************
Name : STPTI_GetPacketArrivalTime
Description : Stub routine to resolve PTI library reference
Returns fail to STCLKRV_GetSTC/GetExtSTC functions
Parameters :
Return Value : Error
See Also : PTI
****************************************************************************/
ST_ErrorCode_t STPTI_GetPacketArrivalTime(STPTI_Handle_t Hndl, STPTI_TimeStamp_t * ArrivalTime_p,
U16 *ArrivalTimeExtension_p)
{
STCLKRV_Print(("GPAT dummy function\n"));
return (ST_NO_ERROR + 1); /* return error */
}
ST_ErrorCode_t STPTI_GetCurrentPTITimer(ST_DeviceName_t DeviceName,
STPTI_TimeStamp_t * TimeStamp)
{
STCLKRV_Print(("GPAT dummy function\n"));
return (ST_NO_ERROR + 1); /* return error */
}
#endif /* CLKRV_TESTING==2 */
#endif /* !STCLKRV_NO_PTI */
#endif /* CLKRV_TESTING */
/****************************************************************************
Name : STCLKRV_GetRevision()
Description : Returns a pointer to the Driver Revision String.
May be called at any time.
Parameters : None
Return Value : ST_Revision_t
See Also : ST_Revision_t
****************************************************************************/
ST_Revision_t STCLKRV_GetRevision( void )
{
return( stclkrv_DriverRev );
}
/****************************************************************************
Name : STCLKRV_Init()
Description : Initializes the Clock Recovery before use.
Parameters : ST_DeviceType_t name needs to be supplied - should not be NULL,
STCLKRV_InitParams_t struct. pointer appropriately filled by app.
Return Value : ST_ErrorCode_t specified as
ST_NO_ERROR No errors determined
ST_ERROR_FEATURE_NOT_SUPPORTED No multiple instance support(5100)
ST_ERROR_ALREADY_INITIALIZED Device already initialized
ST_ERROR_BAD_PARAMETER One or more parameters invalid
ST_ERROR_NO_MEMORY memory_allocate failed
STCLKRV_ERROR_HANDLER_INSTALL Unable to install STPTI Callback
ST_ERROR_INTERRUPT_INSTALL Unable to install internal ISR
STCLKRV_ERROR_EVT_REGISTER Problem registering events
See Also : STCLKRV_InitParams_t
STCLKRV_Term()
****************************************************************************/
ST_ErrorCode_t STCLKRV_Init( const ST_DeviceName_t Name,
const STCLKRV_InitParams_t *InitParams )
{
ST_ErrorCode_t ReturnCode = ST_NO_ERROR;
ST_ErrorCode_t RetCode = ST_NO_ERROR;
STCLKRV_ControlBlock_t *TmpCB_p = NULL;
STCLKRV_ControlBlock_t *NextElem = NULL;
ST_ErrorCode_t IntReturn = 0;
U32 i = 0;
/* Perform parameter validity checks */
if (( Name == NULL) || /* NULL Name ptr */
(InitParams == NULL) || /* NULL structure ptr */
(Name[0] == '\0' ) || /* Device Name undefined */
(strlen( Name ) >= ST_MAX_DEVICE_NAME)) /* string too long? */
{
return( ST_ERROR_BAD_PARAMETER );
}
/* Device of that name already init */
if (FindInstanceByName(Name) != NULL)
{
return (ST_ERROR_ALREADY_INITIALIZED);
}
if((InitParams->DeviceType < STCLKRV_DEVICE_TYPE_5100) ||
(InitParams->DeviceType > STCLKRV_DEVICE_TYPE_BASELINE_ONLY))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -