6defed375ff387e9316b92d844b6efaf5b2f77c6
1 /*
2 * Copyright (c) 2018-2019, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /**
33 * @file profilingHooksR5.c
34 *
35 * @brief R5 Implementations of the runtime programming hooks of the Processor SDK Profiling Tool.
36 *
37 * For more information, see:
38 * - @subpage profCCS
39 * - @subpage profDSS
40 *
41 * ## Usage ##
42 *
43 * Applications that are included in a profiling session must set these
44 * compiler flags for the desired platform:
45 * - ARM: `-finstrument-functions -gdwarf-3 -g`
46 * - DSP: `--entry_parm=address --exit_hook=ti_utils_exit --exit_parm=address --entry_hook=ti_utils_entry -g`
47 * - M4: `--entry_parm=address --exit_hook=ti_utils_exit --exit_parm=address --entry_hook=ti_utils_entry -g`
48 *
49 * The `_ENABLE_BM` flag is used to indicate in a class at compiletime whether
50 * or not profiling is being used.
51 *
52 * For best results, ensure that the optimization levels are consistent between
53 * the library and the project (typically -O3, or optimization level 3).
54 *
55 */
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <stdint.h>
60 #include "profilingHooks.h"
61 #include <ti/csl/arch/r5/csl_arm_r5_pmu.h>
63 int32_t CurrentTaskHookSetId, MaxTaskHookSetId;
65 /*!
66 * @brief Maximum log count
67 *
68 * This is a predefined value to indicate when the instrumentation hooks should
69 * stop logging data. This is important for applications that have long polling
70 * loops or a device that has a small cache.
71 */
72 #define MAX_LOG (1U*1024U*1024U)
74 uint32_t log_idx = 0;
75 uint32_t lvl = 0;
77 /*!
78 * @brief Utils profiling log structure
79 *
80 * Utils log elements have a predefined structure of four words (to avoid the
81 * need of malloc) and are stored in an array of predefined length, `elemlog`.
82 */
83 typedef struct{
84 /*! Indicates either enter or exit */
85 int32_t isEnter;
86 /*! Pointer address of the function in current context */
87 int32_t this_fn;
88 /*! Optional: Pointer address of calling function in current context */
89 int32_t call_site;
90 /*! Timestamp of the entry or exit */
91 uint32_t timestamp;
92 }utilsProfilingElem;
94 utilsProfilingElem elemlog[MAX_LOG] = {{0}};
96 /*!
97 * @brief Empty function for time adjustment
98 *
99 * @ingroup pdk_profiling_hooks
100 *
101 * Nothing more than an empty function that is referenced to measure the time
102 * used by the instrumentation functions themselves. This is recorded and
103 * passed into post-processing for a more accurate result.
104 */
105 #pragma FUNC_CANNOT_INLINE(empty_fn);
106 void empty_fn(void); /*for misra warnings*/
107 void empty_fn(void){
108 }
110 /*!
111 * @brief TI Toolchain Utils Entry Hook
112 *
113 * @ingroup pdk_profiling_hooks
114 *
115 * Instruments the entry point and timestamp of the current function into
116 * memory. Note that this function is automatically referenced at entry of
117 * every function by TI Toolchain.
118 *
119 * @param *func_addr Function Assembly Address (Hexadecimal)
120 */
121 void ti_utils_entry(void (* func_addr)(void)){
122 if (log_idx == 0){
123 uint32_t entry_offset = 0;
124 uint32_t exit_offset = 0;
125 log_idx++;
126 log_idx++;
127 int32_t i;
128 for (i = 0; i < 10; i++){
129 empty_fn();
130 }
131 elemlog[0].isEnter = 2;
132 elemlog[0].this_fn = 3;
133 elemlog[0].call_site = 1;
134 /*Taking 10 sample and subtracting (exit_log - entry log) of present for calculating the entry offset*/
135 for(i=1;i<=10;i++)
136 {
137 entry_offset += (elemlog[(2*i)+1].timestamp - elemlog[(2*i)].timestamp);
138 }
139 /* Saving the average of 10 sample */
140 elemlog[0].timestamp = entry_offset/10U;
141 elemlog[1].isEnter = 2;
142 elemlog[1].this_fn = 3;
143 elemlog[1].call_site = 2;
144 /* Taking 9 sample and subtracting (entry_log of next - exit_log of present) for calculating the exit offset*/
145 for(i=2;i<=10;i++)
146 {
147 exit_offset += (elemlog[(2*i)].timestamp - elemlog[(2*i)-1].timestamp);
148 }
149 /* Saving the average of 9 sample */
150 elemlog[1].timestamp = exit_offset/9U;
151 log_idx = 2U;
152 }
153 if (log_idx < MAX_LOG){
154 elemlog[log_idx].isEnter = 1;
155 elemlog[log_idx].this_fn = (int32_t)func_addr;
156 elemlog[log_idx].timestamp = CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM);
157 log_idx++;
158 }
159 }
161 /*!
162 * @brief TI Toolchain Utils Exit Hook
163 *
164 * @ingroup pdk_profiling_hooks
165 *
166 * Instruments the exit point and timestamp of the current function into
167 * memory. Note that this function is automatically referenced at end of
168 * every function by TI Toolchain.
169 *
170 * @param *func_addr Function Assembly Address (Hexadecimal)
171 */
172 void ti_utils_exit(void (* func_addr)(void)){
173 if (log_idx < MAX_LOG){
174 elemlog[log_idx].isEnter = 0;
175 elemlog[log_idx].this_fn = (int32_t)func_addr;
176 elemlog[log_idx].timestamp = CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM);
177 log_idx++;
178 }
179 }
181 #pragma NO_HOOKS (TaskRegisterId)
182 void TaskRegisterId(int32_t hookSetId); /*for misra warnings*/
183 void TaskRegisterId(int32_t hookSetId)
184 {
185 CurrentTaskHookSetId = hookSetId;
186 if(MaxTaskHookSetId < CurrentTaskHookSetId)
187 {
188 MaxTaskHookSetId = CurrentTaskHookSetId;
189 }
190 }
192 /* ======== mySwitch ========
193 * invoked whenever a Task switch occurs/is made ready to run */
194 #pragma NO_HOOKS (mySwitch)
195 void mySwitch(const void* prev, const void* next); /*for misra warnings*/
196 void mySwitch(const void* prev, const void* next)
197 {
198 if (log_idx < MAX_LOG){
199 elemlog[log_idx].isEnter = 3;
200 elemlog[log_idx].this_fn = (int32_t)next;
201 elemlog[log_idx].call_site = (int32_t)prev;
202 elemlog[log_idx].timestamp = CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM);
203 log_idx++;
204 }
205 }