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 * The hardware abstraction layer for the trace recorder.
9 */
10
11 #include <trcRecorder.h>
12
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
14
15 /* If using DWT timestamping (default on ARM Cortex-M3, M4 and M7), make sure the DWT unit is initialized. */
16 #if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03)))
17 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
18 #ifndef TRC_CFG_ARM_CM_USE_SYSTICK
19
xTraceHardwarePortInitCortexM()20 void xTraceHardwarePortInitCortexM()
21 {
22 /* Make sure the DWT registers are unlocked, in case the debugger doesn't do this. */
23 TRC_REG_ITM_LOCKACCESS = TRC_ITM_LOCKACCESS_UNLOCK;
24
25 /* Make sure DWT is enabled is enabled, if supported */
26 TRC_REG_DEMCR |= TRC_DEMCR_TRCENA;
27
28 do
29 {
30 /* Verify that DWT is supported */
31 if (TRC_REG_DEMCR == 0)
32 {
33 /* This function is called on Cortex-M3, M4 and M7 devices to initialize
34 the DWT unit, assumed present. The DWT cycle counter is used for timestamping.
35
36 If the below error is produced, the DWT unit does not seem to be available.
37
38 In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build
39 to use SysTick timestamping instead, or define your own timestamping by
40 setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED
41 and make the necessary definitions, as explained in trcHardwarePort.h.*/
42
43 xTraceError(TRC_ERROR_DWT_NOT_SUPPORTED);
44 break;
45 }
46
47 /* Verify that DWT_CYCCNT is supported */
48 if (TRC_REG_DWT_CTRL & TRC_DWT_CTRL_NOCYCCNT)
49 {
50 /* This function is called on Cortex-M3, M4 and M7 devices to initialize
51 the DWT unit, assumed present. The DWT cycle counter is used for timestamping.
52
53 If the below error is produced, the cycle counter does not seem to be available.
54
55 In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build
56 to use SysTick timestamping instead, or define your own timestamping by
57 setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED
58 and make the necessary definitions, as explained in trcHardwarePort.h.*/
59
60 xTraceError(TRC_ERROR_DWT_CYCCNT_NOT_SUPPORTED);
61 break;
62 }
63
64 /* Reset the cycle counter */
65 TRC_REG_DWT_CYCCNT = 0;
66
67 /* Enable the cycle counter */
68 TRC_REG_DWT_CTRL |= TRC_DWT_CTRL_CYCCNTENA;
69
70 } while (0); /* breaks above jump here */
71 }
72 #endif /* TRC_CFG_ARM_CM_USE_SYSTICK */
73
74 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
75 #endif /* ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03))) */
76
77 #if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_CYCLONE_V_HPS))
78
79 #define CS_TYPE_NONE 0
80 #define CS_TYPE_TASK 1
81 #define CS_TYPE_ISR_MASK_CHANGED 2
82 #define CS_TYPE_ISR_MASK_NOT_CHANGED 3
83
84 #define CS_TYPE_INVALID 0xFFFFFFFF
85
cortex_a9_r5_enter_critical(void)86 int cortex_a9_r5_enter_critical(void)
87 {
88 uint32_t cs_type = CS_TYPE_INVALID;
89
90 if ((prvGetCPSR() & 0x001F) == 0x13) // CSPR (ASPR) mode = SVC
91 {
92 /* Executing in an ISR other than the context-switch (where interrupts might have been enabled, motivating a critical section). */
93 if (ulPortSetInterruptMask() == pdTRUE)
94 {
95 cs_type = CS_TYPE_ISR_MASK_NOT_CHANGED;
96 }
97 else
98 {
99 cs_type = CS_TYPE_ISR_MASK_CHANGED;
100 }
101 }
102 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
103 else if (pxTraceRecorderData->uiTraceSystemState == TRC_STATE_IN_TASKSWITCH)
104 #else
105 else if (uiTraceSystemState == TRC_STATE_IN_TASKSWITCH)
106 #endif
107 {
108 // In the context-switch code. All interrupts are already masked here, so don't modify the mask.
109 cs_type = CS_TYPE_NONE;
110 }
111 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
112 else if (pxTraceRecorderData->uiTraceSystemState != TRC_STATE_IN_TASKSWITCH)
113 #else
114 else if (uiTraceSystemState != TRC_STATE_IN_TASKSWITCH)
115 #endif
116 {
117 // Not within ISR or task-switch context, use a regular critical section.
118 vPortEnterCritical();
119 cs_type = CS_TYPE_TASK;
120 }
121
122 return cs_type;
123 }
124
cortex_a9_r5_exit_critical(int cs_type)125 void cortex_a9_r5_exit_critical(int cs_type)
126 {
127 switch (cs_type)
128 {
129 case CS_TYPE_TASK:
130 vPortExitCritical();
131 break;
132
133 case CS_TYPE_ISR_MASK_CHANGED:
134 vPortClearInterruptMask(pdFALSE); // pdFALSE means it will reset the IRQ mask.
135 break;
136
137 case CS_TYPE_ISR_MASK_NOT_CHANGED:
138 case CS_TYPE_NONE:
139 // No action in these two cases.
140 break;
141
142 default:
143 // Error, should not be possible;
144 for (;;);
145 }
146 }
147 #endif /* ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5)) */
148
149 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
150