]> granicus.if.org Git - esp-idf/blob - components/esp32/freertos_hooks.c
Merge branch 'feature/esp-wrover-kit-v4_1' into 'master'
[esp-idf] / components / esp32 / freertos_hooks.c
1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16 #include <stdint.h>
17 #include <stdlib.h>
18 #include <stdbool.h>
19 #include "freertos/FreeRTOS.h"
20 #include "esp_attr.h"
21 #include "esp_freertos_hooks.h"
22
23 #include "sdkconfig.h"
24 #include "esp_pm.h"
25 #include "pm_impl.h"
26
27 //We use just a static array here because it's not expected many components will need
28 //an idle or tick hook.
29 #define MAX_HOOKS 8
30
31 static portMUX_TYPE hooks_spinlock = portMUX_INITIALIZER_UNLOCKED;
32 static esp_freertos_idle_cb_t idle_cb[portNUM_PROCESSORS][MAX_HOOKS]={0};
33 static esp_freertos_tick_cb_t tick_cb[portNUM_PROCESSORS][MAX_HOOKS]={0};
34
35 void IRAM_ATTR esp_vApplicationTickHook() 
36 {
37     int n;
38     int core = xPortGetCoreID();
39     for (n=0; n<MAX_HOOKS; n++) {
40         if (tick_cb[core][n]!=NULL) {
41             tick_cb[core][n]();
42         }
43     }
44 }
45
46 void esp_vApplicationIdleHook() 
47 {
48     bool can_go_idle=true;
49     int core = xPortGetCoreID();
50     for (int n = 0; n < MAX_HOOKS; n++) {
51         if (idle_cb[core][n] != NULL && !idle_cb[core][n]()) {
52             can_go_idle = false;
53         }
54     }
55     if (!can_go_idle) {
56         return;
57     }
58
59 #ifdef CONFIG_PM_ENABLE
60     esp_pm_impl_idle_hook();
61 #endif
62 }
63
64 extern void esp_vApplicationWaitiHook( void )
65 {
66     asm("waiti 0");
67 }
68
69 esp_err_t esp_register_freertos_idle_hook_for_cpu(esp_freertos_idle_cb_t new_idle_cb, UBaseType_t cpuid)
70 {
71     if(cpuid >= portNUM_PROCESSORS){
72         return ESP_ERR_INVALID_ARG;
73     }
74     portENTER_CRITICAL(&hooks_spinlock);
75     for(int n = 0; n < MAX_HOOKS; n++){
76         if (idle_cb[cpuid][n]==NULL) {
77             idle_cb[cpuid][n]=new_idle_cb;
78             portEXIT_CRITICAL(&hooks_spinlock);
79             return ESP_OK;
80         }
81     }
82     portEXIT_CRITICAL(&hooks_spinlock);
83     return ESP_ERR_NO_MEM;
84 }
85
86 esp_err_t esp_register_freertos_idle_hook(esp_freertos_idle_cb_t new_idle_cb)
87 {
88     return esp_register_freertos_idle_hook_for_cpu(new_idle_cb, xPortGetCoreID());
89 }
90
91 esp_err_t esp_register_freertos_tick_hook_for_cpu(esp_freertos_tick_cb_t new_tick_cb, UBaseType_t cpuid)
92 {
93     if(cpuid >= portNUM_PROCESSORS){
94         return ESP_ERR_INVALID_ARG;
95     }
96     portENTER_CRITICAL(&hooks_spinlock);
97     for(int n = 0; n < MAX_HOOKS; n++){
98         if (tick_cb[cpuid][n]==NULL) {
99             tick_cb[cpuid][n]=new_tick_cb;
100             portEXIT_CRITICAL(&hooks_spinlock);
101             return ESP_OK;
102         }
103     }
104     portEXIT_CRITICAL(&hooks_spinlock);
105     return ESP_ERR_NO_MEM;
106 }
107
108 esp_err_t esp_register_freertos_tick_hook(esp_freertos_tick_cb_t new_tick_cb) 
109 {
110     return esp_register_freertos_tick_hook_for_cpu(new_tick_cb, xPortGetCoreID());
111 }
112
113 void esp_deregister_freertos_idle_hook_for_cpu(esp_freertos_idle_cb_t old_idle_cb, UBaseType_t cpuid)
114 {
115     portENTER_CRITICAL(&hooks_spinlock);
116     if(cpuid >= portNUM_PROCESSORS){
117         return;
118     }
119     for(int n = 0; n < MAX_HOOKS; n++){
120         if(idle_cb[cpuid][n] == old_idle_cb) idle_cb[cpuid][n] = NULL;
121     }
122     portEXIT_CRITICAL(&hooks_spinlock);
123 }
124
125 void esp_deregister_freertos_idle_hook(esp_freertos_idle_cb_t old_idle_cb)
126 {
127     portENTER_CRITICAL(&hooks_spinlock);
128     for(int m = 0; m < portNUM_PROCESSORS; m++) {
129         esp_deregister_freertos_idle_hook_for_cpu(old_idle_cb, m);
130     }
131     portEXIT_CRITICAL(&hooks_spinlock);
132 }
133
134 void esp_deregister_freertos_tick_hook_for_cpu(esp_freertos_tick_cb_t old_tick_cb, UBaseType_t cpuid)
135 {
136     portENTER_CRITICAL(&hooks_spinlock);
137     if(cpuid >= portNUM_PROCESSORS){
138         return;
139     }
140     for(int n = 0; n < MAX_HOOKS; n++){
141         if(tick_cb[cpuid][n] == old_tick_cb) tick_cb[cpuid][n] = NULL;
142     }
143     portEXIT_CRITICAL(&hooks_spinlock);
144 }
145
146 void esp_deregister_freertos_tick_hook(esp_freertos_tick_cb_t old_tick_cb)
147 {
148     portENTER_CRITICAL(&hooks_spinlock);
149     for(int m = 0; m < portNUM_PROCESSORS; m++){
150         esp_deregister_freertos_tick_hook_for_cpu(old_tick_cb, m);
151     }
152     portEXIT_CRITICAL(&hooks_spinlock);
153 }
154