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