/* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA"). * All rights reserved. * * This software is supplied "AS IS" without any warranties. * RDA assumes no responsibility or liability for the use of the software, * conveys no license or title under any patent, copyright, or mask work * right to the product. RDA reserves the right to make changes in the * software without notification. RDA also make no representation or * warranty that such application will be suitable for the specified use * without further testing or modification. */ #ifndef _OSI_TRACE_H_ #define _OSI_TRACE_H_ #include #include #include #include "osi_api.h" #include "quec_proj_config.h" OSI_EXTERN_C_BEGIN /** * \brief forward declaration for debug port */ struct drvDebugPort; /** * \brief trace output device */ typedef enum { OSI_TRACE_DEVICE_NONE = 0, ///< no output OSI_TRACE_DEVICE_DEBUGHOST = 0x01, ///< output through debughost OSI_TRACE_DEVICE_USBSERIAL = 0x02, ///< output through USB serial #ifndef CONFIG_QUEC_PROJECT_FEATURE OSI_TRACE_DEVICE_FILESYS = 0x04, ///< output to file system, usually on SDCARD #else OSI_TRACE_DEVICE_FILESYS_SD = 0x04, ///< output to file system, usually on SDCARD OSI_TRACE_DEVICE_FILESYS_NAND = 0x05, ///< output to file system, usually on NAND FLASH OSI_TRACE_DEVICE_FILESYS_EXTNOR = 0x6, ///< output to file system, usually on SPI4 EXT NOR FLASH,is not supported by default OSI_TRACE_DEVICE_FILESYS_EXT = 0x7, ///< output to file system, usually on SPI6 EXT NOR FLASH,is not supported by default #endif } osiTraceDevice_t; /** * \brief data structure of host packet * * *frame length* is the length of host packet, *exclude* header. So, * frame length is the packet length minus 4. */ typedef struct { uint8_t sync; ///< sync byte, 0xAD uint8_t frame_len_msb; ///< MSB byte of frame length uint8_t frame_len_lsb; ///< LSB byte of frame length uint8_t flowid; ///< flow ID } osiHostPacketHeader_t; /** * \brief tra packet header data structure */ typedef struct { uint16_t sync; ///< sync 16bits word, 0xBBBB uint8_t plat_id; ///< platform id, fill 1 at unsure. uint8_t type; ///< tra packet type uint32_t sn; ///< serial number uint32_t fn_wcdma; ///< WCDMA frame number, fill tick count when there are no WCDMA uint32_t fn_gge; ///< GSM frame number uint32_t fn_lte; ///< LTE frame number } osiTraPacketHeader_t; /** * \brief diag packet header */ typedef struct { uint32_t seq_num; ///< Message sequence number, used for flow control uint16_t len; ///< The totoal size of the packet uint8_t type; ///< Main command type uint8_t subtype; ///< Sub command type } osiDiagPacketHeader_t; /** * \brief diag log packet header */ typedef struct { uint16_t type; ///< log type uint16_t length; ///< log length } osiDiagLogHeader_t; #ifdef CONFIG_SOC_8910 #define FSTRACE_SUPPORT_TIMESTAMP #elif defined(CONFIG_SOC_8850) #define FSTRACE_SUPPORT_TIMESTAMP #endif #ifdef CONFIG_KERNEL_HOST_TRACE /** * Application trace (Time) header */ typedef struct { osiHostPacketHeader_t host; uint32_t date; ///< trace sequence uint32_t ms; ///< tick of trace } osiTraceTimeStampHeader_t; #elif defined(CONFIG_KERNEL_DIAG_TRACE) #pragma pack(4) typedef struct { osiDiagPacketHeader_t diag; uint64_t llUeTime; uint32_t u32tickcnt; //tick count } osiTraceDiagTimeStampHeader_t; typedef struct { //uint32_t u32size; osiTraceDiagTimeStampHeader_t stTimeStampheader; } osiTraceDiagTimeStamp; #pragma pack() #endif /** * \brief prototype for trace push callback */ typedef void (*osiTracePushCallback_t)(void *param); /** * \brief global trace sequence number * * *Don't* modify it, unless in trace output engine. */ extern uint32_t gTraceSequence; /** * \brief global variable for trace enable/disable * * *Don't* modify it. It is only for trace API for faster check, * to save a little cycles than calling API. */ extern bool gTraceEnabled; /** * \brief tick value for trace * * The unit of tick is platform dependent, to adapt various trace tool. */ uint32_t osiTraceTick(void); /** * \brief time in millisecond for trace */ uint32_t osiTraceTimeMs(void); /** * \brief set trace enable or not * * After disable, trace calls won't put trace data to trace buffer. Also, * debug port will stop trace output (after the already started transfer * finished). * * There are multiple enable controls * - \p osiTraceSetEnable Enable control for log. When disabled, log message * won't come to trace buffer. * - \p osiTraceSetOutputEnable Enable control for log output. Other packets * are not affected by this. When disabled, debug port cannot get log * packets, but can get packets by \p osiTraceBufPutPacket, for example, * diag packets. * - \p osiTraceSetPushEnable Enable control for debug port. When disabled, * debug port cannot get any packets. * * \param enable false for disable, true for enable */ void osiTraceSetEnable(bool enable); /** * \brief set trace output enable or not * * When trace output disabled, \p osiTraceBufFetch won't return trace * buffer, and will only return external buffer by \p osiTraceBufPutPacket. * * \param enable false for disable, true for enable */ void osiTraceSetOutputEnable(bool enable); /** * \brief whether trace output is enable * * \return false for disable, true for enable */ bool osiTraceIsOutputEnable(void); /** * \brief set trace push callback * * When there are new trace data, and there are no trace transfer in * progress, the push callback will be called. * * \param cb trace pusb callback, NULL for no callback * \param ctx trace push callback context */ void osiTraceSetPushCallback(osiTracePushCallback_t cb, void *ctx); /** * \brief set trace push enable/diable * * Typically, it is needed to disable trace push at sleep procedure. * Otherwise, trace itself will affect sleep procedure. * * \param enable true to enable trace push, false to disable trace push */ void osiTraceSetPushEnable(bool enable); /** * \brief get GSM frame number * * When GSM frame number is needed to be embedded into trace, this function * should be implemented outside trace module. * * \return GSM frame number */ uint32_t osiTraceGsmFrameNumber(void); /** * \brief get LTE frame number * * When LTE frame number is needed to be embedded into trace, this function * should be implemented outside trace module. * * \return GSM frame number */ uint32_t osiTraceLteFrameNumber(void); /** * \brief fill host packet header * * It is just a helper to fill host packet header. * * \param [in] header host packet header * \param [in] flowid host packet flowid * \param [in] frame_len host packet frame length */ static inline void osiFillHostHeader(osiHostPacketHeader_t *header, uint8_t flowid, uint16_t frame_len) { header->sync = 0xAD; header->frame_len_msb = frame_len >> 8; header->frame_len_lsb = frame_len & 0xff; header->flowid = flowid; } /** * \brief trace buffer initialization * * It should be called only once at system boot. When this is called, * it is possible that RTOS hasn't initialized. */ void osiTraceBufInit(void); /** * \brief put a trace packet into trace buffer * * Inside, packet data may be copied to global trace buffer or malloc-copy * to dynamic memory, depends on the packet size. After the call, \p data * won't be used any more. * * When diag trace is used, this is the real packet, rather than hdlc * encoded packet. Hdlc encoding will be performed inside. * * \param data packet data * \param size packet total size * \return * - true on success * - false on error, invalid paramters or trace buffer full */ bool osiTraceBufPut(const void *data, unsigned size); /** * \brief put a trace packet into trace buffer * * It is similar to \p osiTraceBufPut, just the packet is described by * multiple pieces of buffer. It can save time for caller to combine them. * * When \p size is -1, the total size will be calculated. Otherwise it will be * used as total size. Total size will only be used to check whether space is * enough, and caller should ensure \p size matches the total size. * * \param bufs buffers of packet data * \param count buffer count * \param size total size, -1 means callee should calculate total size * \return * - true on success * - false on error, invalid paramters or trace buffer full */ bool osiTraceBufPutMulti(const osiBuffer_t *bufs, unsigned count, int size); /** * \brief put an external trace packet into trace buffer * * Put a "reference" of packet to trace output. The data won't be copied, * so \p data will still be accessed after this returns. Only after * \p osiTraceBufPacketFinished returns true, the packet has been transfered, * and won't be accessed any more. * * For host packet, \p size should be 4 bytes aligned. * * For diag packet, it is hdlc encoded packet, with leading and trailing * sync byte. * * There is count limit of raw packets. When there are too many raw packets * are pending, it will return false. * * \param data raw packet data * \param size raw packet total size * \return * - true on success * - false on error, invalid paramters or too many raw packets */ bool osiTraceBufPutPacket(const void *data, unsigned size); /** * \brief put an diag packet into trace buffer * * Put a "reference" of packet to trace output. The data won't be copied, * so \p data will still be accessed after this returns. Only after * \p osiTraceBufPacketFinished returns true, the packet has been transfered, * and won't be accessed any more. * * * For diag packet, it is hdlc encoded packet, with leading and trailing * sync byte. * * There is count limit of raw packets. When there are too many raw packets * are pending, it will return false. * * \param data raw packet data * \param size raw packet total size * \return * - true on success * - false on error, invalid paramters or too many raw packets */ bool osiTraceBufPutDiagPacket(const void *data, unsigned size); /** * \brief whether the external trace packet is transfered * * \p data must be the pointer called by \p osiTraceBufPutPacket. * * \param data raw packet data * \return true if transfer done */ bool osiTraceBufPacketFinished(const void *data); /** * \brief fetch a piece of trace buffer * * When trace buffer is empty, the returned size will be 0. * * The returned buffer may contain one or more packets, and it won't * contain partial packet. * * After \p osiTraceBufFetch is called, it is needed to call * \p osiTraceBufHandled before next call. * * It should be called by trace output only. * * \return buffer with trace data */ osiBuffer_t osiTraceBufFetch(void); /** * \brief indicate trace buffer is handled * * It should be called by trace output only. */ void osiTraceBufHandled(void); /** * \brief get existed trace data size * * In most cases, this shouldn't be cared. One excception is in usb trace, * when the remaining trace data is smaller than the threshold, usb * transfer should wait a while. * * \return existed trace data size */ unsigned osiTraceDataSize(void); /** * \brief set trace debug port * * \p drvDebugPortSetTraceEnable will be called when the current enabled * state changed. * * \param port debug port for trace */ void osiTraceSetDebugPort(struct drvDebugPort *port); OSI_EXTERN_C_END #endif