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>
pull/8170/head
Damien George 2022-01-13 15:16:16 +11:00
rodzic 8957386250
commit e754c2e84f
3 zmienionych plików z 35 dodań i 4 usunięć

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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