freertos_hooks.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdint.h>
  7. #include <stdlib.h>
  8. #include <stdbool.h>
  9. #include "freertos/FreeRTOS.h"
  10. #include "esp_attr.h"
  11. #include "esp_freertos_hooks.h"
  12. #include "sdkconfig.h"
  13. #if CONFIG_PM_ENABLE
  14. #include "esp_pm.h"
  15. #include "esp_private/pm_impl.h"
  16. #endif
  17. //We use just a static array here because it's not expected many components will need
  18. //an idle or tick hook.
  19. #define MAX_HOOKS 8
  20. static portMUX_TYPE hooks_spinlock = portMUX_INITIALIZER_UNLOCKED;
  21. static esp_freertos_idle_cb_t idle_cb[portNUM_PROCESSORS][MAX_HOOKS]={0};
  22. static esp_freertos_tick_cb_t tick_cb[portNUM_PROCESSORS][MAX_HOOKS]={0};
  23. void IRAM_ATTR esp_vApplicationTickHook(void)
  24. {
  25. int n;
  26. int core = xPortGetCoreID();
  27. for (n=0; n<MAX_HOOKS; n++) {
  28. if (tick_cb[core][n]!=NULL) {
  29. tick_cb[core][n]();
  30. }
  31. }
  32. }
  33. void esp_vApplicationIdleHook(void)
  34. {
  35. bool can_go_idle=true;
  36. int core = xPortGetCoreID();
  37. for (int n = 0; n < MAX_HOOKS; n++) {
  38. if (idle_cb[core][n] != NULL && !idle_cb[core][n]()) {
  39. can_go_idle = false;
  40. }
  41. }
  42. if (!can_go_idle) {
  43. return;
  44. }
  45. #ifdef CONFIG_PM_ENABLE
  46. esp_pm_impl_idle_hook();
  47. esp_pm_impl_waiti();
  48. #else
  49. cpu_hal_waiti();
  50. #endif
  51. }
  52. esp_err_t esp_register_freertos_idle_hook_for_cpu(esp_freertos_idle_cb_t new_idle_cb, UBaseType_t cpuid)
  53. {
  54. if(cpuid >= portNUM_PROCESSORS){
  55. return ESP_ERR_INVALID_ARG;
  56. }
  57. portENTER_CRITICAL(&hooks_spinlock);
  58. for(int n = 0; n < MAX_HOOKS; n++){
  59. if (idle_cb[cpuid][n]==NULL) {
  60. idle_cb[cpuid][n]=new_idle_cb;
  61. portEXIT_CRITICAL(&hooks_spinlock);
  62. return ESP_OK;
  63. }
  64. }
  65. portEXIT_CRITICAL(&hooks_spinlock);
  66. return ESP_ERR_NO_MEM;
  67. }
  68. esp_err_t esp_register_freertos_idle_hook(esp_freertos_idle_cb_t new_idle_cb)
  69. {
  70. return esp_register_freertos_idle_hook_for_cpu(new_idle_cb, xPortGetCoreID());
  71. }
  72. esp_err_t esp_register_freertos_tick_hook_for_cpu(esp_freertos_tick_cb_t new_tick_cb, UBaseType_t cpuid)
  73. {
  74. if(cpuid >= portNUM_PROCESSORS){
  75. return ESP_ERR_INVALID_ARG;
  76. }
  77. portENTER_CRITICAL(&hooks_spinlock);
  78. for(int n = 0; n < MAX_HOOKS; n++){
  79. if (tick_cb[cpuid][n]==NULL) {
  80. tick_cb[cpuid][n]=new_tick_cb;
  81. portEXIT_CRITICAL(&hooks_spinlock);
  82. return ESP_OK;
  83. }
  84. }
  85. portEXIT_CRITICAL(&hooks_spinlock);
  86. return ESP_ERR_NO_MEM;
  87. }
  88. esp_err_t esp_register_freertos_tick_hook(esp_freertos_tick_cb_t new_tick_cb)
  89. {
  90. return esp_register_freertos_tick_hook_for_cpu(new_tick_cb, xPortGetCoreID());
  91. }
  92. void esp_deregister_freertos_idle_hook_for_cpu(esp_freertos_idle_cb_t old_idle_cb, UBaseType_t cpuid)
  93. {
  94. if(cpuid >= portNUM_PROCESSORS){
  95. return;
  96. }
  97. portENTER_CRITICAL(&hooks_spinlock);
  98. for(int n = 0; n < MAX_HOOKS; n++){
  99. if(idle_cb[cpuid][n] == old_idle_cb) idle_cb[cpuid][n] = NULL;
  100. }
  101. portEXIT_CRITICAL(&hooks_spinlock);
  102. }
  103. void esp_deregister_freertos_idle_hook(esp_freertos_idle_cb_t old_idle_cb)
  104. {
  105. portENTER_CRITICAL(&hooks_spinlock);
  106. for(int m = 0; m < portNUM_PROCESSORS; m++) {
  107. esp_deregister_freertos_idle_hook_for_cpu(old_idle_cb, m);
  108. }
  109. portEXIT_CRITICAL(&hooks_spinlock);
  110. }
  111. void esp_deregister_freertos_tick_hook_for_cpu(esp_freertos_tick_cb_t old_tick_cb, UBaseType_t cpuid)
  112. {
  113. if(cpuid >= portNUM_PROCESSORS){
  114. return;
  115. }
  116. portENTER_CRITICAL(&hooks_spinlock);
  117. for(int n = 0; n < MAX_HOOKS; n++){
  118. if(tick_cb[cpuid][n] == old_tick_cb) tick_cb[cpuid][n] = NULL;
  119. }
  120. portEXIT_CRITICAL(&hooks_spinlock);
  121. }
  122. void esp_deregister_freertos_tick_hook(esp_freertos_tick_cb_t old_tick_cb)
  123. {
  124. portENTER_CRITICAL(&hooks_spinlock);
  125. for(int m = 0; m < portNUM_PROCESSORS; m++){
  126. esp_deregister_freertos_tick_hook_for_cpu(old_tick_cb, m);
  127. }
  128. portEXIT_CRITICAL(&hooks_spinlock);
  129. }