diff options
| author | Damien George <damien@micropython.org> | 2022-01-13 15:16:16 +1100 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2022-01-14 15:41:59 +1100 |
| commit | e754c2e84f1845313411a68c26821d613e66934e (patch) | |
| tree | e2bb701c4e2b8b75d31cb37058bb51c9e7dc8197 /ports/esp32/esp32_rmt.c | |
| parent | 895738625044b9fada0cf32aeee2f90bc0f52886 (diff) | |
esp32/esp32_rmt: Install RMT driver on core 1.
MicroPython currently runs on core 0 of the esp32. Calling
rmt_driver_install will mean that the RMT interrupt handler is also
serviced on core 0. This can lead to glitches in the RMT output if
WiFi is enabled (for esp32.RMT and machine.bitstream).
This patch calls rmt_driver_install on core 1, ensuring that the RMT
interrupt handler is serviced on core 1. This prevents glitches.
Fixes issue #8161.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'ports/esp32/esp32_rmt.c')
| -rw-r--r-- | ports/esp32/esp32_rmt.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c index 1a7e77b9d..941f20818 100644 --- a/ports/esp32/esp32_rmt.c +++ b/ports/esp32/esp32_rmt.c @@ -27,10 +27,11 @@ #include "py/runtime.h" #include "modmachine.h" #include "mphalport.h" -#include "driver/rmt.h" - #include "modesp32.h" +#include "esp_task.h" +#include "driver/rmt.h" + // This exposes the ESP32's RMT module to MicroPython. RMT is provided by the Espressif ESP-IDF: // // https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html @@ -59,6 +60,34 @@ typedef struct _esp32_rmt_obj_t { bool loop_en; } esp32_rmt_obj_t; +typedef struct _rmt_install_state_t { + SemaphoreHandle_t handle; + uint8_t channel_id; + esp_err_t ret; +} rmt_install_state_t; + +STATIC void rmt_install_task(void *pvParameter) { + rmt_install_state_t *state = pvParameter; + state->ret = rmt_driver_install(state->channel_id, 0, 0); + xSemaphoreGive(state->handle); + vTaskDelete(NULL); + for (;;) { + } +} + +// Call rmt_driver_install on core 1. This ensures that the RMT interrupt handler is +// serviced on core 1, so that WiFi (if active) does not interrupt it and cause glitches. +esp_err_t rmt_driver_install_core1(uint8_t channel_id) { + TaskHandle_t th; + rmt_install_state_t state; + state.handle = xSemaphoreCreateBinary(); + state.channel_id = channel_id; + xTaskCreatePinnedToCore(rmt_install_task, "rmt_install_task", 2048 / sizeof(StackType_t), &state, ESP_TASK_PRIO_MIN + 1, &th, 1); + xSemaphoreTake(state.handle, portMAX_DELAY); + vSemaphoreDelete(state.handle); + return state.ret; +} + STATIC mp_obj_t esp32_rmt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, @@ -125,7 +154,7 @@ STATIC mp_obj_t esp32_rmt_make_new(const mp_obj_type_t *type, size_t n_args, siz config.clk_div = self->clock_div; check_esp_err(rmt_config(&config)); - check_esp_err(rmt_driver_install(config.channel, 0, 0)); + check_esp_err(rmt_driver_install_core1(config.channel)); return MP_OBJ_FROM_PTR(self); } |
