mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/set_driver_default_int_priority' into 'master'
MCPWM: driver-ng follow-up updates Closes IDFGH-8010 and IDFGH-8013 See merge request espressif/esp-idf!19432
This commit is contained in:
commit
814351acdf
@ -787,7 +787,7 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha
|
||||
mcpwm_ll_capture_enable_negedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_NEG_EDGE);
|
||||
mcpwm_ll_capture_enable_posedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_POS_EDGE);
|
||||
mcpwm_ll_capture_set_prescale(hal->dev, cap_channel, cap_conf->cap_prescale);
|
||||
// capture feature should be used with interupt, so enable it by default
|
||||
// capture feature should be used with interrupt, so enable it by default
|
||||
mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_channel), true);
|
||||
mcpwm_ll_intr_clear_capture_status(hal->dev, 1 << cap_channel);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
|
@ -245,7 +245,6 @@ esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer
|
||||
{
|
||||
gptimer_group_t *group = NULL;
|
||||
ESP_RETURN_ON_FALSE(timer && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(timer->fsm == GPTIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state");
|
||||
group = timer->group;
|
||||
int group_id = group->group_id;
|
||||
int timer_id = timer->timer_id;
|
||||
@ -261,6 +260,7 @@ esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer
|
||||
|
||||
// lazy install interrupt service
|
||||
if (!timer->intr) {
|
||||
ESP_RETURN_ON_FALSE(timer->fsm == GPTIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state");
|
||||
// if user wants to control the interrupt allocation more precisely, we can expose more flags in `gptimer_config_t`
|
||||
int isr_flags = timer->flags.intr_shared ? ESP_INTR_FLAG_SHARED | GPTIMER_INTR_ALLOC_FLAGS : GPTIMER_INTR_ALLOC_FLAGS;
|
||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(timer_group_periph_signals.groups[group_id].timer_irq_id[timer_id], isr_flags,
|
||||
@ -318,7 +318,7 @@ esp_err_t gptimer_enable(gptimer_handle_t timer)
|
||||
if (timer->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(timer->pm_lock), TAG, "acquire pm_lock failed");
|
||||
}
|
||||
// enable interrupt interupt service
|
||||
// enable interrupt service
|
||||
if (timer->intr) {
|
||||
ESP_RETURN_ON_ERROR(esp_intr_enable(timer->intr), TAG, "enable interrupt service failed");
|
||||
}
|
||||
|
@ -55,10 +55,10 @@
|
||||
// If ISR handler is allowed to run whilst cache is disabled,
|
||||
// Make sure all the code and related variables used by the handler are in the SRAM
|
||||
#if CONFIG_I2S_ISR_IRAM_SAFE
|
||||
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED)
|
||||
#define I2S_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED)
|
||||
#define I2S_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif //CONFIG_I2S_ISR_IRAM_SAFE
|
||||
#define I2S_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA)
|
||||
|
@ -138,7 +138,8 @@ esp_err_t gptimer_get_raw_count(gptimer_handle_t timer, uint64_t *value);
|
||||
* @brief Set callbacks for GPTimer
|
||||
*
|
||||
* @note User registered callbacks are expected to be runnable within ISR context
|
||||
* @note This function should be called when the timer is in the init state (i.e. before calling `gptimer_enable()`)
|
||||
* @note The first call to this function needs to be before the call to `gptimer_enable`
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
|
@ -134,6 +134,8 @@ typedef struct {
|
||||
/**
|
||||
* @brief Create MCPWM capture channel
|
||||
*
|
||||
* @note The created capture channel won't be enabled until calling `mcpwm_capture_channel_enable`
|
||||
*
|
||||
* @param[in] cap_timer MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`, will be connected to the new capture channel
|
||||
* @param[in] config MCPWM capture channel configuration
|
||||
* @param[out] ret_cap_channel Returned MCPWM capture channel
|
||||
@ -157,6 +159,33 @@ esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mc
|
||||
*/
|
||||
esp_err_t mcpwm_del_capture_channel(mcpwm_cap_channel_handle_t cap_channel);
|
||||
|
||||
/**
|
||||
* @brief Enable MCPWM capture channel
|
||||
*
|
||||
* @note This function will transit the channel state from init to enable.
|
||||
* @note This function will enable the interrupt service, if it's lazy installed in `mcpwm_capture_channel_register_event_callbacks()`.
|
||||
*
|
||||
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
|
||||
* @return
|
||||
* - ESP_OK: Enable MCPWM capture channel successfully
|
||||
* - ESP_ERR_INVALID_ARG: Enable MCPWM capture channel failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Enable MCPWM capture channel failed because the channel is already enabled
|
||||
* - ESP_FAIL: Enable MCPWM capture channel failed because of other error
|
||||
*/
|
||||
esp_err_t mcpwm_capture_channel_enable(mcpwm_cap_channel_handle_t cap_channel);
|
||||
|
||||
/**
|
||||
* @brief Disable MCPWM capture channel
|
||||
*
|
||||
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
|
||||
* @return
|
||||
* - ESP_OK: Disable MCPWM capture channel successfully
|
||||
* - ESP_ERR_INVALID_ARG: Disable MCPWM capture channel failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Disable MCPWM capture channel failed because the channel is not enabled yet
|
||||
* - ESP_FAIL: Disable MCPWM capture channel failed because of other error
|
||||
*/
|
||||
esp_err_t mcpwm_capture_channel_disable(mcpwm_cap_channel_handle_t cap_channel);
|
||||
|
||||
/**
|
||||
* @brief Group of supported MCPWM capture event callbacks
|
||||
* @note The callbacks are all running under ISR environment
|
||||
@ -168,12 +197,16 @@ typedef struct {
|
||||
/**
|
||||
* @brief Set event callbacks for MCPWM capture channel
|
||||
*
|
||||
* @note The first call to this function needs to be before the call to `mcpwm_capture_channel_enable`
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
|
||||
*
|
||||
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
* @param[in] user_data User data, which will be passed to callback functions directly
|
||||
* @return
|
||||
* - ESP_OK: Set event callbacks successfully
|
||||
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Set event callbacks failed because the channel is not in init state
|
||||
* - ESP_FAIL: Set event callbacks failed because of other error
|
||||
*/
|
||||
esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_callbacks_t *cbs, void *user_data);
|
||||
@ -185,6 +218,7 @@ esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handl
|
||||
* @return
|
||||
* - ESP_OK: Trigger software catch successfully
|
||||
* - ESP_ERR_INVALID_ARG: Trigger software catch failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Trigger software catch failed because the channel is not enabled yet
|
||||
* - ESP_FAIL: Trigger software catch failed because of other error
|
||||
*/
|
||||
esp_err_t mcpwm_capture_channel_trigger_soft_catch(mcpwm_cap_channel_handle_t cap_channel);
|
||||
|
@ -63,6 +63,8 @@ typedef struct {
|
||||
/**
|
||||
* @brief Set event callbacks for MCPWM comparator
|
||||
*
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
|
||||
*
|
||||
* @param[in] cmpr MCPWM comparator handle, allocated by `mcpwm_new_comparator()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
* @param[in] user_data User data, which will be passed to callback functions directly
|
||||
|
@ -97,6 +97,8 @@ typedef struct {
|
||||
/**
|
||||
* @brief Set event callbacks for MCPWM fault
|
||||
*
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
|
||||
*
|
||||
* @param[in] fault MCPWM GPIO fault handle, allocated by `mcpwm_new_gpio_fault()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
* @param[in] user_data User data, which will be passed to callback functions directly
|
||||
|
@ -119,6 +119,8 @@ typedef struct {
|
||||
/**
|
||||
* @brief Set event callbacks for MCPWM operator
|
||||
*
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
|
||||
*
|
||||
* @param[in] oper MCPWM operator handle, allocated by `mcpwm_new_operator()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
* @param[in] user_data User data, which will be passed to callback functions directly
|
||||
|
@ -107,6 +107,9 @@ esp_err_t mcpwm_timer_start_stop(mcpwm_timer_handle_t timer, mcpwm_timer_start_s
|
||||
/**
|
||||
* @brief Set event callbacks for MCPWM timer
|
||||
*
|
||||
* @note The first call to this function needs to be before the call to `mcpwm_timer_enable`
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
|
||||
*
|
||||
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
* @param[in] user_data User data, which will be passed to callback functions directly
|
||||
|
@ -233,7 +233,8 @@ esp_err_t pcnt_unit_get_count(pcnt_unit_handle_t unit, int *value);
|
||||
* @brief Set event callbacks for PCNT unit
|
||||
*
|
||||
* @note User registered callbacks are expected to be runnable within ISR context
|
||||
* @note This function is only allowed to be called when the unit is in the init state (i.e. before calling `pcnt_unit_enable()`)
|
||||
* @note The first call to this function needs to be before the call to `pcnt_unit_enable`
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
|
@ -242,7 +242,6 @@ esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mc
|
||||
mcpwm_hal_context_t *hal = &group->hal;
|
||||
int cap_chan_id = cap_chan->cap_chan_id;
|
||||
|
||||
mcpwm_ll_capture_enable_channel(hal->dev, cap_chan_id, true); // enable channel
|
||||
mcpwm_ll_capture_enable_negedge(hal->dev, cap_chan_id, config->flags.neg_edge);
|
||||
mcpwm_ll_capture_enable_posedge(hal->dev, cap_chan_id, config->flags.pos_edge);
|
||||
mcpwm_ll_invert_input(hal->dev, cap_chan_id, config->flags.invert_cap_signal);
|
||||
@ -262,6 +261,7 @@ esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mc
|
||||
}
|
||||
|
||||
cap_chan->gpio_num = config->gpio_num;
|
||||
cap_chan->fsm = MCPWM_CAP_CHAN_FSM_INIT;
|
||||
*ret_cap_channel = cap_chan;
|
||||
ESP_LOGD(TAG, "new capture channel (%d,%d) at %p", group->group_id, cap_chan_id, cap_chan);
|
||||
return ESP_OK;
|
||||
@ -275,6 +275,7 @@ err:
|
||||
esp_err_t mcpwm_del_capture_channel(mcpwm_cap_channel_handle_t cap_channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cap_channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(cap_channel->fsm == MCPWM_CAP_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
|
||||
mcpwm_cap_timer_t *cap_timer = cap_channel->cap_timer;
|
||||
mcpwm_group_t *group = cap_timer->group;
|
||||
mcpwm_hal_context_t *hal = &group->hal;
|
||||
@ -290,14 +291,46 @@ esp_err_t mcpwm_del_capture_channel(mcpwm_cap_channel_handle_t cap_channel)
|
||||
mcpwm_ll_intr_clear_status(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_chan_id));
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
// disable capture channel
|
||||
mcpwm_ll_capture_enable_channel(group->hal.dev, cap_channel->cap_chan_id, false);
|
||||
|
||||
// recycle memory resource
|
||||
ESP_RETURN_ON_ERROR(mcpwm_capture_channel_destory(cap_channel), TAG, "destory capture channel failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t mcpwm_capture_channel_enable(mcpwm_cap_channel_handle_t cap_channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cap_channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(cap_channel->fsm == MCPWM_CAP_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
|
||||
mcpwm_hal_context_t *hal = &cap_channel->cap_timer->group->hal;
|
||||
|
||||
// enable interrupt service
|
||||
if (cap_channel->intr) {
|
||||
ESP_RETURN_ON_ERROR(esp_intr_enable(cap_channel->intr), TAG, "enable interrupt service failed");
|
||||
}
|
||||
// enable channel
|
||||
mcpwm_ll_capture_enable_channel(hal->dev, cap_channel->cap_chan_id, true);
|
||||
|
||||
cap_channel->fsm = MCPWM_CAP_CHAN_FSM_ENABLE;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t mcpwm_capture_channel_disable(mcpwm_cap_channel_handle_t cap_channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cap_channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(cap_channel->fsm == MCPWM_CAP_CHAN_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "channel not in enable state");
|
||||
mcpwm_hal_context_t *hal = &cap_channel->cap_timer->group->hal;
|
||||
|
||||
// disable channel
|
||||
mcpwm_ll_capture_enable_channel(hal->dev, cap_channel->cap_chan_id, false);
|
||||
|
||||
// disable interrupt service
|
||||
if (cap_channel->intr) {
|
||||
ESP_RETURN_ON_ERROR(esp_intr_disable(cap_channel->intr), TAG, "disable interrupt service failed");
|
||||
}
|
||||
|
||||
cap_channel->fsm = MCPWM_CAP_CHAN_FSM_INIT;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_callbacks_t *cbs, void *user_data)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cap_channel && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
@ -317,8 +350,8 @@ esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handl
|
||||
|
||||
// lazy install interrupt service
|
||||
if (!cap_channel->intr) {
|
||||
// we want the interrupt service to be enabled after allocation successfully
|
||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED;
|
||||
ESP_RETURN_ON_FALSE(cap_channel->fsm == MCPWM_CAP_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
|
||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG;
|
||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
||||
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_CAPTURE(cap_chan_id),
|
||||
mcpwm_capture_default_isr, cap_channel, &cap_channel->intr), TAG, "install interrupt service for cap channel failed");
|
||||
@ -337,6 +370,7 @@ esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handl
|
||||
esp_err_t mcpwm_capture_channel_trigger_soft_catch(mcpwm_cap_channel_handle_t cap_channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cap_channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(cap_channel->fsm == MCPWM_CAP_CHAN_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "channel not enabled yet");
|
||||
mcpwm_cap_timer_t *cap_timer = cap_channel->cap_timer;
|
||||
mcpwm_group_t *group = cap_timer->group;
|
||||
|
||||
|
@ -29,9 +29,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_MCPWM_ISR_IRAM_SAFE
|
||||
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
|
||||
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
|
||||
#else
|
||||
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
|
||||
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
|
||||
#endif
|
||||
|
||||
#define MCPWM_PERIPH_CLOCK_PRE_SCALE (2)
|
||||
@ -193,6 +193,11 @@ typedef enum {
|
||||
MCPWM_CAP_TIMER_FSM_ENABLE,
|
||||
} mcpwm_cap_timer_fsm_t;
|
||||
|
||||
typedef enum {
|
||||
MCPWM_CAP_CHAN_FSM_INIT,
|
||||
MCPWM_CAP_CHAN_FSM_ENABLE,
|
||||
} mcpwm_cap_channel_fsm_t;
|
||||
|
||||
struct mcpwm_cap_timer_t {
|
||||
mcpwm_group_t *group; // which group the capture timer belongs to
|
||||
portMUX_TYPE spinlock; // spin lock, to prevent concurrently accessing capture timer level resources, including registers
|
||||
@ -206,7 +211,8 @@ struct mcpwm_cap_channel_t {
|
||||
int cap_chan_id; // capture channel ID, index from 0
|
||||
mcpwm_cap_timer_t *cap_timer; // which capture timer that the channel resides in
|
||||
uint32_t prescale; // prescale of capture signal
|
||||
int gpio_num; // GPIO number used by the channel
|
||||
int gpio_num; // GPIO number used by the channel
|
||||
mcpwm_cap_channel_fsm_t fsm; // driver FSM
|
||||
intr_handle_t intr; // Interrupt handle
|
||||
mcpwm_capture_event_cb_t on_cap; // Callback function which would be invoked in capture interrupt routine
|
||||
void *user_data; // user data which would be passed to the capture callback
|
||||
|
@ -166,7 +166,6 @@ esp_err_t mcpwm_del_timer(mcpwm_timer_handle_t timer)
|
||||
esp_err_t mcpwm_timer_register_event_callbacks(mcpwm_timer_handle_t timer, const mcpwm_timer_event_callbacks_t *cbs, void *user_data)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(timer && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(timer->fsm == MCPWM_TIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state");
|
||||
mcpwm_group_t *group = timer->group;
|
||||
int group_id = group->group_id;
|
||||
int timer_id = timer->timer_id;
|
||||
@ -189,6 +188,7 @@ esp_err_t mcpwm_timer_register_event_callbacks(mcpwm_timer_handle_t timer, const
|
||||
|
||||
// lazy install interrupt service
|
||||
if (!timer->intr) {
|
||||
ESP_RETURN_ON_FALSE(timer->fsm == MCPWM_TIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state");
|
||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG;
|
||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
||||
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_TIMER_MASK(timer_id),
|
||||
|
@ -41,9 +41,9 @@
|
||||
#endif
|
||||
|
||||
#if CONFIG_PCNT_ISR_IRAM_SAFE
|
||||
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||
#else
|
||||
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||
#endif
|
||||
|
||||
#define PCNT_PM_LOCK_NAME_LEN_MAX 16
|
||||
@ -283,7 +283,7 @@ esp_err_t pcnt_unit_enable(pcnt_unit_handle_t unit)
|
||||
if (unit->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(unit->pm_lock), TAG, "acquire pm_lock failed");
|
||||
}
|
||||
// enable interupt service
|
||||
// enable interrupt service
|
||||
if (unit->intr) {
|
||||
ESP_RETURN_ON_ERROR(esp_intr_enable(unit->intr), TAG, "enable interrupt service failed");
|
||||
}
|
||||
@ -366,7 +366,6 @@ esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(unit && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
// unit event callbacks should be registered in init state
|
||||
ESP_RETURN_ON_FALSE(unit->fsm == PCNT_UNIT_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "unit not in init state");
|
||||
pcnt_group_t *group = unit->group;
|
||||
int group_id = group->group_id;
|
||||
int unit_id = unit->unit_id;
|
||||
@ -382,6 +381,7 @@ esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt
|
||||
|
||||
// lazy install interrupt service
|
||||
if (!unit->intr) {
|
||||
ESP_RETURN_ON_FALSE(unit->fsm == PCNT_UNIT_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "unit not in init state");
|
||||
int isr_flags = PCNT_INTR_ALLOC_FLAGS;
|
||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(pcnt_periph_signals.groups[group_id].irq, isr_flags,
|
||||
(uint32_t)pcnt_ll_get_intr_status_reg(group->hal.dev), PCNT_LL_UNIT_WATCH_EVENT(unit_id),
|
||||
|
@ -34,9 +34,9 @@ extern "C" {
|
||||
|
||||
// RMT driver object is per-channel, the interrupt source is shared between channels
|
||||
#if CONFIG_RMT_ISR_IRAM_SAFE
|
||||
#define RMT_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM)
|
||||
#define RMT_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM)
|
||||
#else
|
||||
#define RMT_INTR_ALLOC_FLAG ESP_INTR_FLAG_SHARED
|
||||
#define RMT_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED)
|
||||
#endif
|
||||
|
||||
// Hopefully the channel offset won't change in other targets
|
||||
|
@ -102,6 +102,9 @@ TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]")
|
||||
uint32_t cap_value[2] = {0};
|
||||
TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(pps_channel, &cbs, cap_value));
|
||||
|
||||
printf("enable capture channel\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_channel_enable(pps_channel));
|
||||
|
||||
printf("enable and start capture timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_timer_enable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_start(cap_timer));
|
||||
@ -117,6 +120,7 @@ TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]")
|
||||
TEST_ASSERT_UINT_WITHIN(100000, clk_src_res / 10, cap_value[1] - cap_value[0]);
|
||||
|
||||
printf("uninstall capture channel and timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_channel_disable(pps_channel));
|
||||
TEST_ESP_OK(mcpwm_del_capture_channel(pps_channel));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer));
|
||||
@ -154,12 +158,17 @@ TEST_CASE("mcpwm_capture_software_catch", "[mcpwm]")
|
||||
test_soft_catch_user_data_t test_callback_data = {};
|
||||
TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &cap_channel));
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_capture_channel_trigger_soft_catch(cap_channel));
|
||||
|
||||
printf("register event callback for capture channel\r\n");
|
||||
mcpwm_capture_event_callbacks_t cbs = {
|
||||
.on_cap = soft_cap_callback,
|
||||
};
|
||||
TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(cap_channel, &cbs, &test_callback_data));
|
||||
|
||||
printf("enable capture channel\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_channel_enable(cap_channel));
|
||||
|
||||
printf("enable and start capture timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_timer_enable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_start(cap_timer));
|
||||
@ -179,6 +188,7 @@ TEST_CASE("mcpwm_capture_software_catch", "[mcpwm]")
|
||||
TEST_ASSERT_UINT_WITHIN(80000, clk_src_res / 100, delta);
|
||||
|
||||
printf("uninstall capture channel and timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_channel_disable(cap_channel));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_del_capture_channel(cap_channel));
|
||||
TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer));
|
||||
@ -211,6 +221,7 @@ TEST_CASE("mcpwm_capture_timer_sync_phase_lock", "[mcpwm]")
|
||||
.sync_src = soft_sync,
|
||||
};
|
||||
TEST_ESP_OK(mcpwm_capture_timer_set_phase_on_sync(cap_timer, &sync_config));
|
||||
|
||||
mcpwm_cap_channel_handle_t cap_channel = NULL;
|
||||
mcpwm_capture_channel_config_t cap_chan_config = {
|
||||
.gpio_num = -1, // don't need any GPIO, we use software to trigger a catch
|
||||
@ -224,6 +235,9 @@ TEST_CASE("mcpwm_capture_timer_sync_phase_lock", "[mcpwm]")
|
||||
uint32_t cap_data;
|
||||
TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(cap_channel, &cbs, &cap_data));
|
||||
|
||||
printf("enable capture channel\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_channel_enable(cap_channel));
|
||||
|
||||
TEST_ESP_OK(mcpwm_capture_channel_trigger_soft_catch(cap_channel));
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
printf("capture data before sync: %"PRIu32"\r\n", cap_data);
|
||||
@ -233,6 +247,7 @@ TEST_CASE("mcpwm_capture_timer_sync_phase_lock", "[mcpwm]")
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
printf("capture data after sync: %"PRIu32"\r\n", cap_data);
|
||||
TEST_ASSERT_EQUAL(1000, cap_data);
|
||||
TEST_ESP_OK(mcpwm_capture_channel_disable(cap_channel));
|
||||
TEST_ESP_OK(mcpwm_del_capture_channel(cap_channel));
|
||||
TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_del_sync_src(soft_sync));
|
||||
|
@ -76,7 +76,7 @@ TEST_CASE("mcpwm_comparator_event_callback", "[mcpwm]")
|
||||
.group_id = 0,
|
||||
};
|
||||
mcpwm_comparator_config_t comparator_config = {};
|
||||
printf("install timer, operator and comparator");
|
||||
printf("install timer, operator and comparator\r\n");
|
||||
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
|
||||
TEST_ESP_OK(mcpwm_new_operator(&operator_config, &operator));
|
||||
TEST_ESP_OK(mcpwm_new_comparator(operator, &comparator_config, &comparator));
|
||||
|
@ -69,6 +69,9 @@ TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]")
|
||||
uint32_t cap_value[2] = {0};
|
||||
TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(pps_channel, &cbs, cap_value));
|
||||
|
||||
printf("enable capture channel\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_channel_enable(pps_channel));
|
||||
|
||||
printf("enable and start capture timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_timer_enable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_start(cap_timer));
|
||||
@ -82,6 +85,7 @@ TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]")
|
||||
TEST_ASSERT_UINT_WITHIN(2000, clk_src_res / 1000, cap_value[1] - cap_value[0]);
|
||||
|
||||
printf("uninstall capture channel and timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_channel_disable(pps_channel));
|
||||
TEST_ESP_OK(mcpwm_del_capture_channel(pps_channel));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer));
|
||||
|
@ -764,7 +764,7 @@ static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan)
|
||||
// pre-alloc a interrupt handle, with handler disabled
|
||||
int isr_flags = GDMA_INTR_ALLOC_FLAGS;
|
||||
#if SOC_GDMA_TX_RX_SHARE_INTERRUPT
|
||||
isr_flags |= ESP_INTR_FLAG_SHARED;
|
||||
isr_flags |= ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
|
||||
#endif
|
||||
intr_handle_t intr = NULL;
|
||||
ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[group->group_id].pairs[pair->pair_id].rx_irq_id, isr_flags,
|
||||
@ -791,7 +791,7 @@ static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan)
|
||||
// pre-alloc a interrupt handle, with handler disabled
|
||||
int isr_flags = GDMA_INTR_ALLOC_FLAGS;
|
||||
#if SOC_GDMA_TX_RX_SHARE_INTERRUPT
|
||||
isr_flags |= ESP_INTR_FLAG_SHARED;
|
||||
isr_flags |= ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
|
||||
#endif
|
||||
intr_handle_t intr = NULL;
|
||||
ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[group->group_id].pairs[pair->pair_id].tx_irq_id, isr_flags,
|
||||
|
@ -170,7 +170,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
|
||||
i2s_ll_tx_reset_fifo(bus->hal.dev);
|
||||
// install interrupt service, (I2S LCD mode only uses the "TX Unit", which leaves "RX Unit" for other purpose)
|
||||
// So the interrupt should also be able to share with other functionality
|
||||
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED;
|
||||
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
|
||||
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.buses[bus->bus_id].irq_id, isr_flags,
|
||||
(uint32_t)i2s_ll_get_intr_status_reg(bus->hal.dev),
|
||||
I2S_LL_EVENT_TX_EOF, lcd_default_isr_handler, bus, &bus->intr);
|
||||
|
@ -153,7 +153,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock %d failed", bus_config->clk_src);
|
||||
// install interrupt service, (LCD peripheral shares the same interrupt source with Camera peripheral with different mask)
|
||||
// interrupt is disabled by default
|
||||
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED;
|
||||
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
|
||||
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.buses[bus_id].irq_id, isr_flags,
|
||||
(uint32_t)lcd_ll_get_interrupt_status_reg(bus->hal.dev),
|
||||
LCD_LL_EVENT_TRANS_DONE, lcd_default_isr_handler, bus, &bus->intr);
|
||||
|
@ -278,7 +278,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
|
||||
rgb_panel->lcd_clk_flags |= LCD_HAL_PCLK_FLAG_ALLOW_EQUAL_SYSCLK;
|
||||
}
|
||||
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
|
||||
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED;
|
||||
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
|
||||
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.panels[panel_id].irq_id, isr_flags,
|
||||
(uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
|
||||
LCD_LL_EVENT_VSYNC_END, lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
|
||||
|
@ -814,6 +814,11 @@ The parameter ``user_data`` of :cpp:func:`mcpwm_capture_channel_register_event_c
|
||||
|
||||
This function will lazy install interrupt service for the MCPWM capture channel, whereas the service can only be removed in :cpp:type:`mcpwm_del_capture_channel`.
|
||||
|
||||
Enable and Disable Capture Channel
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The capture channel is not enabled after allocation by :cpp:func:`mcpwm_new_capture_channel`. You should call :cpp:func:`mcpwm_capture_channel_enable` and :cpp:func:`mcpwm_capture_channel_disable` accordingly to enable or disable the channel. If the interrupt service is lazy installed during registering event callbacks for the channel in :cpp:func:`mcpwm_capture_channel_register_event_callbacks`, :cpp:func:`mcpwm_capture_channel_enable` will enable the interrupt service as well.
|
||||
|
||||
Enable and Disable Capture Timer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -308,7 +308,7 @@ LCD
|
||||
- ``mcpwm_fault_set_oneshot_mode``, ``mcpwm_fault_set_cyc_mode`` are replaced by :cpp:func:`mcpwm_operator_set_brake_on_fault` and :cpp:func:`mcpwm_generator_set_actions_on_brake_event`.
|
||||
- ``mcpwm_capture_enable`` is removed. It's duplicated to :cpp:func:`mcpwm_capture_enable_channel`.
|
||||
- ``mcpwm_capture_disable`` is removed. It's duplicated to :cpp:func:`mcpwm_capture_capture_disable_channel`.
|
||||
- ``mcpwm_capture_enable_channel`` and ``mcpwm_capture_disable_channel`` are replaced by :cpp:func:`mcpwm_new_capture_channel` and :cpp:func:`mcpwm_del_capture_channel`.
|
||||
- ``mcpwm_capture_enable_channel`` and ``mcpwm_capture_disable_channel`` are replaced by :cpp:func:`mcpwm_capture_channel_enable` and :cpp:func:`mcpwm_capture_channel_disable`.
|
||||
- ``mcpwm_capture_signal_get_value`` and ``mcpwm_capture_signal_get_edge``: Capture timer count value and capture edge are provided in the capture event callback, via :cpp:type:`mcpwm_capture_event_data_t`. Capture data are only valuable when capture event happens. Providing single API to fetch capture data is meaningless.
|
||||
- ``mcpwm_sync_enable`` is removed. It's duplicated to :cpp:func:`mcpwm_sync_configure`.
|
||||
- ``mcpwm_sync_configure`` is replaced by :cpp:func:`mcpwm_timer_set_phase_on_sync`.
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example mainly illustrates how to drive a brushed DC motor by generating two specific PWM signals. However the PWM signals from ESP chip can't drive motors directly as the motor usually consumes high current. So an H-bridge like [DRV8848](https://www.ti.com/product/DRV8848) should be used to provide the needed voltage and current for brushed DC motor. To simplify the DC motor control of MCPWM peripheral driver, there's a component called [bdc_motor](components/bdc_motor/README.md) which abstracts the common operations into a generic interface. The most useful operations are: `forward`, `reverse`, `coast` and `brake`.
|
||||
This example mainly illustrates how to drive a brushed DC motor by generating two specific PWM signals. However the PWM signals from ESP chip can't drive motors directly as the motor usually consumes high current. So an H-bridge like [DRV8848](https://www.ti.com/product/DRV8848) should be used to provide the needed voltage and current for brushed DC motor. To simplify the DC motor control of MCPWM peripheral driver, there's a component called [bdc_motor](https://components.espressif.com/component/espressif/bdc_motor) which abstracts the common operations into a generic interface. The most useful operations are: `forward`, `reverse`, `coast` and `brake`.
|
||||
|
||||
To measure the speed of motor, a photoelectric encoder is used to generate the "speed feedback" signals (e.g. a pair of quadrature signal). In the example, we use the PCNT peripheral to decode that quadrature signals. For more information, please refer to [rotary encoder example](../../pcnt/rotary_encoder/README.md) as well.
|
||||
|
||||
The example uses a simple PID algorithm to keep the motor spin in a stable speed. The PID component is fetched from the [IDF Component Registry](https://components.espressif.com/component/espressif/pid_ctrl).
|
||||
The example uses a simple PID algorithm to keep the motor spin in a stable speed. Like the [bdc_motor](https://components.espressif.com/component/espressif/bdc_motor), the [PID component](https://components.espressif.com/component/espressif/pid_ctrl) is also managed by the component manager. These components' dependencies are listed in the [manifest file](main/idf_component.yml).
|
||||
|
||||
## How to Use Example
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
set(srcs "src/bdc_motor.c")
|
||||
|
||||
if(CONFIG_SOC_MCPWM_SUPPORTED)
|
||||
list(APPEND srcs "src/bdc_motor_mcpwm_impl.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS "include" "interface"
|
||||
PRIV_REQUIRES "driver")
|
@ -1,7 +0,0 @@
|
||||
# Brushed DC Motor Component
|
||||
|
||||
This directory contains an implementation for Brushed DC Motor by different peripherals. Currently only MCPWM is supported as the BDC motor backend.
|
||||
|
||||
To learn more about how to use this component, please check API Documentation from header file [bdc_motor.h](./include/bdc_motor.h).
|
||||
|
||||
Please note that this component is not considered to be a part of ESP-IDF stable API. It may change and it may be removed in the future releases.
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Brushed DC Motor handle
|
||||
*/
|
||||
typedef struct bdc_motor_t *bdc_motor_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Enable BDC motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Enable motor successfully
|
||||
* - ESP_ERR_INVALID_ARG: Enable motor failed because of invalid parameters
|
||||
* - ESP_FAIL: Enable motor failed because other error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_enable(bdc_motor_handle_t motor);
|
||||
|
||||
/**
|
||||
* @brief Disable BDC motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Disable motor successfully
|
||||
* - ESP_ERR_INVALID_ARG: Disable motor failed because of invalid parameters
|
||||
* - ESP_FAIL: Disable motor failed because other error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_disable(bdc_motor_handle_t motor);
|
||||
|
||||
/**
|
||||
* @brief Set speed for bdc motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
* @param speed: BDC speed
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Set motor speed successfully
|
||||
* - ESP_ERR_INVALID_ARG: Set motor speed failed because of invalid parameters
|
||||
* - ESP_FAIL: Set motor speed failed because other error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_set_speed(bdc_motor_handle_t motor, uint32_t speed);
|
||||
|
||||
/**
|
||||
* @brief Forward BDC motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Forward motor successfully
|
||||
* - ESP_FAIL: Forward motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_forward(bdc_motor_handle_t motor);
|
||||
|
||||
/**
|
||||
* @brief Reverse BDC Motor
|
||||
*
|
||||
* @param strip: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Reverse motor successfully
|
||||
* - ESP_FAIL: Reverse motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_reverse(bdc_motor_handle_t motor);
|
||||
|
||||
/**
|
||||
* @brief Stop motor in a coast way (a.k.a Fast Decay)
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Stop motor successfully
|
||||
* - ESP_FAIL: Stop motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_coast(bdc_motor_handle_t motor);
|
||||
|
||||
/**
|
||||
* @brief Stop motor in a brake way (a.k.a Slow Decay)
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Stop motor successfully
|
||||
* - ESP_FAIL: Stop motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_brake(bdc_motor_handle_t motor);
|
||||
|
||||
/**
|
||||
* @brief Free BDC Motor resources
|
||||
*
|
||||
* @param strip: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Free resources successfully
|
||||
* - ESP_FAIL: Free resources failed because error occurred
|
||||
*/
|
||||
esp_err_t bdc_motor_del(bdc_motor_handle_t motor);
|
||||
|
||||
/**
|
||||
* @brief BDC Motor Configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t pwma_gpio_num; /*!< BDC Motor PWM A gpio number */
|
||||
uint32_t pwmb_gpio_num; /*!< BDC Motor PWM B gpio number */
|
||||
uint32_t pwm_freq_hz; /*!< PWM frequency, in Hz */
|
||||
} bdc_motor_config_t;
|
||||
|
||||
/**
|
||||
* @brief BDC Motor MCPWM specific configuration
|
||||
*/
|
||||
typedef struct {
|
||||
int group_id; /*!< MCPWM group number */
|
||||
uint32_t resolution_hz; /*!< MCPWM timer resolution */
|
||||
} bdc_motor_mcpwm_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create BDC Motor based on MCPWM peripheral
|
||||
*
|
||||
* @param motor_config: BDC Motor configuration
|
||||
* @param mcpwm_config: MCPWM specific configuration
|
||||
* @param ret_motor Returned BDC Motor handle
|
||||
* @return
|
||||
* - ESP_OK: Create BDC Motor handle successfully
|
||||
* - ESP_ERR_INVALID_ARG: Create BDC Motor handle failed because of invalid argument
|
||||
* - ESP_ERR_NO_MEM: Create BDC Motor handle failed because of out of memory
|
||||
* - ESP_FAIL: Create BDC Motor handle failed because some other error
|
||||
*/
|
||||
esp_err_t bdc_motor_new_mcpwm_device(const bdc_motor_config_t *motor_config, const bdc_motor_mcpwm_config_t *mcpwm_config, bdc_motor_handle_t *ret_motor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct bdc_motor_t bdc_motor_t; /*!< Type of BDC motor */
|
||||
|
||||
/**
|
||||
* @brief BDC motor interface definition
|
||||
*/
|
||||
struct bdc_motor_t {
|
||||
/**
|
||||
* @brief Enable BDC motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Enable motor successfully
|
||||
* - ESP_ERR_INVALID_ARG: Enable motor failed because of invalid parameters
|
||||
* - ESP_FAIL: Enable motor failed because other error occurred
|
||||
*/
|
||||
esp_err_t (*enable)(bdc_motor_t *motor);
|
||||
|
||||
/**
|
||||
* @brief Disable BDC motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Disable motor successfully
|
||||
* - ESP_ERR_INVALID_ARG: Disable motor failed because of invalid parameters
|
||||
* - ESP_FAIL: Disable motor failed because other error occurred
|
||||
*/
|
||||
esp_err_t (*disable)(bdc_motor_t *motor);
|
||||
|
||||
/**
|
||||
* @brief Set speed for bdc motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
* @param speed: BDC speed
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Set motor speed successfully
|
||||
* - ESP_ERR_INVALID_ARG: Set motor speed failed because of invalid parameters
|
||||
* - ESP_FAIL: Set motor speed failed because other error occurred
|
||||
*/
|
||||
esp_err_t (*set_speed)(bdc_motor_t *motor, uint32_t speed);
|
||||
|
||||
/**
|
||||
* @brief Forward BDC motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Forward motor successfully
|
||||
* - ESP_FAIL: Forward motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t (*forward)(bdc_motor_t *motor);
|
||||
|
||||
/**
|
||||
* @brief Reverse BDC Motor
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Reverse motor successfully
|
||||
* - ESP_FAIL: Reverse motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t (*reverse)(bdc_motor_t *motor);
|
||||
|
||||
/**
|
||||
* @brief Stop motor in a coast way (a.k.a Fast Decay)
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Stop motor successfully
|
||||
* - ESP_FAIL: Stop motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t (*coast)(bdc_motor_t *motor);
|
||||
|
||||
/**
|
||||
* @brief Stop motor in a brake way (a.k.a Slow Decay)
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Stop motor successfully
|
||||
* - ESP_FAIL: Stop motor failed because some other error occurred
|
||||
*/
|
||||
esp_err_t (*brake)(bdc_motor_t *motor);
|
||||
|
||||
/**
|
||||
* @brief Free BDC Motor handle resources
|
||||
*
|
||||
* @param motor: BDC Motor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Free resources successfully
|
||||
* - ESP_FAIL: Free resources failed because error occurred
|
||||
*/
|
||||
esp_err_t (*del)(bdc_motor_t *motor);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "bdc_motor.h"
|
||||
#include "bdc_motor_interface.h"
|
||||
|
||||
static const char *TAG = "bdc_motor";
|
||||
|
||||
esp_err_t bdc_motor_enable(bdc_motor_handle_t motor)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->enable(motor);
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_disable(bdc_motor_handle_t motor)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->disable(motor);
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_set_speed(bdc_motor_handle_t motor, uint32_t speed)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->set_speed(motor, speed);
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_forward(bdc_motor_handle_t motor)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->forward(motor);
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_reverse(bdc_motor_handle_t motor)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->reverse(motor);
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_coast(bdc_motor_handle_t motor)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->coast(motor);
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_brake(bdc_motor_handle_t motor)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->brake(motor);
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_del(bdc_motor_handle_t motor)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
return motor->del(motor);
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/mcpwm_prelude.h"
|
||||
#include "bdc_motor.h"
|
||||
#include "bdc_motor_interface.h"
|
||||
|
||||
static const char *TAG = "bdc_motor_mcpwm";
|
||||
|
||||
typedef struct {
|
||||
bdc_motor_t base;
|
||||
mcpwm_timer_handle_t timer;
|
||||
mcpwm_oper_handle_t operator;
|
||||
mcpwm_cmpr_handle_t cmpa;
|
||||
mcpwm_cmpr_handle_t cmpb;
|
||||
mcpwm_gen_handle_t gena;
|
||||
mcpwm_gen_handle_t genb;
|
||||
} bdc_motor_mcpwm_obj;
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_set_speed(bdc_motor_t *motor, uint32_t speed)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
ESP_RETURN_ON_ERROR(mcpwm_comparator_set_compare_value(mcpwm_motor->cmpa, speed), TAG, "set compare value failed");
|
||||
ESP_RETURN_ON_ERROR(mcpwm_comparator_set_compare_value(mcpwm_motor->cmpb, speed), TAG, "set compare value failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_enable(bdc_motor_t *motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
ESP_RETURN_ON_ERROR(mcpwm_timer_enable(mcpwm_motor->timer), TAG, "enable timer failed");
|
||||
ESP_RETURN_ON_ERROR(mcpwm_timer_start_stop(mcpwm_motor->timer, MCPWM_TIMER_START_NO_STOP), TAG, "start timer failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_disable(bdc_motor_t *motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
ESP_RETURN_ON_ERROR(mcpwm_timer_start_stop(mcpwm_motor->timer, MCPWM_TIMER_STOP_EMPTY), TAG, "stop timer failed");
|
||||
ESP_RETURN_ON_ERROR(mcpwm_timer_disable(mcpwm_motor->timer), TAG, "disable timer failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_forward(bdc_motor_t *motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, -1, true), TAG, "disable force level for gena failed");
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, 0, true), TAG, "set force level for genb failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_reverse(bdc_motor_t *motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, -1, true), TAG, "disable force level for genb failed");
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, 0, true), TAG, "set force level for gena failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_coast(bdc_motor_t *motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, 0, true), TAG, "set force level for gena failed");
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, 0, true), TAG, "set force level for genb failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_brake(bdc_motor_t *motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, 1, true), TAG, "set force level for gena failed");
|
||||
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, 1, true), TAG, "set force level for genb failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t bdc_motor_mcpwm_del(bdc_motor_t *motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
|
||||
mcpwm_del_generator(mcpwm_motor->gena);
|
||||
mcpwm_del_generator(mcpwm_motor->genb);
|
||||
mcpwm_del_comparator(mcpwm_motor->cmpa);
|
||||
mcpwm_del_comparator(mcpwm_motor->cmpb);
|
||||
mcpwm_del_operator(mcpwm_motor->operator);
|
||||
mcpwm_del_timer(mcpwm_motor->timer);
|
||||
free(mcpwm_motor);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t bdc_motor_new_mcpwm_device(const bdc_motor_config_t *motor_config, const bdc_motor_mcpwm_config_t *mcpwm_config, bdc_motor_handle_t *ret_motor)
|
||||
{
|
||||
bdc_motor_mcpwm_obj *mcpwm_motor = NULL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_GOTO_ON_FALSE(motor_config && mcpwm_config && ret_motor, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
mcpwm_motor = calloc(1, sizeof(bdc_motor_mcpwm_obj));
|
||||
ESP_GOTO_ON_FALSE(mcpwm_motor, ESP_ERR_NO_MEM, err, TAG, "no mem for rmt motor");
|
||||
|
||||
// mcpwm timer
|
||||
mcpwm_timer_config_t timer_config = {
|
||||
.group_id = mcpwm_config->group_id,
|
||||
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
|
||||
.resolution_hz = mcpwm_config->resolution_hz,
|
||||
.period_ticks = mcpwm_config->resolution_hz / motor_config->pwm_freq_hz,
|
||||
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(mcpwm_new_timer(&timer_config, &mcpwm_motor->timer), err, TAG, "create MCPWM timer failed");
|
||||
|
||||
mcpwm_operator_config_t operator_config = {
|
||||
.group_id = mcpwm_config->group_id,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(mcpwm_new_operator(&operator_config, &mcpwm_motor->operator), err, TAG, "create MCPWM operator failed");
|
||||
|
||||
ESP_GOTO_ON_ERROR(mcpwm_operator_connect_timer(mcpwm_motor->operator, mcpwm_motor->timer), err, TAG, "connect timer and operator failed");
|
||||
|
||||
mcpwm_comparator_config_t comparator_config = {
|
||||
.flags.update_cmp_on_tez = true,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(mcpwm_new_comparator(mcpwm_motor->operator, &comparator_config, &mcpwm_motor->cmpa), err, TAG, "create comparator failed");
|
||||
ESP_GOTO_ON_ERROR(mcpwm_new_comparator(mcpwm_motor->operator, &comparator_config, &mcpwm_motor->cmpb), err, TAG, "create comparator failed");
|
||||
|
||||
// set the initial compare value for both comparators
|
||||
mcpwm_comparator_set_compare_value(mcpwm_motor->cmpa, 0);
|
||||
mcpwm_comparator_set_compare_value(mcpwm_motor->cmpb, 0);
|
||||
|
||||
mcpwm_generator_config_t generator_config = {
|
||||
.gen_gpio_num = motor_config->pwma_gpio_num,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(mcpwm_new_generator(mcpwm_motor->operator, &generator_config, &mcpwm_motor->gena), err, TAG, "create generator failed");
|
||||
generator_config.gen_gpio_num = motor_config->pwmb_gpio_num;
|
||||
ESP_GOTO_ON_ERROR(mcpwm_new_generator(mcpwm_motor->operator, &generator_config, &mcpwm_motor->genb), err, TAG, "create generator failed");
|
||||
|
||||
mcpwm_generator_set_actions_on_timer_event(mcpwm_motor->gena,
|
||||
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
|
||||
MCPWM_GEN_TIMER_EVENT_ACTION_END());
|
||||
mcpwm_generator_set_actions_on_compare_event(mcpwm_motor->gena,
|
||||
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, mcpwm_motor->cmpa, MCPWM_GEN_ACTION_LOW),
|
||||
MCPWM_GEN_COMPARE_EVENT_ACTION_END());
|
||||
mcpwm_generator_set_actions_on_timer_event(mcpwm_motor->genb,
|
||||
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
|
||||
MCPWM_GEN_TIMER_EVENT_ACTION_END());
|
||||
mcpwm_generator_set_actions_on_compare_event(mcpwm_motor->genb,
|
||||
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, mcpwm_motor->cmpb, MCPWM_GEN_ACTION_LOW),
|
||||
MCPWM_GEN_COMPARE_EVENT_ACTION_END());
|
||||
|
||||
mcpwm_motor->base.enable = bdc_motor_mcpwm_enable;
|
||||
mcpwm_motor->base.disable = bdc_motor_mcpwm_disable;
|
||||
mcpwm_motor->base.forward = bdc_motor_mcpwm_forward;
|
||||
mcpwm_motor->base.reverse = bdc_motor_mcpwm_reverse;
|
||||
mcpwm_motor->base.coast = bdc_motor_mcpwm_coast;
|
||||
mcpwm_motor->base.brake = bdc_motor_mcpwm_brake;
|
||||
mcpwm_motor->base.set_speed = bdc_motor_mcpwm_set_speed;
|
||||
mcpwm_motor->base.del = bdc_motor_mcpwm_del;
|
||||
*ret_motor = &mcpwm_motor->base;
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (mcpwm_motor) {
|
||||
if (mcpwm_motor->gena) {
|
||||
mcpwm_del_generator(mcpwm_motor->gena);
|
||||
}
|
||||
if (mcpwm_motor->genb) {
|
||||
mcpwm_del_generator(mcpwm_motor->genb);
|
||||
}
|
||||
if (mcpwm_motor->cmpa) {
|
||||
mcpwm_del_comparator(mcpwm_motor->cmpa);
|
||||
}
|
||||
if (mcpwm_motor->cmpb) {
|
||||
mcpwm_del_comparator(mcpwm_motor->cmpb);
|
||||
}
|
||||
if (mcpwm_motor->operator) {
|
||||
mcpwm_del_operator(mcpwm_motor->operator);
|
||||
}
|
||||
if (mcpwm_motor->timer) {
|
||||
mcpwm_del_timer(mcpwm_motor->timer);
|
||||
}
|
||||
free(mcpwm_motor);
|
||||
}
|
||||
return ret;
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
dependencies:
|
||||
pid_ctrl: "^0.1.1"
|
||||
bdc_motor: "^0.1.0"
|
||||
|
@ -321,6 +321,15 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(mcpwm_capture_channel_register_event_callbacks(cap_channels[i], &cbs, task_to_notify));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Enable capture channels");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_channels[i]));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Enable and start capture timer");
|
||||
ESP_ERROR_CHECK(mcpwm_capture_timer_enable(cap_timer));
|
||||
ESP_ERROR_CHECK(mcpwm_capture_timer_start(cap_timer));
|
||||
|
||||
ESP_LOGI(TAG, "Start a timer to adjust motor speed periodically");
|
||||
esp_timer_handle_t periodic_timer = NULL;
|
||||
const esp_timer_create_args_t periodic_timer_args = {
|
||||
|
@ -83,6 +83,9 @@ void app_main(void)
|
||||
};
|
||||
ESP_ERROR_CHECK(mcpwm_capture_channel_register_event_callbacks(cap_chan, &cbs, cur_task));
|
||||
|
||||
ESP_LOGI(TAG, "Enable capture channel");
|
||||
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan));
|
||||
|
||||
ESP_LOGI(TAG, "Configure Trig pin");
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
|
@ -12,5 +12,6 @@ def test_hc_sr04_example(dut: Dut) -> None:
|
||||
dut.expect_exact('example: Install capture timer')
|
||||
dut.expect_exact('example: Install capture channel')
|
||||
dut.expect_exact('example: Register capture callback')
|
||||
dut.expect_exact('example: Enable capture channel')
|
||||
dut.expect_exact('example: Configure Trig pin')
|
||||
dut.expect_exact('example: Enable and start capture timer')
|
||||
|
Loading…
x
Reference in New Issue
Block a user