Skip to content
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

ESP32 S3 MCPWM/PCNT Support #162

Merged
merged 4 commits into from
Mar 2, 2023
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ Comments to pin sharing:
* supports up to four stepper motors using Step/Direction/Enable Control (Direction and Enable is optional)
* Steppers' command queue depth: 32

### ESP32S3

* allows up to 200000 generated steps per second ?
* supports up to four stepper motors using Step/Direction/Enable Control (Direction and Enable is optional)
* Steppers' command queue depth: 32

### Atmel SAM Due

* allows up to 50000 generated steps per second
Expand Down Expand Up @@ -268,6 +274,10 @@ As of now, allocation of steppers on esp32 are: first all 6 mcpwm/pcnt drivers a

This stepper driver uses rmt module.

### ESP32S3

This stepper driver uses mcpwm/pcnt modules. Can drive up to 4 motors. Tested with 2 motors.

### ESP32C3/ESP32-MINI-1

Compatibility with ESP32-C3: Not supported currently. The rmt module has more changes compared to esp32/esp32s2
Expand Down
17 changes: 16 additions & 1 deletion src/StepperISR_esp32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void fas_init_engine(FastAccelStepperEngine *engine, uint8_t cpu_core) {
}

#if defined(SUPPORT_ESP32_PULSE_COUNTER)
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
uint32_t sig_idx[8] = {PCNT_SIG_CH0_IN0_IDX, PCNT_SIG_CH0_IN1_IDX,
PCNT_SIG_CH0_IN2_IDX, PCNT_SIG_CH0_IN3_IDX,
PCNT_SIG_CH0_IN4_IDX, PCNT_SIG_CH0_IN5_IDX,
Expand All @@ -145,7 +146,12 @@ uint32_t ctrl_idx[8] = {PCNT_CTRL_CH0_IN0_IDX, PCNT_CTRL_CH0_IN1_IDX,
PCNT_CTRL_CH0_IN2_IDX, PCNT_CTRL_CH0_IN3_IDX,
PCNT_CTRL_CH0_IN4_IDX, PCNT_CTRL_CH0_IN5_IDX,
PCNT_CTRL_CH0_IN6_IDX, PCNT_CTRL_CH0_IN7_IDX};

#else
uint32_t sig_idx[8] = {PCNT_SIG_CH0_IN0_IDX, PCNT_SIG_CH0_IN1_IDX,
PCNT_SIG_CH0_IN2_IDX};
uint32_t ctrl_idx[8] = {PCNT_CTRL_CH0_IN0_IDX, PCNT_CTRL_CH0_IN1_IDX,
PCNT_CTRL_CH0_IN2_IDX};
#endif
bool _esp32_attachToPulseCounter(uint8_t pcnt_unit, FastAccelStepper *stepper,
int16_t low_value, int16_t high_value) {
// TODO: Check if free pulse counter
Expand Down Expand Up @@ -175,8 +181,13 @@ bool _esp32_attachToPulseCounter(uint8_t pcnt_unit, FastAccelStepper *stepper,
cfg.channel = PCNT_CHANNEL_0;
pcnt_unit_config(&cfg);

#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
PCNT.conf_unit[cfg.unit].conf0.thr_h_lim_en = 0;
PCNT.conf_unit[cfg.unit].conf0.thr_l_lim_en = 0;
#else
PCNT.conf_unit[cfg.unit].conf0.thr_h_lim_en_un = 0;
PCNT.conf_unit[cfg.unit].conf0.thr_l_lim_en_un = 0;
#endif

stepper->detachFromPin();
stepper->reAttachToPin();
Expand All @@ -198,7 +209,11 @@ int16_t _esp32_readPulseCounter(uint8_t pcnt_unit) {
// Serial.println(' ');
// Serial.println(PCNT.cnt_unit[PCNT_UNIT_0].cnt_val);
// Serial.println(PCNT.conf_unit[PCNT_UNIT_0].conf2.cnt_h_lim);
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
return PCNT.cnt_unit[(pcnt_unit_t)pcnt_unit].cnt_val;
#else
return PCNT.cnt_unit[(pcnt_unit_t)pcnt_unit].pulse_cnt_un;
#endif
}
#endif
#endif
42 changes: 42 additions & 0 deletions src/StepperISR_esp32_mcpwm_pcnt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static struct mapping_s channel2mapping[NUM_QUEUES] = {
cmpr_tea_int_ena : MCPWM_OP2_TEA_INT_ENA,
cmpr_tea_int_raw : MCPWM_OP2_TEA_INT_RAW
},
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
{
mcpwm_unit : MCPWM_UNIT_1,
timer : 0,
Expand Down Expand Up @@ -85,6 +86,7 @@ static struct mapping_s channel2mapping[NUM_QUEUES] = {
cmpr_tea_int_ena : MCPWM_OP2_TEA_INT_ENA,
cmpr_tea_int_raw : MCPWM_OP2_TEA_INT_RAW
},
#endif
};

static void IRAM_ATTR prepare_for_next_command(
Expand All @@ -95,7 +97,11 @@ static void IRAM_ATTR prepare_for_next_command(
(const struct mapping_s *)queue->driver_data;
pcnt_unit_t pcnt_unit = mapping->pcnt_unit;
// is updated only on zero
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim = next_steps;
#else
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim_un = next_steps;
#endif
}
}

Expand Down Expand Up @@ -150,7 +156,11 @@ static void IRAM_ATTR apply_command(StepperQueue *queue,
mcpwm->int_ena.val |= mapping->cmpr_tea_int_ena;
} else {
bool disable_mcpwm_interrupt = true;
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
if (PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim != steps) {
#else
if (PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim_un != steps) {
#endif
// For fast pulses, eventually the ISR is late. So take the current pulse
// count into consideration.
//
Expand All @@ -161,11 +171,19 @@ static void IRAM_ATTR apply_command(StepperQueue *queue,
// available yet 3 pulses
//
// Read counter
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
uint16_t val1 = steps - PCNT.cnt_unit[pcnt_unit].cnt_val;
#else
uint16_t val1 = steps - PCNT.cnt_unit[pcnt_unit].pulse_cnt_un;
#endif
// Clear flag for l-->h transition
mcpwm->int_clr.val = mapping->cmpr_tea_int_clr;
// Read counter again
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
uint16_t val2 = steps - PCNT.cnt_unit[pcnt_unit].cnt_val;
#else
uint16_t val2 = steps - PCNT.cnt_unit[pcnt_unit].pulse_cnt_un;
#endif
// If no pulse arrives between val1 and val2:
// val2 == val1
// If pulse arrives between val1 and int_clr:
Expand All @@ -179,17 +197,29 @@ static void IRAM_ATTR apply_command(StepperQueue *queue,
}

// is updated only on zero
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim = val2;
#else
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim_un = val2;
#endif
// force take over
isr_pcnt_counter_clear(pcnt_unit);
// Check, if pulse has come in
if ((mcpwm->int_raw.val & mapping->cmpr_tea_int_raw) != 0) {
// Pulse has come in
// Check if the pulse has been counted or not
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
if (PCNT.cnt_unit[pcnt_unit].cnt_val == 0) {
#else
if (PCNT.cnt_unit[pcnt_unit].pulse_cnt_un == 0) {
#endif
// pulse hasn't been counted, so adjust the limit
// is updated only on zero
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim = val2 - 1;
#else
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim_un = val2 - 1;
#endif
// force take over
isr_pcnt_counter_clear(pcnt_unit);

Expand Down Expand Up @@ -344,9 +374,16 @@ void StepperQueue::init_mcpwm_pcnt(uint8_t channel_num, uint8_t step_pin) {
cfg.channel = PCNT_CHANNEL_0;
pcnt_unit_config(&cfg);

#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim = 1;
PCNT.conf_unit[pcnt_unit].conf0.thr_h_lim_en = 1;
PCNT.conf_unit[pcnt_unit].conf0.thr_l_lim_en = 0;
#else
PCNT.conf_unit[pcnt_unit].conf2.cnt_h_lim_un = 1;
PCNT.conf_unit[pcnt_unit].conf0.thr_h_lim_en_un = 1;
PCNT.conf_unit[pcnt_unit].conf0.thr_l_lim_en_un = 0;
#endif


pcnt_counter_clear(pcnt_unit);
pcnt_counter_resume(pcnt_unit);
Expand Down Expand Up @@ -528,7 +565,12 @@ bool StepperQueue::isReadyForCommands_mcpwm_pcnt() {
}
uint16_t StepperQueue::_getPerformedPulses_mcpwm_pcnt() {
const struct mapping_s *mapping = (const struct mapping_s *)driver_data;
#ifndef SUPPORT_ESP32S3_MCPWM_PCNT
return PCNT.cnt_unit[mapping->pcnt_unit].cnt_val;
#else
return PCNT.cnt_unit[mapping->pcnt_unit].pulse_cnt_un;
#endif

}

#endif
21 changes: 21 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,27 @@ struct queue_end_s {
#define QUEUES_RMT 4
#define FAS_RMT_MEM(channel) ((uint32_t *)RMTMEM.chan[channel].data32)

//==========================================================================
//
// ESP32 derivate - ESP32S3 - NOT SUPPORTED
//
//==========================================================================
#elif CONFIG_IDF_TARGET_ESP32S3
#define SUPPORT_ESP32_MCPWM_PCNT
#include <driver/mcpwm.h>
#include <driver/pcnt.h>
#include <soc/mcpwm_reg.h>
#include <soc/mcpwm_struct.h>
#include <soc/pcnt_reg.h>
#include <soc/pcnt_struct.h>

#include <driver/rmt.h>
#define QUEUES_MCPWM_PCNT 4
#define QUEUES_RMT 0

// have support for pulse counter
#define SUPPORT_ESP32_PULSE_COUNTER

//==========================================================================
//
// ESP32 derivate - ESP32C3 - NOT SUPPORTED
Expand Down