Skip to content

Commit 9ef2085

Browse files
committed
esp32/machine.pwm: Add debugging messages.
1 parent 3bd45f6 commit 9ef2085

File tree

2 files changed

+73
-27
lines changed

2 files changed

+73
-27
lines changed

ports/esp32/machine_pwm.c

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
#include "driver/ledc.h"
3636
#include "esp_err.h"
3737

38-
#define DBG(...)
39-
// #define DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, "\n");
38+
#define DBG_LEVEL -1 // See py/mpprint.h
4039

4140
// Total number of channels
4241
#define PWM_CHANNEL_MAX (LEDC_SPEED_MODE_MAX * LEDC_CHANNEL_MAX)
@@ -74,26 +73,26 @@ STATIC ledc_timer_config_t timers[PWM_TIMER_MAX];
7473

7574
// 10-bit resolution (compatible with esp8266 PWM)
7675
#define PWRES (LEDC_TIMER_10_BIT)
77-
// maximum duty value on 10-bit resolution
76+
// Maximum duty value on 10-bit resolution
7877
#define MAX_DUTY_U10 ((1 << PWRES) - 1)
7978
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/ledc.html#supported-range-of-frequency-and-duty-resolutions
8079
// duty() uses 10-bit resolution or less
8180
// duty_u16() and duty_ns() use 16-bit resolution or less
8281

83-
// possible highest resolution in device
82+
// Possible highest resolution in device
8483
#if CONFIG_IDF_TARGET_ESP32
85-
#define HIGHEST_PWM_RES (LEDC_TIMER_16_BIT) // 20 in fact, but 16 is used
84+
#define HIGHEST_PWM_RES (LEDC_TIMER_16_BIT) // 20 bit in fact, but 16 bit is used
8685
#else
8786
#define HIGHEST_PWM_RES (LEDC_TIMER_14_BIT)
8887
#endif
89-
// duty resolution of user interface in `duty_u16()` and `duty_u16` parameter in constructor/initializer
88+
// Duty resolution of user interface in `duty_u16()` and `duty_u16` parameter in constructor/initializer
9089
#define UI_RES_16_BIT (16)
91-
// maximum duty value on highest resolution
90+
// Maximum duty value on highest user interface resolution
9291
#define UI_MAX_DUTY ((1 << UI_RES_16_BIT) - 1)
93-
// how much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT
92+
// How much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT
9493
#define UI_RES_SHIFT (16 - HIGHEST_PWM_RES) // 0 for ESP32, 2 for S2, S3, C3
9594

96-
// If the PWM frequency is less than EMPIRIC_FREQ, then LEDC_REF_CLK_HZ(1 MHz) is used, else LEDC_APB_CLK_HZ(80 MHz) is used
95+
// If the PWM frequency is less than EMPIRIC_FREQ, then LEDC_REF_CLK_HZ(1 MHz) source is used, else LEDC_APB_CLK_HZ(80 MHz) source is used
9796
#define EMPIRIC_FREQ (10) // Hz
9897

9998
// Config of timer upon which we run all PWM'ed GPIO pins
@@ -108,9 +107,9 @@ typedef struct _machine_pwm_obj_t {
108107
int channel;
109108
int timer;
110109
int duty_x; // PWRES if duty(), HIGHEST_PWM_RES if duty_u16(), -HIGHEST_PWM_RES if duty_ns()
111-
int duty_u10;
112-
int duty_u16;
113-
int duty_ns;
110+
int duty_u10; // stored values from previous duty setters
111+
int duty_u16; // - / -
112+
int duty_ns; // - / -
114113
} machine_pwm_obj_t;
115114

116115
STATIC void pwm_init(void) {
@@ -128,12 +127,12 @@ STATIC void pwm_init(void) {
128127
timers[i].freq_hz = -1;
129128
timers[i].speed_mode = TIMER_IDX_TO_MODE(i);
130129
timers[i].timer_num = TIMER_IDX_TO_TIMER(i);
131-
timers[i].clk_cfg = LEDC_AUTO_CLK;
130+
timers[i].clk_cfg = LEDC_AUTO_CLK; // will reinstall later according to the EMPIRIC_FREQ
132131
}
133132
}
134133

135134
STATIC void configure_channel(machine_pwm_obj_t *self) {
136-
DBG("configure_channel")
135+
DBG(5, "configure_channel")
137136
ledc_channel_config_t cfg = {
138137
.channel = self->channel,
139138
.duty = (1 << (timers[TIMER_IDX(self->mode, self->timer)].duty_resolution)) / 2,
@@ -155,7 +154,7 @@ STATIC void set_freq(unsigned int freq, ledc_timer_config_t *timer, machine_pwm_
155154
// Even if the timer frequency is already set,
156155
// the set_duty_x() is required to reconfigure the channel duty anyway
157156
if (freq != timer->freq_hz) {
158-
DBG("set_freq(%d)", freq)
157+
DBG(3, "set_freq(%d)", freq)
159158

160159
// Find the highest bit resolution for the requested frequency
161160
unsigned int i = LEDC_APB_CLK_HZ; // 80 MHz
@@ -201,10 +200,10 @@ STATIC void set_freq(unsigned int freq, ledc_timer_config_t *timer, machine_pwm_
201200

202201
// Set frequency
203202
esp_err_t err = ledc_timer_config(timer);
204-
DBG("ledc_timer_config")
203+
DBG(4, "ledc_timer_config")
205204
if (err != ESP_OK) {
206205
if (err == ESP_FAIL) {
207-
DBG(" (timer timer->speed_mode %d, timer->timer_num %d, timer->clk_cfg %d, timer->freq_hz %d, timer->duty_resolution %d) ", timer->speed_mode, timer->timer_num, timer->clk_cfg, timer->freq_hz, timer->duty_resolution);
206+
DBG(1, " (timer timer->speed_mode %d, timer->timer_num %d, timer->clk_cfg %d, timer->freq_hz %d, timer->duty_resolution %d) ", timer->speed_mode, timer->timer_num, timer->clk_cfg, timer->freq_hz, timer->duty_resolution);
208207
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unreachable frequency %d"), freq);
209208
} else {
210209
check_esp_err(err);
@@ -213,7 +212,7 @@ STATIC void set_freq(unsigned int freq, ledc_timer_config_t *timer, machine_pwm_
213212
// Reset the timer if low speed
214213
if (self->mode == LEDC_LOW_SPEED_MODE) {
215214
check_esp_err(ledc_timer_rst(self->mode, self->timer));
216-
DBG("ledc_timer_rst LEDC_LOW_SPEED_MODE")
215+
DBG(4, "ledc_timer_rst LEDC_LOW_SPEED_MODE")
217216
}
218217
}
219218

@@ -236,14 +235,14 @@ STATIC int ns_to_duty(machine_pwm_obj_t *self, int ns) {
236235
} else if (duty > UI_MAX_DUTY) {
237236
duty = UI_MAX_DUTY;
238237
}
239-
// DBG(" ns_to_duty(UI_MAX_DUTY=%d freq_hz=%d duty=%d=%f <- ns=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)ns * UI_MAX_DUTY * timer.freq_hz / 1000000000.0, ns);
238+
// DBG(3, " ns_to_duty(UI_MAX_DUTY=%d freq_hz=%d duty=%d=%f <- ns=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)ns * UI_MAX_DUTY * timer.freq_hz / 1000000000.0, ns);
240239
return duty;
241240
}
242241

243242
STATIC int duty_to_ns(machine_pwm_obj_t *self, int duty) {
244243
ledc_timer_config_t timer = timers[TIMER_IDX(self->mode, self->timer)];
245244
int64_t ns = ((int64_t)duty * 1000000000LL + (int64_t)timer.freq_hz * UI_MAX_DUTY / 2) / ((int64_t)timer.freq_hz * UI_MAX_DUTY);
246-
// DBG(" duty_to_ns(UI_MAX_DUTY=%d freq_hz=%d duty=%d -> ns=%f=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)duty * 1000000000.0 / ((float)timer.freq_hz * UI_MAX_DUTY), ns);
245+
// DBG(3, " duty_to_ns(UI_MAX_DUTY=%d freq_hz=%d duty=%d -> ns=%f=%d) ", UI_MAX_DUTY, timer.freq_hz, duty, (float)duty * 1000000000.0 / ((float)timer.freq_hz * UI_MAX_DUTY), ns);
247246
return ns;
248247
}
249248

@@ -262,7 +261,7 @@ STATIC uint32_t get_duty_ns(machine_pwm_obj_t *self) {
262261
}
263262

264263
STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
265-
DBG("set_duty_u16(%d)", duty)
264+
DBG(5, "set_duty_u16(%d)", duty)
266265
if ((duty < 0) || (duty > UI_MAX_DUTY)) {
267266
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty_u16 must be from 0 to %d"), UI_MAX_DUTY);
268267
}
@@ -283,7 +282,7 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
283282
if (duty != get_duty_u16(self)) {
284283
ets_delay_us(100);
285284
if (duty != get_duty_u16(self)) {
286-
DBG(" (set_duty_u16(%u) get_duty_u16()=%u duty_resolution=%d) ", duty, get_duty_u16(self), timers[TIMER_IDX(self->mode, self->timer)].duty_resolution);
285+
DBG(2, " (set_duty_u16(%u) get_duty_u16()=%u duty_resolution=%d) ", duty, get_duty_u16(self), timers[TIMER_IDX(self->mode, self->timer)].duty_resolution);
287286
}
288287
}
289288
*/
@@ -293,7 +292,7 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
293292
}
294293

295294
STATIC void set_duty_u10(machine_pwm_obj_t *self, int duty) {
296-
DBG("set_duty(%d)", duty)
295+
DBG(5, "set_duty(%d)", duty)
297296
if ((duty < 0) || (duty > MAX_DUTY_U10)) {
298297
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty must be from 0 to %u"), MAX_DUTY_U10);
299298
}
@@ -303,7 +302,7 @@ STATIC void set_duty_u10(machine_pwm_obj_t *self, int duty) {
303302
}
304303

305304
STATIC void set_duty_ns(machine_pwm_obj_t *self, int ns) {
306-
DBG("set_duty_ns(%d)", ns)
305+
DBG(5, "set_duty_ns(%d)", ns)
307306
if ((ns < 0) || (ns > duty_to_ns(self, UI_MAX_DUTY))) {
308307
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty_ns must be from 0 to %d ns"), duty_to_ns(self, UI_MAX_DUTY));
309308
}
@@ -394,9 +393,10 @@ STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_p
394393
mp_printf(print, ")");
395394
}
396395

396+
// This called from pwm.init() method
397397
STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
398398
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
399-
DBG("mp_machine_pwm_init_helper")
399+
DBG(5, "mp_machine_pwm_init_helper")
400400
enum { ARG_freq, ARG_duty, ARG_duty_u16, ARG_duty_ns };
401401
static const mp_arg_t allowed_args[] = {
402402
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
@@ -494,9 +494,10 @@ STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
494494
}
495495
}
496496

497+
// This called from PWM() constructor
497498
STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type,
498499
size_t n_args, size_t n_kw, const mp_obj_t *args) {
499-
DBG("mp_machine_pwm_make_new")
500+
DBG(5, "mp_machine_pwm_make_new")
500501
mp_arg_check_num(n_args, n_kw, 1, 2, true);
501502
gpio_num_t pin_id = machine_pin_get_id(args[0]);
502503

@@ -524,6 +525,7 @@ STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type,
524525
return MP_OBJ_FROM_PTR(self);
525526
}
526527

528+
// Deinit channel and timer if the timer is unused
527529
STATIC void pwm_deinit(int channel_idx) {
528530
// Valid channel?
529531
if ((channel_idx >= 0) && (channel_idx < PWM_CHANNEL_MAX)) {
@@ -562,6 +564,7 @@ STATIC void pwm_deinit(int channel_idx) {
562564
}
563565
}
564566

567+
// This called from pwm.deinit() method
565568
STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
566569
int channel_idx = CHANNEL_IDX(self->mode, self->channel);
567570
pwm_deinit(channel_idx);
@@ -572,6 +575,7 @@ STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
572575
self->duty_x = 0;
573576
}
574577

578+
// This called from Ctrl-D soft reboot
575579
void machine_pwms_deinit(void) {
576580
if (pwm_inited) {
577581
for (int channel_idx = 0; channel_idx < PWM_CHANNEL_MAX; ++channel_idx) {
@@ -581,6 +585,8 @@ void machine_pwms_deinit(void) {
581585
}
582586
}
583587

588+
// Set's and get's methods of PWM class
589+
584590
STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
585591
return MP_OBJ_NEW_SMALL_INT(ledc_get_freq(self->mode, self->timer));
586592
}
@@ -620,7 +626,7 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
620626
if (!current_in_use) {
621627
// Free the old timer
622628
check_esp_err(ledc_timer_rst(self->mode, self->timer));
623-
DBG("ledc_timer_rst(%d, %d) Free", self->mode, self->timer)
629+
DBG(4, "ledc_timer_rst(%d, %d) Free", self->mode, self->timer)
624630
// Flag it unused
625631
timers[current_timer_idx].freq_hz = -1;
626632
}

py/mpprint.h

100644100755
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,44 @@ int mp_printf(const mp_print_t *print, const char *fmt, ...);
7979
int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args);
8080
#endif
8181

82+
// Debug messages during code developing.
83+
// An approximate hierarchy of debug levels is:
84+
// -1 - SUPPRES all messages in release version
85+
// 0 - the most CRITICAL errors, often requiring a system reset, use message with this level if possible raising an exception
86+
// 1 - ERROR requiring program restart, use message with this level before raising an exception
87+
// 2 - WARNING, something went wrong, but you can fix it with additional operations in code right now
88+
// 3 - INFO, it is interesting and useful for understanding a bug
89+
// 4 - DEBUG, more detaled info, dig deeper
90+
// 5 - TRACE, show algorithm flow
91+
// In real you may use own classification of debug levels.
92+
#define DBG(level, ...) \
93+
do { \
94+
if (level <= DBG_LEVEL) { \
95+
mp_printf(MP_PYTHON_PRINTER, "%d:: ", level); \
96+
mp_printf(MP_PYTHON_PRINTER, __VA_ARGS__); \
97+
mp_printf(MP_PYTHON_PRINTER, "\n"); \
98+
} \
99+
} while(0);
100+
/*
101+
// How to use:
102+
// Set DBG_LEVEL in developed *.C or *.CPP file
103+
#define DBG_LEVEL 1000 // show all messages
104+
// Add DBG() macro in code, like
105+
void foo() {
106+
DBG(5, "Enter foo()")
107+
...
108+
int value;
109+
...
110+
// calculate value
111+
DBG(3, "See a value=%d", value)
112+
...
113+
DBG(5, "Exit foo()")
114+
}
115+
// See usage in ports/esp32/machine_pwm.c
116+
// It is not a dogma. You may start debugging from level 3.
117+
#define DBG_LEVEL 3
118+
// Then add DBG(3, ...) and when gets too much messages then change some messages to the next level DBG(4, ...), or DBG(2, ...)
119+
// Then you may change DBG_LEVEL to 2, and finally to -1.
120+
*/
121+
82122
#endif // MICROPY_INCLUDED_PY_MPPRINT_H

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy