📄 freemaster_rec.c
字号:
/******************************************************************************
*
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2005 Freescale Semiconductor, Inc.
* (c) Copyright 2001-2004 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
****************************************************************************//*!
*
* @file freemaster_rec.c
*
* @brief FreeMaster Recorder implementation
*
* @version 1.0.3.0
*
* @date Jul-25-2006
*
*******************************************************************************/
#include "freemaster.h"
#include "freemaster_private.h"
#include "freemaster_protocol.h"
#if FMSTR_USE_RECORDER
/***********************************
* local variables
***********************************/
// configuration variables
static FMSTR_U16 pcm_wRecTotalSmps; ///< number of samples to measure
static FMSTR_U16 pcm_wRecPostTrigger; ///< number of post-trigger samples to keep
static FMSTR_U8 pcm_nRecTriggerMode; ///< triger mode (0 = disabled, 1 = _/, 2 = \_)
static FMSTR_U16 pcm_wRecTimeDiv; ///< divisor of recorder "clock"
static FMSTR_ADDR pcm_nTrgVarAddr; ///< trigger variable address
static FMSTR_U8 pcm_nTrgVarSize; ///< trigger variable threshold size
static FMSTR_U8 pcm_bTrgVarSigned; ///< trigger compare mode (0 = unsigned, 1 = signed)
static union
{
#if FMSTR_CFG_BUS_WIDTH == 1
FMSTR_U8 u8;
FMSTR_S8 s8;
#endif
FMSTR_U16 u16;
FMSTR_S16 s16;
FMSTR_U32 u32;
FMSTR_S32 s32;
} pcm_uTrgThreshold; ///< trigger threshold level (1,2 or 4 bytes)
static FMSTR_U8 pcm_nRecVarCount; ///< number of active recorder variables
static FMSTR_ADDR pcm_pRecVarAddr[FMSTR_MAX_SCOPE_VARS]; ///< addresses of recorded variables
static FMSTR_SIZE8 pcm_pRecVarSize[FMSTR_MAX_SCOPE_VARS]; ///< sizes of recorded variables
static FMSTR_ADDR pcm_nRecBuffAddr; ///< recorder buffer address
static FMSTR_SIZE pcm_wRecBuffSize; ///< recorder buffer size
static FMSTR_U16 pcm_wRecBuffStartIx; ///< first sample index
// runtime variables
static FMSTR_ADDR pcm_dwRecWritePtr; ///< write pointer in recorder buffer
static FMSTR_ADDR pcm_dwRecEndBuffPtr; ///< pointer to end of active recorder buffer
static FMSTR_U16 pcm_wRecTimeDivCtr; ///< recorder "clock" divisor counter
static FMSTR_U16 pcm_wStoprecCountDown; ///< post-trigger countdown counter
// recorder runtime flags
static volatile union
{
FMSTR_FLAGS all;
struct
{
unsigned bIsConfigured : 1; // recorder is configured
unsigned bIsRunning : 1; // recorder is running
unsigned bIsStopping : 1; // trigger activated, sample countdown
unsigned bInvirginCycle : 1; // virgin cycle of the circular buffer in-progress
unsigned bTrgCrossActive : 1; // trigger trheshold was crossed
} flg;
} pcm_wRecFlags;
/// compare functions prototype
typedef FMSTR_BOOL (*FMSTR_PCOMPAREFUNC)(void);
/// pointer to active compare function
static FMSTR_PCOMPAREFUNC pcm_pCompareFunc;
#if !FMSTR_REC_OWNBUFF
// put buffer into far memory ?
#if FMSTR_REC_FARBUFF
#pragma section fardata begin
#endif // FMSTR_REC_FARBUFF
/// statically allocated recorder buffer (FMSTR_REC_OWNBUFF is FALSE)
static FMSTR_U8 pcm_pOwnRecBuffer[FMSTR_REC_BUFF_SIZE];
// end of far memory section
#if FMSTR_REC_FARBUFF
#pragma section fardata end
#endif // FMSTR_REC_FARBUFF
#endif // FMSTR_REC_OWNBUFF
/***********************************
* local functions
***********************************/
static FMSTR_BOOL FMSTR_Compare8S(void);
static FMSTR_BOOL FMSTR_Compare8U(void);
static FMSTR_BOOL FMSTR_Compare16S(void);
static FMSTR_BOOL FMSTR_Compare16U(void);
static FMSTR_BOOL FMSTR_Compare32S(void);
static FMSTR_BOOL FMSTR_Compare32U(void);
static void FMSTR_Recorder2(void);
/**************************************************************************//*!
*
* @brief Recorder Initialization
*
******************************************************************************/
void FMSTR_InitRec(void)
{
// setup buffer pointer and size so IsInRecBuffer works even
// before the recorder is first initialized and used
#if FMSTR_REC_OWNBUFF
// user wants to use his own buffer
pcm_nRecBuffAddr = 0;
pcm_wRecBuffSize = 0;
#else
// size in native sizeof units (=bytes on most platforms)
pcm_wRecBuffSize = FMSTR_REC_BUFF_SIZE;
FMSTR_ARR2ADDR(pcm_nRecBuffAddr, pcm_pOwnRecBuffer);
#endif
}
/**************************************************************************//*!
*
* @brief API: Replacing the recorder buffer with the user's one
*
* @param pBuffer - user buffer pointer
* @param wBuffSize - buffer size
*
* @note Use the FMSTR_SetUpBuff32 to pass the forced 32bit address in SDM
*
******************************************************************************/
void FMSTR_SetUpRecBuff(FMSTR_ADDR pBuffer, FMSTR_SIZE nBuffSize)
{
pcm_nRecBuffAddr = pBuffer;
pcm_wRecBuffSize = nBuffSize;
}
/**************************************************************************//*!
*
* @brief Handling SETUPREC and SETUPREC_EX commands
*
* @param pMessageIO - original command (in) and response buffer (out)
*
* @return As all command handlers, the return value should be the buffer
* pointer where the response output finished (except checksum)
*
******************************************************************************/
FMSTR_BPTR FMSTR_SetUpRec(FMSTR_BPTR pMessageIO)
{
FMSTR_BPTR pResponse = pMessageIO;
FMSTR_SIZE8 nRecVarsetSize;
FMSTR_U8 i, sz;
FMSTR_SIZE blen;
// de-initialize first
FMSTR_AbortRec();
#if FMSTR_REC_OWNBUFF
// user wants to use his own buffer, check if it is valid
if(!pcm_nRecBuffAddr || !pcm_wRecBuffSize)
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_INVBUFF);
#else
// size in native sizeof units (=bytes on most platforms)
pcm_wRecBuffSize = FMSTR_REC_BUFF_SIZE;
FMSTR_ARR2ADDR(pcm_nRecBuffAddr, pcm_pOwnRecBuffer);
#endif
// seek the setup data
pMessageIO = FMSTR_SkipInBuffer(pMessageIO, 2);
pMessageIO = FMSTR_ValueFromBuffer8(&pcm_nRecTriggerMode, pMessageIO);
pMessageIO = FMSTR_ValueFromBuffer16(&pcm_wRecTotalSmps, pMessageIO);
pMessageIO = FMSTR_ValueFromBuffer16(&pcm_wRecPostTrigger, pMessageIO);
pMessageIO = FMSTR_ValueFromBuffer16(&pcm_wRecTimeDiv, pMessageIO);
// address & size of trigger variable
pMessageIO = FMSTR_AddressFromBuffer(&pcm_nTrgVarAddr, pMessageIO);
pMessageIO = FMSTR_ValueFromBuffer8(&pcm_nTrgVarSize, pMessageIO);
// trigger compare mode
pMessageIO = FMSTR_ValueFromBuffer8(&pcm_bTrgVarSigned, pMessageIO);
// threshold value
pMessageIO = FMSTR_ValueFromBuffer32(&pcm_uTrgThreshold.u32, pMessageIO);
// recorder variable count
pMessageIO = FMSTR_ValueFromBuffer8(&pcm_nRecVarCount, pMessageIO);
// rec variable information must fit into our buffers
if(!pcm_nRecVarCount || pcm_nRecVarCount > FMSTR_MAX_REC_VARS)
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_INVBUFF);
// calculate sum of sizes of all variables
nRecVarsetSize = 0;
// get all addresses and sizes
for(i=0; i<pcm_nRecVarCount; i++)
{
// variable size
pMessageIO = FMSTR_ValueFromBuffer8(&sz, pMessageIO);
pcm_pRecVarSize[i] = sz;
nRecVarsetSize += sz;
// variable address
pMessageIO = FMSTR_AddressFromBuffer(&pcm_pRecVarAddr[i], pMessageIO);
// valid numeric variable sizes only
if(sz == 0 || sz > 8)
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_INVSIZE);
#if FMSTR_CFG_BUS_WIDTH > 1
// even sizes only
if(sz & 1)
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_INVSIZE);
#endif
#if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY
if(!FMSTR_CheckTsaSpace(pcm_pRecVarAddr[i], sz, 0))
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_EACCESS);
#endif
}
// any trigger?
pcm_pCompareFunc = NULL;
if(pcm_nRecTriggerMode)
{
// access to trigger variable?
#if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY
if(!FMSTR_CheckTsaSpace(pcm_nTrgVarAddr, pcm_nTrgVarSize, 0))
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_EACCESS);
#endif
// get compare function
switch(pcm_nTrgVarSize)
{
#if FMSTR_CFG_BUS_WIDTH == 1
case 1: pcm_pCompareFunc = pcm_bTrgVarSigned ? FMSTR_Compare8S : FMSTR_Compare8U; break;
#endif
case 2: pcm_pCompareFunc = pcm_bTrgVarSigned ? FMSTR_Compare16S : FMSTR_Compare16U; break;
case 4: pcm_pCompareFunc = pcm_bTrgVarSigned ? FMSTR_Compare32S : FMSTR_Compare32U; break;
// invalid trigger variable size
default:
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_INVSIZE);
}
}
// total recorder buffer length in native sizeof units (=bytes on most platforms)
blen = pcm_wRecTotalSmps * nRecVarsetSize / FMSTR_CFG_BUS_WIDTH;
// recorder memory available?
if(blen > pcm_wRecBuffSize)
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STC_INVSIZE);
// remember the effective end of circular buffer
pcm_dwRecEndBuffPtr = pcm_nRecBuffAddr + blen;
// everything is okay
pcm_wRecFlags.flg.bIsConfigured = 1;
return FMSTR_ConstToBuffer8(pResponse, FMSTR_STS_OK);
}
/**************************************************************************//*!
*
* @brief Abort and de-initialize recorder
*
******************************************************************************/
void FMSTR_AbortRec(void)
{
// clear flags
pcm_wRecFlags.all = 0;
}
/**************************************************************************//*!
*
* @brief Check wether given memory region is inside the recorder buffer
*
* @param dwAddr - address of the memory to be checked
* @param wSize - size of the memory to be checked
*
* @return This function returns non-zero if user space is in recorder buffer
*
* This function is called as a pert of TSA-checking process when the PC host
* is requesting memory contents
*
******************************************************************************/
FMSTR_BOOL FMSTR_IsInRecBuffer(FMSTR_ADDR dwAddr, FMSTR_SIZE8 wSize)
{
if(dwAddr < pcm_nRecBuffAddr)
return 0;
return (dwAddr + wSize) <= (pcm_nRecBuffAddr + FMSTR_GetRecBuffSize());
}
/**************************************************************************//*!
*
* @brief Get recorder memory size
*
* @return Recorder memory size in native sizeof units (=bytes on most platforms)
*
******************************************************************************/
FMSTR_SIZE FMSTR_GetRecBuffSize()
{
#if FMSTR_REC_OWNBUFF
return pcm_wRecBuffSize;
#else
return FMSTR_REC_BUFF_SIZE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -