qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

basic_profiling.h (4271B)


      1 // Copyright 2023 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 #pragma once
      4 
      5 /*
      6     This API allows for basic profiling information to be printed out over console.
      7 
      8     Usage example:
      9 
     10         #include "basic_profiling.h"
     11 
     12         // Original code:
     13         matrix_task();
     14 
     15         // Delete the original, replace with the following (variant 1, automatic naming):
     16         PROFILE_CALL(1000, matrix_task());
     17 
     18         // Delete the original, replace with the following (variant 2, explicit naming):
     19         PROFILE_CALL_NAMED(1000, "matrix_task", {
     20             matrix_task();
     21         });
     22 */
     23 
     24 #if defined(PROTOCOL_LUFA) || defined(PROTOCOL_VUSB)
     25 #    define TIMESTAMP_GETTER TCNT0
     26 #elif defined(PROTOCOL_CHIBIOS)
     27 #    define TIMESTAMP_GETTER chSysGetRealtimeCounterX()
     28 #else
     29 #    error Unknown protocol in use
     30 #endif
     31 
     32 #ifndef CONSOLE_ENABLE
     33 // Can't do anything if we don't have console output enabled.
     34 #    define PROFILE_CALL_NAMED(count, name, call) \
     35         do {                                      \
     36         } while (0)
     37 #else
     38 #    define PROFILE_CALL_NAMED(count, name, call)                                                                         \
     39         do {                                                                                                              \
     40             static uint64_t inner_sum = 0;                                                                                \
     41             static uint64_t outer_sum = 0;                                                                                \
     42             uint32_t        start_ts;                                                                                     \
     43             static uint32_t end_ts;                                                                                       \
     44             static uint32_t write_location = 0;                                                                           \
     45             start_ts                       = TIMESTAMP_GETTER;                                                            \
     46             if (write_location > 0) {                                                                                     \
     47                 outer_sum += start_ts - end_ts;                                                                           \
     48             }                                                                                                             \
     49             do {                                                                                                          \
     50                 call;                                                                                                     \
     51             } while (0);                                                                                                  \
     52             end_ts = TIMESTAMP_GETTER;                                                                                    \
     53             inner_sum += end_ts - start_ts;                                                                               \
     54             ++write_location;                                                                                             \
     55             if (write_location >= ((uint32_t)count)) {                                                                    \
     56                 uint32_t inner_avg = inner_sum / (((uint32_t)count) - 1);                                                 \
     57                 uint32_t outer_avg = outer_sum / (((uint32_t)count) - 1);                                                 \
     58                 dprintf("%s -- Percentage time spent: %d%%\n", (name), (int)(inner_avg * 100 / (inner_avg + outer_avg))); \
     59                 inner_sum      = 0;                                                                                       \
     60                 outer_sum      = 0;                                                                                       \
     61                 write_location = 0;                                                                                       \
     62             }                                                                                                             \
     63         } while (0)
     64 
     65 #endif // CONSOLE_ENABLE
     66 
     67 #define PROFILE_CALL(count, call) PROFILE_CALL_NAMED(count, #call, call)