espShow() время от времени дает сбой в Adafruit NeoPixel/Adafruit_NeoPixel 2.cpp на ESP32.
Я столкнулся со сбоем в файле Adafruit NeoPixel/Adafruit_NeoPixel 2.cpp
библиотеки.
Согласно стеку, проблема возникает в строке 129 файла Adafruit NeoPixel/esp 2.c в espShow()
, что соответствует настройке члена tx_config
в rmt_config` (см. исходный код ниже).
[ОБНОВЛЕНИЕ] Иногда `abort() происходит со строки 165, иначе:
164 // Инициализировать автоматический транслятор времени
165 rmt_translator_init(config.channel, ws2812_rmt_adapter);
Как мне решить эту проблему?
1 // Реализует периферийное устройство RMT на SoC Espressif
2 // Copyright (c) 2020 Lucian Copeland for Adafruit Industries
3
4 /* Uses code from Espressif RGB LED Strip demo and drivers
5 * Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #if defined(ESP32)
21
22 #include <Arduino.h>
23 #include "driver/rmt.h"
24
25 #if defined(ESP_IDF_VERSION)
26 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
27 #define HAS_ESP_IDF_4
28 #endif
29 #endif
30
31 // Этот код адаптирован из ESP-IDF v3.4 RMT "led_strip" пример, измененный
32 // для работы с версией ESP-IDF для Arduino (3.2)
33
34 #define WS2812_T0H_NS (400)
35 #define WS2812_T0L_NS (850)
36 #define WS2812_T1H_NS (800)
37 #define WS2812_T1L_NS (450)
38
39 #define WS2811_T0H_NS (500)
40 #define WS2811_T0L_NS (2000)
41 #define WS2811_T1H_NS (1200)
42 #define WS2811_T1L_NS (1300)
43
44 static uint32_t t0h_ticks = 0;
45 static uint32_t t1h_ticks = 0;
46 static uint32_t t0l_ticks = 0;
47 static uint32_t t1l_ticks = 0;
48
49 // Ограничить количество каналов RMT, доступных для Neopixels. По умолчанию для всех
50 // каналов (8 на ESP32, 4 на ESP32-S2 и S3). Переопределение этого значения освободит
51 // любые каналы с более высоким номером для других целей, таких как отправка и получение ИК
52 // библиотеки. Переопределите как 1, чтобы ограничить Neopixels только одним каналом.
53 #define ADAFRUIT_RMT_CHANNEL_MAX RMT_CHANNEL_MAX
54
55 #define RMT_LL_HW_BASE (&RMT)
56
57 bool rmt_reserved_channels[ADAFRUIT_RMT_CHANNEL_MAX];
58
59 static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
60 size_t wanted_num, size_t *translated_size, size_t *item_num)
61 {
62 if (src == NULL || dest == NULL) {
63 *translated_size = 0;
64 *item_num = 0;
65 return;
66 }
67 const rmt_item32_t bit0 = {{{ t0h_ticks, 1, t0l_ticks, 0 }}}; // Логический 0
68 const rmt_item32_t bit1 = {{{ t1h_ticks, 1, t1l_ticks, 0 }}}; // Логический 1
69 size_t size = 0;
70 size_t num = 0;
71 uint8_t *psrc = (uint8_t *)src;
72 rmt_item32_t *pdest = dest;
73 while (size < src_size && num < wanted_num) {
74 for (int i = 0; i < 8; i++) {
75 // сначала старший бит
76 if (*psrc & (1 << (7 - i))) {
77 pdest->val = bit1.val;
78 } else {
79 pdest->val = bit0.val;
80 }
81 num++;
82 pdest++;
83 }
84 size++;
85 psrc++;
86 }
87 *translated_size = size;
88 *item_num = num;
89 }
90
91 void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
92 // Резервный канал
93 rmt_channel_t channel = ADAFRUIT_RMT_CHANNEL_MAX;
94 for (size_t i = 0; i < ADAFRUIT_RMT_CHANNEL_MAX; i++) {
95 if (!rmt_reserved_channels[i]) {
96 rmt_reserved_channels[i] = true;
97 channel = i;
98 break;
99 }
100 }
101 if (channel == ADAFRUIT_RMT_CHANNEL_MAX) {
102 // Закончились каналы!
103 return;
104 }
105
106 #if defined(HAS_ESP_IDF_4)
107 rmt_config_t config = RMT_DEFAULT_CONFIG_TX(pin, channel);
108 config.clk_div = 2;
109 #else
110 // Соответствует конфигурации TX по умолчанию из ESP-IDF версии 3.4
111 rmt_config_t config = {
112 .rmt_mode = RMT_MODE_TX,
113 .channel = channel,
114 .gpio_num = pin,
115 .clk_div = 2,
116 .mem_block_num = 1,
117 .tx_config = {
118 .carrier_freq_hz = 38000,
119 .carrier_level = RMT_CARRIER_LEVEL_HIGH,
120 .idle_level = RMT_IDLE_LEVEL_LOW,
121 .carrier_duty_percent = 33,
122 .carrier_en = false,
123 .loop_en = false,
124 .idle_output_en = true,
125 }
126 };
127 #endif
128 rmt_config(&config);
129 rmt_driver_install(config.channel, 0, 0);
130
131 // Преобразование таймингов NS в тики
132 uint32_t counter_clk_hz = 0;
133
134 #if defined(HAS_ESP_IDF_4)
135 rmt_get_counter_clock(channel, &counter_clk_hz);
136 #else
137 // это эмулирует функцию rmt_get_counter_clock() из ESP-IDF 3.4
138 if (RMT_LL_HW_BASE->conf_ch[config.channel].conf1.ref_always_on == RMT_BASECLK_REF) {
139 uint32_t div_cnt = RMT_LL_HW_BASE->conf_ch[config.channel].conf0.div_cnt;
140 uint32_t div = div_cnt == 0 ? 256 : div_cnt;
141 counter_clk_hz = REF_CLK_FREQ / (div);
142 } else {
143 uint32_t div_cnt = RMT_LL_HW_BASE->conf_ch[config.channel].conf0.div_cnt;
144 uint32_t div = div_cnt == 0 ? 256 : div_cnt;
145 counter_clk_hz = APB_CLK_FREQ / (div);
146 }
147 #endif
148
149 // Конвертер NS в тики
150 float ratio = (float)counter_clk_hz / 1e9;
151
152 if (is800KHz) {
153 t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
154 t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
155 t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
156 t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
157 } else {
158 t0h_ticks = (uint32_t)(ratio * WS2811_T0H_NS);
159 t0l_ticks = (uint32_t)(ratio * WS2811_T0L_NS);
160 t1h_ticks = (uint32_t)(ratio * WS2811_T1H_NS);
161 t1l_ticks = (uint32_t)(ratio * WS2811_T1L_NS);
162 }
163
164 // Инициализировать автоматический преобразователь времени
165 rmt_translator_init(config.channel, ws2812_rmt_adapter);
166
167 // Запись и ожидание завершения
168 rmt_write_sample(config.channel, pixels, (size_t)numBytes, true);
169 rmt_wait_tx_done(config.channel, pdMS_TO_TICKS(100));
170
171 // Снова свободный канал
172 rmt_driver_uninstall(config.channel);
173 rmt_reserved_channels[channel] = false;
174
175 gpio_set_direction(pin, GPIO_MODE_OUTPUT);
176 }
177
178 #endif
Трассировка стека выглядит следующим образом:
/Users/stephanedeluca/.espressif/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-addr2line -pfiaC -e .pio/build/esp32dev/firmware.elf 0x40095618:0x3fff9ec0 0x40095891:0x3fff9ee0 0x40096cd6:0x3fff9f00 0x401e2d7d:0x3fff9f40 0x400dfa83:0x3fff9f70 0x400df96c:0x3fff9fd0 0x400dbdda:0x3fff9ff0 0x400dc0ce:0x3fffa040 0x400dcc3d:0x3fffa080 0x4009739e:0x3fffa0a0
0x40095618: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:156
0x40095891: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:171
0x40096cd6: xQueueGenericSend at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:719 (discriminator 1)
0x401e2d7d: rmt_driver_install at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/rmt.c:777
0x400dfa83: espShow at /Users/stephanedeluca/XXX/.pio/libdeps/esp32dev/Adafruit NeoPixel/esp 2.c:129
0x400df96c: Adafruit_NeoPixel::show() at /Users/stephanedeluca/XXX/.pio/libdeps/esp32dev/Adafruit NeoPixel/Adafruit_NeoPixel 2.cpp:2885
0x400dbdda: LedIndicator::showSocAndCurrent() at /Users/stephanedeluca/XXX/src/ledIndicator.cpp:648
0x400dc0ce: LedIndicator::loop() at /Users/stephanedeluca/XXX/src/ledIndicator.cpp:172 (discriminator 3)
0x400dcc3d: Module::_loop()::{lambda(void*)#1}::_FUN(void*) at /Users/stephanedeluca/XXX/src/module.cpp:256
(inlined by) _FUN at /Users/stephanedeluca/XXX/src/module.cpp:264
0x4009739e: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:143
0
Смотрите также:
- Контакты ESP32 не помещаются в беспаянную макетную плату
- После восстановления смещения BNO055 на датчике все значения калибровки равны 0.
- Использование кольца NeoPixel без Arduino
- Увеличить частоту дискретизации на плате ESP32
- Adafruit esp32 Feather не удалось скомпилировать
- ESP32 световые полосы, показывающие неправильные цвета
- Переключение между циклами Arduino ИК-пульт дистанционного управления
- Значения кватернионов из BNO055 недоступны.
Возможно, вам лучше поднять вопрос о github (я полагаю, что это где-то на github) с авторами библиотеки., @Majenko