Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.3 KiB

  1. /*
  2. Show extended heap stats when EspClass::getHeapStats() is available
  3. */
  4. #pragma once
  5. #include "TypeChecks.h"
  6. struct heap_stats_t {
  7. uint32_t available;
  8. uint16_t usable;
  9. uint8_t frag_pct;
  10. };
  11. namespace heap_stats {
  12. template <typename T>
  13. using has_getHeapStats_t = decltype(std::declval<T>().getHeapStats(0,0,0));
  14. template <typename T>
  15. using has_getHeapStats = is_detected<has_getHeapStats_t, T>;
  16. }
  17. template <typename T>
  18. void _getHeapStats(const std::true_type&, T& instance, heap_stats_t& stats) {
  19. instance.getHeapStats(&stats.available, &stats.usable, &stats.frag_pct);
  20. }
  21. template <typename T>
  22. void _getHeapStats(const std::false_type&, T& instance, heap_stats_t& stats) {
  23. stats.available = instance.getFreeHeap();
  24. stats.usable = 0;
  25. stats.frag_pct = 0;
  26. }
  27. void getHeapStats(heap_stats_t& stats) {
  28. _getHeapStats(heap_stats::has_getHeapStats<decltype(ESP)>{}, ESP, stats);
  29. }
  30. // WTF
  31. // Calling ESP.getFreeHeap() is making the system crash on a specific
  32. // AiLight bulb, but anywhere else it should work as expected
  33. static bool _heap_value_wtf = false;
  34. heap_stats_t getHeapStats() {
  35. heap_stats_t stats;
  36. if (_heap_value_wtf) {
  37. stats.available = 9999;
  38. stats.usable = 9999;
  39. stats.frag_pct = 0;
  40. return stats;
  41. }
  42. getHeapStats(stats);
  43. return stats;
  44. }
  45. void wtfHeap(bool value) {
  46. _heap_value_wtf = value;
  47. }
  48. unsigned int getFreeHeap() {
  49. return ESP.getFreeHeap();
  50. }
  51. static unsigned int _initial_heap_value = 0;
  52. void setInitialFreeHeap() {
  53. _initial_heap_value = getFreeHeap();
  54. }
  55. unsigned int getInitialFreeHeap() {
  56. if (0 == _initial_heap_value) {
  57. setInitialFreeHeap();
  58. }
  59. return _initial_heap_value;
  60. }
  61. void infoMemory(const char* name, const heap_stats_t& stats) {
  62. infoMemory(name, getInitialFreeHeap(), stats.available);
  63. }
  64. void infoHeapStats(const char* name, const heap_stats_t& stats) {
  65. DEBUG_MSG_P(
  66. PSTR("[MAIN] %-6s: %5u contiguous bytes available (%u%% fragmentation)\n"),
  67. name,
  68. stats.usable,
  69. stats.frag_pct
  70. );
  71. }
  72. void infoHeapStats(bool show_frag_stats = true) {
  73. const auto stats = getHeapStats();
  74. infoMemory("Heap", stats);
  75. if (show_frag_stats && heap_stats::has_getHeapStats<decltype(ESP)>{}) {
  76. infoHeapStats("Heap", stats);
  77. }
  78. }