diff --git a/components/esp32/pm_trace.c b/components/esp32/pm_trace.c new file mode 100644 index 000000000..c1f240017 --- /dev/null +++ b/components/esp32/pm_trace.c @@ -0,0 +1,51 @@ +// Copyright 2016-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include "pm_trace.h" +#include "driver/gpio.h" +#include "soc/gpio_reg.h" + +/* GPIOs to use for tracing of esp_pm events. + * Two entries in the array for each type, one for each CPU. + * Feel free to change when debugging. + */ +static const int DRAM_ATTR s_trace_io[] = { + BIT(4), BIT(5), // ESP_PM_TRACE_IDLE + BIT(16), BIT(17), // ESP_PM_TRACE_TICK + BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH + BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE + BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK +}; + +void esp_pm_trace_init() +{ + for (size_t i = 0; i < sizeof(s_trace_io)/sizeof(s_trace_io[0]); ++i) { + int io = __builtin_ffs(s_trace_io[i]); + if (io == 0) { + continue; + } + gpio_set_direction(io - 1, GPIO_MODE_OUTPUT); + } +} + +void IRAM_ATTR esp_pm_trace_enter(esp_pm_trace_event_t event, int core_id) +{ + REG_WRITE(GPIO_OUT_W1TS_REG, s_trace_io[2 * event + core_id]); +} + +void IRAM_ATTR esp_pm_trace_exit(esp_pm_trace_event_t event, int core_id) +{ + REG_WRITE(GPIO_OUT_W1TC_REG, s_trace_io[2 * event + core_id]); +} diff --git a/components/esp32/pm_trace.h b/components/esp32/pm_trace.h new file mode 100644 index 000000000..1aff1ac80 --- /dev/null +++ b/components/esp32/pm_trace.h @@ -0,0 +1,44 @@ +// Copyright 2016-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "sdkconfig.h" + +typedef enum { + ESP_PM_TRACE_IDLE, + ESP_PM_TRACE_TICK, + ESP_PM_TRACE_FREQ_SWITCH, + ESP_PM_TRACE_CCOMPARE_UPDATE, + ESP_PM_TRACE_ISR_HOOK, + ESP_PM_TRACE_TYPE_MAX +} esp_pm_trace_event_t; + +void esp_pm_trace_init(); +void esp_pm_trace_enter(esp_pm_trace_event_t event, int core_id); +void esp_pm_trace_exit(esp_pm_trace_event_t event, int core_id); + +#ifdef CONFIG_PM_TRACE + +#define ESP_PM_TRACE_ENTER(event, core_id) \ + esp_pm_trace_enter(ESP_PM_TRACE_ ## event, core_id) +#define ESP_PM_TRACE_EXIT(event, core_id) \ + esp_pm_trace_exit(ESP_PM_TRACE_ ## event, core_id) + +#else // CONFIG_PM_TRACE + +#define ESP_PM_TRACE_ENTER(type, core_id) do { (void) core_id; } while(0); +#define ESP_PM_TRACE_EXIT(type, core_id) do { (void) core_id; } while(0); + +#endif // CONFIG_PM_TRACE diff --git a/components/freertos/portasm.S b/components/freertos/portasm.S index de4b0d558..f5b280fd8 100644 --- a/components/freertos/portasm.S +++ b/components/freertos/portasm.S @@ -24,6 +24,7 @@ */ #include "xtensa_rtos.h" +#include "sdkconfig.h" #define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */ #define CP_TOPOFSTACK_OFFS 0x04 /* xMPU_SETTINGS.coproc_area */ @@ -269,6 +270,12 @@ _frxt_timer_int: ENTRY(16) + #ifdef CONFIG_PM_TRACE + movi a6, 1 /* = ESP_PM_TRACE_TICK */ + getcoreid a7 + call4 esp_pm_trace_enter + #endif // CONFIG_PM_TRACE + .L_xt_timer_int_catchup: /* Update the timer comparator for the next tick. */ @@ -308,6 +315,12 @@ _frxt_timer_int: sub a4, a4, a3 /* diff = ccount - old comparator */ blt a2, a4, .L_xt_timer_int_catchup /* repeat while diff > divisor */ +#ifdef CONFIG_PM_TRACE + movi a6, 1 /* = ESP_PM_TRACE_TICK */ + getcoreid a7 + call4 esp_pm_trace_exit +#endif // CONFIG_PM_TRACE + RET(16) /* diff --git a/components/freertos/xtensa_vectors.S b/components/freertos/xtensa_vectors.S index 46750081e..b0238375a 100644 --- a/components/freertos/xtensa_vectors.S +++ b/components/freertos/xtensa_vectors.S @@ -175,7 +175,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. NOTE: For CALL0 ABI, a12-a15 have not yet been saved. - NOTE: This macro will use registers a0 and a2-a6. The arguments are: + NOTE: This macro will use registers a0 and a2-a7. The arguments are: level -- interrupt level mask -- interrupt bitmask for this level -------------------------------------------------------------------------------- @@ -183,6 +183,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .macro dispatch_c_isr level mask + #ifdef CONFIG_PM_TRACE + movi a6, 0 /* = ESP_PM_TRACE_IDLE */ + getcoreid a7 + call4 esp_pm_trace_exit + #endif // CONFIG_PM_TRACE + /* Get mask of pending, enabled interrupts at this level into a2. */ .L_xt_user_int_&level&: