1 /*
2 * Percepio Trace Recorder for Tracealyzer v4.9.2
3 * Copyright 2023 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * The implementation for ISR tagging.
9 */
10 
11 #include <trcRecorder.h>
12 
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1) && (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
14 
15 TraceISRData_t* pxTraceISRData TRC_CFG_RECORDER_DATA_ATTRIBUTE;
16 
xTraceISRInitialize(TraceISRData_t * pxBuffer)17 traceResult xTraceISRInitialize(TraceISRData_t *pxBuffer)
18 {
19 	uint32_t uiCoreIndex;
20 	uint32_t uiStackIndex;
21 
22 	/* This should never fail */
23 	TRC_ASSERT(pxBuffer != (void*)0);
24 
25 	pxTraceISRData = pxBuffer;
26 
27 	for (uiCoreIndex = 0u; uiCoreIndex < (uint32_t)(TRC_CFG_CORE_COUNT); uiCoreIndex++)
28 	{
29 		TraceISRCoreData_t* pxCoreData = &pxTraceISRData->cores[uiCoreIndex];
30 
31 		/* Initialize ISR stack */
32 		for (uiStackIndex = 0u; uiStackIndex < (uint32_t)(TRC_CFG_MAX_ISR_NESTING); uiStackIndex++)
33 		{
34 			pxCoreData->handleStack[uiStackIndex] = 0;
35 		}
36 
37 		pxCoreData->stackIndex = -1;
38 		pxCoreData->isPendingContextSwitch = 0u;
39 	}
40 
41 	xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ISR);
42 
43 	return TRC_SUCCESS;
44 }
45 
46 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceISRRegister(const char * szName,uint32_t uiPriority,TraceISRHandle_t * pxISRHandle)47 traceResult xTraceISRRegister(const char* szName, uint32_t uiPriority, TraceISRHandle_t *pxISRHandle)
48 {
49 	TraceEntryHandle_t xEntryHandle;
50 	uint32_t i, uiLength = 0u;
51 
52 	/* We need to check this */
53 	if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR) == 0U)
54 	{
55 		return TRC_FAIL;
56 	}
57 
58 	/* This should never fail */
59 	TRC_ASSERT(pxISRHandle != (void*)0);
60 
61 	if (szName == (void*)0)
62 	{
63 		szName = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
64 	}
65 
66 	/* Always save in symbol table, in case the recording has not yet started */
67 	/* We need to check this */
68 	if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL)
69 	{
70 		return TRC_FAIL;
71 	}
72 
73 	for (i = 0u; (szName[i] != (char)0) && (i < 128u); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
74 
75 	uiLength = i;
76 
77 	/* This should never fail */
78 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetSymbol(xEntryHandle, szName, uiLength) == TRC_SUCCESS);
79 
80 	/* This should never fail */
81 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, 0u, (TraceUnsignedBaseType_t)uiPriority) == TRC_SUCCESS);
82 
83 	*pxISRHandle = (TraceISRHandle_t)xEntryHandle;
84 
85 	return xTraceEventCreateData2(
86 		PSF_EVENT_DEFINE_ISR,
87 		(TraceUnsignedBaseType_t)xEntryHandle,
88 		(TraceUnsignedBaseType_t)uiPriority,
89 		(TraceUnsignedBaseType_t*)szName,
90 		uiLength + 1
91 	);
92 }
93 
xTraceISRBegin(TraceISRHandle_t xISRHandle)94 traceResult xTraceISRBegin(TraceISRHandle_t xISRHandle)
95 {
96 	TraceISRCoreData_t* pxCoreData;
97 	TRACE_ALLOC_CRITICAL_SECTION();
98 
99 	/* This should never fail */
100 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR));
101 
102 	TRACE_ENTER_CRITICAL_SECTION();
103 
104 	/* We are at the start of a possible ISR chain.
105 	 * No context switches should have been triggered now.
106 	 */
107 	pxCoreData = &pxTraceISRData->cores[TRC_CFG_GET_CURRENT_CORE()];
108 
109 	if (pxCoreData->stackIndex == -1)
110 	{
111 		pxCoreData->isPendingContextSwitch = 0u;
112 	}
113 
114 	if (pxCoreData->stackIndex < ((TRC_CFG_MAX_ISR_NESTING) - 1))
115 	{
116 		pxCoreData->stackIndex++;
117 		pxCoreData->handleStack[pxCoreData->stackIndex] = xISRHandle;
118 
119 #if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
120 		(void)xTraceEventCreate1(PSF_EVENT_ISR_BEGIN, (TraceUnsignedBaseType_t)xISRHandle); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 Suppress conversion from pointer to integer check*/
121 #endif
122 	}
123 	else
124 	{
125 		TRACE_EXIT_CRITICAL_SECTION();
126 
127 		(void)xTraceError(TRC_ERROR_ISR_NESTING_OVERFLOW);
128 
129 		return TRC_FAIL;
130 	}
131 
132 	TRACE_EXIT_CRITICAL_SECTION();
133 
134 	return TRC_SUCCESS;
135 }
136 
xTraceISREnd(TraceBaseType_t xIsTaskSwitchRequired)137 traceResult xTraceISREnd(TraceBaseType_t xIsTaskSwitchRequired)
138 {
139 	TraceISRCoreData_t* pxCoreData;
140 	TRACE_ALLOC_CRITICAL_SECTION();
141 
142 	(void)xIsTaskSwitchRequired;
143 
144 	/* This should never fail */
145 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR));
146 
147 	TRACE_ENTER_CRITICAL_SECTION();
148 
149 	pxCoreData = &pxTraceISRData->cores[TRC_CFG_GET_CURRENT_CORE()];
150 
151 	pxCoreData->stackIndex--;
152 
153 #if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
154 	/* Is there a pending task-switch? (perhaps from an earlier ISR) */
155 	pxCoreData->isPendingContextSwitch |= (uint32_t)xIsTaskSwitchRequired;
156 
157 	if (pxCoreData->stackIndex >= 0)
158 	{
159 		/* Store return to interrupted ISR (if nested ISRs)*/
160 		(void)xTraceEventCreate1(PSF_EVENT_ISR_RESUME, (TraceUnsignedBaseType_t)pxCoreData->handleStack[pxCoreData->stackIndex]); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 Suppress conversion from pointer to integer check*/
161 	}
162 	else
163 	{
164 		/* Store return to interrupted task, if no context switch will occur in between. */
165 		if ((pxCoreData->isPendingContextSwitch == 0U) || (xTraceKernelPortIsSchedulerSuspended() == 1U)) /*cstat !MISRAC2004-13.7_b For some kernel ports xTraceKernelPortIsSchedulerSuspended() will never return 1, and that is expected*/
166 		{
167 			(void)xTraceEventCreate1(PSF_EVENT_TASK_ACTIVATE, (TraceUnsignedBaseType_t)xTraceTaskGetCurrentReturn());  /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 !MISRAC2012-Rule-11.6 Suppress conversion from pointer to integer check*/
168 		}
169 	}
170 #endif
171 
172 	TRACE_EXIT_CRITICAL_SECTION();
173 
174 	return TRC_SUCCESS;
175 }
176 
177 #if ((TRC_CFG_USE_TRACE_ASSERT) == 1)
178 
xTraceISRGetCurrentNesting(int32_t * puiValue)179 traceResult xTraceISRGetCurrentNesting(int32_t* puiValue)
180 {
181 	/* This should never fail */
182 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR));
183 
184 	/* This should never fail */
185 	TRC_ASSERT(puiValue != (void*)0);
186 
187 	TraceISRCoreData_t* pxCoreData = &pxTraceISRData->cores[TRC_CFG_GET_CURRENT_CORE()];
188 	*puiValue = pxCoreData->stackIndex;
189 
190 	return TRC_SUCCESS;
191 }
192 
xTraceISRGetCurrentNestingReturned(void)193 int32_t xTraceISRGetCurrentNestingReturned(void)
194 {
195 	/* This should never fail */
196 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR));
197 
198 	return pxTraceISRData->cores[TRC_CFG_GET_CURRENT_CORE()].stackIndex;
199 }
200 
xTraceISRGetCurrent(TraceISRHandle_t * pxISRHandle)201 traceResult xTraceISRGetCurrent(TraceISRHandle_t* pxISRHandle)
202 {
203 	/* This should never fail */
204 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR));
205 
206 	/* This should never fail */
207 	TRC_ASSERT(pxISRHandle != (void*)0);
208 
209 	TraceISRCoreData_t* pxCoreData = &pxTraceISRData->cores[TRC_CFG_GET_CURRENT_CORE()];
210 
211 	if (pxCoreData->stackIndex < 0)
212 	{
213 		return TRC_FAIL;
214 	}
215 
216 	*pxISRHandle = pxCoreData->handleStack[pxCoreData->stackIndex];
217 
218 	return TRC_SUCCESS;
219 }
220 
221 #endif
222 
223 /* DEPRECATED */
224 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceSetISRProperties(const char * szName,uint32_t uiPriority)225 TraceISRHandle_t xTraceSetISRProperties(const char* szName, uint32_t uiPriority)
226 {
227 	TraceISRHandle_t xISRHandle = 0;
228 
229 	(void)xTraceISRRegister(szName, uiPriority, &xISRHandle);
230 
231 	return xISRHandle;
232 }
233 
234 #endif
235