Skip to content

Fix ledc panic’ed when wrong setup of frequency and bit width #6371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 24 additions & 10 deletions cores/esp32/esp32-hal-ledc.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ uint8_t channels_resolution[LEDC_CHANNELS] = {0};

double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
{
if(chan >= LEDC_CHANNELS){
log_e("No more LEDC channels available! You can have maximum %u", LEDC_CHANNELS);
if(chan >= LEDC_CHANNELS || bit_num > LEDC_MAX_BIT_WIDTH){
log_e("No more LEDC channels available! (maximum %u) or bit width too big (maximum %u)", LEDC_CHANNELS, LEDC_MAX_BIT_WIDTH);
return 0;
}

uint8_t group=(chan/8), timer=((chan/2)%4);

ledc_timer_config_t ledc_timer = {
Expand All @@ -69,9 +70,12 @@ double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
.freq_hz = freq,
.clk_cfg = LEDC_DEFAULT_CLK
};
ledc_timer_config(&ledc_timer);
if(ledc_timer_config(&ledc_timer) != ESP_OK)
{
log_e("ledc setup failed!");
return 0;
}
channels_resolution[chan] = bit_num;

return ledc_get_freq(group,timer);
}

Expand All @@ -95,7 +99,7 @@ void ledcWrite(uint8_t chan, uint32_t duty)

uint32_t ledcRead(uint8_t chan)
{
if(chan >= LEDC_CHANNELS){
if(chan >= LEDC_CHANNELS){
return 0;
}
uint8_t group=(chan/8), channel=(chan%8);
Expand Down Expand Up @@ -130,7 +134,12 @@ double ledcWriteTone(uint8_t chan, double freq)
.freq_hz = freq,
.clk_cfg = LEDC_DEFAULT_CLK
};
ledc_timer_config(&ledc_timer);

if(ledc_timer_config(&ledc_timer) != ESP_OK)
{
log_e("ledcSetup failed!");
return 0;
}
channels_resolution[chan] = 10;

double res_freq = ledc_get_freq(group,timer);
Expand All @@ -153,7 +162,7 @@ double ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){

void ledcAttachPin(uint8_t pin, uint8_t chan)
{
if(chan >= LEDC_CHANNELS){
if(chan >= LEDC_CHANNELS){
return;
}
uint8_t group=(chan/8), channel=(chan%8), timer=((chan/2)%4);
Expand All @@ -177,7 +186,8 @@ void ledcDetachPin(uint8_t pin)

double ledcChangeFrequency(uint8_t chan, double freq, uint8_t bit_num)
{
if(chan >= LEDC_CHANNELS){
if(chan >= LEDC_CHANNELS || bit_num > LEDC_MAX_BIT_WIDTH){
log_e("LEDC channel not available! (maximum %u) or bit width too big (maximum %u)", LEDC_CHANNELS, LEDC_MAX_BIT_WIDTH);
return 0;
}
uint8_t group=(chan/8), timer=((chan/2)%4);
Expand All @@ -189,9 +199,13 @@ double ledcChangeFrequency(uint8_t chan, double freq, uint8_t bit_num)
.freq_hz = freq,
.clk_cfg = LEDC_DEFAULT_CLK
};
ledc_timer_config(&ledc_timer);
channels_resolution[chan] = bit_num;

if(ledc_timer_config(&ledc_timer) != ESP_OK)
{
log_e("ledcChangeFrequency failed!");
return 0;
}
channels_resolution[chan] = bit_num;
return ledc_get_freq(group,timer);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
// use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_0 0

// use 13 bit precission for LEDC timer
#define LEDC_TIMER_13_BIT 13
// use 12 bit precission for LEDC timer
#define LEDC_TIMER_12_BIT 12

// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ 5000
Expand All @@ -28,16 +28,16 @@ int fadeAmount = 5; // how many points to fade the LED by
// Arduino like analogWrite
// value has to be between 0 and valueMax
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
// calculate duty, 8191 from 2 ^ 13 - 1
uint32_t duty = (8191 / valueMax) * min(value, valueMax);
// calculate duty, 4095 from 2 ^ 12 - 1
uint32_t duty = (4095 / valueMax) * min(value, valueMax);

// write duty to LEDC
ledcWrite(channel, duty);
}

void setup() {
// Setup timer and attach timer to a led pin
ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT);
ledcAttachPin(LED_PIN, LEDC_CHANNEL_0);
}

Expand Down