1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35
36
37 package ti.sysbios.family.arm.v7a;
38
39 import xdc.rov.ViewInfo;
40 import xdc.runtime.Assert;
41
42 import ti.sysbios.hal.Hwi;
43
44 /*!
45 * ======== Pmu ========
46 * ARM Performance Monitoring Unit module
47 *
48 * This module manages the performance monitor unit's counters on ARM v7A
49 * processors. This module does not manage the cycle counter. The cycle
50 * counter is managed by the Timestamp module on most ARM cores.
51 *
52 * The following is an example of how to configure one of the Pmu counters
53 * to count L2 cache access events on a Cortex-A15 processor:
54 *
55 * C source file:
56 * @p(code)
57 * #include <ti/sysbios/family/arm/v7a/Pmu.h>
58 *
59 * Int main(Int argc, char *argv[])
60 * {
61 * // Set L2 cache access as the event type for event counter 0.
62 * // The event number corresponding to each event type can be determined
63 * // using the Cortex-A15 reference manual.
64 * Pmu_configureCounter(0, 0x16, FALSE);
65 *
66 * // Reset the count
67 * Pmu_resetCount(0);
68 *
69 * // Start the counter
70 * Pmu_startCounter(0);
71 *
72 * // code
73 * ...
74 *
75 * // Stop the counter
76 * Pmu_stopCounter(0);
77 *
78 * // Read and print the count
79 * System_printf("L2 access count: %d\n", Pmu_getCount(0));
80 *
81 * return 0;
82 * }
83 * @p
84 *
85 * *.cfg file:
86 * @p(code)
87 * var Pmu = xdc.useModule('ti.sysbios.family.arm.v7a.Pmu');
88 * @p
89 *
90 * @p(html)
91 * <h3> Calling Context </h3>
92 * <table border="1" cellpadding="3">
93 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
94 * </colgroup>
95 *
96 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
97 * <th> Task </th><th> Main </th><th> Startup </th></tr>
98 * <!-- -->
99 * <tr><td> {@link #configureCounter} </td><td> Y </td>
100 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
101 * <tr><td> {@link #clearOverflowStatus} </td><td> Y </td>
102 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
103 * <tr><td> {@link #disableInterrupt} </td><td> Y </td>
104 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
105 * <tr><td> {@link #enableInterrupt} </td><td> Y </td>
106 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
107 * <tr><td> {@link #getCount} </td><td> Y </td><td> Y </td>
108 * <td> Y </td><td> Y </td><td> N </td></tr>
109 * <tr><td> {@link #getOverflowStatus} </td><td> Y </td>
110 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
111 * <tr><td> {@link #resetCount} </td><td> Y </td><td> Y </td>
112 * <td> Y </td><td> Y </td><td> N </td></tr>
113 * <tr><td> {@link #setCount} </td><td> Y </td><td> Y </td>
114 * <td> Y </td><td> Y </td><td> N </td></tr>
115 * <tr><td> {@link #setInterruptFunc} </td><td> Y </td>
116 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
117 * <tr><td> {@link #startCounter} </td><td> Y </td><td> Y </td>
118 * <td> Y </td><td> Y </td><td> N </td></tr>
119 * <tr><td> {@link #stopCounter} </td><td> Y </td><td> Y </td>
120 * <td> Y </td><td> Y </td><td> N </td></tr>
121 * <tr><td colspan="6"> Definitions: <br />
122 * <ul>
123 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
124 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
125 * <li> <b>Task</b>: API is callable from a Task thread. </li>
126 * <li> <b>Main</b>: API is callable during any of these phases: </li>
127 * <ul>
128 * <li> In your module startup after this module is started
129 * (e.g. PerfMonitor_Module_startupDone() returns TRUE). </li>
130 * <li> During xdc.runtime.Startup.lastFxns. </li>
131 * <li> During main().</li>
132 * <li> During BIOS.startupFxns.</li>
133 * </ul>
134 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
135 * <ul>
136 * <li> During xdc.runtime.Startup.firstFxns.</li>
137 * <li> In your module startup before this module is started
138 * (e.g. Cache_Module_startupDone() returns FALSE).</li>
139 * </ul>
140 * </ul>
141 * </td></tr>
142 *
143 * </table>
144 * @p
145 */
146
147 @ModuleStartup
148 @DirectCall
149 module Pmu
150 {
151 /*!
152 * ======== intNum ========
153 * A Hwi is created for the interrupt number 'pmuIntNum'
154 *
155 * pmuIntNum specifies the interrupt number that is connected to the
156 * nPMUIRQ signal from the PMU module.
157 */
158 config UInt intNum = (~0);
159
160 /*! Pmu interrupt handler function type definition. */
161 typedef Void (*IntHandlerFuncPtr)(UArg);
162
163 /*!
164 * ======== ModView ========
165 * @_nodoc
166 */
167 metaonly struct PmuInfoView {
168 UInt numEventCounters; 169
170 };
171
172 /*!
173 * ======== rovViewInfo ========
174 * @_nodoc
175 */
176 @Facet
177 metaonly config ViewInfo.Instance rovViewInfo =
178 ViewInfo.create({
179 viewMap: [
180 ['Pmu Info', { type: ViewInfo.MODULE_DATA,
181 viewInitFxn: 'viewInitPmuInfo',
182 structName: 'PmuInfoView'}],
183 ]
184 });
185
186 /*!
187 * ======== A_badIntNum ========
188 * Assert raised when module cannot determine PMU interrupt number
189 * for the given target/platform and the user is not providing the
190 * interrupt number using intNum config param.
191 */
192 config xdc.runtime.Assert.Id A_badIntNum = {
193 msg: "A_badIntNum: Set PMU interrupt number using Pmu.intNum config param."
194 };
195
196 /*!
197 * ======== A_invalidCounterId ========
198 * Assert raised when invalid PMU counter Id passed.
199 */
200 config xdc.runtime.Assert.Id A_invalidCounterId = {
201 msg: "A_invalidCounterId: Invalid PMU counter Id passed."
202 };
203
204 /*!
205 * ======== interruptFunc ========
206 * PMU overflow interrupt callback function pointer
207 *
208 * When a counter overflow interrupt occurs, the registered
209 * callback function is called with the contents of the Overflow
210 * Flag Status Register passed as an argument. The overflow
211 * status flag can be used to determine which counter generated
212 * the interrupt when multiple counters are running with
213 * overflow interrupt enabled.
214 */
215 metaonly config IntHandlerFuncPtr interruptFunc = null;
216
217 /*!
218 * ======== setInterruptFunc ========
219 * Set callback function
220 *
221 * When a counter overflow interrupt occurs, the registered
222 * callback function is called with the contents of the Overflow
223 * Flag Status Register passed as an argument. The overflow
224 * status flag can be used to determine which counter generated
225 * the interrupt when multiple counters are running with
226 * overflow interrupt enabled.
227 *
228 * Setting the callback function through this API overrides
229 * the callback function set through {@link #interruptFunc} config param.
230 *
231 * @param(interruptFunc) Callback function
232 */
233 Void setInterruptFunc(IntHandlerFuncPtr interruptFunc);
234
235 /*!
236 * ======== startCounter ========
237 * Start an event counter
238 *
239 * @param(counterId) Event counter Id
240 */
241 Void startCounter(UInt counterId);
242
243 /*!
244 * ======== stopCounter ========
245 * Stop an event counter
246 *
247 * @param(counterId) Event counter Id
248 */
249 Void stopCounter(UInt counterId);
250
251 /*!
252 * ======== resetCount ========
253 * Reset the event counter's count to 0
254 *
255 * @param(counterId) Event counter Id
256 */
257 Void resetCount(UInt counterId);
258
259 /*!
260 * ======== setCount ========
261 * Set the event counter's count to counterVal.
262 *
263 * @param(counterId) Event counter Id
264 * @param(counterVal) Counter value to set
265 */
266 Void setCount(UInt counterId, UInt32 counterVal);
267
268 /*!
269 * ======== configureCounter ========
270 * Set the event type for an event counter and enable/disable
271 * interrupt generation on a counter overflow
272 *
273 * This function disables/stops the counter, sets the new event type,
274 * enables/disables interrupt generation and then re-enables the
275 * counter if it was enabled before.
276 *
277 * Please refer the device's Technical Reference Manual for a list of
278 * supported event types and their corresponding event numbers.
279 *
280 * @param(counterId) Event counter Id
281 * @param(eventNum) Event number
282 * @param(interruptEnable) Enable/Disable Interrupt generation
283 */
284 Void configureCounter(UInt counterId, UInt eventNum, Bool interruptEnable);
285
286 /*!
287 * ======== enableInterrupt ========
288 * Enable interrupt generation on a counter overflow
289 *
290 * @param(counterId) Event counter Id
291 */
292 Void enableInterrupt(UInt counterId);
293
294 /*!
295 * ======== disableInterrupt ========
296 * Disable interrupt generation on a counter overflow
297 *
298 * @param(counterId) Event counter Id
299 */
300 Void disableInterrupt(UInt counterId);
301
302 /*!
303 * ======== clearOverflowStatus ========
304 * Clear overflow status flag
305 *
306 * @param(counterId) Event counter Id
307 */
308 Void clearOverflowStatus(UInt counterId);
309
310 /*!
311 * ======== getCount ========
312 * Read the event count
313 *
314 * @param(counterId) Event counter Id
315 * @b(returns) Event count
316 */
317 UInt32 getCount(UInt counterId);
318
319 /*!
320 * ======== getNumCounters ========
321 * Reads and returns the number of event counters
322 * implemented in HW.
323 */
324 UInt getNumCounters();
325
326 /*!
327 * ======== getOverflowStatus ========
328 * Returns a boolean indicating status of overflow flag
329 *
330 * @param(counterId) Event counter Id
331 * @b(returns) Overflow status
332 */
333 Bool getOverflowStatus(UInt counterId);
334
335 /*!
336 * @_nodoc
337 * ======== getEnabled ========
338 * Get the bit mask of counter enable.
339 */
340 UInt32 getEnabled();
341
342 /*!
343 * @_nodoc
344 * ======== startCounterI ========
345 * Internal inline asm implementation.
346 */
347 Void startCounterI(UInt counterId);
348
349 /*!
350 * @_nodoc
351 * ======== stopCounterI ========
352 * Internal inline asm implementation.
353 */
354 Void stopCounterI(UInt counterId);
355
356 /*!
357 * @_nodoc
358 * ======== resetCountI ========
359 * Internal inline asm implementation.
360 */
361 Void resetCountI(UInt counterId);
362
363 /*!
364 * @_nodoc
365 * ======== setCountI ========
366 * Internal inline asm implementation.
367 */
368 Void setCountI(UInt counterId, UInt32 counterVal);
369
370 /*!
371 * @_nodoc
372 * ======== enableInterrupt ========
373 * Internal inline asm implementation.
374 */
375 Void enableInterruptI(UInt counterId);
376
377 /*!
378 * @_nodoc
379 * ======== disableInterrupt ========
380 * Internal inline asm implementation.
381 */
382 Void disableInterruptI(UInt counterId);
383
384 /*!
385 * @_nodoc
386 * ======== clearOverflowStatusI ========
387 * Internal inline asm implementation.
388 */
389 Void clearOverflowStatusI(UInt counterId);
390
391 /*!
392 * @_nodoc
393 * ======== getCountI ========
394 * Internal inline asm implementation.
395 */
396 UInt32 getCountI(UInt counterId);
397
398 /*!
399 * @_nodoc
400 * ======== getOverflowStatus ========
401 * Internal inline asm implementation.
402 */
403 UInt32 getOverflowStatusI(UInt counterId);
404
405 internal:
406
407 408 409 410
411 Void configureCounterI(UInt counterId, UInt eventNum);
412
413 414 415 416
417 Void clearOverflowStatusReg(UInt32 clearMask);
418
419 420 421 422
423 UInt32 getOverflowStatusReg();
424
425 426 427 428 429 430 431
432 Void initCounters(UInt32 counterMask);
433
434 435 436 437
438 Void interruptHandler(UArg arg);
439
440 struct Module_State {
441 UInt numCounters; 442
443 Hwi.Handle hwiHandle;
444 IntHandlerFuncPtr interruptFunc;
445 }
446 }