Commit fadf462a authored by Benoit Rat's avatar Benoit Rat

src: add initial source code

parent ffa347c5
/*
* WBMemTestFileCon.cpp
*
* Created on: Oct 31, 2013
* Author: Benoit Rat (benoit<AT>sevensols.com)
*/
#include "WBMemTestFileCon.h"
#include <cstring>
#include "awbpd_trace.h"
#define TRACE_P_VDEBUG(...) TRACE_P_DEBUG( __VA_ARGS__)
#define TRACE_P_VVDEBUG(...) //TRACE_P_DEBUG( __VA_ARGS__)
#define BUFF_MAX_SIZEB 4096 //Size in bytes
/**
* Constructor of the WBMemTestFileCon
*
* This function will allocate one internal buffer of
* BUFF_MAX_SIZEB for both read and write.
* It will also try to open the file.
*/
WBMemTestFileCon::WBMemTestFileCon(const std::string& fname)
: WBMemCon(WBMemCon::TFILE), fname(fname), lastpos(0)
{
o_file.open(fname.c_str(),std::fstream::out|std::fstream::in);
TRACE_P_INFO("tfile=%d (%s)",o_file.is_open(),fname.c_str());
pData = (uint32_t*)malloc(BUFF_MAX_SIZEB);
}
/**
* Destructor
*
* - Close the file
* - Free the internal buffer
*/
WBMemTestFileCon::~WBMemTestFileCon()
{
o_file.close();
free(pData);
}
/**
* Function that fill the file with the all the registers in the wishbone structure.
*/
void WBMemTestFileCon::generate(WBNode* node)
{
WBReg *reg=NULL;
uint32_t data;
if(node==NULL) return;
//If the file does not exist it can't be open as in|out (only out)...
if(o_file.is_open()==false)
{
o_file.open(fname.c_str(),std::fstream::out); //...,so we create it as out...
o_file.sync();
o_file.close();
o_file.open(fname.c_str(),std::fstream::out|std::fstream::in); //and reopen as in|out.
}
TRACE_P_DEBUG("%s (%d)",node->getCName(), node->getChildren().size());
while( (reg=node->getNextReg(reg)) != NULL)
{
TRACE_P_VDEBUG("%s (@0x%08X) 0x%08x",reg->getCName(),reg->getOffset(true),reg->getData());
data=reg->getData();
mem_access(reg->getOffset(true),&data,true);
}
std::vector<WBNode *> children = node->getChildren();
for(size_t i=0;i<children.size();i++)
generate(children[i]);
}
/**
* Single line access of a wishbone register in the device.
*
* \param[in] wb_addr The address of the data we want to access.
* \param[inout] data the read "read from/write to" the file.
* \param[in] to_dev if true we write to the file (aka device).
*/
bool WBMemTestFileCon::mem_access(uint32_t wb_addr, uint32_t* data, bool to_dev)
{
uint32_t rdata=0xDA1AFEED;
char buff[50];
std::string line;
//std::fstream tfile(fname.c_str(), std::ios::in|std::ios::out);
TRACE_CHECK(isValid(),false,"Not valid file");
o_file.sync();
//first seek position
int pos=seek(o_file,wb_addr,true);
if(to_dev) //writing to file
{
//Move to correct position
if(pos>=0) o_file.seekp(pos,std::ios::beg);
else o_file.seekp(0,std::ios::end);
snprintf(buff,50,"0x%08X: %08x",wb_addr,*data);
TRACE_P_VDEBUG("%d <=> '%s' (g=%ld, p=%ld)",pos, buff, o_file.tellg(), o_file.tellp());
o_file << buff << std::endl;
}
else //Reading from file
{
if(pos>0)
{
o_file.seekg(pos,std::ios::beg);
if(getline (o_file,line))
{
std::string strdata = line.substr(12,8);
char * p;
rdata= strtoul( strdata.c_str(), & p, 16 );
TRACE_P_VVDEBUG("%s => '%s' => 0x%x",line.c_str(),strdata.c_str(),rdata);
}
//tfile >> "0x" >> tmp >> ": " >> rdata;
}
*data=rdata;
}
TRACE_P_VDEBUG("%s@%08X %s %08x (%d)",(to_dev)?"W":"R", wb_addr,(to_dev)?"=>":"<=",*data, pos);
o_file.sync();
o_file.flush();
return true;
}
uint32_t WBMemTestFileCon::get_block_buffer(uint32_t** hDma, bool to_dev)
{
*hDma=pData;
return BUFF_MAX_SIZEB;
}
/**
* Block access to the test file
*
* First seek the starting position of the block given by dev_addr and then read/write
* consecutively all the other position to the file
*
* \warning This method is intend to be very basic. It is working well on pre-formated test file
* obtained by the generate() method.
* - When writing this function will override all the line after the first position
* - When reading this function will just check that the next line address corresponds to
* its next expected line. If there are some swapping or missing reg on the text file the function
* will not behave correctly.
*
* \param[in] dev_addr The address on the device of the data we want to access.
* \param[in] nsize The size in byte that we want to read/write.
* \param[in] to_dev if true we write to the device.
*/
bool WBMemTestFileCon::mem_block_access(uint32_t dev_addr, uint32_t nsize,bool to_dev)
{
char buff[50], *p;
std::string line;
uint32_t defdata=0xDA1AFEED;
block_busy=true;
std::fstream tfile(fname.c_str(), std::ios::in|std::ios::out);
int pos=seek(tfile,dev_addr,true);
TRACE_P_DEBUG("0x%08X nsize=%03d (%s) fpos=%d",dev_addr,nsize,(to_dev)?"W":"R",pos);
if(to_dev)
{
TRACE_P_WARNING("Write not implemented");
block_busy=false;
return false;
}
else
{
tfile.seekg(pos,std::ios::beg);
if(nsize>BUFF_MAX_SIZEB)
{
TRACE_P_WARNING("nsize=%d > BUFF_MAX_SIZEB=%d",nsize,BUFF_MAX_SIZEB);
nsize=BUFF_MAX_SIZEB;
}
for(size_t i=0;i<nsize;i++)
{
pData[i]=defdata;
if(pos>0 && getline (tfile,line))
{
snprintf(buff,50,"0x%08X",dev_addr+i*sizeof(uint32_t));
if(strncmp(buff,line.substr(0,10).c_str(),10)==0)
pData[i]= strtoul( line.substr(12,8).c_str(), & p, 16 );
TRACE_P_VDEBUG("#%03d@0x%08X : 0x%8x (%s)",
i,dev_addr+i*sizeof(uint32_t),pData[i],line.c_str());
}
}
}
block_busy=false;
return true;
}
/**
* Search for the first occurence of wb_addr on the test file.
*
* This method also modified the lastpos value.
*
* \param[inout] tfile the given test file (only the position pointer will be moved)
* \param[in] wb_addr the address that we are looking for
* \param[in] rewind if true we start the search from the beginning, otherwise from the current position.
* \return the position of the line that contains the address or -1 if it was not found.
*/
long WBMemTestFileCon::seek(std::fstream& tfile, uint32_t wb_addr, bool rewind)
{
std::string line;
//Create comparation buffer
char buff[20];
snprintf(buff,20,"0x%08X",wb_addr);
std::string test(buff);
//Put the file to the correct place
if(rewind) tfile.seekg(0, std::ios::beg);
else tfile.seekg(lastpos,std::ios::beg);
long pos=tfile.tellg();
while (getline (tfile,line))
{
if(line.size()>10 && (line[0] != '#'))
//if(line.size()>10)
{
TRACE_P_VVDEBUG("'%s'=='%s'",line.substr(0,10).c_str(),test.c_str());
if(line.substr(0,10)==test)
{
lastpos=pos;
return lastpos;
}
}
pos=tfile.tellg();
}
//If we reach the eof we reset
if(tfile.eof())
{
tfile.clear(tfile.eofbit);
lastpos=0;
tfile.seekg(lastpos, std::ios::beg);
}
return -1;
}
/**
* \file
* \brief Contains the class WBMemTestFileCon.
*
*
* \date Nov 4, 2013
* \author Benoit Rat (benoit<AT>sevensols.com)
*/
#ifndef WBMEMTFILECON_H_
#define WBMEMTFILECON_H_
#include "WBNode.h"
#include <iostream>
#include <fstream>
#include <string>
/**
* Fake WB memory connector by testing on a file
*
* The operation will read and write in the test file.
*
* A typical testfile is shown below:
* \code
* # Format as below
* # 0x<hex_address> : <hex_value>
* 0x10000024: 0ABCD000
* 0x20000000: 01e1389c
* 0x20000004: 00060005
* 0x20000008: e99c4fb5
* 0x2000000C: 00000000
* \endcode
*
*/
class WBMemTestFileCon: public WBMemCon {
public:
WBMemTestFileCon(const std::string& fname);
virtual ~WBMemTestFileCon();
void generate(WBNode* node);
virtual bool isValid() { return o_file.is_open(); } //!< Return true if the file has been opened
bool mem_access(uint32_t addr, uint32_t *data, bool from_dev);
uint32_t get_block_buffer(uint32_t **hDma, bool to_dev);
bool mem_block_access(uint32_t dev_addr, uint32_t nsize, bool to_dev);
private:
long seek(std::fstream& tfile, uint32_t wb_addr, bool rewind=false);
std::fstream o_file;
std::string fname;
long lastpos;
uint32_t *pData;
};
#endif /* WBMEMTFILECON_H_ */
/*
* WBMemX1052Con.cpp
*
* Created on: Oct 31, 2013
* Author: Benoit Rat (benoit<AT>sevensols.com)
*/
#include "awbpd_trace.h"
#ifndef AWBPD_NO_X1052
#define TRACE_H
#include <x1052_api.h>
#include <wdc_lib.h>
//TODO: Quick fix
#ifndef BOOL
#define BOOL int
#endif
#include "WBMemX1052Con.h"
#define TRACE_P_VDEBUG(...) TRACE_P_DEBUG( __VA_ARGS__)
#define TRACE_P_VVDEBUG(...) //TRACE_P_DEBUG( __VA_ARGS__)
/**
* Constructor of the WBMemX1052Con class.
*
* The constructor init the X1052 library and open an handler
* on the corresponding device.
* You need to use a valid WinDriver licence to open this driver.
*
* \param[in] idxPCIe The index of PCIe slot for X1052 Devices
*/
WBMemX1052Con::WBMemX1052Con(uint32_t idxPCIe,uint32_t magic_addr, uint32_t magic_val)
: WBMemCon(WBMemCon::X1052,"X1052")
{
uint32_t dwStatus, tmp;
dwStatus = X1052_LibInit();
if (WD_STATUS_SUCCESS != dwStatus)
{
TRACE_P_ERROR("Failed to init the X1052 library: %s",
X1052_GetLastErr());
}
//Obtain version info
std::stringstream ss1,ss2;
int ret;
char buf[MAX_DESC];
X1052_GetInfo(buf,'v');
ss1 << buf;
ret = X1052_GetInfo(buf,'w');
ss1 <<" (WD:" << ret/100 << "." << ret%100 << ")";
ver=ss1.str();
ss2 << "Slot index: "<< idxPCIe;
desc=ss2.str();
/* Find and open a X1052 device (by default ID) */
hDev = X1052_DeviceOpen(idxPCIe);
/* Finaly check the magic address value */
if(magic_addr!=0xFFFFFFFF)
{
this->mem_access(magic_addr,&tmp,false);
if(tmp!=magic_val)
{
X1052_DeviceClose(hDev);
hDev=NULL;
TRACE_P_ERROR("Failed to Open device magic_number: 0x%0x (!=0x%0x)",tmp,magic_val);
}
}
}
/**
* Desctructor of the WBMemX1052 class
*
* It will close the handler on the PCIe device.
*/
WBMemX1052Con::~WBMemX1052Con()
{
uint32_t dwStatus;
if(hDev)
{
/* Perform necessary cleanup before exiting the program */
X1052_DeviceClose(hDev);
}
dwStatus = X1052_LibUninit();
if (WD_STATUS_SUCCESS != dwStatus)
{
TRACE_P_ERROR("Failed to un-init the X1052 library: %s",
X1052_GetLastErr());
}
}
/**
* Return true if the handler on the PCIe is valid
*/
bool WBMemX1052Con::isValid()
{
return hDev!=NULL;
}
/**
* Single 32bit access to the wishbone device (seen as a memory map)
*
* \param[in] wb_addr The address of the data we want to access.
* \param[inout] data the read "read from/write to" the device.
* \param[in] to_dev if true we write to the device.
* \see X1052_Wishbone_CSR() function
*/
bool WBMemX1052Con::mem_access(uint32_t wb_addr, uint32_t* data, bool to_dev)
{
int status;
TRACE_CHECK_PTR(hDev,false);
if(to_dev) status=X1052_Wishbone_CSR(hDev,wb_addr,data,(int)to_dev);
else status=X1052_Wishbone_CSR(hDev,wb_addr,data,to_dev);
TRACE_P_VDEBUG("%s@%08X %s %08x (%d)",(to_dev)?"W":"R", wb_addr,(to_dev)?"=>":"<=",*data,status);
return (status==S_OK);
}
/**
* Block access to the wishbone device (seen as a memory map)
*
* This use the DMA of the device to access by blocks of [0x80-0x8000]
* to the device.
*
* \param[in] dev_addr The address on the device of the data we want to access.
* \param[in] nsize The size in byte that we want to read/write.
* \param[in] to_dev if true we write to the device.
* \see X1052_DMAToDev() and X1052_DMAFromDev() function.
*/
bool WBMemX1052Con::mem_block_access(uint32_t dev_addr, uint32_t nsize,bool to_dev)
{
int mbps;
TRACE_CHECK_PTR(hDev,false);
block_busy=true;
if(nsize<0x80) nsize=X1052_DMA_TRANSFER_MINB;
if(nsize>X1052_DMA_TRANSFER_MAXB)
{
TRACE_P_WARNING("@0x%08X: buffer size %d truncated to %d bytes",dev_addr,nsize, X1052_DMA_TRANSFER_MAXB);
}
if(to_dev) mbps=X1052_DMAToDev(0,dev_addr, nsize);
else mbps=X1052_DMAFromDev(0,dev_addr, nsize);
block_busy=false;
TRACE_P_VDEBUG("%s@%08X %s (nsize=%d, %.2f Gpbs)",(to_dev)?"W":"R", dev_addr,(to_dev)?"=>":"<=",nsize,mbps/1000.0);
TRACE_CHECK_VA(mbps>0,false,
"DMA failed #%d %s \n%s@%08X %s (nsize=%d)",
mbps,X1052_GetLastErr(),
(to_dev)?"W":"R", dev_addr,(to_dev)?"=>":"<=",nsize);
return true;
}
/**
* Retrieve the internal block buffer
*
* This directly retrieve the R or W buffer used for DMA transfer
* by the X1052 library.
*
* \param[out] hDma handler on the dma buffer
* \param[in] to_dev if true we return the write to dev buffer,
* otherwise we return the read to dev buffer.
* \return The size in byte of the retrieved buffer
*/
uint32_t WBMemX1052Con::get_block_buffer(uint32_t** hDma, bool to_dev)
{
(*hDma)=(uint32_t*)X1052_DMAGetUserSpaceBuffer((int)to_dev);
return X1052_DMA_TRANSFER_MAXB;
}
#endif
/**
* \file
* \brief Contains the class WBMemX1052Con.
*
*
*
* \see This class use the:
* - X1052 driver API
* - Jungo Windriver API (10.10)
*
*
* \date Oct 31, 2013
* \author Benoit Rat (benoit<AT>sevensols.com)
*/
#ifndef WBMEMX1052CON_H_
#define WBMEMX1052CON_H_
#include "WBNode.h"
#ifndef _WDC_LIB_H_
typedef void *WDC_DEVICE_HANDLE; //!< Hack to not include all the X1052 api in this header
#endif
/**
* WB memory connector using X1052 driver
*
* \warning
* The x1052_api and Jungo Windriver libraries must be linked
* during the compilation if we want to compile this class.\n
* You might also define the \b AWBPD_NO_X1052 preprocessor variable
* if you want to disable the compilation of the cpp file.
*
*/
class WBMemX1052Con: public WBMemCon {
public:
WBMemX1052Con(uint32_t idPCIe,uint32_t magic_addr=0xFFFFFFFF, uint32_t magic_val=-1);
virtual ~WBMemX1052Con();
bool isValid();
bool mem_access(uint32_t addr, uint32_t *data, bool from_dev);
uint32_t get_block_buffer(uint32_t **hDma, bool from_dev);
bool mem_block_access(uint32_t dev_addr, uint32_t nsize, bool from_dev);
private:
WDC_DEVICE_HANDLE hDev;
};
#endif /* WBMEMX1052CON_H_ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/**
* \file
* \brief Contains the class asynWBPortDrvr
*
* \ref AsynWBSync
*
* \date Oct 28, 2013
* \author Benoit Rat
*/
#ifndef ASYNWBORTDRVR_H_
#define ASYNWBORTDRVR_H_
#include <string>
#include <map>
#include "WBNode.h"
#include <asynPortDriver.h>
//! Type of synchronization between the memory, Wishbone tree and Process variable
enum AsynWBSync {
AWB_SYNC_DEVICE=0, //!< Sync to/from the device using WBMemCon on the field
AWB_SYNC_WBSTRUCT, //!< Sync to/from the WBNode (no access to device)
AWB_SYNC_PRMLIST, //!< Sync quickly on paramList using Get/Set (no access to device)
AWB_SYNC_DERIVED, //!< Sync must be performed on the children class.
};
struct AsynWBField {
WBField* pFld;
int syncmode;
};
/**
* Structure that overload standard operator of asynStatus enum in order to ease its manipulation.
*/
struct AsynStatusObj {
asynStatus data;
AsynStatusObj(asynStatus data): data(data) {};
AsynStatusObj& operator&=(const asynStatus &data) { if(data!=asynSuccess || (this->data!=asynSuccess && data!=asynSuccess)) {this->data=data;} return *this; }
AsynStatusObj& operator=(const asynStatus &data) { this->data=data; return *this; }
bool operator==(asynStatus data) const { return (this->data==data); }
asynStatus operator &() const { return this->data; };
operator asynStatus() const { return this->data; };
};
/**
* The generic abstract AsynWBPortDrv class
*
* This class has been designed to ease the development of a real application class.
* It provide the method to synchronize easily from/to a wishbone-able device and the process
* variable from EPICS.
*
* It mimic part of the asynPortDriver but it also includes the synchronize to the device
* in an automatic mode if necessary
*
* \note In the children class you must redefine the setup() method.
* There you can create all the parameters need using the WBNode tree structure
* and also instantiate a memory connector.
*
* \ref AsynWBSync
*/
class asynWBPortDrvr : public asynPortDriver {
public:
asynWBPortDrvr(const char *portName, int max_nprm);
virtual ~asynWBPortDrvr();
virtual asynStatus setup()=0; //!< Need to be overriden
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
virtual asynStatus readFloat64(asynUser *pasynUser, epicsFloat64 *value);
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
virtual asynStatus writeOctet(asynUser *pasynUser, const char *value, size_t maxChars,size_t *nActual);
virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars, size_t *nActual, int *eomReason);
bool isValid() { return pRoot!=NULL; } //!< return true if the child class has been properly setup()
protected:
asynStatus createParam(WBField *fld, int *index=NULL,int syncmode=AWB_SYNC_DEVICE);
asynStatus createParam(const char *name, WBField *fld, int *index=NULL, int syncmode=AWB_SYNC_DEVICE);
asynStatus createParam(const char *name, asynParamType type,int *index=NULL,int syncmode=AWB_SYNC_PRMLIST);
bool cvtWBNodetoPrmList(WBNode *node);
int getParamIndex(const char *name);
WBNode *pRoot; //!< pointer on the WB tree structure.
WBMemCon* pMemCon; //!< generic pointer on the memory connector.
private:
std::vector<AsynWBField> fldPrms;
std::string driverName;
};
#endif
/*
* awbpd_trace.h
*
* Created on: Nov 4, 2013
* Author: Benoit Rat (benoit<AT>sevensols.com)
*/
#ifndef AWBPD_TRACE_H_
#define AWBPD_TRACE_H_
#if defined(TRACE_STDERR)
#define errlogPrintf(...) fprintf(stderr,__VA_ARGS__)
#else
#include <epicsPrint.h>
#endif
//------------------------------------------------------------------------------
// Global Definitions
//------------------------------------------------------------------------------
#define TRACE_LEVEL_DEBUG 5
#define TRACE_LEVEL_INFO 4
#define TRACE_LEVEL_WARNING 3
#define TRACE_LEVEL_ERROR 2
#define TRACE_LEVEL_FATAL 1
#define TRACE_LEVEL_NO_TRACE 0
// By default, all traces are output except the debug one.
#if !defined(TRACE_LEVEL)
#define TRACE_LEVEL TRACE_LEVEL_DEBUG
#endif
// By default, trace level is static (not dynamic)
#if !defined(DYN_TRACES)
#define DYN_TRACES 0
#endif
#if defined(NOTRACE)
#error "Error: NOTRACE has to be not defined !"
#endif
#undef NOTRACE
#if (DYN_TRACES==0)
#if (TRACE_LEVEL == TRACE_LEVEL_NO_TRACE)
#define NOTRACE
#endif
#endif
//------------------------------------------------------------------------------
// Global Macros
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Outputs a formatted string using <printf> if the log level is high
/// enough. Can be disabled by defining TRACE_LEVEL=0 during compilation.
/// \param format Formatted string to output.
/// \param ... Additional parameters depending on formatted string.
//------------------------------------------------------------------------------
#if defined(NOTRACE)
// Empty macro
#define TRACE_P_DEBUG(...) { }
#define TRACE_P_INFO(...) { }
#define TRACE_P_WARNING(...) { }
#define TRACE_P_ERROR(...) { }
#define TRACE_P_FATAL(...) { while(1); }
#else
#define TRACE_FILE stderr
#endif
#if defined(DYN_TRACES_EDES)
// Trace output depends on traceLevel value
#define TRACE(level,prefix,...) { if (traceLevel >= level) { errlogPrintf(prefix __VA_ARGS__); } }
#define TRACE_P_DEBUG(...) TRACE(TRACE_LEVEL_DEBUG, "-D- ", __VA_ARGS__)
#define TRACE_P_INFO(...) TRACE(TRACE_LEVEL_INFO, "-I- ", __VA_ARGS__)
#define TRACE_P_WARNING(...) TRACE(TRACE_LEVEL_WARNING, "-W- ", __VA_ARGS__)
#define TRACE_P_ERROR(...) TRACE(TRACE_LEVEL_ERROR, "-E- ", __VA_ARGS__)
#define TRACE_P_FATAL(...) { TRACE(TRACE_LEVEL_FATAL, "-F- ", __VA_ARGS__); while(1); }
#else
// Trace output depends on traceLevel value
#define TRACE(level,...) { if (TRACE_LEVEL >= level) { errlogPrintf(__VA_ARGS__); } }
#define END_PRINT errlogPrintf("\n")
#define S(x) #x
#define S_(x) S(x)
#if defined(WIN32)
#define BEG_PRINT(lvlstr)
#define MYLINE __FUNCTION__ "() #" S_(__LINE__) ": "
#else
#define BEG_PRINT(lvlstr) errlogPrintf("%s#%03d %12s(): ",lvlstr, __LINE__, __func__)
#define MYLINE
#endif
#define TRACE_P_PRINT(lvlstr,...) { BEG_PRINT(lvlstr); errlogPrintf(MYLINE __VA_ARGS__); END_PRINT; }
// Trace compilation depends on TRACE_LEVEL value
#if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
#define TRACE_P_DEBUG(...) TRACE_P_PRINT("-D- ",__VA_ARGS__)
#else
#define TRACE_P_DEBUG(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
#define TRACE_P_INFO(...) TRACE_P_PRINT("-I- ",__VA_ARGS__)
#else
#define TRACE_P_INFO(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_WARNING)
#define TRACE_P_WARNING(...) TRACE_P_PRINT("-W- ",__VA_ARGS__)
#else
#define TRACE_P_WARNING(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_ERROR)
#define TRACE_P_ERROR(...) TRACE_P_PRINT("-E- ",__VA_ARGS__)
#else
#define TRACE_P_ERROR(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_FATAL)
#define TRACE_P_FATAL(...) { TRACE_P_PRINT("-F- ",__VA_ARGS__) while(1); }
#else
#define TRACE_P_FATAL(...) { while(1); }
#endif
#endif
#define TRACE_CHECK(assert_expr,ret,str) { if(!(assert_expr)) { TRACE_P_WARNING(str); return ret; } }
#define TRACE_CHECK_VA(assert_expr,ret,str,...) { if(!(assert_expr)) { TRACE_P_WARNING(str,__VA_ARGS__); return ret; } }
#define TRACE_CHECK_PTR(ptr, ret) { if(ptr==0) { TRACE_P_WARNING("%s is NULL",#ptr); return ret; }} //EFAULT
//------------------------------------------------------------------------------
// Exported variables
//------------------------------------------------------------------------------
// Depending on DYN_TRACES, traceLevel is a modifable runtime variable
// or a define
#if !defined(NOTRACE) && (DYN_TRACES == 1)
extern unsigned int traceLevel;
#endif
#include <sstream>
#endif /* AWBPD_TRACE_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment