1 /*
2 * Trace Recorder for Tracealyzer v4.6.6
3 * Copyright 2021 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Supporting functions for trace streaming ("stream ports").
9 * This "stream port" sets up the recorder to use USB CDC as streaming channel.
10 * The example is for STM32 using STM32Cube.
11 */
12
13 #include <trcRecorder.h>
14
15 #include <usb_device.h>
16 #include <usbd_CDC_if.h>
17
18 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
19 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
20
21 static void prvCDCInit(void);
22
23 static int8_t CDC_Receive_FS_modified(uint8_t* pbuf, uint32_t *puiLength);
24
25 extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;
26
27 static int8_t(*CDC_Receive_FS)(uint8_t* Buf, uint32_t* Len);
28
29 typedef struct TraceStreamPortUSBCommandBuffer {
30 TraceUnsignedBaseType_t idx;
31 uint8_t bufferUSB[TRC_STREAM_PORT_USB_BUFFER_SIZE];
32 uint8_t bufferInternal[TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE];
33 } TraceStreamPortUSBBuffers_t;
34
35 TraceStreamPortUSBBuffers_t* pxUSBBuffers;
36
CDC_Receive_FS_modified(uint8_t * pBuffer,uint32_t * puiLength)37 static int8_t CDC_Receive_FS_modified(uint8_t* pBuffer, uint32_t *puiLength)
38 {
39 for(uint32_t i = 0; i < *puiLength; i++)
40 {
41 pxUSBBuffers->bufferUSB[pxUSBBuffers->idx] = pBuffer[i];
42 pxUSBBuffers->idx++;
43 }
44
45 CDC_Receive_FS(pBuffer, puiLength);
46
47 return (USBD_OK);
48 }
49
prvCDCInit(void)50 static void prvCDCInit(void)
51 {
52 /* Store the original "Receive" function, from the static initialization */
53 CDC_Receive_FS = USBD_Interface_fops_FS.Receive;
54
55 /* Update the function pointer with our modified variant */
56 USBD_Interface_fops_FS.Receive = CDC_Receive_FS_modified;
57
58 pxUSBBuffers->idx = 0;
59
60 MX_USB_DEVICE_Init();
61 }
62
63 /* The READ function, used in trcStreamPort.h */
prvTraceCDCReceive(void * data,uint32_t uiSize,int32_t * piBytesReceived)64 traceResult prvTraceCDCReceive(void *data, uint32_t uiSize, int32_t* piBytesReceived)
65 {
66 uint32_t i, uiDiff;
67
68 if(pxUSBBuffers->idx > 0)
69 {
70 if ((TraceUnsignedBaseType_t)uiSize >= pxUSBBuffers->idx) // More than what is stored, number of bytes will be .idx
71 {
72 TRC_MEMCPY(data, pxUSBBuffers->bufferUSB, pxUSBBuffers->idx);
73 *piBytesReceived = (int32_t)pxUSBBuffers->idx;
74 pxUSBBuffers->idx = 0; // Make the buffer ready for a new command
75 }
76 else // If some data in the buffer is not read
77 {
78 uiDiff = pxUSBBuffers->idx - uiSize;
79 TRC_MEMCPY(data, pxUSBBuffers->bufferUSB, uiSize);
80
81 for(i = 0; i < uiDiff; i++)
82 {
83 pxUSBBuffers->bufferUSB[i] = pxUSBBuffers->bufferUSB[i + uiSize];
84 }
85
86 *piBytesReceived = uiSize;
87
88 pxUSBBuffers->idx = uiDiff;
89 }
90 }
91 else
92 {
93 *piBytesReceived = 0;
94 }
95
96 return TRC_SUCCESS;
97 }
98
99 /* The WRITE function, used in trcStreamPort.h */
prvTraceCDCTransmit(void * pvData,uint32_t uiSize,int32_t * piBytesSent)100 traceResult prvTraceCDCTransmit(void* pvData, uint32_t uiSize, int32_t * piBytesSent )
101 {
102 static int fail_counter = 0;
103
104 int32_t result;
105
106 *piBytesSent = 0;
107
108 result = CDC_Transmit_FS(pvData, uiSize);
109
110 if (result == USBD_OK)
111 {
112 fail_counter = 0;
113 *piBytesSent = uiSize;
114 return TRC_SUCCESS;
115 }
116 else
117 {
118 fail_counter++;
119
120 /* We keep trying to send more pvData. If busy, we delay for a while. This function will be called again afterwards. */
121 xTraceKernelPortDelay(TRC_CFG_STREAM_PORT_DELAY_ON_BUSY);
122
123 if (fail_counter >= 100)
124 {
125 /* If many unsuccessful attempts in a row, something is very wrong. Returning -1 will stop the recorder. */
126 return TRC_FAIL;
127 }
128 }
129
130 return TRC_SUCCESS;
131 }
132
xTraceStreamPortInitialize(TraceStreamPortBuffer_t * pxBuffer)133 traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer)
134 {
135 TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortUSBBuffers_t);
136
137 if (pxBuffer == 0)
138 {
139 return TRC_FAIL;
140 }
141
142 pxUSBBuffers = (TraceStreamPortUSBBuffers_t*)pxBuffer;
143
144 prvCDCInit();
145
146 return xTraceInternalEventBufferInitialize(pxUSBBuffers->bufferInternal, sizeof(pxUSBBuffers->bufferInternal));
147 }
148
149 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
150 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
151
152