2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include <ao_sample_profile.h>
23 #ifndef AO_SAMPLE_PROFILE_LOW_PC
24 #define AO_SAMPLE_PROFILE_LOW_PC 0x08002000
27 #ifndef AO_SAMPLE_PROFILE_HIGH_PC
28 #define AO_SAMPLE_PROFILE_HIGH_PC 0x0800f000
31 #ifndef AO_SAMPLE_PROFILE_SHIFT
32 #define AO_SAMPLE_PROFILE_SHIFT 6
35 #define AO_SAMPLE_PROFILE_RANGE (AO_SAMPLE_PROFILE_HIGH_PC - AO_SAMPLE_PROFILE_LOW_PC)
36 #define AO_SAMPLE_PROFILE_NUM (AO_SAMPLE_PROFILE_RANGE >> AO_SAMPLE_PROFILE_SHIFT)
38 static uint16_t prev_tick;
39 static uint16_t samples[AO_SAMPLE_PROFILE_NUM];
40 static uint8_t missed[AO_SAMPLE_PROFILE_NUM/8];
41 static uint16_t max_miss;
42 static uint32_t task, isr, os, idle;
44 extern uint8_t ao_idle_loc;
47 ao_sample_profile_point(uint32_t pc, uint16_t tick, uint8_t in_isr)
49 uint16_t delta = tick - prev_tick;
51 if (pc < AO_SAMPLE_PROFILE_LOW_PC)
53 if (pc >= AO_SAMPLE_PROFILE_HIGH_PC)
59 asm("mov %0,sp" : "=&r" (sp));
60 sp_delta = sp - (uint8_t *) ao_cur_task->stack;
61 if (-96 < sp_delta && sp_delta < 16)
62 ao_panic(AO_PANIC_STACK);
67 else if (ao_cur_task) {
68 ao_cur_task->ticks += delta;
70 } else if (pc == (uint32_t) &ao_idle_loc)
75 pc -= AO_SAMPLE_PROFILE_LOW_PC;
76 pc >>= AO_SAMPLE_PROFILE_SHIFT;
80 missed[pc >> 3] |= (1 << (pc & 7));
87 ao_sample_profile_start(void)
89 prev_tick = ao_sample_profile_timer_start();
93 ao_sample_profile_stop(void)
95 ao_sample_profile_timer_stop();
99 ao_sample_profile_dump(void)
104 printf ("task %6d\n", task);
105 printf ("isr %6d\n", isr);
106 printf ("os %6d\n", os);
107 printf ("idle %6d\n", idle);
108 printf ("irq blocked %d\n", max_miss);
109 for (t = 0; t < ao_num_tasks; t++)
110 printf ("task %6d %6d %6d %s\n",
113 ao_tasks[t]->max_run,
115 for (a = 0; a < AO_SAMPLE_PROFILE_NUM; a++) {
117 printf ("%04x %c %u\n",
118 (a << AO_SAMPLE_PROFILE_SHIFT) + AO_SAMPLE_PROFILE_LOW_PC,
119 missed[a >> 3] & (1 << (a & 7)) ? '*' : ' ',
125 ao_sample_profile_clear(void)
129 task = isr = os = idle = 0;
131 memset(samples, '\0', sizeof (samples));
132 memset(missed, '\0', sizeof (missed));
133 for (t = 0; t < ao_num_tasks; t++) {
134 ao_tasks[t]->ticks = 0;
135 ao_tasks[t]->yields = 0;
136 ao_tasks[t]->max_run = 0;
141 ao_sample_profile_cmd(void)
144 switch (ao_cmd_lex_c) {
146 ao_sample_profile_start();
149 ao_sample_profile_stop();
152 ao_sample_profile_dump();
155 ao_sample_profile_clear();
158 ao_cmd_status = ao_cmd_syntax_error;
163 static const struct ao_cmds ao_sample_profile_cmds[] = {
164 { ao_sample_profile_cmd, "S <1 start,0 stop, d dump,c clear>\0Sample profile" },
169 ao_sample_profile_init(void)
171 ao_sample_profile_timer_init();
172 ao_cmd_register(&ao_sample_profile_cmds[0]);
173 ao_sample_profile_clear();