summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-01-13 15:16:16 +1100
committerDamien George <damien@micropython.org>2022-01-14 15:41:59 +1100
commite754c2e84f1845313411a68c26821d613e66934e (patch)
treee2bb701c4e2b8b75d31cb37058bb51c9e7dc8197
parent895738625044b9fada0cf32aeee2f90bc0f52886 (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>
-rw-r--r--ports/esp32/esp32_rmt.c35
-rw-r--r--ports/esp32/machine_bitstream.c2
-rw-r--r--ports/esp32/modesp32.h2
3 files changed, 35 insertions, 4 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);
}
diff --git a/ports/esp32/machine_bitstream.c b/ports/esp32/machine_bitstream.c
index 4ba05e889..5f9eb32c3 100644
--- a/ports/esp32/machine_bitstream.c
+++ b/ports/esp32/machine_bitstream.c
@@ -101,7 +101,7 @@ void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const
// Install the driver on this channel & pin.
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));
// Get the tick rate in kHz (this will likely be 40000).
uint32_t counter_clk_khz = 0;
diff --git a/ports/esp32/modesp32.h b/ports/esp32/modesp32.h
index 86979f0b3..368b40db0 100644
--- a/ports/esp32/modesp32.h
+++ b/ports/esp32/modesp32.h
@@ -34,4 +34,6 @@ extern const mp_obj_type_t esp32_ulp_type;
// Reserve the last channel for machine.bitstream.
#define MICROPY_HW_ESP32_RMT_CHANNEL_BITSTREAM (RMT_CHANNEL_MAX - 1)
+esp_err_t rmt_driver_install_core1(uint8_t channel_id);
+
#endif // MICROPY_INCLUDED_ESP32_MODESP32_H