mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 17:48:33 -04:00
Update trace recorder code.
Add TCP Echo server to the FreeR_Plus_TCP_Minimal_Window_Simulator project.
This commit is contained in:
parent
f7fc215247
commit
d525d5092d
35 changed files with 4431 additions and 2436 deletions
|
@ -0,0 +1,52 @@
|
|||
/************************************************************
|
||||
* Percepio Tracealyzer - ITM Trace Exporter for Keil uVision
|
||||
* Copyright (c) 2018, Percepio AB.
|
||||
* https://percepio.com
|
||||
************************************************************/
|
||||
|
||||
FUNC void tzSetEnable(int enable)
|
||||
{
|
||||
if (enable == 1)
|
||||
{
|
||||
printf("Starting Tracealyzer recorder\n");
|
||||
|
||||
// Forward the ITM data to file
|
||||
exec("ITMLOG 1 > .\\tracealyzer.psf");
|
||||
|
||||
// Send start command to Tracealyzer (not required if using vTraceEnable(TRC_START))
|
||||
exec("E CHAR tz_host_command_data = 1, 1, 0, 0, 0, 0, 0xFD, 0xFF");
|
||||
exec("tz_host_command_bytes_to_read = 8");
|
||||
}
|
||||
else if (enable == 0)
|
||||
{
|
||||
printf("Stopping Tracealyzer recorder...\n");
|
||||
|
||||
// Send stop command to Tracealyzer, to stop writing ITM data.
|
||||
exec("E CHAR tz_host_command_data = 1, 0, 0, 0, 0, 0, 0xFE, 0xFF");
|
||||
exec("tz_host_command_bytes_to_read = 8");
|
||||
|
||||
_sleep_(2000); // Wait a while to let all data be written the host file.
|
||||
|
||||
// Stop forwarding the ITM data to file and close the file.
|
||||
exec("ITMLOG 1 OFF");
|
||||
|
||||
printf("Tracealyzer recorder stopped.\n");
|
||||
|
||||
}
|
||||
else printf("Usage: tzSetEnable(0 or 1), where 0 is disable (stops recorder) and 1 enable (starts recording)");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// The Tracealyzer ITM stream port for Keil µVision can be used in two ways.
|
||||
//
|
||||
// 1. Start tracing directly from startup.
|
||||
// Make sure tzSetEnable(1) is called below and vTraceEnable(TRC_START) in your target startup.
|
||||
//
|
||||
// 2. Start the trace manually, using the "Start Recording" button in Keil µVision.
|
||||
// In this case, comment out the below call to tzSetEnable and make sure you call vTraceEnable(TRC_INIT) in your target startup (not TRC_START).
|
||||
|
||||
tzSetEnable(1);
|
||||
|
||||
DEFINE BUTTON "Start Recording", "tzSetEnable(1)";
|
||||
DEFINE BUTTON "Stop Recording", "tzSetEnable(0)";
|
|
@ -0,0 +1,28 @@
|
|||
Tracealyzer Stream Port for ARM Cortex-M ITM
|
||||
--------------------------------------------
|
||||
2018-05-04
|
||||
|
||||
This directory contains a "stream port" for the Tracealyzer recorder library,
|
||||
i.e., the specific code needed to use a particular interface for streaming a
|
||||
Tracealyzer RTOS trace. The stream port is defined by a set of macros in
|
||||
trcStreamingPort.h, found in the "include" directory.
|
||||
|
||||
This particular stream port targets ARM's ITM interface, which together with
|
||||
a fast debug probe such as a Keil ULINKpro or ULINKplus provides excellent
|
||||
performance. This stream port does not use any RAM buffer for the trace, but
|
||||
writes the data directly to the ITM registers. This is very fast.
|
||||
|
||||
To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus),
|
||||
see Percepio Application Note PA-021 https://percepio.com/2018/05/04/keil-itm-support/
|
||||
|
||||
Learning more:
|
||||
- Tracealyzer User Manual (Help -> User Manual)
|
||||
- https://percepio.com/gettingstarted
|
||||
- Percepio Application Note PA-021 https://percepio.com/2018/05/04/keil-itm-support/
|
||||
- About ITM trace, https://percepio.com/2016/06/09/arm-itm/
|
||||
- About the recorder and custom streaming, http://percepio.com/2016/10/05/rtos-tracing
|
||||
|
||||
For questions, please contact support@percepio.com
|
||||
|
||||
Percepio AB
|
||||
www.percepio.com
|
|
@ -0,0 +1,91 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.h
|
||||
*
|
||||
* The interface definitions for trace streaming ("stream ports").
|
||||
* This "stream port" sets up the recorder to use ARM ITM as streaming channel.
|
||||
*
|
||||
* Terms of Use
|
||||
* This file is part of the trace recorder library (RECORDER), which is the
|
||||
* intellectual property of Percepio AB (PERCEPIO) and provided under a
|
||||
* license as follows.
|
||||
* The RECORDER may be used free of charge for the purpose of recording data
|
||||
* intended for analysis in PERCEPIO products. It may not be used or modified
|
||||
* for other purposes without explicit permission from PERCEPIO.
|
||||
* You may distribute the RECORDER in its original source code form, assuming
|
||||
* this text (terms of use, disclaimer, copyright notice) is unchanged. You are
|
||||
* allowed to distribute the RECORDER with minor modifications intended for
|
||||
* configuration or porting of the RECORDER, e.g., to allow using it on a
|
||||
* specific processor, processor family or with a specific communication
|
||||
* interface. Any such modifications should be documented directly below
|
||||
* this comment block.
|
||||
*
|
||||
* Disclaimer
|
||||
* The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
|
||||
* as to its use or performance. PERCEPIO does not and cannot warrant the
|
||||
* performance or results you may obtain by using the RECORDER or documentation.
|
||||
* PERCEPIO make no warranties, express or implied, as to noninfringement of
|
||||
* third party rights, merchantability, or fitness for any particular purpose.
|
||||
* In no event will PERCEPIO, its technology partners, or distributors be liable
|
||||
* to you for any consequential, incidental or special damages, including any
|
||||
* lost profits or lost savings, even if a representative of PERCEPIO has been
|
||||
* advised of the possibility of such damages, or for any claim by any third
|
||||
* party. Some jurisdictions do not allow the exclusion or limitation of
|
||||
* incidental, consequential or special damages, or the exclusion of implied
|
||||
* warranties or limitations on how long an implied warranty may last, so the
|
||||
* above limitations may not apply to you.
|
||||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef TRC_STREAMING_PORT_H
|
||||
#define TRC_STREAMING_PORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
|
||||
int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
|
||||
|
||||
/*******************************************************************************
|
||||
* TRC_CFG_ITM_PORT
|
||||
*
|
||||
* Possible values: 0 - 31
|
||||
*
|
||||
* What ITM port to use for the ITM software events. Make sure the IDE is
|
||||
* configured for the same channel.
|
||||
*
|
||||
* Default: 1 (0 is typically terminal output and 31 is used by Keil)
|
||||
*
|
||||
******************************************************************************/
|
||||
#define TRC_CFG_ITM_PORT 1
|
||||
|
||||
#if (TRC_CFG_ITM_PORT < 0) || (TRC_CFG_ITM_PORT > 31)
|
||||
#error "Bad ITM port selected."
|
||||
#endif
|
||||
|
||||
// Not used for ITM - no RAM buffer...
|
||||
#define TRC_STREAM_PORT_ALLOCATE_FIELDS()
|
||||
|
||||
// Not used for ITM - assume the IDE configures the ITM setup
|
||||
#define TRC_STREAM_PORT_INIT()
|
||||
|
||||
/* Important for the ITM port - no RAM buffer, direct writes. In most other ports this can be skipped (default is 1) */
|
||||
#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0
|
||||
|
||||
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) itm_write(_ptrData, _size, _ptrBytesWritten)
|
||||
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) read_from_host(_ptrData, _size, _ptrBytesRead)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TRC_STREAMING_PORT_H */
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
#include "trcRecorder.h"
|
||||
|
||||
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
||||
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
|
||||
static void itm_write_32(uint32_t data);
|
||||
|
||||
volatile int32_t tz_host_command_bytes_to_read = 0; // This is set by the Tracealyzer host application (to the number of bytes written), after having written to tz_host_commands. Set to zero by the read function after the message in tz_host_commands has been read.
|
||||
volatile char tz_host_command_data[32];
|
||||
|
||||
/* This reads "command" data from a RAM buffer, written by a host macro in the debugger */
|
||||
int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead)
|
||||
{
|
||||
if ( tz_host_command_bytes_to_read > 0)
|
||||
{
|
||||
int i;
|
||||
uint8_t * bytesBuffer = (uint8_t*) ptrData;
|
||||
|
||||
if (ptrBytesRead != NULL)
|
||||
*ptrBytesRead = (int32_t)tz_host_command_bytes_to_read;
|
||||
|
||||
if (tz_host_command_bytes_to_read != size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i < tz_host_command_bytes_to_read; i++)
|
||||
{
|
||||
bytesBuffer[i] = tz_host_command_data[i];
|
||||
}
|
||||
|
||||
tz_host_command_bytes_to_read = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void itm_write_32(uint32_t data)
|
||||
{
|
||||
if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && // Trace enabled
|
||||
(ITM->TCR & ITM_TCR_ITMENA_Msk) && // ITM enabled
|
||||
(ITM->TER & (1UL << 0))) // ITM Port #0 enabled
|
||||
{
|
||||
while (ITM->PORT[TRC_CFG_ITM_PORT].u32 == 0); // Block until room in ITM FIFO - This stream port is always in "blocking mode", since intended for high-speed ITM!
|
||||
ITM->PORT[TRC_CFG_ITM_PORT].u32 = data; // Write the data
|
||||
}
|
||||
}
|
||||
|
||||
/* This is assumed to execute from within the recorder, with interrupts disabled */
|
||||
int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten)
|
||||
{
|
||||
uint32_t bytesWritten = 0;
|
||||
uint32_t* ptr32 = (uint32_t*)ptrData;
|
||||
|
||||
if (size % 4 != 0) return -2;
|
||||
|
||||
while(bytesWritten < size)
|
||||
{
|
||||
itm_write_32(*ptr32);
|
||||
ptr32++;
|
||||
bytesWritten += 4;
|
||||
}
|
||||
|
||||
*ptrBytesWritten = bytesWritten;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
Tracealyzer Stream Port for Files
|
||||
-------------------------------------------------
|
||||
|
||||
This directory contains a "stream port" for the Tracealyzer recorder library,
|
||||
i.e., the specific code needed to use a particular interface for streaming a
|
||||
Tracealyzer RTOS trace. The stream port is defined by a set of macros in
|
||||
trcStreamingPort.h, found in the "include" directory.
|
||||
|
||||
This particular stream port is for streaming to a file via stdio.h (fwrite).
|
||||
|
||||
To use this stream port, make sure that include/trcStreamingPort.h is found
|
||||
by the compiler (i.e., add this folder to your project's include paths) and
|
||||
add all included source files to your build. Make sure no other versions of
|
||||
trcStreamingPort.h are included by mistake!
|
||||
|
||||
See also http://percepio.com/2016/10/05/rtos-tracing.
|
||||
|
||||
Percepio AB
|
||||
www.percepio.com
|
|
@ -0,0 +1,87 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.h
|
||||
*
|
||||
* The interface definitions for trace streaming ("stream ports").
|
||||
* This "stream port" sets up the recorder to stream the trace to file.
|
||||
*
|
||||
* Terms of Use
|
||||
* This file is part of the trace recorder library (RECORDER), which is the
|
||||
* intellectual property of Percepio AB (PERCEPIO) and provided under a
|
||||
* license as follows.
|
||||
* The RECORDER may be used free of charge for the purpose of recording data
|
||||
* intended for analysis in PERCEPIO products. It may not be used or modified
|
||||
* for other purposes without explicit permission from PERCEPIO.
|
||||
* You may distribute the RECORDER in its original source code form, assuming
|
||||
* this text (terms of use, disclaimer, copyright notice) is unchanged. You are
|
||||
* allowed to distribute the RECORDER with minor modifications intended for
|
||||
* configuration or porting of the RECORDER, e.g., to allow using it on a
|
||||
* specific processor, processor family or with a specific communication
|
||||
* interface. Any such modifications should be documented directly below
|
||||
* this comment block.
|
||||
*
|
||||
* Disclaimer
|
||||
* The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
|
||||
* as to its use or performance. PERCEPIO does not and cannot warrant the
|
||||
* performance or results you may obtain by using the RECORDER or documentation.
|
||||
* PERCEPIO make no warranties, express or implied, as to noninfringement of
|
||||
* third party rights, merchantability, or fitness for any particular purpose.
|
||||
* In no event will PERCEPIO, its technology partners, or distributors be liable
|
||||
* to you for any consequential, incidental or special damages, including any
|
||||
* lost profits or lost savings, even if a representative of PERCEPIO has been
|
||||
* advised of the possibility of such damages, or for any claim by any third
|
||||
* party. Some jurisdictions do not allow the exclusion or limitation of
|
||||
* incidental, consequential or special damages, or the exclusion of implied
|
||||
* warranties or limitations on how long an implied warranty may last, so the
|
||||
* above limitations may not apply to you.
|
||||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef TRC_STREAMING_PORT_H
|
||||
#define TRC_STREAMING_PORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten);
|
||||
|
||||
void closeFile(void);
|
||||
|
||||
void openFile(char* fileName);
|
||||
|
||||
/* This define will determine whether to use the internal PagedEventBuffer or not.
|
||||
If file writing creates additional trace events (i.e. it uses semaphores or mutexes),
|
||||
then the paged event buffer must be enabled to avoid infinite recursion. */
|
||||
#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1
|
||||
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) 0 /* Does not read commands from Tz (yet) */
|
||||
|
||||
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) writeToFile(_ptrData, _size, _ptrBytesSent)
|
||||
|
||||
#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC)
|
||||
#define TRC_STREAM_PORT_MALLOC() \
|
||||
_TzTraceData = TRC_PORT_MALLOC((TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE));
|
||||
extern char* _TzTraceData;
|
||||
#else
|
||||
#define TRC_STREAM_PORT_MALLOC() /* Custom or static allocation. Not used. */
|
||||
#endif
|
||||
#define TRC_STREAM_PORT_INIT() \
|
||||
TRC_STREAM_PORT_MALLOC(); \
|
||||
openFile("trace.psf")
|
||||
|
||||
#define TRC_STREAM_PORT_ON_TRACE_END() closeFile()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TRC_STREAMING_PORT_H */
|
|
@ -0,0 +1,103 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.c
|
||||
*
|
||||
* Supporting functions for trace streaming, used by the "stream ports"
|
||||
* for reading and writing data to the interface.
|
||||
* Existing ports can easily be modified to fit another setup, e.g., a
|
||||
* different TCP/IP stack, or to define your own stream port.
|
||||
*
|
||||
* Terms of Use
|
||||
* This file is part of the trace recorder library (RECORDER), which is the
|
||||
* intellectual property of Percepio AB (PERCEPIO) and provided under a
|
||||
* license as follows.
|
||||
* The RECORDER may be used free of charge for the purpose of recording data
|
||||
* intended for analysis in PERCEPIO products. It may not be used or modified
|
||||
* for other purposes without explicit permission from PERCEPIO.
|
||||
* You may distribute the RECORDER in its original source code form, assuming
|
||||
* this text (terms of use, disclaimer, copyright notice) is unchanged. You are
|
||||
* allowed to distribute the RECORDER with minor modifications intended for
|
||||
* configuration or porting of the RECORDER, e.g., to allow using it on a
|
||||
* specific processor, processor family or with a specific communication
|
||||
* interface. Any such modifications should be documented directly below
|
||||
* this comment block.
|
||||
*
|
||||
* Disclaimer
|
||||
* The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
|
||||
* as to its use or performance. PERCEPIO does not and cannot warrant the
|
||||
* performance or results you may obtain by using the RECORDER or documentation.
|
||||
* PERCEPIO make no warranties, express or implied, as to noninfringement of
|
||||
* third party rights, merchantability, or fitness for any particular purpose.
|
||||
* In no event will PERCEPIO, its technology partners, or distributors be liable
|
||||
* to you for any consequential, incidental or special damages, including any
|
||||
* lost profits or lost savings, even if a representative of PERCEPIO has been
|
||||
* advised of the possibility of such damages, or for any claim by any third
|
||||
* party. Some jurisdictions do not allow the exclusion or limitation of
|
||||
* incidental, consequential or special damages, or the exclusion of implied
|
||||
* warranties or limitations on how long an implied warranty may last, so the
|
||||
* above limitations may not apply to you.
|
||||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
#include "trcRecorder.h"
|
||||
|
||||
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
||||
|
||||
FILE* traceFile = NULL;
|
||||
|
||||
void openFile(char* fileName)
|
||||
{
|
||||
if (traceFile == NULL)
|
||||
{
|
||||
errno_t err = fopen_s(&traceFile, fileName, "wb");
|
||||
if (err != 0)
|
||||
{
|
||||
printf("Could not open trace file, error code %d.\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
else {
|
||||
printf("Trace file created.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten)
|
||||
{
|
||||
int32_t written = 0;
|
||||
if (traceFile != NULL)
|
||||
{
|
||||
written = fwrite(data, 1, size, traceFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
written = 0;
|
||||
}
|
||||
|
||||
if (ptrBytesWritten != 0)
|
||||
*ptrBytesWritten = written;
|
||||
|
||||
if ((int32_t)size == written)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void closeFile(void)
|
||||
{
|
||||
if (traceFile != NULL)
|
||||
{
|
||||
fclose(traceFile);
|
||||
traceFile = NULL;
|
||||
printf("Trace file closed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
|
||||
#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
|
|
@ -1,505 +0,0 @@
|
|||
/*********************************************************************
|
||||
* SEGGER MICROCONTROLLER GmbH & Co. KG *
|
||||
* Solutions for real time microcontroller applications *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* * This software may in its unmodified form be freely redistributed *
|
||||
* in source, linkable, or executable form. *
|
||||
* * The source code may be modified, provided the source code *
|
||||
* retains the above copyright notice, this list of conditions and *
|
||||
* the following disclaimer. *
|
||||
* * Modified versions of this software in source, executable, or *
|
||||
* linkable form may not be distributed without prior consent of *
|
||||
* SEGGER. *
|
||||
* * This software may only be used for communication with SEGGER *
|
||||
* J-Link debug probes. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 6.00e *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_printf.c
|
||||
Purpose : Replacement for printf to write formatted data via RTT
|
||||
Revision: $Rev: 3667 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
|
||||
#define FORMAT_FLAG_PAD_ZERO (1u << 1)
|
||||
#define FORMAT_FLAG_PRINT_SIGN (1u << 2)
|
||||
#define FORMAT_FLAG_ALTERNATE (1u << 3)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char* pBuffer;
|
||||
unsigned BufferSize;
|
||||
unsigned Cnt;
|
||||
|
||||
int ReturnValue;
|
||||
|
||||
unsigned RTTBufferIndex;
|
||||
} SEGGER_RTT_PRINTF_DESC;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Static code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* _StoreChar
|
||||
*/
|
||||
static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
|
||||
unsigned Cnt;
|
||||
|
||||
Cnt = p->Cnt;
|
||||
if ((Cnt + 1u) <= p->BufferSize) {
|
||||
*(p->pBuffer + Cnt) = c;
|
||||
p->Cnt = Cnt + 1u;
|
||||
p->ReturnValue++;
|
||||
}
|
||||
//
|
||||
// Write part of string, when the buffer is full
|
||||
//
|
||||
if (p->Cnt == p->BufferSize) {
|
||||
if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
|
||||
p->ReturnValue = -1;
|
||||
} else {
|
||||
p->Cnt = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _PrintUnsigned
|
||||
*/
|
||||
static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||
static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
unsigned Div;
|
||||
unsigned Digit;
|
||||
unsigned Number;
|
||||
unsigned Width;
|
||||
char c;
|
||||
|
||||
Number = v;
|
||||
Digit = 1u;
|
||||
//
|
||||
// Get actual field width
|
||||
//
|
||||
Width = 1u;
|
||||
while (Number >= Base) {
|
||||
Number = (Number / Base);
|
||||
Width++;
|
||||
}
|
||||
if (NumDigits > Width) {
|
||||
Width = NumDigits;
|
||||
}
|
||||
//
|
||||
// Print leading chars if necessary
|
||||
//
|
||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
|
||||
if (FieldWidth != 0u) {
|
||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, c);
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Compute Digit.
|
||||
// Loop until Digit has the value of the highest digit required.
|
||||
// Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
|
||||
//
|
||||
while (1) {
|
||||
if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
|
||||
NumDigits--;
|
||||
} else {
|
||||
Div = v / Digit;
|
||||
if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
|
||||
break;
|
||||
}
|
||||
}
|
||||
Digit *= Base;
|
||||
}
|
||||
//
|
||||
// Output digits
|
||||
//
|
||||
do {
|
||||
Div = v / Digit;
|
||||
v -= Div * Digit;
|
||||
_StoreChar(pBufferDesc, _aV2C[Div]);
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
Digit /= Base;
|
||||
} while (Digit);
|
||||
//
|
||||
// Print trailing spaces if necessary
|
||||
//
|
||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, ' ');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _PrintInt
|
||||
*/
|
||||
static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||
unsigned Width;
|
||||
int Number;
|
||||
|
||||
Number = (v < 0) ? -v : v;
|
||||
|
||||
//
|
||||
// Get actual field width
|
||||
//
|
||||
Width = 1u;
|
||||
while (Number >= (int)Base) {
|
||||
Number = (Number / (int)Base);
|
||||
Width++;
|
||||
}
|
||||
if (NumDigits > Width) {
|
||||
Width = NumDigits;
|
||||
}
|
||||
if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
|
||||
FieldWidth--;
|
||||
}
|
||||
|
||||
//
|
||||
// Print leading spaces if necessary
|
||||
//
|
||||
if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, ' ');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Print sign if necessary
|
||||
//
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
if (v < 0) {
|
||||
v = -v;
|
||||
_StoreChar(pBufferDesc, '-');
|
||||
} else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
|
||||
_StoreChar(pBufferDesc, '+');
|
||||
} else {
|
||||
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Print leading zeros if necessary
|
||||
//
|
||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, '0');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Print number without sign
|
||||
//
|
||||
_PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_vprintf
|
||||
*
|
||||
* Function description
|
||||
* Stores a formatted string in SEGGER RTT control block.
|
||||
* This data is read by the host.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||
* sFormat Pointer to format string
|
||||
* pParamList Pointer to the list of arguments for the format string
|
||||
*
|
||||
* Return values
|
||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||
* < 0: Error
|
||||
*/
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
|
||||
char c;
|
||||
SEGGER_RTT_PRINTF_DESC BufferDesc;
|
||||
int v;
|
||||
unsigned NumDigits;
|
||||
unsigned FormatFlags;
|
||||
unsigned FieldWidth;
|
||||
char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
|
||||
|
||||
BufferDesc.pBuffer = acBuffer;
|
||||
BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE;
|
||||
BufferDesc.Cnt = 0u;
|
||||
BufferDesc.RTTBufferIndex = BufferIndex;
|
||||
BufferDesc.ReturnValue = 0;
|
||||
|
||||
do {
|
||||
c = *sFormat;
|
||||
sFormat++;
|
||||
if (c == 0u) {
|
||||
break;
|
||||
}
|
||||
if (c == '%') {
|
||||
//
|
||||
// Filter out flags
|
||||
//
|
||||
FormatFlags = 0u;
|
||||
v = 1;
|
||||
do {
|
||||
c = *sFormat;
|
||||
switch (c) {
|
||||
case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
|
||||
case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
|
||||
case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
|
||||
case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
|
||||
default: v = 0; break;
|
||||
}
|
||||
} while (v);
|
||||
//
|
||||
// filter out field with
|
||||
//
|
||||
FieldWidth = 0u;
|
||||
do {
|
||||
c = *sFormat;
|
||||
if ((c < '0') || (c > '9')) {
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
|
||||
} while (1);
|
||||
|
||||
//
|
||||
// Filter out precision (number of digits to display)
|
||||
//
|
||||
NumDigits = 0u;
|
||||
c = *sFormat;
|
||||
if (c == '.') {
|
||||
sFormat++;
|
||||
do {
|
||||
c = *sFormat;
|
||||
if ((c < '0') || (c > '9')) {
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
NumDigits = NumDigits * 10u + ((unsigned)c - '0');
|
||||
} while (1);
|
||||
}
|
||||
//
|
||||
// Filter out length modifier
|
||||
//
|
||||
c = *sFormat;
|
||||
do {
|
||||
if ((c == 'l') || (c == 'h')) {
|
||||
sFormat++;
|
||||
c = *sFormat;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
//
|
||||
// Handle specifiers
|
||||
//
|
||||
switch (c) {
|
||||
case 'c': {
|
||||
char c0;
|
||||
v = va_arg(*pParamList, int);
|
||||
c0 = (char)v;
|
||||
_StoreChar(&BufferDesc, c0);
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'u':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
const char * s = va_arg(*pParamList, const char *);
|
||||
do {
|
||||
c = *s;
|
||||
s++;
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
_StoreChar(&BufferDesc, c);
|
||||
} while (BufferDesc.ReturnValue >= 0);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
|
||||
break;
|
||||
case '%':
|
||||
_StoreChar(&BufferDesc, '%');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
} else {
|
||||
_StoreChar(&BufferDesc, c);
|
||||
}
|
||||
} while (BufferDesc.ReturnValue >= 0);
|
||||
|
||||
if (BufferDesc.ReturnValue > 0) {
|
||||
//
|
||||
// Write remaining data, if any
|
||||
//
|
||||
if (BufferDesc.Cnt != 0u) {
|
||||
SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
|
||||
}
|
||||
BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
|
||||
}
|
||||
return BufferDesc.ReturnValue;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_printf
|
||||
*
|
||||
* Function description
|
||||
* Stores a formatted string in SEGGER RTT control block.
|
||||
* This data is read by the host.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||
* sFormat Pointer to format string, followed by the arguments for conversion
|
||||
*
|
||||
* Return values
|
||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||
* < 0: Error
|
||||
*
|
||||
* Notes
|
||||
* (1) Conversion specifications have following syntax:
|
||||
* %[flags][FieldWidth][.Precision]ConversionSpecifier
|
||||
* (2) Supported flags:
|
||||
* -: Left justify within the field width
|
||||
* +: Always print sign extension for signed conversions
|
||||
* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
|
||||
* Supported conversion specifiers:
|
||||
* c: Print the argument as one char
|
||||
* d: Print the argument as a signed integer
|
||||
* u: Print the argument as an unsigned integer
|
||||
* x: Print the argument as an hexadecimal integer
|
||||
* s: Print the string pointed to by the argument
|
||||
* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
|
||||
*/
|
||||
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
|
||||
int r;
|
||||
va_list ParamList;
|
||||
|
||||
va_start(ParamList, sFormat);
|
||||
r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
|
||||
va_end(ParamList);
|
||||
return r;
|
||||
}
|
||||
/*************************** End of file ****************************/
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v3.1.2
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.h
|
||||
|
@ -7,6 +7,11 @@
|
|||
* The interface definitions for trace streaming ("stream ports").
|
||||
* This "stream port" sets up the recorder to use SEGGER RTT as streaming channel.
|
||||
*
|
||||
* Note that this stream port is more complex than the typical case, since
|
||||
* the J-Link interface uses a separate RAM buffer in SEGGER_RTT.c, instead
|
||||
* of the default buffer included in the recorder core. The other stream ports
|
||||
* offer more typical examples of how to define a custom streaming interface.
|
||||
*
|
||||
* Terms of Use
|
||||
* This file is part of the trace recorder library (RECORDER), which is the
|
||||
* intellectual property of Percepio AB (PERCEPIO) and provided under a
|
||||
|
@ -39,7 +44,7 @@
|
|||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2017.
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -113,17 +118,18 @@ extern "C" {
|
|||
* internal RAM buffer read by the J-Link probes during execution.
|
||||
*
|
||||
* Possible values:
|
||||
* - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (default)
|
||||
* - SEGGER_RTT_MODE_NO_BLOCK_SKIP
|
||||
* - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
|
||||
* - SEGGER_RTT_MODE_NO_BLOCK_SKIP (default)
|
||||
*
|
||||
* We recommend using SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL, to ensure you get a
|
||||
* Using SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL ensure that you get a
|
||||
* complete and valid trace. This may however cause blocking if your streaming
|
||||
* interface isn't fast enough, which may disturb the real-time behavior.
|
||||
* We therefore recommend to try SEGGER_RTT_MODE_NO_BLOCK_SKIP as well.
|
||||
* In this mode, Tracealyzer will report lost events if the transfer is not
|
||||
*
|
||||
* We therefore recommend SEGGER_RTT_MODE_NO_BLOCK_SKIP. In this mode,
|
||||
* Tracealyzer will report lost events if the transfer is not
|
||||
* fast enough. In that case, try increasing the size of the "up buffer".
|
||||
******************************************************************************/
|
||||
#define TRC_CFG_RTT_MODE SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
|
||||
#define TRC_CFG_RTT_MODE SEGGER_RTT_MODE_NO_BLOCK_SKIP
|
||||
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
#include "SEGGER_RTT.h"
|
||||
|
@ -140,22 +146,18 @@ extern "C" {
|
|||
#if TRC_CFG_RTT_UP_BUFFER_INDEX == 0
|
||||
#define TRC_RTT_ALLOC_UP() static char* _TzTraceData = NULL; /* Not actually used. Ignore allocation method. */
|
||||
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
|
||||
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) /* Only for custom allocation */
|
||||
#else
|
||||
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
|
||||
#define TRC_RTT_ALLOC_UP() char _TzTraceData[TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Static allocation */
|
||||
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
|
||||
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) /* Only for custom allocation */
|
||||
#endif
|
||||
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC
|
||||
#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Dynamic allocation */
|
||||
#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_CFG_RTT_BUFFER_SIZE_UP);
|
||||
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) /* Only for custom allocation */
|
||||
#endif
|
||||
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM
|
||||
#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Custom allocation, user needs to call vTraceSetRecorderDataBuffer before vTraceEnable, to assign this */
|
||||
#define TRC_STREAM_PORT_MALLOC() /* Not used in custom mode */
|
||||
#define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Not static in this case, since declared in user code */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -170,20 +172,22 @@ extern "C" {
|
|||
TRC_RTT_ALLOC_UP() /* Macro that will result in proper UP buffer allocation */ \
|
||||
TRC_RTT_ALLOC_DOWN() /* Macro that will result in proper DOWN buffer allocation */
|
||||
|
||||
int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
|
||||
|
||||
int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
|
||||
|
||||
|
||||
#define TRC_STREAM_PORT_INIT() \
|
||||
TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */ \
|
||||
SEGGER_RTT_ConfigUpBuffer(TRC_CFG_RTT_UP_BUFFER_INDEX, "TzData", _TzTraceData, TRC_CFG_RTT_BUFFER_SIZE_UP, TRC_CFG_RTT_MODE ); \
|
||||
SEGGER_RTT_ConfigDownBuffer(TRC_CFG_RTT_DOWN_BUFFER_INDEX, "TzCtrl", _TzCtrlData, TRC_CFG_RTT_BUFFER_SIZE_DOWN, TRC_CFG_RTT_MODE);
|
||||
|
||||
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type _tmpArray[_size / sizeof(_type)]; _type* _ptrData = _tmpArray;
|
||||
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) _type _tmpArray[sizeof(largestEventType) / sizeof(_type)]; _type* _ptrData = _tmpArray;
|
||||
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) SEGGER_RTT_Write(TRC_CFG_RTT_UP_BUFFER_INDEX, (const char*)_ptrData, _size);
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) if (SEGGER_RTT_HASDATA(TRC_CFG_RTT_DOWN_BUFFER_INDEX)) *_ptrBytesRead = (int)SEGGER_RTT_Read(TRC_CFG_RTT_DOWN_BUFFER_INDEX, (char*)_ptrData, _size);
|
||||
#define TRC_STREAM_PORT_PERIODIC_SEND_DATA(_ptrBytesSent)
|
||||
/* Important for the J-Link port, in most other ports this can be skipped (default is 1) */
|
||||
#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0
|
||||
|
||||
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) writeToRTT(_ptrData, _size, _ptrBytesWritten)
|
||||
|
||||
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() /* Do nothing */
|
||||
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
|
||||
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) readFromRTT(_ptrData, _size, _ptrBytesRead)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
#include "trcRecorder.h"
|
||||
|
||||
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
||||
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
|
||||
int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead)
|
||||
{
|
||||
uint32_t bytesRead = 0;
|
||||
|
||||
if (SEGGER_RTT_HASDATA(TRC_CFG_RTT_DOWN_BUFFER_INDEX))
|
||||
{
|
||||
bytesRead = SEGGER_RTT_Read((TRC_CFG_RTT_DOWN_BUFFER_INDEX), (char*)ptrData, size);
|
||||
|
||||
if (ptrBytesRead != NULL)
|
||||
*ptrBytesRead = (int32_t)bytesRead;
|
||||
|
||||
if (bytesRead != size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten)
|
||||
{
|
||||
uint32_t bytesWritten = SEGGER_RTT_Write((TRC_CFG_RTT_UP_BUFFER_INDEX), (const char*)ptrData, size);
|
||||
|
||||
if (ptrBytesWritten != NULL)
|
||||
*ptrBytesWritten = (int32_t)bytesWritten;
|
||||
|
||||
if (bytesWritten != size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v3.1.2
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.h
|
||||
|
@ -40,7 +40,7 @@
|
|||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2017.
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -51,37 +51,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* TRC_RECORDER_TRANSFER_METHOD_TCPIP
|
||||
*
|
||||
* This stream port for TCP/IP uses a temporary buffer consisting of multiple
|
||||
* pages, that are transmitted periodically by the TzCtrl task. You can modify
|
||||
* the supporting functions to match your system. See trcStreamingPort.c
|
||||
******************************************************************************/
|
||||
|
||||
int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten);
|
||||
int32_t trcTcpRead(void* data, uint32_t size, int32_t *ptrBytesRead);
|
||||
|
||||
#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
|
||||
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char _TzTraceData[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE]; /* Static allocation. */
|
||||
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
|
||||
#else
|
||||
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char* _TzTraceData = NULL; /* Dynamic allocation. */
|
||||
#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
|
||||
#endif
|
||||
int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten);
|
||||
|
||||
#define TRC_STREAM_PORT_INIT() \
|
||||
TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */ \
|
||||
prvPagedEventBufferInit(_TzTraceData);
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcTcpRead(_ptrData, _size, _ptrBytesRead)
|
||||
|
||||
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type* _ptrData; _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size);
|
||||
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */
|
||||
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not needed since we write immediately into the buffer received above by TRC_STREAM_PORT_ALLOCATE_EVENT, and the TRC_STREAM_PORT_PERIODIC_SEND_DATA defined below will take care of the actual trace transfer. */
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcTcpRead(_ptrData, _size, _ptrBytesRead);
|
||||
#define TRC_STREAM_PORT_PERIODIC_SEND_DATA(_ptrBytesSent) prvPagedEventBufferTransfer(trcTcpWrite, _ptrBytesSent);
|
||||
|
||||
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() prvPagedEventBufferInit(_TzTraceData);
|
||||
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
|
||||
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcTcpWrite(_ptrData, _size, _ptrBytesSent)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v3.1.2
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.c
|
||||
|
@ -41,7 +41,7 @@
|
|||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2017.
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
|||
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
||||
|
||||
/* TCP/IP includes */
|
||||
/* TCP/IP includes - for lwIP in this case */
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
|
@ -68,11 +68,14 @@ int32_t trcSocketSend( void* data, int32_t size, int32_t* bytesWritten )
|
|||
if (new_sd < 0)
|
||||
return -1;
|
||||
|
||||
if (bytesWritten == NULL)
|
||||
return -1;
|
||||
|
||||
*bytesWritten = send( new_sd, data, size, 0 );
|
||||
if (*bytesWritten < 0)
|
||||
{
|
||||
/* EWOULDBLOCK may be expected when buffers are full */
|
||||
if (errno != EWOULDBLOCK)
|
||||
if (errno != 0 && errno != EWOULDBLOCK)
|
||||
{
|
||||
closesocket(new_sd);
|
||||
new_sd = -1;
|
||||
|
@ -94,7 +97,7 @@ int32_t trcSocketReceive( void* data, int32_t size, int32_t* bytesRead )
|
|||
if ( *bytesRead < 0 )
|
||||
{
|
||||
/* EWOULDBLOCK may be expected when there is no data to receive */
|
||||
if (errno != EWOULDBLOCK)
|
||||
if (errno != 0 && errno != EWOULDBLOCK)
|
||||
{
|
||||
closesocket(new_sd);
|
||||
new_sd = -1;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v3.1.2
|
||||
* Trace Recorder Library for Tracealyzer v4.1.1
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.h
|
||||
|
@ -40,7 +40,7 @@
|
|||
*
|
||||
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
||||
*
|
||||
* Copyright Percepio AB, 2017.
|
||||
* Copyright Percepio AB, 2018.
|
||||
* www.percepio.com
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -51,16 +51,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Implement the below macros to define your own stream port. If your transfer
|
||||
* method uses RTOS functions, you should not send the data directly but use
|
||||
* the recorder's internal buffer to store the trace data, for later transfer by
|
||||
* the TzCtrl task. Check the predefined stream ports for examples on how to use
|
||||
* the internal buffer (e.g., TCP/IP, UART or USB CDC).
|
||||
*
|
||||
* Read more at http://percepio.com/2016/10/05/rtos-tracing/
|
||||
******************************************************************************/
|
||||
|
||||
/* Include files as needed, in this case it is files from STM32Cube FW_F7 V1.4.1 */
|
||||
#include "usb_device.h"
|
||||
#include "usbd_cdc.h"
|
||||
|
@ -70,32 +60,21 @@ extern "C" {
|
|||
/* Tested on STM32 devices using Keil/CMSIS USB stack */
|
||||
|
||||
extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;
|
||||
|
||||
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
|
||||
|
||||
int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes);
|
||||
int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent );
|
||||
|
||||
#if TRC_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
|
||||
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char _TzTraceData[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE]; /* Static allocation. */
|
||||
#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
|
||||
#else
|
||||
#define TRC_STREAM_PORT_ALLOCATE_FIELDS() static char* _TzTraceData = NULL; /* Dynamic allocation. */
|
||||
#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_PAGED_EVENT_BUFFER_PAGE_SIZE);
|
||||
#endif
|
||||
int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent );
|
||||
|
||||
#define TRC_STREAM_PORT_INIT() \
|
||||
MX_USB_DEVICE_Init(); \
|
||||
TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */
|
||||
|
||||
#define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type* _ptrData; _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size);
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcCDCReceive(_ptrData, _size, _ptrBytesRead)
|
||||
|
||||
#define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */
|
||||
#define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not needed since we write immediately into the buffer received above by TRC_STREAM_PORT_ALLOCATE_EVENT, and the TRC_STREAM_PORT_PERIODIC_SEND_DATA defined below will take care of the actual trace transfer. */
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcCDCReceive(_ptrData, _size, _ptrBytesRead);
|
||||
#define TRC_STREAM_PORT_PERIODIC_SEND_DATA(_ptrBytesSent) prvPagedEventBufferTransfer(trcCDCTransmit, _ptrBytesSent);
|
||||
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcCDCTransmit(_ptrData, _size, _ptrBytesSent)
|
||||
|
||||
#define TRC_STREAM_PORT_ON_TRACE_BEGIN() { prvPagedEventBufferInit(_TzTraceData); }
|
||||
#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
|
||||
#include "trcRecorder.h"
|
||||
|
||||
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
||||
#if(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
@ -29,8 +30,8 @@ uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
|
|||
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
|
||||
|
||||
extern USBD_HandleTypeDef hUsbDeviceFS;
|
||||
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
|
||||
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
|
||||
recBuf commandBuffer;
|
||||
|
||||
|
@ -186,6 +187,7 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* The READ function, used in trcStreamingPort.h */
|
||||
int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes)
|
||||
{
|
||||
uint32_t i,diff;
|
||||
|
@ -217,13 +219,18 @@ int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* The WRITE function, used in trcStreamingPort.h */
|
||||
int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent )
|
||||
{
|
||||
int32_t result;
|
||||
result=CDC_Transmit_FS(data,size);
|
||||
*noOfBytesSent=size;
|
||||
|
||||
return result;
|
||||
result=CDC_Transmit_FS(data, size);
|
||||
*noOfBytesSent = size;
|
||||
|
||||
/* Return value should be 0 on success (not sure what the value of USBD_OK is) */
|
||||
if (result == USBD_OK)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue