]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c
Final commit before tagging - cosmetic changes only.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcHardwarePort.c
1 /*******************************************************************************\r
2  * Tracealyzer v2.7.7 Recorder Library\r
3  * Percepio AB, www.percepio.com\r
4  *\r
5  * trcBase.c\r
6  *\r
7  * Core functionality of the trace recorder library.\r
8  *\r
9  * Terms of Use\r
10  * This software is copyright Percepio AB. The recorder library is free for\r
11  * use together with Percepio products. You may distribute the recorder library\r
12  * in its original form, including modifications in trcHardwarePort.c/.h\r
13  * given that these modification are clearly marked as your own modifications\r
14  * and documented in the initial comment section of these source files.\r
15  * This software is the intellectual property of Percepio AB and may not be\r
16  * sold or in other ways commercially redistributed without explicit written\r
17  * permission by Percepio AB.\r
18  *\r
19  * Disclaimer\r
20  * The trace tool and recorder library is being delivered to you AS IS and\r
21  * Percepio AB makes no warranty as to its use or performance. Percepio AB does\r
22  * not and cannot warrant the performance or results you may obtain by using the\r
23  * software or documentation. Percepio AB make no warranties, express or\r
24  * implied, as to noninfringement of third party rights, merchantability, or\r
25  * fitness for any particular purpose. In no event will Percepio AB, its\r
26  * technology partners, or distributors be liable to you for any consequential,\r
27  * incidental or special damages, including any lost profits or lost savings,\r
28  * even if a representative of Percepio AB has been advised of the possibility\r
29  * of such damages, or for any claim by any third party. Some jurisdictions do\r
30  * not allow the exclusion or limitation of incidental, consequential or special\r
31  * damages, or the exclusion of implied warranties or limitations on how long an\r
32  * implied warranty may last, so the above limitations may not apply to you.\r
33  *\r
34  * Tabs are used for indent in this file (1 tab = 4 spaces)\r
35  *\r
36  * Copyright Percepio AB, 2012-2015.\r
37  * www.percepio.com\r
38  ******************************************************************************/\r
39 \r
40 #include "trcHardwarePort.h"\r
41 #include "trcKernelPort.h"\r
42 \r
43 #if (USE_TRACEALYZER_RECORDER == 1)\r
44 \r
45 #include <stdint.h>\r
46 \r
47 uint32_t trace_disable_timestamp = 0;\r
48 uint32_t last_timestamp = 0;\r
49 \r
50 /*******************************************************************************\r
51  * uiTraceTickCount\r
52  *\r
53  * This variable is should be updated by the Kernel tick interrupt. This does\r
54  * not need to be modified when developing a new timer port. It is preferred to\r
55  * keep any timer port changes in the HWTC macro definitions, which typically\r
56  * give sufficient flexibility.\r
57  ******************************************************************************/\r
58 uint32_t uiTraceTickCount = 0;\r
59 \r
60 uint32_t DWT_CYCLES_ADDED = 0; /* Used on ARM Cortex-M only */\r
61 \r
62 #if (SELECTED_PORT == PORT_ARM_CortexM)\r
63 \r
64 void prvTraceInitCortexM()\r
65 {\r
66         /* Make sure DWT is enabled is enabled, if supported */\r
67         REG_DEMCR |= DEMCR_TRCENA;\r
68 \r
69         do{\r
70                 /* Verify that DWT is supported */\r
71                 if (REG_DEMCR == 0)\r
72                 {\r
73                         vTraceError("DWT not supported by this chip!");\r
74                         break;\r
75                 }\r
76 \r
77                 /* Verify that DWT_CYCCNT is supported */\r
78                 if (REG_DWT_CTRL & DWT_CTRL_NOCYCCNT)\r
79                 {\r
80                         vTraceError("DWT_CYCCNT not supported by this chip!");\r
81                         break;\r
82                 }\r
83 \r
84                 /* Reset the cycle counter */\r
85                 REG_DWT_CYCCNT = 0;\r
86 \r
87                 /* Enable the cycle counter */\r
88                 REG_DWT_CTRL |= DWT_CTRL_CYCCNTENA;\r
89 \r
90         }while(0);      /* breaks above jump here */\r
91 \r
92         if (RecorderDataPtr->frequency == 0)\r
93         {\r
94                 RecorderDataPtr->frequency = TRACE_CPU_CLOCK_HZ / HWTC_DIVISOR;\r
95         }\r
96 }\r
97 \r
98 #endif\r
99 \r
100 /******************************************************************************\r
101  * vTracePortGetTimeStamp\r
102  *\r
103  * Returns the current time based on the HWTC macros which provide a hardware\r
104  * isolation layer towards the hardware timer/counter.\r
105  *\r
106  * The HWTC macros and vTracePortGetTimeStamp is the main porting issue\r
107  * or the trace recorder library. Typically you should not need to change\r
108  * the code of vTracePortGetTimeStamp if using the HWTC macros.\r
109  *\r
110  ******************************************************************************/\r
111 void vTracePortGetTimeStamp(uint32_t *pTimestamp)\r
112 {\r
113         static uint32_t last_traceTickCount = 0;\r
114         static uint32_t last_hwtc_count = 0;\r
115         uint32_t traceTickCount = 0;\r
116         uint32_t hwtc_count = 0;\r
117 \r
118         if (trace_disable_timestamp == 1)\r
119         {\r
120                 if (pTimestamp)\r
121                         *pTimestamp = last_timestamp;\r
122                 return;\r
123         }\r
124 \r
125         /* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */\r
126 #if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING)\r
127         hwtc_count = HWTC_COUNT;\r
128 #elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)\r
129         hwtc_count = HWTC_PERIOD - HWTC_COUNT;\r
130 #else\r
131         Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!\r
132         Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING\r
133 #endif\r
134 \r
135 #if (SELECTED_PORT == PORT_Win32)\r
136         /* The Win32 port uses ulGetRunTimeCounterValue for timestamping, which in turn\r
137         uses QueryPerformanceCounter. That function is not always reliable when used over\r
138         multiple threads. We must therefore handle rare cases where the timestamp is less\r
139         than the previous. In practice, the Win32 should "never" roll over since the\r
140         performance counter is 64 bit wide. */\r
141 \r
142         if (last_hwtc_count > hwtc_count)\r
143         {\r
144                 hwtc_count = last_hwtc_count;\r
145         }\r
146 #endif\r
147 \r
148         if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)\r
149         {\r
150                 /* This means last_traceTickCount is higher than uiTraceTickCount,\r
151                 so we have previously compensated for a missed tick.\r
152                 Therefore we use the last stored value because that is more accurate. */\r
153                 traceTickCount = last_traceTickCount;\r
154         }\r
155         else\r
156         {\r
157                 /* Business as usual */\r
158                 traceTickCount = uiTraceTickCount;\r
159         }\r
160 \r
161         /* Check for overflow. May occur if the update of uiTraceTickCount has been\r
162         delayed due to disabled interrupts. */\r
163         if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count)\r
164         {\r
165                 /* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */\r
166                 traceTickCount++;\r
167         }\r
168 \r
169         /* Check if the return address is OK, then we perform the calculation. */\r
170         if (pTimestamp)\r
171         {\r
172                 /* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */\r
173                 *pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);\r
174                 /* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */\r
175                 *pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR;\r
176 \r
177                 last_timestamp = *pTimestamp;\r
178         }\r
179 \r
180         /* Store the previous values. */\r
181         last_traceTickCount = traceTickCount;\r
182         last_hwtc_count = hwtc_count;\r
183 }\r
184 \r
185 #endif\r