module ti.uia.sysbios.LoggerStreamer2

General purpose logger enabling applications to stream data to an instrumentation host

This logger is an enhancement of LoggerStreamer, and is useful in situations where the application wants to manage the buffers used to store and transmit events. This includes managing the sending of the buffers to an instrumentation host (e.g. System Analyzer in CCS). LoggerStreamer2 enables the application to send a stream of packets containing UIA event data to the instrumentation host. [ more ... ]
C synopsis target-domain sourced in ti/uia/sysbios/LoggerStreamer2.xdc
#include <ti/uia/sysbios/LoggerStreamer2.h>
Functions
Void
Void
Void
Void 
SizeT 
UArg 
Void 
Void
Bool 
Void 
Void 
Functions common to all ILogger modules
Bool 
Bool 
Void 
Void 
Void 
Void 
Void 
LoggerStreamer2_write8// Process a log event with 8 arguments and the calling address(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid, IArg a1, IArg a2, IArg a3, IArg a4, IArg a5, IArg a6, IArg a7, IArg a8);
Functions common to all IUIATransfer modules
Bool 
UInt16 
SizeT 
Bool 
Void 
Functions common to all IFilterLogger modules
Void 
Functions common to all ILoggerSnapshot modules
Void 
LoggerStreamer2_writeMemoryRange// Log an event along with values from a range of memory addresses(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid, UInt32 snapshotId, IArg fileName, IArg LineNum, IArg fmt, IArg startAdrs, UInt32 lengthInMAUs);
Functions common to all target instances
LoggerStreamer2_handle// Convert this instance structure pointer into an instance handle, LoggerStreamer2_Handle_downCast// conditionally move one level down the inheritance hierarchy; NULL upon failure, LoggerStreamer2_Handle_downCast2// conditionally move 2 levels down the inheritance hierarchy; NULL upon failure, LoggerStreamer2_Handle_downCast3// conditionally move 3 levels down the inheritance hierarchy; NULL upon failure, LoggerStreamer2_Handle_downCast4// conditionally move 4 levels down the inheritance hierarchy; NULL upon failure, LoggerStreamer2_Handle_label// The label associated with this instance object, LoggerStreamer2_Handle_name// The name of this instance object, LoggerStreamer2_Handle_upCast// unconditionally move one level up the inheritance hierarchy, LoggerStreamer2_Handle_upCast2// unconditionally move 2 levels up the inheritance hierarchy, LoggerStreamer2_Handle_upCast3// unconditionally move 3 levels up the inheritance hierarchy, LoggerStreamer2_Handle_upCast4// unconditionally move 4 levels up the inheritance hierarchy, LoggerStreamer2_Object_count// The number of statically-created instance objects, LoggerStreamer2_Object_first// The handle of the first dynamically-created instance object, or NULL, LoggerStreamer2_Object_get// The handle of the i-th statically-created instance object (array == NULL), LoggerStreamer2_Object_heap// The heap used to allocate dynamically-created instance objects, LoggerStreamer2_Object_next// The handle of the next dynamically-created instance object, or NULL, LoggerStreamer2_struct// Convert this instance handle into an instance structure pointer
Functions common to all target modules
Typedefs
typedef Ptr 
typedef struct
typedef struct
typedef Ptr 
typedef struct
typedef enum
typedef enum
Constants
extern const Assert_Id 
extern const String 
extern const Bool 
extern const Bool 
extern const Diags_Mask 
extern const Diags_Mask 
extern const Diags_Mask 
extern const Diags_Mask 
extern const IFilterLogger_Handle 
extern const Bool 
extern const Bool 
 
DETAILS
This logger is an enhancement of LoggerStreamer, and is useful in situations where the application wants to manage the buffers used to store and transmit events. This includes managing the sending of the buffers to an instrumentation host (e.g. System Analyzer in CCS). LoggerStreamer2 enables the application to send a stream of packets containing UIA event data to the instrumentation host.
The difference between LoggerStreamer2 and LoggerStreamer, is that each LoggerStreamer2 instance has its own buffer for events logged to that instance. By including the header file, ti/uia/runtime/LogUC.h, you can specify the LoggerStreamer2 instance that you want the event logged to.
The application is responsible for providing the buffers that LoggerStreamer2 loggers use. There are two ways to accomplish this.
  • Provide a prime callback function via the primeFxn configuration parameter.
  • Call the prime API once.
The logger stores the events in a UIAPacket_Hdr structure that allows them to be sent directly to System Analyzer (e.g. via UDP), enabling efficient streaming of the data from the target to the host. The first four 32-bit words contain a UIAPacket_Hdr structure. This struct is used by the host (e.g. System Analyzer in CCS) to help decode the data (e.g. endianess, length of data, etc.). The UIAPacket_Hdr structure is initialized via the initBuffer API. All buffers given to LoggerStreamer2 loggers (via priming or exchange) must be initialized via initBuffer.
The size of the buffer includes the UIAPacket_Hdr. LoggerStreamer2 treats the buffer as a UInt32 array, so the application must guarantee the buffers are aligned on word addresses. Alignment on cache line boundaries is recommended for best performance.
When the buffer is filled, LoggerStreamer2 will hand it off to the application using an application-provided exchange function (exchangeFxn). The exchange function must be of type ExchangeFxnType. The exchange function takes the Log instance as a parameter.
The exchange function is called within the context of a Log call, so the exchange function should be designed to be fast. Since the exchange function is called within the context of the Log call, LoggerStreamer2 guarantees no Log records are dropped (i.e. LoggerStreamer2 is lossless).
LoggerStreamer2 was designed to have as minimal impact as possible on an application when calling a Log function. There are several configuration parameters that allow an application to get the optimal performance in exchange for certain restrictions.
Interrupts are disabled during the duration of the log call including when the exchange function is called. LoggerStreamer2 will ignore any log events generated during the exchangeFxn (e.g. posting a semaphore).
NOTE: You can use LoggingSetup, but you will need to set the loggers first. LoggingSetup cannot create LoggerStreamer2 instances, since it does not know what config parameters to use. See example of LoggingSetup use below.
EXAMPLES
The following XDC configuration statements create a logger module, and assign it as the default logger for all modules.
  var Defaults = xdc.useModule('xdc.runtime.Defaults');
  var Diags = xdc.useModule('xdc.runtime.Diags');
  var LoggerStreamer2 = xdc.useModule('ti.uia.sysbios.LoggerStreamer2');

  LoggerStreamer2.isTimestampEnabled = true;

  var loggerParams = new LoggerStreamer2.Params();
  loggerParams.primeFxn = '&prime';
  loggerParams.exchangeFxn = '&exchange';
  loggerParams.context = 0;

  Program.global.logger0 = LoggerStreamer2.create(loggerParams);
  Defaults.common$.logger = Program.global.logger0;

  loggerParams.context = 1;
  Program.global.logger1 = LoggerStreamer2.create(loggerParams);

The following C code demonstrates basic prime and exchange functions, and logging to different LoggerStreamer2 instances. A real implementation would send the buffer to an instrumentation host (e.g. System Analyzer in CCS) via a transport such as UDP.
  #include <xdc/std.h>
  #include <xdc/runtime/Diags.h>
  #include <xdc/runtime/Log.h>

  #include <ti/uia/runtime/LogUC.h>

  UInt32 buffer_0[2][BUFSIZE_0];
  UInt32 buffer_1[2][BUFSIZE_1];

  Int main(Int argc, String argv[])
  {
      Log_iwriteUC0(logger0, LoggerStreamer2_L_test);
      Log_iwriteUC1(logger1, LoggerStreamer2_L_test, 0x1000);
  }

  Ptr prime(LoggerStreamer2_Object *log)
  {
      UInt32 id = (UInt32)LoggerStreamer2_getContext(log);

      if (id == 0) {
          LoggerStreamer2_initBuffer(buffer_0[0], 0);
          LoggerStreamer2_initBuffer(buffer_0[1], 0);
          return ((Ptr)buffer_0[0]);
      }
      if (id == 1) {
          LoggerStreamer2_initBuffer(buffer_1[0], 0);
          LoggerStreamer2_initBuffer(buffer_1[1], 0);
          return ((Ptr)(buffer_1[0]));
      }

      return (NULL); // Error
  }

  Ptr exchange(LoggerStreamer2_Object *log, Ptr *full)
  {
      UInt32 id = (UInt32)LoggerStreamer2_getContext(log);

      if (id == 0) {
          count_0++;
          // Ping-pong between the two buffers
          return ((Ptr*)buffer_0[count_0 & 1]);
      }
      if (id == 1) {
          count_1++;
          // Ping-pong between the two buffers
          return ((Ptr*)buffer_1[count_1 & 1]);
      }
      return (NULL);  // Error
  }
The following XDC configuration statements show how to use LoggingSetup with LoggerStreamer2.
  var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');
  LoggingSetup.eventUploadMode = LoggingSetup.UploadMode_STREAMER2;
  LoggingSetup.mainLogger = Program.global.logger0;
  LoggingSetup.sysbiosLogger = Program.global.logger0;

 
enum LoggerStreamer2_TransferType
C synopsis target-domain
typedef enum LoggerStreamer2_TransferType {
    LoggerStreamer2_TransferType_RELIABLE,
    LoggerStreamer2_TransferType_LOSSY
} LoggerStreamer2_TransferType;
 
 
enum LoggerStreamer2_TransportType

Used to specify the type of transport to use

C synopsis target-domain
typedef enum LoggerStreamer2_TransportType {
    LoggerStreamer2_TransportType_UART,
    LoggerStreamer2_TransportType_USB,
    LoggerStreamer2_TransportType_ETHERNET,
    LoggerStreamer2_TransportType_CUSTOM
} LoggerStreamer2_TransportType;
 
DETAILS
This enum is used by the instrumentation host to determine what the transport is. It is not used by the target code.
 
typedef LoggerStreamer2_ExchangeFxnType

Typedef for the exchange function pointer

C synopsis target-domain
typedef Ptr (*LoggerStreamer2_ExchangeFxnType)(LoggerStreamer2_Object*,Ptr);
 
DETAILS
The exchange function takes a LoggerStreamer2 object and a pointer to the full buffer as arguments. If using the same exchange function for multiple LoggerStreamer2 instances, getContext() can be called within the exchange function to determine which buffer to exchange.
 
typedef LoggerStreamer2_PrimeFxnType

Typedef for the exchange function pointer

C synopsis target-domain
typedef Ptr (*LoggerStreamer2_PrimeFxnType)(LoggerStreamer2_Object*);
 
 
config LoggerStreamer2_A_invalidBuffer  // module-wide

Assert raised when the buffer parameter is NULL

C synopsis target-domain
extern const Assert_Id LoggerStreamer2_A_invalidBuffer;
 
 
config LoggerStreamer2_customTransportType  // module-wide

Custom transport used to send the records to an instrumentation host

C synopsis target-domain
extern const String LoggerStreamer2_customTransportType;
 
DETAILS
If the desired transport is not in the TransportType enum, and transportType is set to TransportType_CUSTOM, this parameter must be filled in with the correct transport name.
If transportType is NOT set to TransportType_CUSTOM, this parameter is ignored.
 
config LoggerStreamer2_filterByLevel  // module-wide

Support filtering of events by event level

C synopsis target-domain
extern const Bool LoggerStreamer2_filterByLevel;
 
DETAILS
To improve logging performance, this feature can be disabled by setting filterByLevel to false.
See 'setFilterLevel' for an explanation of level filtering.
 
config LoggerStreamer2_isTimestampEnabled  // module-wide

Enable or disable logging the 64b local CPU timestamp at the start of each event

C synopsis target-domain
extern const Bool LoggerStreamer2_isTimestampEnabled;
 
DETAILS
Having a timestamp allows an instrumentation host (e.g. System Analyzer) to display events with the correct system time.
 
config LoggerStreamer2_level1Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL1

C synopsis target-domain
extern const Diags_Mask LoggerStreamer2_level1Mask;
 
DETAILS
See 'level4Mask' for details.
 
config LoggerStreamer2_level2Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL2

C synopsis target-domain
extern const Diags_Mask LoggerStreamer2_level2Mask;
 
DETAILS
See 'level4Mask' for details.
 
config LoggerStreamer2_level3Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL3

C synopsis target-domain
extern const Diags_Mask LoggerStreamer2_level3Mask;
 
DETAILS
See 'level4Mask' for details.
 
config LoggerStreamer2_level4Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL4

C synopsis target-domain
extern const Diags_Mask LoggerStreamer2_level4Mask;
 
DETAILS
If 'filterByLevel' is true, then all LoggerBuf instances will filter incoming events based on their event level.
The LoggerCircBuf module allows for specifying a different filter level for every Diags bit. These filtering levels are module wide; LoggerBuf does not support specifying the levels on a per-instance basis.
The setFilterLevel API can be used to change the filtering levels at runtime.
The default filtering levels are assigned using the 'level1Mask' - 'level4Mask' config parameters. These are used to specify, for each of the four event levels, the set of bits which should filter at that level by default.
The default filtering configuration sets the filter level to Diags.LEVEL4 for all logging-related diags bits so that all events are logged by default.
 
config LoggerStreamer2_statusLogger  // module-wide

This configuration option is not supported by this logger and should be left null

C synopsis target-domain
extern const IFilterLogger_Handle LoggerStreamer2_statusLogger;
 
 
config LoggerStreamer2_supportLoggerDisable  // module-wide

Allow LoggerStreamer2 instances to be enabled/disabled during runtime

C synopsis target-domain
extern const Bool LoggerStreamer2_supportLoggerDisable;
 
 
config LoggerStreamer2_testForNullWrPtr  // module-wide

Protect against log calls during the exchange function

C synopsis target-domain
extern const Bool LoggerStreamer2_testForNullWrPtr;
 
 
LoggerStreamer2_setModuleIdToRouteToStatusLogger()  // module-wide

This function is provided for compatibility with the ILoggerSnapshot interface only and simply returns when called

C synopsis target-domain
Void LoggerStreamer2_setModuleIdToRouteToStatusLogger(Types_ModuleId mid);
 
Module-Wide Built-Ins

C synopsis target-domain
Types_ModuleId LoggerStreamer2_Module_id();
// Get this module's unique id
 
Bool LoggerStreamer2_Module_startupDone();
// Test if this module has completed startup
 
IHeap_Handle LoggerStreamer2_Module_heap();
// The heap from which this module allocates memory
 
Bool LoggerStreamer2_Module_hasMask();
// Test whether this module has a diagnostics mask
 
Bits16 LoggerStreamer2_Module_getMask();
// Returns the diagnostics mask for this module
 
Void LoggerStreamer2_Module_setMask(Bits16 mask);
// Set the diagnostics mask for this module
Instance Object Types

C synopsis target-domain
typedef struct LoggerStreamer2_Object LoggerStreamer2_Object;
// Opaque internal representation of an instance object
 
typedef LoggerStreamer2_Object *LoggerStreamer2_Handle;
// Client reference to an instance object
 
typedef struct LoggerStreamer2_Struct LoggerStreamer2_Struct;
// Opaque client structure large enough to hold an instance object
 
LoggerStreamer2_Handle LoggerStreamer2_handle(LoggerStreamer2_Struct *structP);
// Convert this instance structure pointer into an instance handle
 
LoggerStreamer2_Struct *LoggerStreamer2_struct(LoggerStreamer2_Handle handle);
// Convert this instance handle into an instance structure pointer
Instance Config Parameters

C synopsis target-domain
typedef struct LoggerStreamer2_Params {
// Instance config-params structure
    IInstance_Params *instance;
    // Common per-instance configs
    SizeT bufSize;
    // LoggerStreamer2 instance's buffer size in MAUs (Minimum Addressable Units e.g. Bytes)
    UArg context;
    // Context that can be used in exchangeFxn and primeFxn
    LoggerStreamer2_ExchangeFxnType exchangeFxn;
    // Function pointer to the exchange function
    Int16 instanceId;
    // Unique id of the LoggerStreamer2 instance
    SizeT maxEventSize;
    // The maximum event size (in Maus) that can be written with a single event. Must be less than or equal to bufSize - 64
    LoggerStreamer2_PrimeFxnType primeFxn;
    // Function pointer to the prime function
    IUIATransfer_TransferType transferType;
    // 
} LoggerStreamer2_Params;
 
Void LoggerStreamer2_Params_init(LoggerStreamer2_Params *params);
// Initialize this config-params structure with supplier-specified defaults before instance creation
 
config LoggerStreamer2_Params.bufSize  // instance

LoggerStreamer2 instance's buffer size in MAUs (Minimum Addressable Units e.g. Bytes)

C synopsis target-domain
      ...
    SizeT bufSize;
 
DETAILS
NOTE: the buffer size must contain an integer number of 32b words (e.g. if a MAU = 1 byte, then the buffer size must be a multiple of 4). The buffer size must also be at least maxEventSize + 64.
 
config LoggerStreamer2_Params.context  // instance

Context that can be used in exchangeFxn and primeFxn

C synopsis target-domain
      ...
    UArg context;
 
DETAILS
The context can be used to identify the logger instance, when using the same exchangeFxn or primeFxn for multiple LoggerStreamer2 instances. Use getContext() to get the logger context. The context can be changed, if needed, by calling setContext(). The context can be set to null if using a different exchangeFxn and primeFxn for each LoggerStreamer2 instance.
 
config LoggerStreamer2_Params.exchangeFxn  // instance

Function pointer to the exchange function

C synopsis target-domain
      ...
    LoggerStreamer2_ExchangeFxnType exchangeFxn;
 
DETAILS
The exchange function must return a pointer to a buffer that is word aligned, initialized with a UIA header and the correct size. This is called in the context of a log so generally the exchange function should be quick to execute.
 
config LoggerStreamer2_Params.instanceId  // instance

Unique id of the LoggerStreamer2 instance

C synopsis target-domain
      ...
    Int16 instanceId;
 
 
config LoggerStreamer2_Params.maxEventSize  // instance

The maximum event size (in Maus) that can be written with a single event. Must be less than or equal to bufSize - 64

C synopsis target-domain
      ...
    SizeT maxEventSize;
 
DETAILS
The writeMemoryRange API checks to see if the event size required to write the block of memory is larger than maxEventSize. If so, it will split the memory range up into a number of smaller blocks and log the blocks using separate events with a common snapshot ID in order to allow the events to be collated and the original memory block to be reconstructed on the host.
 
config LoggerStreamer2_Params.primeFxn  // instance

Function pointer to the prime function

C synopsis target-domain
      ...
    LoggerStreamer2_PrimeFxnType primeFxn;
 
 
config LoggerStreamer2_Params.transferType  // instance
C synopsis target-domain
      ...
    IUIATransfer_TransferType transferType;
 
Runtime Instance Creation

C synopsis target-domain
LoggerStreamer2_Handle LoggerStreamer2_create(const LoggerStreamer2_Params *params, Error_Block *eb);
// Allocate and initialize a new instance object and return its handle
 
Void LoggerStreamer2_construct(LoggerStreamer2_Struct *structP, const LoggerStreamer2_Params *params);
// Initialize a new instance object inside the provided structure
ARGUMENTS
params — per-instance config params, or NULL to select default values (target-domain only)
eb — active error-handling block, or NULL to select default policy (target-domain only)
Instance Deletion

C synopsis target-domain
Void LoggerStreamer2_delete(LoggerStreamer2_Handle *handleP);
// Finalize and free this previously allocated instance object, setting the referenced handle to NULL
 
Void LoggerStreamer2_destruct(LoggerStreamer2_Struct *structP);
// Finalize the instance object inside the provided structure
 
LoggerStreamer2_disable()  // instance

Disable a log

C synopsis target-domain
Bool LoggerStreamer2_disable(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
Events written to a disabled log are silently discarded.
RETURNS
The function returns the state of the log (TRUE if enabled, FALSE if disabled) before the call. This return value allows clients to restore the previous state. Note: not thread safe.
 
LoggerStreamer2_enable()  // instance

Enable a log

C synopsis target-domain
Bool LoggerStreamer2_enable(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
RETURNS
The function returns the state of the log (TRUE if enabled, FALSE if disabled) before the call. This return value allows clients to restore the previous state. Note: not thread safe.
 
LoggerStreamer2_flush()  // instance

Force LoggerStreamer2 to call the exchange function

C synopsis target-domain
Void LoggerStreamer2_flush(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
This API makes LoggerStreamer2 call the application provided exchangeFxn function if there are Log events present in the buffer.
The call to the exchangeFxn function is called in the context of the flush call.
 
LoggerStreamer2_getBufSize()  // instance

Returns the Log's configured buffer size

C synopsis target-domain
SizeT LoggerStreamer2_getBufSize(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
RETURNS
Log's configured buffer size.
 
LoggerStreamer2_getContents()  // instance

Fills buffer that is passed in with unread data, up to size bytes in length

C synopsis target-domain
Bool LoggerStreamer2_getContents(LoggerStreamer2_Handle handle, Ptr hdrBuf, SizeT size, SizeT *cpSize);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
hdrBuf — Ptr to a buffer that is at least <size> bytes in length
size — The max number of bytes to be read into the buffer
cpSize — The number of bytes actually copied
DETAILS
The logger is responsible for ensuring that no partial event records are stored in the buffer. Bytes are in target endianness.
RETURN
returns false if logger has no more records to read
 
LoggerStreamer2_getContext()  // instance

Returns the Log's context

C synopsis target-domain
UArg LoggerStreamer2_getContext(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
RETURNS
context
 
LoggerStreamer2_getFilterLevel()  // instance

Returns the mask of diags categories currently set to the specified level

C synopsis target-domain
Diags_Mask LoggerStreamer2_getFilterLevel(LoggerStreamer2_Handle handle, Diags_EventLevel level);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
See 'setFilterLevel' for an explanation of level filtering.
See 'setFilterLevel' for an explanation of level filtering.
 
LoggerStreamer2_getInstanceId()  // instance

Returns an ID value that uniquely identifies this instance of the logger

C synopsis target-domain
UInt16 LoggerStreamer2_getInstanceId(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
Note that a value of 0 is reserved to indicate that the instance ID has not been initialized yet and a unique value needs to be generated.
 
LoggerStreamer2_getMaxLength()  // instance
C synopsis target-domain
SizeT LoggerStreamer2_getMaxLength(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
 
LoggerStreamer2_getTransferType()  // instance
C synopsis target-domain
IUIATransfer_TransferType LoggerStreamer2_getTransferType(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
 
LoggerStreamer2_initBuffer()  // instance

Initializes the UIA packet header

C synopsis target-domain
Void LoggerStreamer2_initBuffer(LoggerStreamer2_Handle handle, Ptr buffer, UInt16 src);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
buffer — Pointer to the buffer that LoggerStreamer2 will fill with Log events. The first four 32-bit words will contain the UIAPacket_Hdr structure.
src — Used to initialize the UIA source address. For a single core device, this will generally be 0. For multi-core devices, it generally corresponds to the DNUM (on C6xxxx deviecs) or the Ipc MultiProc id. It must be unique for all cores and match the configuration in the System Analyzer endpoint configuration.
DETAILS
This API is used to initialize a buffer before it is given to LoggerStreamer2 (via priming or exchange). The function initializes the UIAPacket_Hdr portion of the buffer.
 
LoggerStreamer2_isEmpty()  // instance

Returns true if the transfer buffer has no unread data

C synopsis target-domain
Bool LoggerStreamer2_isEmpty(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
RETURN
true if no unread data
 
LoggerStreamer2_prime()  // instance

If PrimeFxn is not set the user must call prime with the first buffer

C synopsis target-domain
Bool LoggerStreamer2_prime(LoggerStreamer2_Handle handle, Ptr buffer);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
 
LoggerStreamer2_reset()  // instance

Reset a log to empty state and enable it

C synopsis target-domain
Void LoggerStreamer2_reset(LoggerStreamer2_Handle handle);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
WARNING
This method is not synchronized with other instance methods and, as a result, it must never be called when there is a chance that another instance method is currently in operation or when another method on this instance may preempt this call.
 
LoggerStreamer2_setContext()  // instance

Set the Log's context

C synopsis target-domain
Void LoggerStreamer2_setContext(LoggerStreamer2_Handle handle, UArg context);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
context — New value of Log's context
 
LoggerStreamer2_setFilterLevel()  // instance

Sets the level of detail that instances will log

C synopsis target-domain
Void LoggerStreamer2_setFilterLevel(LoggerStreamer2_Handle handle, Diags_Mask mask, Diags_EventLevel filterLevel);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
mask — The diags categories to set the level for
The diags categories to set the level for
filterLevel — The new filtering level for the specified categories
The new filtering level for the specified categories
DETAILS
Events with the specified level or higher will be logged, events below the specified level will be dropped.
Events are filtered first by diags category, then by level. If an event's diags category is disabled in the module's diags mask, then it will be filtered out regardless of level. The event will not even be passed to the logger.
This API allows for setting the filtering level for more than one diags category at a time. The mask parameter can be a single category or multiple categories combined, and the level will be set for all of those categories.
Events with the specified level or higher will be logged, events below the specified level will be dropped.
Events are filtered first by diags category, then by level. If an event's diags category is disabled in the module's diags mask, then it will be filtered out regardless of level. The event will not even be passed to the logger.
This API allows for setting the filtering level for more than one diags category at a time. The mask parameter can be a single category or multiple categories combined, and the level will be set for all of those categories.
 
LoggerStreamer2_write0()  // instance

Process a log event with 0 arguments and the calling address

C synopsis target-domain
Void LoggerStreamer2_write0(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
Same as write4 except with 0 arguments rather than 4.
Same as write4 except with 0 arguments rather than 4.
SEE
 
LoggerStreamer2_write1()  // instance

Process a log event with 1 arguments and the calling address

C synopsis target-domain
Void LoggerStreamer2_write1(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid, IArg a1);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
Same as write4 except with 1 arguments rather than 4.
Same as write4 except with 1 arguments rather than 4.
SEE
 
LoggerStreamer2_write2()  // instance

Process a log event with 2 arguments and the calling address

C synopsis target-domain
Void LoggerStreamer2_write2(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid, IArg a1, IArg a2);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
Same as write4 except with 2 arguments rather than 4.
Same as write4 except with 2 arguments rather than 4.
SEE
 
LoggerStreamer2_write4()  // instance

Process a log event with 4 arguments and the calling address

C synopsis target-domain
Void LoggerStreamer2_write4(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid, IArg a1, IArg a2, IArg a3, IArg a4);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
evt — event to be logged
mid — module ID of the module which logged the event
a1 — arbitrary argument passed by caller
DETAILS
The evt argument is of type Log.Event, which encodes the Log.EventId, the Diags.Mask, and the Diags.EventLevel of the event. The event ID can be obtained via Types.getEventId(evt), the Diags mask can be obtained via Diags.getMask(evt), and the event level can be obtained via Diags.getLevel(evt).
The modId argument is the module ID of the module that logged the event.
The event information can be used by the logger to handle different events specially. For example, the event ID can be used to compare against other known Log.Events.
      if (Log_getEventId(MY_EVENT) == Log_getEventId(evt)) {
          :
      }
The Diags mask and event level can be used for filtering of events based on event level (see IFilterLogger), or even routing events to separate loggers based on diags category (see, for example, LoggerBuf.statusLogger).
The Diags mask and event level are useful for handling the event, but are generally not recorded by the logger because they are not needed in decoding and displaying the event. A more suitable value to record is a Types.Event, which encodes the event ID and module ID. For example, the Log.EventRec type stores a Types.Event in its record definition. A Types.Event can be created using the Types.makeEvent API given the event ID and module ID.
The event ID value of 0 is used to indicate an event triggered by a call to one of the Log_print[0-6] methods. These methods take a format string rather than a Log_Event argument and, as a result, the event ID encoded in evt is 0 and the parameter a1 is the format string.
Non-zero event IDs can also be used to access the msg string associated with the Log.EventDesc that originally defined the Log event.
      Log_EventId id = Log_getEventId(evt));
      if (id != 0) {
          String msg = Text_ropeText(id);
          System_aprintf(msg, a1, a2, a3, a4);
      }
This works because an event's ID is simply an offset into a table of characters (maintained by the Text module) containing the event's msg string.
The arguments a1, a2, etc. are parameters that are to be interpreted according to the message format string associated with evt.
SEE
 
LoggerStreamer2_write8()  // instance

Process a log event with 8 arguments and the calling address

C synopsis target-domain
Void LoggerStreamer2_write8(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid, IArg a1, IArg a2, IArg a3, IArg a4, IArg a5, IArg a6, IArg a7, IArg a8);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
DETAILS
Same as write4 except with 8 arguments rather than 4.
Same as write4 except with 8 arguments rather than 4.
SEE
 
LoggerStreamer2_writeMemoryRange()  // instance

Log an event along with values from a range of memory addresses

C synopsis target-domain
Void LoggerStreamer2_writeMemoryRange(LoggerStreamer2_Handle handle, Log_Event evt, Types_ModuleId mid, UInt32 snapshotId, IArg fileName, IArg LineNum, IArg fmt, IArg startAdrs, UInt32 lengthInMAUs);
 
ARGUMENTS
handle — handle of a previously-created LoggerStreamer2 instance object
evt — event to be logged
snapshotId — 0 = no other snapshot groups, Use value from LogSnapshot.getSnapshotId() for all snapshots to be grouped.
fileName — __FILE__ result
lineNum — __LINE__ result
fmt — a printf style format string
startAdrs — value for first format conversion character
lengthInMAUs — value for second format conversion character
DETAILS
If the mask in the specified LogSnapshot event has any bit set which is also set in the current module's diagnostics mask, then this call to write will "raise" the given LogSnapshot event.
Note that this API supports null terminated strings, arrays of characters and memory mapped registgers as well as blocks of memory. The LogSnapshot module provides macros that map the appropriate values to the writeMemoryRange API's arguments
SEE
Instance Convertors

C synopsis target-domain
ILoggerSnapshot_Handle LoggerStreamer2_Handle_upCast(LoggerStreamer2_Handle handle);
// unconditionally move one level up the inheritance hierarchy
 
LoggerStreamer2_Handle LoggerStreamer2_Handle_downCast(ILoggerSnapshot_Handle handle);
// conditionally move one level down the inheritance hierarchy; NULL upon failure
 
IUIATransfer_Handle LoggerStreamer2_Handle_upCast2(LoggerStreamer2_Handle handle);
// unconditionally move 2 levels up the inheritance hierarchy
 
LoggerStreamer2_Handle LoggerStreamer2_Handle_downCast2(IUIATransfer_Handle handle);
// conditionally move 2 levels down the inheritance hierarchy; NULL upon failure
 
IFilterLogger_Handle LoggerStreamer2_Handle_upCast3(LoggerStreamer2_Handle handle);
// unconditionally move 3 levels up the inheritance hierarchy
 
LoggerStreamer2_Handle LoggerStreamer2_Handle_downCast3(IFilterLogger_Handle handle);
// conditionally move 3 levels down the inheritance hierarchy; NULL upon failure
 
ILogger_Handle LoggerStreamer2_Handle_upCast4(LoggerStreamer2_Handle handle);
// unconditionally move 4 levels up the inheritance hierarchy
 
LoggerStreamer2_Handle LoggerStreamer2_Handle_downCast4(ILogger_Handle handle);
// conditionally move 4 levels down the inheritance hierarchy; NULL upon failure
Instance Built-Ins

C synopsis target-domain
Int LoggerStreamer2_Object_count();
// The number of statically-created instance objects
 
LoggerStreamer2_Handle LoggerStreamer2_Object_get(LoggerStreamer2_Object *array, Int i);
// The handle of the i-th statically-created instance object (array == NULL)
 
LoggerStreamer2_Handle LoggerStreamer2_Object_first();
// The handle of the first dynamically-created instance object, or NULL
 
LoggerStreamer2_Handle LoggerStreamer2_Object_next(LoggerStreamer2_Handle handle);
// The handle of the next dynamically-created instance object, or NULL
 
IHeap_Handle LoggerStreamer2_Object_heap();
// The heap used to allocate dynamically-created instance objects
 
Types_Label *LoggerStreamer2_Handle_label(LoggerStreamer2_Handle handle, Types_Label *buf);
// The label associated with this instance object
 
String LoggerStreamer2_Handle_name(LoggerStreamer2_Handle handle);
// The name of this instance object
 
Configuration settings sourced in ti/uia/sysbios/LoggerStreamer2.xdc
var LoggerStreamer2 = xdc.useModule('ti.uia.sysbios.LoggerStreamer2');
module-wide constants & types
    values of type LoggerStreamer2.TransferType// 
        const LoggerStreamer2.TransferType_RELIABLE;
        const LoggerStreamer2.TransferType_LOSSY;
 
        const LoggerStreamer2.TransportType_UART;
        const LoggerStreamer2.TransportType_USB;
        const LoggerStreamer2.TransportType_CUSTOM;
 
        obj.instanceId = Int  ...
        obj.priority = Int  ...
 
    var obj = new LoggerStreamer2.RecordView// ;
        obj.sequence = Int  ...
        obj.timestampRaw = Long  ...
        obj.modName = String  ...
        obj.text = String  ...
        obj.eventId = Int  ...
        obj.eventName = String  ...
        obj.arg0 = IArg  ...
        obj.arg1 = IArg  ...
        obj.arg2 = IArg  ...
        obj.arg3 = IArg  ...
        obj.arg4 = IArg  ...
        obj.arg5 = IArg  ...
        obj.arg6 = IArg  ...
        obj.arg7 = IArg  ...
 
        obj.instanceId = Int  ...
module-wide config parameters
        msg: "LoggerStreamer2_create's buffer returned by primeFxn is NULL"
    };
 
module-wide functions
per-instance config parameters
    var params = new LoggerStreamer2.Params// Instance config-params object;
        params.ptrToQueueDescriptorMeta//  = Ptr null;
per-instance creation
    var inst = LoggerStreamer2.create// Create an instance-object(params);
 
 
enum LoggerStreamer2.TransferType
Configuration settings
values of type LoggerStreamer2.TransferType
    const LoggerStreamer2.TransferType_RELIABLE;
    const LoggerStreamer2.TransferType_LOSSY;
 
C SYNOPSIS
 
enum LoggerStreamer2.TransportType

Used to specify the type of transport to use

Configuration settings
values of type LoggerStreamer2.TransportType
    const LoggerStreamer2.TransportType_UART;
    const LoggerStreamer2.TransportType_USB;
    const LoggerStreamer2.TransportType_ETHERNET;
    const LoggerStreamer2.TransportType_CUSTOM;
 
DETAILS
This enum is used by the instrumentation host to determine what the transport is. It is not used by the target code.
C SYNOPSIS
 
metaonly struct LoggerStreamer2.MetaData

This data is added to the RTA MetaData file to support stop mode RTA

Configuration settings
var obj = new LoggerStreamer2.MetaData;
 
    obj.instanceId = Int  ...
    obj.priority = Int  ...
 
 
metaonly struct LoggerStreamer2.RecordView
Configuration settings
var obj = new LoggerStreamer2.RecordView;
 
    obj.sequence = Int  ...
    obj.timestampRaw = Long  ...
    obj.modName = String  ...
    obj.text = String  ...
    obj.eventId = Int  ...
    obj.eventName = String  ...
    obj.arg0 = IArg  ...
    obj.arg1 = IArg  ...
    obj.arg2 = IArg  ...
    obj.arg3 = IArg  ...
    obj.arg4 = IArg  ...
    obj.arg5 = IArg  ...
    obj.arg6 = IArg  ...
    obj.arg7 = IArg  ...
 
 
metaonly struct LoggerStreamer2.RtaData

Data added to the RTA MetaData file to support System Analyzer

Configuration settings
var obj = new LoggerStreamer2.RtaData;
 
    obj.instanceId = Int  ...
 
 
config LoggerStreamer2.A_invalidBuffer  // module-wide

Assert raised when the buffer parameter is NULL

Configuration settings
LoggerStreamer2.A_invalidBuffer = Assert.Desc {
    msg: "LoggerStreamer2_create's buffer returned by primeFxn is NULL"
};
 
C SYNOPSIS
 
config LoggerStreamer2.customTransportType  // module-wide

Custom transport used to send the records to an instrumentation host

Configuration settings
LoggerStreamer2.customTransportType = String null;
 
DETAILS
If the desired transport is not in the TransportType enum, and transportType is set to TransportType_CUSTOM, this parameter must be filled in with the correct transport name.
If transportType is NOT set to TransportType_CUSTOM, this parameter is ignored.
C SYNOPSIS
 
config LoggerStreamer2.filterByLevel  // module-wide

Support filtering of events by event level

Configuration settings
LoggerStreamer2.filterByLevel = Bool false;
 
DETAILS
To improve logging performance, this feature can be disabled by setting filterByLevel to false.
See 'setFilterLevel' for an explanation of level filtering.
C SYNOPSIS
 
config LoggerStreamer2.isTimestampEnabled  // module-wide

Enable or disable logging the 64b local CPU timestamp at the start of each event

Configuration settings
LoggerStreamer2.isTimestampEnabled = Bool false;
 
DETAILS
Having a timestamp allows an instrumentation host (e.g. System Analyzer) to display events with the correct system time.
C SYNOPSIS
 
config LoggerStreamer2.level1Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL1

Configuration settings
LoggerStreamer2.level1Mask = Bits16 0;
 
DETAILS
See 'level4Mask' for details.
C SYNOPSIS
 
config LoggerStreamer2.level2Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL2

Configuration settings
LoggerStreamer2.level2Mask = Bits16 0;
 
DETAILS
See 'level4Mask' for details.
C SYNOPSIS
 
config LoggerStreamer2.level3Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL3

Configuration settings
LoggerStreamer2.level3Mask = Bits16 0;
 
DETAILS
See 'level4Mask' for details.
C SYNOPSIS
 
config LoggerStreamer2.level4Mask  // module-wide

Mask of diags categories whose initial filtering level is Diags.LEVEL4

Configuration settings
LoggerStreamer2.level4Mask = Bits16 Diags.ALL_LOGGING;
 
DETAILS
If 'filterByLevel' is true, then all LoggerBuf instances will filter incoming events based on their event level.
The LoggerCircBuf module allows for specifying a different filter level for every Diags bit. These filtering levels are module wide; LoggerBuf does not support specifying the levels on a per-instance basis.
The setFilterLevel API can be used to change the filtering levels at runtime.
The default filtering levels are assigned using the 'level1Mask' - 'level4Mask' config parameters. These are used to specify, for each of the four event levels, the set of bits which should filter at that level by default.
The default filtering configuration sets the filter level to Diags.LEVEL4 for all logging-related diags bits so that all events are logged by default.
C SYNOPSIS
 
config LoggerStreamer2.statusLogger  // module-wide

This configuration option is not supported by this logger and should be left null

Configuration settings
LoggerStreamer2.statusLogger = IFilterLogger.Handle null;
 
C SYNOPSIS
 
config LoggerStreamer2.supportLoggerDisable  // module-wide

Allow LoggerStreamer2 instances to be enabled/disabled during runtime

Configuration settings
LoggerStreamer2.supportLoggerDisable = Bool false;
 
C SYNOPSIS
 
config LoggerStreamer2.testForNullWrPtr  // module-wide

Protect against log calls during the exchange function

Configuration settings
LoggerStreamer2.testForNullWrPtr = Bool true;
 
C SYNOPSIS
 
metaonly config LoggerStreamer2.common$  // module-wide

Common module configuration parameters

Configuration settings
LoggerStreamer2.common$ = Types.Common$ undefined;
 
DETAILS
All modules have this configuration parameter. Its name contains the '$' character to ensure it does not conflict with configuration parameters declared by the module. This allows new configuration parameters to be added in the future without any chance of breaking existing modules.
 
metaonly config LoggerStreamer2.moduleToRouteToStatusLogger  // module-wide

This configuration option is not supported by this logger and should be left unconfigured

Configuration settings
LoggerStreamer2.moduleToRouteToStatusLogger = String undefined;
 
 
metaonly config LoggerStreamer2.transportType  // module-wide

Transport used to send the records to an instrumentation host

Configuration settings
 
DETAILS
This parameter is used to specify the transport that the exchangeFxn function will use to send the buffer to an instrumentation host (e.g. System Analyzer in CCS).
This parameter is placed into the generated UIA XML file. The instrumentation host can use the XML file to help it auto-detect as much as possible and act accordingly.
If the desired transport is not in the TransportType enum, select TransportType_CUSTOM and set the customTransportType string with the desired string.
 
metaonly LoggerStreamer2.getLoggerInstanceId()  // module-wide

returns the id of this logger instance

Configuration settings
LoggerStreamer2.getLoggerInstanceId(Any inst) returns Any
 
 
metaonly LoggerStreamer2.getMetaArgs()  // module-wide

Returns any meta data needed to support RTA

Configuration settings
LoggerStreamer2.getMetaArgs(Any inst, Any instNum) returns Any
 
DETAILS
This meta data should be returned in the form of a structure which can be converted into XML. This data is added to the RTA XML file during the application's configuration, and can be accessed later through the xdc.rta.MetaData module.
The MetaData is returned per instance of the ILogger module. The instance object is passed to the function as the first argument.
The second argument is the index of the instance in the list of the ILogger's static instances.
 
metaonly LoggerStreamer2.getPtrToQueueDescriptorMeta()  // module-wide

Each logger instance has a unique queue descriptor address that is stored in the Event Record header to identify itself to the host. This metaonly configuration parameter allows the UIA Metadata to determine what the address is for each statically created logger instance in order to emit XML code to allow the host to look up information about the logger instance (such as its name) based on the queue descriptor address that is stored in the event record header

Configuration settings
LoggerStreamer2.getPtrToQueueDescriptorMeta(Any inst) returns Any
 
DETAILS
The pointer is returned per instance of the logger module. The instance object is passed to the function as the first argument.
 
metaonly LoggerStreamer2.setPtrToQueueDescriptorMeta()  // module-wide

Sets the queue descriptor address in the logger's object instance data

Configuration settings
LoggerStreamer2.setPtrToQueueDescriptorMeta(Any inst, Any queueDescriptorAdrs) returns Any
 
Instance Config Parameters

Configuration settings
var params = new LoggerStreamer2.Params;
// Instance config-params object
    params.bufSize = SizeT 1400;
    // LoggerStreamer2 instance's buffer size in MAUs (Minimum Addressable Units e.g. Bytes)
    params.context = UArg null;
    // Context that can be used in exchangeFxn and primeFxn
    params.exchangeFxn = Ptr(*)(LoggerStreamer2.Object*,Ptr) null;
    // Function pointer to the exchange function
    params.instanceId = Int16 1;
    // Unique id of the LoggerStreamer2 instance
    params.maxEventSize = SizeT 512;
    // The maximum event size (in Maus) that can be written with a single event. Must be less than or equal to bufSize - 64
    params.primeFxn = Ptr(*)(LoggerStreamer2.Object*) null;
    // Function pointer to the prime function
    params.ptrToQueueDescriptorMeta = Ptr null;
    // 
    // 
 
config LoggerStreamer2.Params.bufSize  // instance

LoggerStreamer2 instance's buffer size in MAUs (Minimum Addressable Units e.g. Bytes)

Configuration settings
var params = new LoggerStreamer2.Params;
  ...
params.bufSize = SizeT 1400;
 
DETAILS
NOTE: the buffer size must contain an integer number of 32b words (e.g. if a MAU = 1 byte, then the buffer size must be a multiple of 4). The buffer size must also be at least maxEventSize + 64.
C SYNOPSIS
 
config LoggerStreamer2.Params.context  // instance

Context that can be used in exchangeFxn and primeFxn

Configuration settings
var params = new LoggerStreamer2.Params;
  ...
params.context = UArg null;
 
DETAILS
The context can be used to identify the logger instance, when using the same exchangeFxn or primeFxn for multiple LoggerStreamer2 instances. Use getContext() to get the logger context. The context can be changed, if needed, by calling setContext(). The context can be set to null if using a different exchangeFxn and primeFxn for each LoggerStreamer2 instance.
C SYNOPSIS
 
config LoggerStreamer2.Params.exchangeFxn  // instance

Function pointer to the exchange function

Configuration settings
var params = new LoggerStreamer2.Params;
  ...
params.exchangeFxn = Ptr(*)(LoggerStreamer2.Object*,Ptr) null;
 
DETAILS
The exchange function must return a pointer to a buffer that is word aligned, initialized with a UIA header and the correct size. This is called in the context of a log so generally the exchange function should be quick to execute.
C SYNOPSIS
 
config LoggerStreamer2.Params.instanceId  // instance

Unique id of the LoggerStreamer2 instance

Configuration settings
var params = new LoggerStreamer2.Params;
  ...
params.instanceId = Int16 1;
 
C SYNOPSIS
 
config LoggerStreamer2.Params.maxEventSize  // instance

The maximum event size (in Maus) that can be written with a single event. Must be less than or equal to bufSize - 64

Configuration settings
var params = new LoggerStreamer2.Params;
  ...
params.maxEventSize = SizeT 512;
 
DETAILS
The writeMemoryRange API checks to see if the event size required to write the block of memory is larger than maxEventSize. If so, it will split the memory range up into a number of smaller blocks and log the blocks using separate events with a common snapshot ID in order to allow the events to be collated and the original memory block to be reconstructed on the host.
C SYNOPSIS
 
config LoggerStreamer2.Params.primeFxn  // instance

Function pointer to the prime function

Configuration settings
var params = new LoggerStreamer2.Params;
  ...
params.primeFxn = Ptr(*)(LoggerStreamer2.Object*) null;
 
C SYNOPSIS
 
config LoggerStreamer2.Params.transferType  // instance
Configuration settings
var params = new LoggerStreamer2.Params;
  ...
 
C SYNOPSIS
 
metaonly config LoggerStreamer2.Params.ptrToQueueDescriptorMeta  // instance
Configuration settings
var params = new LoggerStreamer2.Params;
  ...
params.ptrToQueueDescriptorMeta = Ptr null;
 
Static Instance Creation

Configuration settings
var params = new LoggerStreamer2.Params;
// Allocate instance config-params
params.config =   ...
// Assign individual configs
 
var inst = LoggerStreamer2.create(params);
// Create an instance-object
ARGUMENTS
params — per-instance config params, or NULL to select default values (target-domain only)
eb — active error-handling block, or NULL to select default policy (target-domain only)
generated on Tue, 14 Feb 2017 00:15:19 GMT