]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c
ac4a6f263b6159c99edbb8e3897cd8b04fb7a283
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcHardwarePort.c
1 /******************************************************************************* \r
2  * Tracealyzer v2.6.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  * Copyright Percepio AB, 2013.\r
36  * www.percepio.com\r
37  ******************************************************************************/\r
38 \r
39 #include "trcHardwarePort.h"\r
40 #include "trcKernelPort.h"\r
41 \r
42 #if (USE_TRACEALYZER_RECORDER == 1)\r
43 \r
44 #include <stdint.h>\r
45 \r
46 uint32_t trace_disable_timestamp = 0;\r
47 uint32_t last_timestamp = 0;\r
48 \r
49 /*******************************************************************************\r
50  * uiTraceTickCount\r
51  *\r
52  * This variable is should be updated by the Kernel tick interrupt. This does \r
53  * not need to be modified when developing a new timer port. It is preferred to \r
54  * keep any timer port changes in the HWTC macro definitions, which typically \r
55  * give sufficient flexibility.\r
56  ******************************************************************************/\r
57 uint32_t uiTraceTickCount = 0;\r
58 \r
59 uint32_t DWT_CYCLES_ADDED = 0;\r
60 \r
61 #if (SELECTED_PORT == PORT_ARM_CortexM)\r
62 \r
63 void prvTraceEnableIRQ(void)\r
64 {\r
65         asm volatile ("cpsie i");\r
66 }\r
67 \r
68 void prvTraceDisableIRQ(void)\r
69 {\r
70         asm volatile ("cpsid i");\r
71 }\r
72 \r
73 void prvTraceSetIRQMask(uint32_t priMask)\r
74 {\r
75         asm volatile ("MSR primask, %0" : : "r" (priMask) );\r
76 }\r
77 \r
78 uint32_t prvTraceGetIRQMask(void)\r
79 {\r
80         uint32_t result;\r
81         asm volatile ("MRS %0, primask" : "=r" (result) );\r
82         return result;\r
83 }\r
84 \r
85 void prvTraceInitCortexM()\r
86 {\r
87         DWT_CTRL_REG |= 1;     /* Enable the cycle counter */\r
88         DWT_CYCLE_COUNTER = 0;\r
89         \r
90         if (RecorderDataPtr->frequency == 0)\r
91         {               \r
92                 RecorderDataPtr->frequency = TRACE_CPU_CLOCK_HZ / HWTC_DIVISOR;\r
93         }\r
94 }\r
95 \r
96 #endif\r
97 \r
98 /******************************************************************************\r
99  * vTracePortGetTimeStamp\r
100  *\r
101  * Returns the current time based on the HWTC macros which provide a hardware\r
102  * isolation layer towards the hardware timer/counter.\r
103  *\r
104  * The HWTC macros and vTracePortGetTimeStamp is the main porting issue\r
105  * or the trace recorder library. Typically you should not need to change\r
106  * the code of vTracePortGetTimeStamp if using the HWTC macros.\r
107  *\r
108  ******************************************************************************/\r
109 void vTracePortGetTimeStamp(uint32_t *pTimestamp)\r
110 {\r
111         static uint32_t last_traceTickCount = 0;\r
112     static uint32_t last_hwtc_count = 0;\r
113     uint32_t traceTickCount = 0;\r
114     uint32_t hwtc_count = 0;\r
115     \r
116         if (trace_disable_timestamp == 1)\r
117         {\r
118                 if (pTimestamp)\r
119                         *pTimestamp = last_timestamp;\r
120                 return;\r
121         }\r
122                         \r
123     /* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */\r
124 #if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING)\r
125     hwtc_count = HWTC_COUNT;\r
126 #elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)\r
127     hwtc_count = HWTC_PERIOD - HWTC_COUNT;\r
128 #else\r
129     Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!\r
130     Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING\r
131 #endif\r
132     \r
133     if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)\r
134     {\r
135         /* This means last_traceTickCount is higher than uiTraceTickCount,\r
136         so we have previously compensated for a missed tick.\r
137         Therefore we use the last stored value because that is more accurate. */\r
138         traceTickCount = last_traceTickCount;\r
139     }\r
140     else\r
141     {\r
142         /* Business as usual */\r
143         traceTickCount = uiTraceTickCount;\r
144     }\r
145 \r
146     /* Check for overflow. May occur if the update of uiTraceTickCount has been \r
147     delayed due to disabled interrupts. */\r
148     if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count)\r
149     {\r
150         /* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */\r
151         traceTickCount++;\r
152     }\r
153     \r
154     /* Check if the return address is OK, then we perform the calculation. */\r
155     if (pTimestamp)\r
156     {\r
157         /* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */\r
158         *pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);\r
159         /* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */\r
160         *pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR;\r
161                 \r
162                 last_timestamp = *pTimestamp;\r
163     }\r
164     \r
165     /* Store the previous values. */\r
166     last_traceTickCount = traceTickCount;\r
167     last_hwtc_count = hwtc_count;\r
168 }\r
169 \r
170 #endif