Initial version
This commit is contained in:
@ -0,0 +1,27 @@
|
||||
Tracealyzer Stream Port for USB CDC (STM32 example)
|
||||
---------------------------------------------------
|
||||
|
||||
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 USB CDC. This is an example for the STM32 USB
|
||||
stack (from the STM32CubeMX code generation tool, v1.4.1) and has been tested on
|
||||
a STM32F767ZI device on a Nucleo board. See this blog post:
|
||||
|
||||
http://percepio.com/2017/02/03/usb-trace-streaming-st-nucleo-f767zi-board/
|
||||
|
||||
However, it should be straight-forward to modify this for other USB stacks.
|
||||
|
||||
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!
|
||||
|
||||
Note that the USB stack not included, but assumed to exist in the project already.
|
||||
|
||||
See also http://percepio.com/2016/10/05/rtos-tracing.
|
||||
|
||||
Percepio AB
|
||||
www.percepio.com
|
@ -0,0 +1,83 @@
|
||||
/*******************************************************************************
|
||||
* Trace Recorder Library for Tracealyzer v4.1.5
|
||||
* Percepio AB, www.percepio.com
|
||||
*
|
||||
* trcStreamingPort.h
|
||||
*
|
||||
* The interface definitions for trace streaming ("stream ports").
|
||||
* This "stream port" sets up the recorder to use USB CDC as streaming channel.
|
||||
* The example is for STM32 using STM32Cube.
|
||||
*
|
||||
* 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
|
||||
|
||||
/* 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"
|
||||
#include "usbd_CDC_if.h"
|
||||
#include "usb_device.h"
|
||||
|
||||
/* 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 );
|
||||
|
||||
#define TRC_STREAM_PORT_INIT() \
|
||||
MX_USB_DEVICE_Init(); \
|
||||
TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */
|
||||
|
||||
#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcCDCReceive(_ptrData, _size, _ptrBytesRead)
|
||||
|
||||
#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcCDCTransmit(_ptrData, _size, _ptrBytesSent)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TRC_STREAMING_PORT_H */
|
@ -0,0 +1,246 @@
|
||||
|
||||
#include "trcRecorder.h"
|
||||
|
||||
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
||||
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
/* 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"
|
||||
#include "usbd_CDC_if.h"
|
||||
#include "usb_device.h"
|
||||
|
||||
#define BUFSIZE 64
|
||||
|
||||
typedef struct{
|
||||
uint32_t idx;
|
||||
uint8_t data[BUFSIZE];
|
||||
}recBuf;
|
||||
|
||||
/* Define size for the receive and transmit buffer over CDC */
|
||||
#define APP_RX_DATA_SIZE 8
|
||||
#define APP_TX_DATA_SIZE 64
|
||||
|
||||
/* Received Data over USB are stored in this buffer */
|
||||
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
|
||||
|
||||
/* Send Data over USB CDC are stored in this buffer */
|
||||
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
|
||||
|
||||
extern USBD_HandleTypeDef hUsbDeviceFS;
|
||||
|
||||
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
|
||||
recBuf commandBuffer;
|
||||
|
||||
static int8_t CDC_Init_FS (void);
|
||||
static int8_t CDC_DeInit_FS (void);
|
||||
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
|
||||
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
|
||||
|
||||
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
|
||||
{
|
||||
CDC_Init_FS,
|
||||
CDC_DeInit_FS,
|
||||
CDC_Control_FS,
|
||||
CDC_Receive_FS
|
||||
};
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief CDC_Init_FS
|
||||
* Initializes the CDC media low layer over the FS USB IP
|
||||
* @param None
|
||||
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
|
||||
*/
|
||||
static int8_t CDC_Init_FS(void)
|
||||
{
|
||||
/* Set Application Buffers */
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
|
||||
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
|
||||
return (USBD_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CDC_DeInit_FS
|
||||
* DeInitializes the CDC media low layer
|
||||
* @param None
|
||||
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
|
||||
*/
|
||||
static int8_t CDC_DeInit_FS(void)
|
||||
{
|
||||
return (USBD_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CDC_Control_FS
|
||||
* Manage the CDC class requests
|
||||
* @param cmd: Command code
|
||||
* @param pbuf: Buffer containing command data (request parameters)
|
||||
* @param length: Number of data to be sent (in bytes)
|
||||
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
|
||||
*/
|
||||
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case CDC_SEND_ENCAPSULATED_COMMAND:
|
||||
break;
|
||||
|
||||
case CDC_GET_ENCAPSULATED_RESPONSE:
|
||||
break;
|
||||
|
||||
case CDC_SET_COMM_FEATURE:
|
||||
break;
|
||||
|
||||
case CDC_GET_COMM_FEATURE:
|
||||
break;
|
||||
|
||||
case CDC_CLEAR_COMM_FEATURE:
|
||||
break;
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Line Coding Structure */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Offset | Field | Size | Value | Description */
|
||||
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
|
||||
/* 4 | bCharFormat | 1 | Number | Stop bits */
|
||||
/* 0 - 1 Stop bit */
|
||||
/* 1 - 1.5 Stop bits */
|
||||
/* 2 - 2 Stop bits */
|
||||
/* 5 | bParityType | 1 | Number | Parity */
|
||||
/* 0 - None */
|
||||
/* 1 - Odd */
|
||||
/* 2 - Even */
|
||||
/* 3 - Mark */
|
||||
/* 4 - Space */
|
||||
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
|
||||
/*******************************************************************************/
|
||||
case CDC_SET_LINE_CODING:
|
||||
break;
|
||||
|
||||
case CDC_GET_LINE_CODING:
|
||||
break;
|
||||
|
||||
case CDC_SET_CONTROL_LINE_STATE:
|
||||
break;
|
||||
|
||||
case CDC_SEND_BREAK:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (USBD_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CDC_Receive_FS
|
||||
* Data received over USB OUT endpoint are sent over CDC interface
|
||||
* through this function.
|
||||
*
|
||||
* @note
|
||||
* This function will block any OUT packet reception on USB endpoint
|
||||
* until exiting this function. If you exit this function before transfer
|
||||
* is complete on CDC interface (i.e. using DMA controller) it will result
|
||||
* in receiving more data while previous ones are still not sent.
|
||||
*
|
||||
* @param Buf: Buffer of data to be received
|
||||
* @param Len: Number of data received (in bytes)
|
||||
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
|
||||
*/
|
||||
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
|
||||
{
|
||||
for( uint32_t i=0;i<* Len;i++)
|
||||
{
|
||||
commandBuffer.data[commandBuffer.idx]=Buf[i];
|
||||
commandBuffer.idx++;
|
||||
}
|
||||
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
|
||||
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
|
||||
|
||||
return (USBD_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CDC_Transmit_FS
|
||||
* Data send over USB IN endpoint are sent over CDC interface
|
||||
* through this function.
|
||||
* @note
|
||||
*
|
||||
*
|
||||
* @param Buf: Buffer of data to be send
|
||||
* @param Len: Number of data to be send (in bytes)
|
||||
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
|
||||
*/
|
||||
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
|
||||
{
|
||||
uint8_t result = USBD_OK;
|
||||
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
|
||||
if (hcdc->TxState != 0){
|
||||
return USBD_BUSY;
|
||||
}
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
|
||||
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The READ function, used in trcStreamingPort.h */
|
||||
int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes)
|
||||
{
|
||||
uint32_t i,diff;
|
||||
|
||||
if(commandBuffer.idx>0)
|
||||
{
|
||||
if (size >= commandBuffer.idx) // more than what is stored, number of bytes will be .idx
|
||||
{
|
||||
memcpy(data,commandBuffer.data, commandBuffer.idx);
|
||||
*NumBytes=commandBuffer.idx;
|
||||
commandBuffer.idx=0; // Make the buffer ready for a new command
|
||||
}
|
||||
else //If some data in the buffer is not read
|
||||
{
|
||||
diff = commandBuffer.idx-size;
|
||||
memcpy(data,commandBuffer.data, size);
|
||||
for(i=0;i<diff;i++)
|
||||
{
|
||||
commandBuffer.data[i]=commandBuffer.data[i+size];
|
||||
}
|
||||
*NumBytes=size;
|
||||
commandBuffer.idx=diff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*NumBytes=0;
|
||||
}
|
||||
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 value should be 0 on success (not sure what the value of USBD_OK is) */
|
||||
if (result == USBD_OK)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles USB On The Go FS global interrupt.
|
||||
*/
|
||||
void OTG_FS_IRQHandler(void)
|
||||
{
|
||||
HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
|
||||
}
|
||||
|
||||
#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
|
||||
#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
|
||||
|
Reference in New Issue
Block a user