mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-06 00:59:30 +01:00
Merge branch 'feature/driver_ng_enable_disable_logic' into 'master'
driver_ng: added explicit enable/disable functions Closes IDF-4204 See merge request espressif/esp-idf!17885
This commit is contained in:
@@ -198,6 +198,7 @@ static void SEGGER_SYSVIEW_TS_Init(void)
|
||||
// pick any free GPTimer instance
|
||||
ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_sv_gptimer));
|
||||
/* Start counting */
|
||||
gptimer_enable(s_sv_gptimer);
|
||||
gptimer_start(s_sv_gptimer);
|
||||
#endif // TS_USE_TIMERGROUP
|
||||
}
|
||||
|
||||
@@ -172,6 +172,7 @@ static void esp_apptrace_dummy_task(void *p)
|
||||
.on_alarm = arg->timers[i].isr_func,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(arg->timers[i].gptimer, &cbs, &arg->timers[i]));
|
||||
TEST_ESP_OK(gptimer_enable(arg->timers[i].gptimer));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(arg->timers[i].gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_start(arg->timers[i].gptimer));
|
||||
}
|
||||
@@ -186,6 +187,7 @@ static void esp_apptrace_dummy_task(void *p)
|
||||
|
||||
for (int i = 0; i < arg->timers_num; i++) {
|
||||
TEST_ESP_OK(gptimer_stop(arg->timers[i].gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(arg->timers[i].gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(arg->timers[i].gptimer));
|
||||
}
|
||||
xSemaphoreGive(arg->done);
|
||||
@@ -219,6 +221,7 @@ static void esp_apptrace_test_task(void *p)
|
||||
.on_alarm = arg->timers[i].isr_func,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(arg->timers[i].gptimer, &cbs, &arg->timers[i]));
|
||||
TEST_ESP_OK(gptimer_enable(arg->timers[i].gptimer));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(arg->timers[i].gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_start(arg->timers[i].gptimer));
|
||||
}
|
||||
@@ -257,6 +260,7 @@ static void esp_apptrace_test_task(void *p)
|
||||
|
||||
for (int i = 0; i < arg->timers_num; i++) {
|
||||
TEST_ESP_OK(gptimer_stop(arg->timers[i].gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(arg->timers[i].gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(arg->timers[i].gptimer));
|
||||
}
|
||||
xSemaphoreGive(arg->done);
|
||||
@@ -311,12 +315,14 @@ static void esp_apptrace_test_ts_init(void)
|
||||
};
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &ts_gptimer));
|
||||
ESP_APPTRACE_TEST_LOGI("Use timer %x for TS", ts_gptimer);
|
||||
TEST_ESP_OK(gptimer_enable(ts_gptimer));
|
||||
TEST_ESP_OK(gptimer_start(ts_gptimer));
|
||||
}
|
||||
|
||||
static void esp_apptrace_test_ts_cleanup(void)
|
||||
{
|
||||
TEST_ESP_OK(gptimer_stop(ts_gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(ts_gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(ts_gptimer));
|
||||
ts_gptimer = NULL;
|
||||
}
|
||||
@@ -729,6 +735,7 @@ static void esp_sysviewtrace_test_task(void *p)
|
||||
.on_alarm = esp_sysview_test_timer_isr,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(arg->timer->gptimer, &cbs, arg->timer));
|
||||
TEST_ESP_OK(gptimer_enable(arg->timer->gptimer));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(arg->timer->gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_start(arg->timer->gptimer));
|
||||
}
|
||||
@@ -814,8 +821,10 @@ TEST_CASE("SysView trace test 1", "[trace][ignore]")
|
||||
xSemaphoreTake(arg2.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg2.done);
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer));
|
||||
}
|
||||
|
||||
@@ -907,8 +916,10 @@ TEST_CASE("SysView trace test 2", "[trace][ignore]")
|
||||
vSemaphoreDelete(arg4.done);
|
||||
vSemaphoreDelete(test_sync);
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer));
|
||||
}
|
||||
#endif // #if CONFIG_APPTRACE_SV_ENABLE == 0
|
||||
|
||||
@@ -64,9 +64,9 @@ struct gptimer_group_t {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GPTIMER_FSM_STOP,
|
||||
GPTIMER_FSM_START,
|
||||
} gptimer_lifecycle_fsm_t;
|
||||
GPTIMER_FSM_INIT,
|
||||
GPTIMER_FSM_ENABLE,
|
||||
} gptimer_fsm_t;
|
||||
|
||||
struct gptimer_t {
|
||||
gptimer_group_t *group;
|
||||
@@ -76,7 +76,7 @@ struct gptimer_t {
|
||||
unsigned long long alarm_count;
|
||||
gptimer_count_direction_t direction;
|
||||
timer_hal_context_t hal;
|
||||
gptimer_lifecycle_fsm_t fsm; // access to fsm should be protect by spinlock, as fsm is also accessed from ISR handler
|
||||
gptimer_fsm_t fsm;
|
||||
intr_handle_t intr;
|
||||
portMUX_TYPE spinlock; // to protect per-timer resources concurent accessed by task and ISR handler
|
||||
gptimer_alarm_cb_t on_alarm;
|
||||
@@ -194,7 +194,7 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
// initialize other members of timer
|
||||
timer->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
timer->fsm = GPTIMER_FSM_STOP;
|
||||
timer->fsm = GPTIMER_FSM_INIT; // put the timer into init state
|
||||
timer->direction = config->direction;
|
||||
timer->flags.intr_shared = config->flags.intr_shared;
|
||||
ESP_LOGD(TAG, "new gptimer (%d,%d) at %p, resolution=%uHz", group_id, timer_id, timer, timer->resolution_hz);
|
||||
@@ -211,16 +211,10 @@ err:
|
||||
esp_err_t gptimer_del_timer(gptimer_handle_t timer)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(timer, 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");
|
||||
gptimer_group_t *group = timer->group;
|
||||
int group_id = group->group_id;
|
||||
int timer_id = timer->timer_id;
|
||||
|
||||
bool valid_state = true;
|
||||
portENTER_CRITICAL(&timer->spinlock);
|
||||
valid_state = timer->fsm == GPTIMER_FSM_STOP;
|
||||
portEXIT_CRITICAL(&timer->spinlock);
|
||||
ESP_RETURN_ON_FALSE(valid_state, ESP_ERR_INVALID_STATE, TAG, "can't delete timer as it's not stop yet");
|
||||
|
||||
ESP_LOGD(TAG, "del timer (%d,%d)", group_id, timer_id);
|
||||
// recycle memory resource
|
||||
ESP_RETURN_ON_ERROR(gptimer_destory(timer), TAG, "destory gptimer failed");
|
||||
@@ -251,6 +245,7 @@ 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;
|
||||
@@ -314,23 +309,50 @@ esp_err_t gptimer_set_alarm_action(gptimer_handle_t timer, const gptimer_alarm_c
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gptimer_start(gptimer_handle_t timer)
|
||||
esp_err_t gptimer_enable(gptimer_handle_t timer)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(timer, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(timer, 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");
|
||||
|
||||
// acquire power manager lock
|
||||
if (timer->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_pm_lock_acquire(timer->pm_lock), TAG, "acquire APB_FREQ_MAX lock failed");
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(timer->pm_lock), TAG, "acquire pm_lock failed");
|
||||
}
|
||||
// interrupt interupt service
|
||||
// enable interrupt interupt service
|
||||
if (timer->intr) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_intr_enable(timer->intr), TAG, "enable interrupt service failed");
|
||||
ESP_RETURN_ON_ERROR(esp_intr_enable(timer->intr), TAG, "enable interrupt service failed");
|
||||
}
|
||||
|
||||
timer->fsm = GPTIMER_FSM_ENABLE;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gptimer_disable(gptimer_handle_t timer)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(timer, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(timer->fsm == GPTIMER_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "timer not in enable state");
|
||||
|
||||
// disable interrupt service
|
||||
if (timer->intr) {
|
||||
ESP_RETURN_ON_ERROR(esp_intr_disable(timer->intr), TAG, "disable interrupt service failed");
|
||||
}
|
||||
// release power manager lock
|
||||
if (timer->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_release(timer->pm_lock), TAG, "release pm_lock failed");
|
||||
}
|
||||
|
||||
timer->fsm = GPTIMER_FSM_INIT;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gptimer_start(gptimer_handle_t timer)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(timer, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE_ISR(timer->fsm == GPTIMER_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "timer not enabled yet");
|
||||
|
||||
portENTER_CRITICAL_SAFE(&timer->spinlock);
|
||||
timer_ll_enable_counter(timer->hal.dev, timer->timer_id, true);
|
||||
timer_ll_enable_alarm(timer->hal.dev, timer->timer_id, timer->flags.alarm_en);
|
||||
timer->fsm = GPTIMER_FSM_START;
|
||||
portEXIT_CRITICAL_SAFE(&timer->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
@@ -339,23 +361,14 @@ esp_err_t gptimer_start(gptimer_handle_t timer)
|
||||
esp_err_t gptimer_stop(gptimer_handle_t timer)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(timer, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE_ISR(timer->fsm == GPTIMER_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "timer not enabled yet");
|
||||
|
||||
// disable counter, alarm, autoreload
|
||||
// disable counter, alarm, auto-reload
|
||||
portENTER_CRITICAL_SAFE(&timer->spinlock);
|
||||
timer_ll_enable_counter(timer->hal.dev, timer->timer_id, false);
|
||||
timer_ll_enable_alarm(timer->hal.dev, timer->timer_id, false);
|
||||
timer->fsm = GPTIMER_FSM_STOP;
|
||||
portEXIT_CRITICAL_SAFE(&timer->spinlock);
|
||||
|
||||
// disable interrupt service
|
||||
if (timer->intr) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_intr_disable(timer->intr), TAG, "disable interrupt service failed");
|
||||
}
|
||||
// release power manager lock
|
||||
if (timer->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_pm_lock_release(timer->pm_lock), TAG, "release APB_FREQ_MAX lock failed");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef bool (*gptimer_alarm_cb_t) (gptimer_handle_t timer, const gptimer_alarm_
|
||||
/**
|
||||
* @brief Group of supported GPTimer callbacks
|
||||
* @note The callbacks are all running under ISR environment
|
||||
* @note When CONFIG_GPTIMER_ISR_IRAM_SAFE is enabled, the callback itself and functions callbed by it should be placed in IRAM.
|
||||
*/
|
||||
typedef struct {
|
||||
gptimer_alarm_cb_t on_alarm; /*!< Timer alarm callback */
|
||||
@@ -73,7 +74,7 @@ typedef struct {
|
||||
/**
|
||||
* @brief Create a new General Purpose Timer, and return the handle
|
||||
*
|
||||
* @note Once a timer is created, it is placed in the stopped state and will not start until `gptimer_start()` is called.
|
||||
* @note The newly created timer is put in the init state.
|
||||
*
|
||||
* @param[in] config GPTimer configuration
|
||||
* @param[out] ret_timer Returned timer handle
|
||||
@@ -89,13 +90,14 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re
|
||||
/**
|
||||
* @brief Delete the GPTimer handle
|
||||
*
|
||||
* @note A timer must be in a stop state before it can be deleted.
|
||||
* @note A timer can't be in the enable state when this function is invoked.
|
||||
* See also `gptimer_disable()` for how to disable a timer.
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
* @return
|
||||
* - ESP_OK: Delete GPTimer successfully
|
||||
* - ESP_ERR_INVALID_ARG: Delete GPTimer failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Delete GPTimer failed because the timer has not stopped
|
||||
* - ESP_ERR_INVALID_STATE: Delete GPTimer failed because the timer is not in init state
|
||||
* - ESP_FAIL: Delete GPTimer failed because of other error
|
||||
*/
|
||||
esp_err_t gptimer_del_timer(gptimer_handle_t timer);
|
||||
@@ -135,7 +137,8 @@ esp_err_t gptimer_get_raw_count(gptimer_handle_t timer, uint64_t *value);
|
||||
/**
|
||||
* @brief Set callbacks for GPTimer
|
||||
*
|
||||
* @note The user registered callbacks are expected to be runnable within ISR context
|
||||
* @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()`)
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
@@ -143,6 +146,7 @@ esp_err_t gptimer_get_raw_count(gptimer_handle_t timer, uint64_t *value);
|
||||
* @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 timer is not in init state
|
||||
* - ESP_FAIL: Set event callbacks failed because of other error
|
||||
*/
|
||||
esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer_event_callbacks_t *cbs, void *user_data);
|
||||
@@ -150,7 +154,7 @@ esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer
|
||||
/**
|
||||
* @brief Set alarm event actions for GPTimer.
|
||||
*
|
||||
* @note This function is allowed to run within ISR context
|
||||
* @note This function is allowed to run within ISR context, so that user can set new alarm action immediately in the ISR callback.
|
||||
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
@@ -163,31 +167,65 @@ esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer
|
||||
esp_err_t gptimer_set_alarm_action(gptimer_handle_t timer, const gptimer_alarm_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Start GPTimer
|
||||
* @brief Enable GPTimer
|
||||
*
|
||||
* @note This function will transit the timer state from init to enable.
|
||||
* @note This function will enable the interrupt service, if it's lazy installed in `gptimer_register_event_callbacks()`.
|
||||
* @note This function will acquire a PM lock, if a specific source clock (e.g. APB) is selected in the `gptimer_config_t`, while `CONFIG_PM_ENABLE` is enabled.
|
||||
* @note Enable a timer doesn't mean to start it. See also `gptimer_start()` for how to make the timer start counting.
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
* @return
|
||||
* - ESP_OK: Enable GPTimer successfully
|
||||
* - ESP_ERR_INVALID_ARG: Enable GPTimer failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Enable GPTimer failed because the timer is already enabled
|
||||
* - ESP_FAIL: Enable GPTimer failed because of other error
|
||||
*/
|
||||
esp_err_t gptimer_enable(gptimer_handle_t timer);
|
||||
|
||||
/**
|
||||
* @brief Disable GPTimer
|
||||
*
|
||||
* @note This function will do the opposite work to the `gptimer_enable()`
|
||||
* @note Disable a timer doesn't mean to stop it. See also `gptimer_stop()` for how to make the timer stop counting.
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
* @return
|
||||
* - ESP_OK: Disable GPTimer successfully
|
||||
* - ESP_ERR_INVALID_ARG: Disable GPTimer failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Disable GPTimer failed because the timer is not enabled yet
|
||||
* - ESP_FAIL: Disable GPTimer failed because of other error
|
||||
*/
|
||||
esp_err_t gptimer_disable(gptimer_handle_t timer);
|
||||
|
||||
/**
|
||||
* @brief Start GPTimer (internal counter starts counting)
|
||||
*
|
||||
* @note This function should be called when the timer is in the enable state (i.e. after calling `gptimer_enable()`)
|
||||
* @note This function is allowed to run within ISR context
|
||||
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
|
||||
* @note This function will be placed into IRAM if `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is on, so that it's allowed to be executed when Cache is disabled
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
* @return
|
||||
* - ESP_OK: Start GPTimer successfully
|
||||
* - ESP_ERR_INVALID_ARG: Start GPTimer failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Start GPTimer failed because the timer is not in stop state
|
||||
* - ESP_ERR_INVALID_STATE: Start GPTimer failed because the timer is not enabled yet
|
||||
* - ESP_FAIL: Start GPTimer failed because of other error
|
||||
*/
|
||||
esp_err_t gptimer_start(gptimer_handle_t timer);
|
||||
|
||||
/**
|
||||
* @brief Stop GPTimer
|
||||
* @brief Stop GPTimer (internal counter stops counting)
|
||||
*
|
||||
* @note This function should be called when the timer is in the enable state (i.e. after calling `gptimer_enable()`)
|
||||
* @note This function is allowed to run within ISR context
|
||||
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
|
||||
* @note This function will be placed into IRAM if `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is on, so that it's allowed to be executed when Cache is disabled
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer()`
|
||||
* @return
|
||||
* - ESP_OK: Stop GPTimer successfully
|
||||
* - ESP_ERR_INVALID_ARG: Stop GPTimer failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Stop GPTimer failed because the timer is not in start state
|
||||
* - ESP_ERR_INVALID_STATE: Stop GPTimer failed because the timer is not enabled yet
|
||||
* - ESP_FAIL: Stop GPTimer failed because of other error
|
||||
*/
|
||||
esp_err_t gptimer_stop(gptimer_handle_t timer);
|
||||
|
||||
@@ -86,7 +86,7 @@ typedef struct {
|
||||
/**
|
||||
* @brief Create a new PCNT unit, and return the handle
|
||||
*
|
||||
* @note The newly created PCNT unit is put into the stopped state.
|
||||
* @note The newly created PCNT unit is put in the init state.
|
||||
*
|
||||
* @param[in] config PCNT unit configuration
|
||||
* @param[out] ret_unit Returned PCNT unit handle
|
||||
@@ -102,13 +102,14 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re
|
||||
/**
|
||||
* @brief Delete the PCNT unit handle
|
||||
*
|
||||
* @note Users must ensure that the PCNT unit is stopped before deleting the unit. Users can force a working unit into the stopped state via `pcnt_unit_stop()`.
|
||||
* @note A PCNT unit can't be in the enable state when this function is invoked.
|
||||
* See also `pcnt_unit_disable()` for how to disable a unit.
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @return
|
||||
* - ESP_OK: Delete the PCNT unit successfully
|
||||
* - ESP_ERR_INVALID_ARG: Delete the PCNT unit failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Delete the PCNT unit failed because corresponding PCNT channels and/or watch points are still in working
|
||||
* - ESP_ERR_INVALID_STATE: Delete the PCNT unit failed because the unit is not in init state or some PCNT channel is still in working
|
||||
* - ESP_FAIL: Delete the PCNT unit failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_del_unit(pcnt_unit_handle_t unit);
|
||||
@@ -118,29 +119,63 @@ esp_err_t pcnt_del_unit(pcnt_unit_handle_t unit);
|
||||
*
|
||||
* @note The glitch filter module is clocked from APB, and APB frequency can be changed during DFS, which in return make the filter out of action.
|
||||
* So this function will lazy-install a PM lock internally when the power management is enabled. With this lock, the APB frequency won't be changed.
|
||||
* The PM lock can only be uninstalled in `pcnt_del_unit()`.
|
||||
* The PM lock can be uninstalled in `pcnt_del_unit()`.
|
||||
* @note This function should be called when the PCNT unit is in the init state (i.e. before calling `pcnt_unit_enable()`)
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] config PCNT filter configuration, set config to NULL means disabling the filter function
|
||||
* @return
|
||||
* - ESP_OK: Set glitch filter successfully
|
||||
* - ESP_ERR_INVALID_ARG: Set glitch filter failed because of invalid argument (e.g. glitch width is too big)
|
||||
* - ESP_ERR_INVALID_STATE: Set glitch filter failed because the unit is not in the init state
|
||||
* - ESP_FAIL: Set glitch filter failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_set_glitch_filter(pcnt_unit_handle_t unit, const pcnt_glitch_filter_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable the PCNT unit
|
||||
*
|
||||
* @note This function will transit the unit state from init to enable.
|
||||
* @note This function will enable the interrupt service, if it's lazy installed in `pcnt_unit_register_event_callbacks()`.
|
||||
* @note This function will acquire the PM lock if it's lazy installed in `pcnt_unit_set_glitch_filter()`.
|
||||
* @note Enable a PCNT unit doesn't mean to start it. See also `pcnt_unit_start()` for how to start the PCNT counter.
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @return
|
||||
* - ESP_OK: Enable PCNT unit successfully
|
||||
* - ESP_ERR_INVALID_ARG: Enable PCNT unit failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Enable PCNT unit failed because the unit is already enabled
|
||||
* - ESP_FAIL: Enable PCNT unit failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_enable(pcnt_unit_handle_t unit);
|
||||
|
||||
/**
|
||||
* @brief Disable the PCNT unit
|
||||
*
|
||||
* @note This function will do the opposite work to the `pcnt_unit_enable()`
|
||||
* @note Disable a PCNT unit doesn't mean to stop it. See also `pcnt_unit_stop()` for how to stop the PCNT counter.
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @return
|
||||
* - ESP_OK: Disable PCNT unit successfully
|
||||
* - ESP_ERR_INVALID_ARG: Disable PCNT unit failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Disable PCNT unit failed because the unit is not enabled yet
|
||||
* - ESP_FAIL: Disable PCNT unit failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_disable(pcnt_unit_handle_t unit);
|
||||
|
||||
/**
|
||||
* @brief Start the PCNT unit, the counter will start to count according to the edge and/or level input signals
|
||||
*
|
||||
* @note This function will acquire the PM lock when power management is enabled. Also see `pcnt_unit_set_glitch_filter()` for the condition of PM lock installation.
|
||||
* @note The number of calls to this function should be equal to the number of calls to `pcnt_unit_stop()`.
|
||||
* @note This function should be called when the unit is in the enable state (i.e. after calling `pcnt_unit_enable()`)
|
||||
* @note This function is allowed to run within ISR context
|
||||
* @note This function will be placed into IRAM if `CONFIG_PCNT_CTRL_FUNC_IN_IRAM`, so that it's allowed to be executed when Cache is disabled
|
||||
* @note This function will be placed into IRAM if `CONFIG_PCNT_CTRL_FUNC_IN_IRAM` is on, so that it's allowed to be executed when Cache is disabled
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @return
|
||||
* - ESP_OK: Start PCNT unit successfully
|
||||
* - ESP_ERR_INVALID_ARG: Start PCNT unit failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Start PCNT unit failed because the unit is not enabled yet
|
||||
* - ESP_FAIL: Start PCNT unit failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_start(pcnt_unit_handle_t unit);
|
||||
@@ -148,10 +183,8 @@ esp_err_t pcnt_unit_start(pcnt_unit_handle_t unit);
|
||||
/**
|
||||
* @brief Stop PCNT from counting
|
||||
*
|
||||
* @note If power management is enabled, this function will release the PM lock acquired in `pcnt_unit_start()`.
|
||||
* Also see `pcnt_unit_set_glitch_filter()` for the condition of PM lock installation.
|
||||
* @note This function should be called when the unit is in the enable state (i.e. after calling `pcnt_unit_enable()`)
|
||||
* @note The stop operation won't clear the counter. Also see `pcnt_unit_clear_count()` for how to clear pulse count value.
|
||||
* @note The number of calls to this function should be equal to the number of calls to `pcnt_unit_start()`.
|
||||
* @note This function is allowed to run within ISR context
|
||||
* @note This function will be placed into IRAM if `CONFIG_PCNT_CTRL_FUNC_IN_IRAM`, so that it is allowed to be executed when Cache is disabled
|
||||
*
|
||||
@@ -159,6 +192,7 @@ esp_err_t pcnt_unit_start(pcnt_unit_handle_t unit);
|
||||
* @return
|
||||
* - ESP_OK: Stop PCNT unit successfully
|
||||
* - ESP_ERR_INVALID_ARG: Stop PCNT unit failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Stop PCNT unit failed because the unit is not enabled yet
|
||||
* - ESP_FAIL: Stop PCNT unit failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_stop(pcnt_unit_handle_t unit);
|
||||
@@ -196,7 +230,8 @@ esp_err_t pcnt_unit_get_count(pcnt_unit_handle_t unit, int *value);
|
||||
/**
|
||||
* @brief Set event callbacks for PCNT unit
|
||||
*
|
||||
* @note User can deregister the previous callback by calling this function with an empty `cbs`.
|
||||
* @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()`)
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] cbs Group of callback functions
|
||||
@@ -204,6 +239,7 @@ esp_err_t pcnt_unit_get_count(pcnt_unit_handle_t unit, int *value);
|
||||
* @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 unit is not in init state
|
||||
* - ESP_FAIL: Set event callbacks failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt_event_callbacks_t *cbs, void *user_data);
|
||||
@@ -211,8 +247,6 @@ esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt
|
||||
/**
|
||||
* @brief Add a watch point for PCNT unit, PCNT will generate an event when the counter value reaches the watch point value
|
||||
*
|
||||
* @note The number of calls to this function should be equal to the number of calls to `pcnt_unit_remove_watch_point()`, otherwise the unit can't be deleted
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] watch_point Value to be watched
|
||||
* @return
|
||||
@@ -227,8 +261,6 @@ esp_err_t pcnt_unit_add_watch_point(pcnt_unit_handle_t unit, int watch_point);
|
||||
/**
|
||||
* @brief Remove a watch point for PCNT unit
|
||||
*
|
||||
* @note The number of calls to this function should be equal to the number of calls to `pcnt_unit_add_watch_point()`, otherwise the unit can't be deleted
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] watch_point Watch point value
|
||||
* @return
|
||||
@@ -242,6 +274,8 @@ esp_err_t pcnt_unit_remove_watch_point(pcnt_unit_handle_t unit, int watch_point)
|
||||
/**
|
||||
* @brief Create PCNT channel for specific unit, each PCNT has several channels associated with it
|
||||
*
|
||||
* @note This function should be called when the unit is in init state (i.e. before calling `pcnt_unit_enable()`)
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] config PCNT channel configuration
|
||||
* @param[out] ret_chan Returned channel handle
|
||||
@@ -250,6 +284,7 @@ esp_err_t pcnt_unit_remove_watch_point(pcnt_unit_handle_t unit, int watch_point)
|
||||
* - ESP_ERR_INVALID_ARG: Create PCNT channel failed because of invalid argument
|
||||
* - ESP_ERR_NO_MEM: Create PCNT channel failed because of insufficient memory
|
||||
* - ESP_ERR_NOT_FOUND: Create PCNT channel failed because all PCNT channels are used up and no more free one
|
||||
* - ESP_ERR_INVALID_STATE: Create PCNT channel failed because the unit is not in the init state
|
||||
* - ESP_FAIL: Create PCNT channel failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *config, pcnt_channel_handle_t *ret_chan);
|
||||
|
||||
@@ -61,24 +61,24 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co
|
||||
esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens);
|
||||
|
||||
/**
|
||||
* @brief Start temperature measurement.
|
||||
* @brief Enable the temperature sensor
|
||||
*
|
||||
* @param tsens The handle created by `temperature_sensor_install()`.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE if temperature sensor is started already.
|
||||
* - ESP_ERR_INVALID_STATE if temperature sensor is enabled already.
|
||||
*/
|
||||
esp_err_t temperature_sensor_start(temperature_sensor_handle_t tsens);
|
||||
esp_err_t temperature_sensor_enable(temperature_sensor_handle_t tsens);
|
||||
|
||||
/**
|
||||
* @brief Stop temperature sensor measure.
|
||||
* @brief Disable temperature sensor
|
||||
*
|
||||
* @param tsens The handle created by `temperature_sensor_install()`.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE if temperature sensor is stopped already.
|
||||
* - ESP_ERR_INVALID_STATE if temperature sensor is not enabled yet.
|
||||
*/
|
||||
esp_err_t temperature_sensor_stop(temperature_sensor_handle_t tsens);
|
||||
esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens);
|
||||
|
||||
/**
|
||||
* @brief Read temperature sensor data that is converted to degrees Celsius.
|
||||
@@ -88,8 +88,9 @@ esp_err_t temperature_sensor_stop(temperature_sensor_handle_t tsens);
|
||||
* @param out_celsius The measure output value.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG ARG is NULL.
|
||||
* - ESP_ERR_INVALID_STATE The ambient temperature is out of range.
|
||||
* - ESP_ERR_INVALID_ARG invalid arguments
|
||||
* - ESP_ERR_INVALID_STATE Temperature sensor is not enabled yet.
|
||||
* - ESP_FAIL Parse the sensor data into ambient temperature failed (e.g. out of the range).
|
||||
*/
|
||||
esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius);
|
||||
|
||||
|
||||
@@ -72,9 +72,9 @@ typedef struct {
|
||||
} pcnt_watch_point_t;
|
||||
|
||||
typedef enum {
|
||||
PCNT_FSM_STOP,
|
||||
PCNT_FSM_START,
|
||||
} pcnt_lifecycle_fsm_t;
|
||||
PCNT_UNIT_FSM_INIT,
|
||||
PCNT_UNIT_FSM_ENABLE,
|
||||
} pcnt_unit_fsm_t;
|
||||
|
||||
struct pcnt_unit_t {
|
||||
pcnt_group_t *group; // which group the pcnt unit belongs to
|
||||
@@ -89,7 +89,7 @@ struct pcnt_unit_t {
|
||||
#if CONFIG_PM_ENABLE
|
||||
char pm_lock_name[PCNT_PM_LOCK_NAME_LEN_MAX]; // pm lock name
|
||||
#endif
|
||||
pcnt_lifecycle_fsm_t fsm; // access to fsm should be protect by spinlock, as fsm can also accessed from ISR handler
|
||||
pcnt_unit_fsm_t fsm; // record PCNT unit's driver state
|
||||
pcnt_watch_cb_t on_reach; // user registered callback function
|
||||
void *user_data; // user data registered by user, which would be passed to the right callback function
|
||||
};
|
||||
@@ -152,8 +152,6 @@ static void pcnt_unregister_from_group(pcnt_unit_t *unit)
|
||||
static esp_err_t pcnt_destory(pcnt_unit_t *unit)
|
||||
{
|
||||
if (unit->pm_lock) {
|
||||
// if pcnt_unit_start and pcnt_unit_stop are not called the same number of times, deleting pm_lock will return invalid state
|
||||
// which in return also reflects an invalid state of PCNT driver
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(unit->pm_lock), TAG, "delete pm lock failed");
|
||||
}
|
||||
if (unit->intr) {
|
||||
@@ -206,7 +204,7 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
unit->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
unit->fsm = PCNT_FSM_STOP;
|
||||
unit->fsm = PCNT_UNIT_FSM_INIT;
|
||||
for (int i = 0; i < PCNT_LL_WATCH_EVENT_MAX; i++) {
|
||||
unit->watchers[i].event_id = PCNT_LL_WATCH_EVENT_INVALID; // invalid all watch point
|
||||
}
|
||||
@@ -224,23 +222,14 @@ err:
|
||||
esp_err_t pcnt_del_unit(pcnt_unit_handle_t unit)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
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;
|
||||
|
||||
bool valid_state = true;
|
||||
portENTER_CRITICAL(&unit->spinlock);
|
||||
valid_state = unit->fsm == PCNT_FSM_STOP;
|
||||
portEXIT_CRITICAL(&unit->spinlock);
|
||||
ESP_RETURN_ON_FALSE(valid_state, ESP_ERR_INVALID_STATE, TAG, "can't delete unit as it's not stop yet");
|
||||
|
||||
for (int i = 0; i < SOC_PCNT_CHANNELS_PER_UNIT; i++) {
|
||||
ESP_RETURN_ON_FALSE(!unit->channels[i], ESP_ERR_INVALID_STATE, TAG, "channel %d still in working", i);
|
||||
}
|
||||
for (int i = 0; i < PCNT_LL_WATCH_EVENT_MAX; i++) {
|
||||
ESP_RETURN_ON_FALSE(unit->watchers[i].event_id == PCNT_LL_WATCH_EVENT_INVALID, ESP_ERR_INVALID_STATE, TAG,
|
||||
"watch point %d still in working", unit->watchers[i].watch_point_value);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "del unit (%d,%d)", group_id, unit_id);
|
||||
// recycle memory resource
|
||||
@@ -253,6 +242,8 @@ esp_err_t pcnt_unit_set_glitch_filter(pcnt_unit_handle_t unit, const pcnt_glitch
|
||||
pcnt_group_t *group = NULL;
|
||||
uint32_t glitch_filter_thres = 0;
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
// glitch filter should be set only when unit is in init state
|
||||
ESP_RETURN_ON_FALSE(unit->fsm == PCNT_UNIT_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "unit not in init state");
|
||||
group = unit->group;
|
||||
if (config) {
|
||||
glitch_filter_thres = esp_clk_apb_freq() / 1000000 * config->max_glitch_ns / 1000;
|
||||
@@ -281,57 +272,67 @@ esp_err_t pcnt_unit_set_glitch_filter(pcnt_unit_handle_t unit, const pcnt_glitch
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_start(pcnt_unit_handle_t unit)
|
||||
esp_err_t pcnt_unit_enable(pcnt_unit_handle_t unit)
|
||||
{
|
||||
pcnt_group_t *group = NULL;
|
||||
ESP_RETURN_ON_FALSE_ISR(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
group = unit->group;
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(unit->fsm == PCNT_UNIT_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "unit not in init state");
|
||||
|
||||
// acquire power manager lock
|
||||
if (unit->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_pm_lock_acquire(unit->pm_lock), TAG, "acquire APB_FREQ_MAX lock failed");
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(unit->pm_lock), TAG, "acquire pm_lock failed");
|
||||
}
|
||||
// enable interupt service
|
||||
if (unit->intr) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_intr_enable(unit->intr), TAG, "enable interrupt service failed");
|
||||
ESP_RETURN_ON_ERROR(esp_intr_enable(unit->intr), TAG, "enable interrupt service failed");
|
||||
}
|
||||
|
||||
unit->fsm = PCNT_UNIT_FSM_ENABLE;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_disable(pcnt_unit_handle_t unit)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(unit->fsm = PCNT_UNIT_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "unit not in enable state");
|
||||
|
||||
// disable interrupt service
|
||||
if (unit->intr) {
|
||||
ESP_RETURN_ON_ERROR(esp_intr_disable(unit->intr), TAG, "disable interrupt service failed");
|
||||
}
|
||||
// release power manager lock
|
||||
if (unit->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_release(unit->pm_lock), TAG, "release APB_FREQ_MAX lock failed");
|
||||
}
|
||||
|
||||
unit->fsm = PCNT_UNIT_FSM_INIT;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_start(pcnt_unit_handle_t unit)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE_ISR(unit->fsm == PCNT_UNIT_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "unit not enabled yet");
|
||||
pcnt_group_t *group = unit->group;
|
||||
|
||||
// all PCNT units share the same register to control counter
|
||||
portENTER_CRITICAL_SAFE(&group->spinlock);
|
||||
pcnt_ll_start_count(group->hal.dev, unit->unit_id);
|
||||
portEXIT_CRITICAL_SAFE(&group->spinlock);
|
||||
|
||||
portENTER_CRITICAL_SAFE(&unit->spinlock);
|
||||
unit->fsm = PCNT_FSM_START;
|
||||
portEXIT_CRITICAL_SAFE(&unit->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_stop(pcnt_unit_handle_t unit)
|
||||
{
|
||||
pcnt_group_t *group = NULL;
|
||||
ESP_RETURN_ON_FALSE_ISR(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
group = unit->group;
|
||||
ESP_RETURN_ON_FALSE_ISR(unit->fsm == PCNT_UNIT_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "unit not enabled yet");
|
||||
pcnt_group_t *group = unit->group;
|
||||
|
||||
// all PCNT units share the same register to control counter
|
||||
portENTER_CRITICAL_SAFE(&group->spinlock);
|
||||
pcnt_ll_stop_count(group->hal.dev, unit->unit_id);
|
||||
portEXIT_CRITICAL_SAFE(&group->spinlock);
|
||||
|
||||
portENTER_CRITICAL_SAFE(&unit->spinlock);
|
||||
unit->fsm = PCNT_FSM_STOP;
|
||||
portEXIT_CRITICAL_SAFE(&unit->spinlock);
|
||||
|
||||
// disable interrupt service
|
||||
if (unit->intr) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_intr_disable(unit->intr), TAG, "disable interrupt service failed");
|
||||
}
|
||||
// release power manager lock
|
||||
if (unit->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_pm_lock_release(unit->pm_lock), TAG, "release APB_FREQ_MAX lock failed");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -361,9 +362,10 @@ esp_err_t pcnt_unit_get_count(pcnt_unit_handle_t unit, int *value)
|
||||
|
||||
esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt_event_callbacks_t *cbs, void *user_data)
|
||||
{
|
||||
pcnt_group_t *group = NULL;
|
||||
ESP_RETURN_ON_FALSE(unit && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
group = unit->group;
|
||||
// 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;
|
||||
|
||||
@@ -520,6 +522,7 @@ esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *co
|
||||
pcnt_chan_t *channel = NULL;
|
||||
pcnt_group_t *group = NULL;
|
||||
ESP_GOTO_ON_FALSE(unit && config && ret_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
ESP_GOTO_ON_FALSE(unit->fsm == PCNT_UNIT_FSM_INIT, ESP_ERR_INVALID_STATE, err, TAG, "unit not in init state");
|
||||
group = unit->group;
|
||||
int group_id = group->group_id;
|
||||
int unit_id = unit->unit_id;
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG
|
||||
// The local log level must be defined before including esp_log.h
|
||||
// Set the maximum log level for this source file
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "sys/lock.h"
|
||||
#include "soc/rtc.h"
|
||||
@@ -25,7 +24,6 @@
|
||||
#include "driver/temperature_sensor.h"
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "hal/temperature_sensor_types.h"
|
||||
#include "hal/temperature_sensor_ll.h"
|
||||
|
||||
static const char *TAG = "temperature_sensor";
|
||||
@@ -35,10 +33,9 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
|
||||
#define TEMPERATURE_SENSOR_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
typedef enum {
|
||||
TSENS_HW_STATE_UNCONFIGURED,
|
||||
TSENS_HW_STATE_CONFIGURED,
|
||||
TSENS_HW_STATE_STARTED,
|
||||
} temp_sensor_state_t;
|
||||
TEMP_SENSOR_FSM_INIT,
|
||||
TEMP_SENSOR_FSM_ENABLE,
|
||||
} temp_sensor_fsm_t;
|
||||
|
||||
static float s_deltaT = NAN; // unused number
|
||||
|
||||
@@ -46,7 +43,7 @@ typedef struct temperature_sensor_obj_t temperature_sensor_obj_t;
|
||||
|
||||
struct temperature_sensor_obj_t {
|
||||
const temp_sensor_ll_attribute_t *tsens_attribute;
|
||||
temp_sensor_state_t tsens_hw_state;
|
||||
temp_sensor_fsm_t fsm;
|
||||
temperature_sensor_clk_src_t clk_src;
|
||||
};
|
||||
|
||||
@@ -89,9 +86,9 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_RETURN_ON_FALSE((tsens_config && ret_tsens), ESP_ERR_INVALID_ARG, TAG, "Invalid argument");
|
||||
ESP_RETURN_ON_FALSE((s_tsens_attribute_copy == NULL), ESP_ERR_INVALID_STATE, TAG, "Already installed");
|
||||
temperature_sensor_handle_t tsens;
|
||||
temperature_sensor_handle_t tsens = NULL;
|
||||
tsens = (temperature_sensor_obj_t *) heap_caps_calloc(1, sizeof(temperature_sensor_obj_t), MALLOC_CAP_DEFAULT);
|
||||
ESP_GOTO_ON_FALSE(tsens != NULL, ESP_ERR_NO_MEM, err, TAG, "install fail...");
|
||||
ESP_GOTO_ON_FALSE(tsens != NULL, ESP_ERR_NO_MEM, err, TAG, "no mem for temp sensor");
|
||||
tsens->clk_src = tsens_config->clk_src;
|
||||
|
||||
periph_module_enable(PERIPH_TEMPSENSOR_MODULE);
|
||||
@@ -103,10 +100,13 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co
|
||||
tsens->tsens_attribute->range_min,
|
||||
tsens->tsens_attribute->range_max,
|
||||
tsens->tsens_attribute->error_max);
|
||||
|
||||
TEMPERATURE_SENSOR_ENTER_CRITICAL();
|
||||
temperature_sensor_ll_set_range(tsens->tsens_attribute->reg_val);
|
||||
temperature_sensor_ll_enable(false); // disable the sensor by default
|
||||
TEMPERATURE_SENSOR_EXIT_CRITICAL();
|
||||
tsens->tsens_hw_state = TSENS_HW_STATE_CONFIGURED;
|
||||
|
||||
tsens->fsm = TEMP_SENSOR_FSM_INIT;
|
||||
*ret_tsens = tsens;
|
||||
return ESP_OK;
|
||||
err:
|
||||
@@ -116,52 +116,50 @@ err:
|
||||
|
||||
esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Has already been uninstalled");
|
||||
ESP_RETURN_ON_FALSE(tsens->tsens_hw_state != TSENS_HW_STATE_STARTED, ESP_ERR_INVALID_STATE, TAG, "Has not been stopped");
|
||||
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "tsens not in init state");
|
||||
|
||||
if (s_tsens_attribute_copy) {
|
||||
free(s_tsens_attribute_copy);
|
||||
}
|
||||
s_tsens_attribute_copy = NULL;
|
||||
tsens->tsens_hw_state = TSENS_HW_STATE_UNCONFIGURED;
|
||||
heap_caps_free(tsens);
|
||||
tsens = NULL;
|
||||
|
||||
periph_module_disable(PERIPH_TEMPSENSOR_MODULE);
|
||||
free(tsens);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t temperature_sensor_start(temperature_sensor_handle_t tsens)
|
||||
esp_err_t temperature_sensor_enable(temperature_sensor_handle_t tsens)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Has not been installed");
|
||||
ESP_RETURN_ON_FALSE(tsens->tsens_hw_state == TSENS_HW_STATE_CONFIGURED, ESP_ERR_INVALID_STATE, TAG, "Is already running or has not been configured");
|
||||
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "tsens not in init state");
|
||||
|
||||
#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
|
||||
if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_RC_FAST) {
|
||||
periph_rtc_dig_clk8m_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
temperature_sensor_ll_clk_enable(true);
|
||||
temperature_sensor_ll_clk_sel(tsens->clk_src);
|
||||
temperature_sensor_ll_enable(true);
|
||||
tsens->tsens_hw_state = TSENS_HW_STATE_STARTED;
|
||||
tsens->fsm = TEMP_SENSOR_FSM_ENABLE;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t temperature_sensor_stop(temperature_sensor_handle_t tsens)
|
||||
esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(tsens->tsens_hw_state == TSENS_HW_STATE_STARTED, ESP_ERR_INVALID_STATE, TAG, "Has not been started");
|
||||
ESP_RETURN_ON_FALSE(tsens, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "tsens not enabled yet");
|
||||
|
||||
temperature_sensor_ll_enable(false);
|
||||
#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
|
||||
if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_RC_FAST) {
|
||||
periph_rtc_dig_clk8m_disable();
|
||||
}
|
||||
#endif
|
||||
periph_module_disable(PERIPH_TEMPSENSOR_MODULE);
|
||||
tsens->tsens_hw_state = TSENS_HW_STATE_CONFIGURED;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t temp_sensor_read_raw(uint32_t *tsens_out)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(tsens_out != NULL, ESP_ERR_INVALID_ARG, TAG, "No tsens_out specified");
|
||||
*tsens_out = temperature_sensor_ll_get_raw_value();
|
||||
tsens->fsm = TEMP_SENSOR_FSM_INIT;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -187,14 +185,15 @@ esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, floa
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Has not been installed");
|
||||
ESP_RETURN_ON_FALSE(out_celsius != NULL, ESP_ERR_INVALID_ARG, TAG, "Celsius points to nothing");
|
||||
ESP_RETURN_ON_FALSE(tsens->tsens_hw_state == TSENS_HW_STATE_STARTED, ESP_ERR_INVALID_ARG, TAG, "Has not been started");
|
||||
uint32_t tsens_out = 0;
|
||||
temp_sensor_read_raw(&tsens_out);
|
||||
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "tsens not enabled yet");
|
||||
|
||||
uint32_t tsens_out = temperature_sensor_ll_get_raw_value();
|
||||
ESP_LOGV(TAG, "tsens_out %d", tsens_out);
|
||||
|
||||
*out_celsius = parse_temp_sensor_raw_value(tsens_out, tsens->tsens_attribute->offset);
|
||||
if (*out_celsius < tsens->tsens_attribute->range_min || *out_celsius > tsens->tsens_attribute->range_max) {
|
||||
ESP_LOGW(TAG, "Temperature range exceeded!");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
ESP_LOGW(TAG, "value out of range, probably invalid");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -422,10 +422,12 @@ static void setup_testbench(void)
|
||||
TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit));
|
||||
}
|
||||
|
||||
static void tear_testbench(void)
|
||||
{
|
||||
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_del_unit(pcnt_unit));
|
||||
}
|
||||
@@ -496,7 +498,7 @@ TEST_CASE("LEDC set and get frequency", "[ledc][timeout=60][ignore]")
|
||||
}
|
||||
|
||||
static void timer_set_clk_src_and_freq_test(ledc_mode_t speed_mode, ledc_clk_cfg_t clk_src, uint32_t duty_res,
|
||||
uint32_t freq_hz)
|
||||
uint32_t freq_hz)
|
||||
{
|
||||
ledc_timer_config_t ledc_time_config = {
|
||||
.speed_mode = speed_mode,
|
||||
|
||||
@@ -112,6 +112,7 @@ static void pcnt_setup_testbench(void)
|
||||
TEST_ESP_OK(pcnt_new_channel(pcnt_unit_a, &chan_a_config, &pcnt_chan_a));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan_a, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan_a, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit_a));
|
||||
|
||||
// PWMB <--> PCNT UNIT1
|
||||
pcnt_unit_config_t unit_b_config = {
|
||||
@@ -126,10 +127,13 @@ static void pcnt_setup_testbench(void)
|
||||
TEST_ESP_OK(pcnt_new_channel(pcnt_unit_b, &chan_b_config, &pcnt_chan_b));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan_b, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan_b, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit_b));
|
||||
}
|
||||
|
||||
static void pcnt_tear_testbench(void)
|
||||
{
|
||||
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit_a));
|
||||
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit_b));
|
||||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan_a));
|
||||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan_b));
|
||||
TEST_ESP_OK(pcnt_del_unit(pcnt_unit_a));
|
||||
|
||||
@@ -72,6 +72,12 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]")
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &timers[i]));
|
||||
}
|
||||
// start timer before enable should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gptimer_start(timers[0]));
|
||||
printf("enable timers\r\n");
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_enable(timers[i]));
|
||||
}
|
||||
printf("start timers\r\n");
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
@@ -109,6 +115,11 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]")
|
||||
printf("get raw count of gptimer %d: %llu\r\n", i, value);
|
||||
TEST_ASSERT_UINT_WITHIN(2000, 40000, value);
|
||||
}
|
||||
printf("disable timers\r\n");
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_disable(timers[i]));
|
||||
}
|
||||
printf("delete timers\r\n");
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_del_timer(timers[i]));
|
||||
}
|
||||
@@ -149,6 +160,7 @@ TEST_CASE("gptimer_stop_on_alarm", "[gptimer]")
|
||||
alarm_config.alarm_count = 100000 * (i + 1);
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(timers[i], &alarm_config));
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(timers[i], &cbs, task_handle));
|
||||
TEST_ESP_OK(gptimer_enable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
printf("alarm value for gptimer %d: %llu\r\n", i, alarm_config.alarm_count);
|
||||
}
|
||||
@@ -184,6 +196,7 @@ TEST_CASE("gptimer_stop_on_alarm", "[gptimer]")
|
||||
}
|
||||
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_disable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(timers[i]));
|
||||
}
|
||||
}
|
||||
@@ -226,16 +239,18 @@ TEST_CASE("gptimer_auto_reload_on_alarm", "[gptimer]")
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(timers[i], &alarm_config));
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(timers[i], &cbs, task_handle));
|
||||
TEST_ESP_OK(gptimer_enable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
|
||||
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
|
||||
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
|
||||
// delete should fail if timer is not stopped
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, gptimer_del_timer(timers[i]));
|
||||
// delete should fail if timer is not disabled
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gptimer_del_timer(timers[i]));
|
||||
TEST_ESP_OK(gptimer_stop(timers[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_disable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(timers[i]));
|
||||
}
|
||||
}
|
||||
@@ -276,6 +291,7 @@ TEST_CASE("gptimer_one_shot_alarm", "[gptimer]")
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(timers[i], &alarm_config));
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(timers[i], &cbs, task_handle));
|
||||
TEST_ESP_OK(gptimer_enable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
|
||||
// no alarm event should trigger again, as auto-reload is not enabled and alarm value hasn't changed in the isr
|
||||
@@ -296,6 +312,7 @@ TEST_CASE("gptimer_one_shot_alarm", "[gptimer]")
|
||||
}
|
||||
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_disable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(timers[i]));
|
||||
}
|
||||
}
|
||||
@@ -337,6 +354,7 @@ TEST_CASE("gptimer_update_alarm_dynamically", "[gptimer]")
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(timers[i], &alarm_config));
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(timers[i], &cbs, task_handle));
|
||||
TEST_ESP_OK(gptimer_enable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
// check the alarm event for multiple times
|
||||
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(500)));
|
||||
@@ -360,6 +378,7 @@ TEST_CASE("gptimer_update_alarm_dynamically", "[gptimer]")
|
||||
}
|
||||
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_disable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(timers[i]));
|
||||
}
|
||||
}
|
||||
@@ -402,6 +421,7 @@ TEST_CASE("gptimer_count_down_reload", "[gptimer]")
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(timers[i], &alarm_config));
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(timers[i], &cbs, task_handle));
|
||||
TEST_ESP_OK(gptimer_enable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
// check twice, as it's a period event
|
||||
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
|
||||
@@ -419,6 +439,7 @@ TEST_CASE("gptimer_count_down_reload", "[gptimer]")
|
||||
}
|
||||
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_disable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(timers[i]));
|
||||
}
|
||||
}
|
||||
@@ -467,12 +488,14 @@ TEST_CASE("gptimer_overflow", "[gptimer]")
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(timers[i], &cbs, task_handle));
|
||||
// we start from the reload value
|
||||
TEST_ESP_OK(gptimer_set_raw_count(timers[i], reload_at));
|
||||
TEST_ESP_OK(gptimer_enable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(400)));
|
||||
TEST_ESP_OK(gptimer_stop(timers[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_disable(timers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(timers[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ TEST_CASE("gptimer_iram_interrupt_safe", "[gptimer]")
|
||||
};
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, &block_arg));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
|
||||
xTaskCreatePinnedToCore(flash_read_task, "read_flash", 2048, &read_arg, 3, NULL, portNUM_PROCESSORS - 1);
|
||||
@@ -93,6 +94,7 @@ TEST_CASE("gptimer_iram_interrupt_safe", "[gptimer]")
|
||||
TEST_ASSERT_GREATER_THAN(1000, block_arg.repeat_count);
|
||||
// delete gptimer
|
||||
TEST_ESP_OK(gptimer_stop(gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
vSemaphoreDelete(done_sem);
|
||||
free(buf);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
set(srcs "test_app_main.c"
|
||||
"test_pulse_cnt.c")
|
||||
"test_pulse_cnt_simulator.c"
|
||||
"test_pulse_cnt.c"
|
||||
"test_pulse_cnt_iram.c")
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
|
||||
@@ -13,43 +13,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#define TEST_PCNT_GPIO_A 0
|
||||
#define TEST_PCNT_GPIO_B 2
|
||||
|
||||
#if CONFIG_PCNT_ISR_IRAM_SAFE
|
||||
#define TEST_PCNT_CALLBACK_ATTR IRAM_ATTR
|
||||
#else
|
||||
#define TEST_PCNT_CALLBACK_ATTR
|
||||
#endif // CONFIG_PCNT_ISR_IRAM_SAFE
|
||||
|
||||
// helper function to simulate several rising edges on gpio
|
||||
static void test_gpio_simulate_rising_edge(int gpio_sig, size_t times)
|
||||
{
|
||||
while (times--) {
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig, 0));
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to simulate several groups of quadrature signals
|
||||
static void test_gpio_simulate_quadrature_signals(int gpio_sig_a, int gpio_sig_b, size_t times)
|
||||
{
|
||||
while (times--) {
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_a, 1));
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_b, 0));
|
||||
vTaskDelay(1);
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_a, 0));
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_b, 0));
|
||||
vTaskDelay(1);
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_a, 0));
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_b, 1));
|
||||
vTaskDelay(1);
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_a, 1));
|
||||
TEST_ESP_OK(gpio_set_level(gpio_sig_b, 1));
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
#include "test_pulse_cnt_board.h"
|
||||
|
||||
TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
|
||||
{
|
||||
@@ -80,18 +44,28 @@ TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
|
||||
filter_config.max_glitch_ns = 500000;
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_set_glitch_filter(units[0], &filter_config));
|
||||
|
||||
printf("enable pcnt units\r\n");
|
||||
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_enable(units[i]));
|
||||
}
|
||||
|
||||
printf("start pcnt units\r\n");
|
||||
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_start(units[i]));
|
||||
}
|
||||
// can't uninstall unit before stop it
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[0]));
|
||||
|
||||
printf("stop pcnt units\r\n");
|
||||
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_stop(units[i]));
|
||||
}
|
||||
|
||||
// can't uninstall unit before disable it
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[0]));
|
||||
printf("disable pcnt units\r\n");
|
||||
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_disable(units[i]));
|
||||
}
|
||||
|
||||
printf("uninstall pcnt units\r\n");
|
||||
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
TEST_ESP_OK(pcnt_del_unit(units[i]));
|
||||
@@ -125,6 +99,7 @@ TEST_CASE("pcnt_channel_install_uninstall", "[pcnt]")
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(chans[i][j], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
}
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_new_channel(units[i], &chan_config, &chans[i][0]));
|
||||
TEST_ESP_OK(pcnt_unit_enable(units[i]));
|
||||
}
|
||||
|
||||
printf("start units\r\n");
|
||||
@@ -174,6 +149,7 @@ TEST_CASE("pcnt_channel_install_uninstall", "[pcnt]")
|
||||
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
// stop unit
|
||||
TEST_ESP_OK(pcnt_unit_stop(units[i]));
|
||||
TEST_ESP_OK(pcnt_unit_disable(units[i]));
|
||||
// can't uninstall unit when channel is still alive
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[i]));
|
||||
for (int j = 0; j < SOC_PCNT_CHANNELS_PER_UNIT; j++) {
|
||||
@@ -257,6 +233,9 @@ TEST_CASE("pcnt_quadrature_decode_event", "[pcnt]")
|
||||
|
||||
// Clear internal counter, and make the watch points take effect
|
||||
TEST_ESP_OK(pcnt_unit_clear_count(unit));
|
||||
// start unit should fail if it's not enabled yet
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_start(unit));
|
||||
TEST_ESP_OK(pcnt_unit_enable(unit));
|
||||
TEST_ESP_OK(pcnt_unit_start(unit));
|
||||
|
||||
printf("simulating quadrature signals\r\n");
|
||||
@@ -300,6 +279,7 @@ TEST_CASE("pcnt_quadrature_decode_event", "[pcnt]")
|
||||
TEST_ESP_OK(pcnt_del_channel(channelA));
|
||||
TEST_ESP_OK(pcnt_del_channel(channelB));
|
||||
TEST_ESP_OK(pcnt_unit_stop(unit));
|
||||
TEST_ESP_OK(pcnt_unit_disable(unit));
|
||||
TEST_ESP_OK(pcnt_del_unit(unit));
|
||||
}
|
||||
|
||||
@@ -354,6 +334,9 @@ TEST_CASE("pcnt_zero_cross_mode", "[pcnt]")
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(channelB, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
|
||||
printf("enable unit\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_enable(unit));
|
||||
|
||||
printf("start unit\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_start(unit));
|
||||
|
||||
@@ -397,6 +380,7 @@ TEST_CASE("pcnt_zero_cross_mode", "[pcnt]")
|
||||
TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_NEG_ZERO, user_data.mode);
|
||||
|
||||
TEST_ESP_OK(pcnt_unit_stop(unit));
|
||||
TEST_ESP_OK(pcnt_unit_disable(unit));
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 0));
|
||||
TEST_ESP_OK(pcnt_del_channel(channelA));
|
||||
TEST_ESP_OK(pcnt_del_channel(channelB));
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TEST_PCNT_GPIO_A 0
|
||||
#define TEST_PCNT_GPIO_B 2
|
||||
|
||||
#if CONFIG_PCNT_ISR_IRAM_SAFE
|
||||
#define TEST_PCNT_CALLBACK_ATTR IRAM_ATTR
|
||||
#else
|
||||
#define TEST_PCNT_CALLBACK_ATTR
|
||||
#endif // CONFIG_PCNT_ISR_IRAM_SAFE
|
||||
|
||||
void test_gpio_simulate_rising_edge(int gpio_sig, size_t times);
|
||||
void test_gpio_simulate_quadrature_signals(int gpio_sig_a, int gpio_sig_b, size_t times);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
104
components/driver/test_apps/pulse_cnt/main/test_pulse_cnt_iram.c
Normal file
104
components/driver/test_apps/pulse_cnt/main/test_pulse_cnt_iram.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "driver/pulse_cnt.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "test_pulse_cnt_board.h"
|
||||
|
||||
#if CONFIG_PCNT_ISR_IRAM_SAFE
|
||||
|
||||
static bool IRAM_ATTR test_pcnt_iram_safe_callback(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
uint32_t *data = (uint32_t *)user_data;
|
||||
(*data)++;
|
||||
// PCNT control function can still work in ISR
|
||||
pcnt_unit_stop(unit);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR test_pcnt_iram_simulation(int gpio_sig)
|
||||
{
|
||||
// disable flash cache
|
||||
spi_flash_guard_get()->start();
|
||||
test_gpio_simulate_rising_edge(gpio_sig, 2);
|
||||
// enable flash cache
|
||||
spi_flash_guard_get()->end();
|
||||
}
|
||||
|
||||
TEST_CASE("pcnt_iram_interrupt_safe", "[pcnt]")
|
||||
{
|
||||
pcnt_unit_config_t unit_config = {
|
||||
.low_limit = -100,
|
||||
.high_limit = 100
|
||||
};
|
||||
|
||||
printf("install pcnt unit\r\n");
|
||||
pcnt_unit_handle_t unit = NULL;
|
||||
TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
|
||||
|
||||
printf("add watch point and event callback\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 2));
|
||||
pcnt_event_callbacks_t cbs = {
|
||||
.on_reach = test_pcnt_iram_safe_callback,
|
||||
};
|
||||
uint32_t num_of_event_triggered = 0;
|
||||
TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &num_of_event_triggered));
|
||||
|
||||
printf("install pcnt channels\r\n");
|
||||
pcnt_chan_config_t channel_config = {
|
||||
.edge_gpio_num = TEST_PCNT_GPIO_A,
|
||||
.level_gpio_num = -1,
|
||||
.flags.io_loop_back = true,
|
||||
};
|
||||
pcnt_channel_handle_t channelA = NULL;
|
||||
pcnt_channel_handle_t channelB = NULL;
|
||||
TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelA));
|
||||
TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelB));
|
||||
|
||||
printf("enable unit\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_enable(unit));
|
||||
|
||||
printf("Set pcnt actions for channels\r\n");
|
||||
// both channels increase on pulse edge
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(channelA, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(channelB, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
|
||||
printf("start unit\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_start(unit));
|
||||
|
||||
printf("disable cache and check interrupt triggered\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_clear_count(unit));
|
||||
// the function that will disable the flash must be placed in the IRAM
|
||||
test_pcnt_iram_simulation(TEST_PCNT_GPIO_A);
|
||||
// check if the interrupt has fired up
|
||||
TEST_ASSERT_EQUAL(1, num_of_event_triggered);
|
||||
|
||||
printf("check current count value\r\n");
|
||||
int cur_count = 0;
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &cur_count));
|
||||
// when the watch point got triggered, we disabled the PCNT unit in thr `test_pcnt_iram_safe_callback()`
|
||||
// so the finally count value should equal to the watch point value
|
||||
TEST_ASSERT_EQUAL(2, cur_count);
|
||||
|
||||
printf("delete channels and unit\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_disable(unit));
|
||||
TEST_ESP_OK(pcnt_del_channel(channelA));
|
||||
TEST_ESP_OK(pcnt_del_channel(channelB));
|
||||
TEST_ESP_OK(pcnt_del_unit(unit));
|
||||
}
|
||||
|
||||
#endif // CONFIG_PCNT_ISR_IRAM_SAFE
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_attr.h"
|
||||
#include "test_pulse_cnt_board.h"
|
||||
|
||||
// helper function to simulate several rising edges on gpio
|
||||
IRAM_ATTR void test_gpio_simulate_rising_edge(int gpio_sig, size_t times)
|
||||
{
|
||||
while (times--) {
|
||||
gpio_set_level(gpio_sig, 0);
|
||||
gpio_set_level(gpio_sig, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to simulate several groups of quadrature signals
|
||||
IRAM_ATTR void test_gpio_simulate_quadrature_signals(int gpio_sig_a, int gpio_sig_b, size_t times)
|
||||
{
|
||||
while (times--) {
|
||||
gpio_set_level(gpio_sig_a, 1);
|
||||
gpio_set_level(gpio_sig_b, 0);
|
||||
vTaskDelay(1);
|
||||
gpio_set_level(gpio_sig_a, 0);
|
||||
gpio_set_level(gpio_sig_b, 0);
|
||||
vTaskDelay(1);
|
||||
gpio_set_level(gpio_sig_a, 0);
|
||||
gpio_set_level(gpio_sig_b, 1);
|
||||
vTaskDelay(1);
|
||||
gpio_set_level(gpio_sig_a, 1);
|
||||
gpio_set_level(gpio_sig_b, 1);
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_PCNT_CTRL_FUNC_IN_IRAM=y
|
||||
CONFIG_PCNT_ISR_IRAM_SAFE=y
|
||||
CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y
|
||||
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
@@ -36,5 +36,17 @@ void tearDown(void)
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// _____ ____
|
||||
// |_ _|__ _ __ ___ _ __ / ___| ___ _ __ ___ ___ _ __
|
||||
// | |/ _ \ '_ ` _ \| '_ \ \___ \ / _ \ '_ \/ __|/ _ \| '__|
|
||||
// | | __/ | | | | | |_) | ___) | __/ | | \__ \ (_) | |
|
||||
// |_|\___|_| |_| |_| .__/ |____/ \___|_| |_|___/\___/|_|
|
||||
// |_|
|
||||
printf(" _____ ____\r\n");
|
||||
printf("|_ _|__ _ __ ___ _ __ / ___| ___ _ __ ___ ___ _ __\r\n");
|
||||
printf(" | |/ _ \\ '_ ` _ \\| '_ \\ \\___ \\ / _ \\ '_ \\/ __|/ _ \\| '__|\r\n");
|
||||
printf(" | | __/ | | | | | |_) | ___) | __/ | | \\__ \\ (_) | |\r\n");
|
||||
printf(" |_|\\___|_| |_| |_| .__/ |____/ \\___|_| |_|___/\\___/|_|\r\n");
|
||||
printf(" |_|\r\n");
|
||||
unity_run_menu();
|
||||
}
|
||||
|
||||
@@ -16,21 +16,25 @@ TEST_CASE("Temperature_sensor_driver_workflow_test", "[temperature_sensor]")
|
||||
temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50);
|
||||
temperature_sensor_handle_t temp_handle = NULL;
|
||||
TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_start(temp_handle));
|
||||
// read sensor before enable it should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, temperature_sensor_get_celsius(temp_handle, &tsens_out));
|
||||
TEST_ESP_OK(temperature_sensor_enable(temp_handle));
|
||||
printf("Temperature sensor started\n");
|
||||
TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out));
|
||||
printf("Temperature out celsius %f°C\n", tsens_out);
|
||||
TEST_ESP_OK(temperature_sensor_stop(temp_handle));
|
||||
// uninstall driver before disable it should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, temperature_sensor_uninstall(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_disable(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_uninstall(temp_handle));
|
||||
// Reconfig the temperature sensor.
|
||||
temp_sensor.range_min = -20;
|
||||
temp_sensor.range_max = 45;
|
||||
TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_start(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_enable(temp_handle));
|
||||
printf("Temperature sensor started again\n");
|
||||
TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out));
|
||||
printf("Temperature out celsius %f°C\n", tsens_out);
|
||||
TEST_ESP_OK(temperature_sensor_stop(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_disable(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_uninstall(temp_handle));
|
||||
}
|
||||
|
||||
@@ -50,9 +54,9 @@ TEST_CASE("Double start error cause test", "[temperature_sensor]")
|
||||
temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50);
|
||||
temperature_sensor_handle_t temp_handle = NULL;
|
||||
TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_start(temp_handle));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, temperature_sensor_start(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_stop(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_enable(temp_handle));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, temperature_sensor_enable(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_disable(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_uninstall(temp_handle));
|
||||
}
|
||||
|
||||
@@ -63,15 +67,15 @@ TEST_CASE("Double Start-Stop test", "[temperature_sensor]")
|
||||
temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50);
|
||||
temperature_sensor_handle_t temp_handle = NULL;
|
||||
TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_start(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_enable(temp_handle));
|
||||
printf("Temperature sensor started\n");
|
||||
TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out));
|
||||
printf("Temperature out celsius %f°C\n", tsens_out);
|
||||
TEST_ESP_OK(temperature_sensor_stop(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_start(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_disable(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_enable(temp_handle));
|
||||
printf("Temperature sensor started again\n");
|
||||
TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out));
|
||||
printf("Temperature out celsius %f°C\n", tsens_out);
|
||||
TEST_ESP_OK(temperature_sensor_stop(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_disable(temp_handle));
|
||||
TEST_ESP_OK(temperature_sensor_uninstall(temp_handle));
|
||||
}
|
||||
|
||||
@@ -2002,6 +2002,7 @@ TEST_CASE("can post events from interrupt handler", "[event]")
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, sem));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
|
||||
TEST_SETUP();
|
||||
@@ -2012,6 +2013,7 @@ TEST_CASE("can post events from interrupt handler", "[event]")
|
||||
xSemaphoreTake(sem, portMAX_DELAY);
|
||||
|
||||
TEST_TEARDOWN();
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ static void timer_test(int flags)
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimers[i], &cbs, &count[i]));
|
||||
alarm_config.alarm_count += 10000 * i;
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimers[i], &alarm_config));
|
||||
TEST_ESP_OK(gptimer_enable(gptimers[i]));
|
||||
TEST_ESP_OK(gptimer_start(gptimers[i]));
|
||||
TEST_ESP_OK(gptimer_get_intr_handle(gptimers[i], &inth[i]));
|
||||
printf("Interrupts allocated: %d\r\n", esp_intr_get_intno(inth[i]));
|
||||
@@ -93,6 +94,7 @@ static void timer_test(int flags)
|
||||
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_stop(gptimers[i]));
|
||||
TEST_ESP_OK(gptimer_disable(gptimers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimers[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]")
|
||||
.resolution_hz = 1000000, /* 1 us per tick */
|
||||
};
|
||||
TEST_ESP_OK(gptimer_new_timer(&config, &gptimer));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
// if GPTimer is clocked from APB, when PM is enabled, the driver will acquire the PM lock
|
||||
// causing the auto light sleep doesn't take effect
|
||||
@@ -174,6 +175,7 @@ TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]")
|
||||
light_sleep_disable();
|
||||
TEST_ESP_OK(esp_pm_lock_acquire(gptimer_pm_lock));
|
||||
TEST_ESP_OK(gptimer_stop(gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
}
|
||||
|
||||
|
||||
@@ -779,12 +779,14 @@ TEST_CASE("Test ring buffer ISR", "[esp_ringbuf]")
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
//Wait for ISR to complete multiple iterations
|
||||
xSemaphoreTake(done_sem, portMAX_DELAY);
|
||||
|
||||
//Cleanup
|
||||
TEST_ESP_OK(gptimer_stop(gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
vSemaphoreDelete(done_sem);
|
||||
for (int i = 0; i < NO_OF_RB_TYPES; i++) {
|
||||
|
||||
@@ -176,6 +176,7 @@ TEST_CASE("FreeRTOS Event Group ISR", "[freertos]")
|
||||
.on_alarm = on_timer_alarm_cb,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
|
||||
//Test set bits
|
||||
@@ -195,6 +196,7 @@ TEST_CASE("FreeRTOS Event Group ISR", "[freertos]")
|
||||
TEST_ASSERT_EQUAL(0, xEventGroupGetBits(eg)); //Check bits are cleared
|
||||
|
||||
//Clean up
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
vEventGroupDelete(eg);
|
||||
vSemaphoreDelete(done_sem);
|
||||
|
||||
@@ -63,10 +63,6 @@ static void test_gptimer_start(void *arg)
|
||||
.alarm_count = 1000,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_set_raw_count(gptimer, 0));
|
||||
gptimer_event_callbacks_t cbs = {
|
||||
.on_alarm = on_alarm_sender_cb,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
}
|
||||
@@ -144,6 +140,11 @@ static void install_gptimer_on_core(void *arg)
|
||||
.resolution_hz = 1000000, // 1MHz, 1 tick = 1us
|
||||
};
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimers[core_id]));
|
||||
gptimer_event_callbacks_t cbs = {
|
||||
.on_alarm = on_alarm_sender_cb,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimers[core_id], &cbs, NULL));
|
||||
TEST_ESP_OK(gptimer_enable(gptimers[core_id]));
|
||||
test_gptimer_start(gptimers[core_id]);
|
||||
xSemaphoreGive(task_delete_semphr);
|
||||
vTaskDelete(NULL);
|
||||
@@ -191,6 +192,7 @@ TEST_CASE("Test Task_Notify", "[freertos]")
|
||||
vSemaphoreDelete(task_delete_semphr);
|
||||
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
||||
TEST_ESP_OK(gptimer_stop(gptimers[i]));
|
||||
TEST_ESP_OK(gptimer_disable(gptimers[i]));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimers[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
|
||||
.on_alarm = on_timer_alarm_cb,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
TEST_ESP_OK(gptimer_get_intr_handle(gptimer, &intr_handle));
|
||||
@@ -130,6 +131,7 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
|
||||
}
|
||||
|
||||
TEST_ESP_OK(gptimer_stop(gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
vTaskDelete(counter_task);
|
||||
vSemaphoreDelete(isr_semaphore);
|
||||
|
||||
@@ -173,6 +173,7 @@ static void test_resume_task_from_isr(int target_core)
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, suspend_task));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
// wait the timer interrupt fires up
|
||||
vTaskDelay(2);
|
||||
@@ -184,6 +185,7 @@ static void test_resume_task_from_isr(int target_core)
|
||||
TEST_ASSERT_UINT32_WITHIN(100, alarm_config.alarm_count, (unsigned)resumed_counter);
|
||||
|
||||
// clean up
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
}
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ TEST_CASE("eventfd signal from ISR", "[vfs][eventfd]")
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, &fd));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_enable(gptimer));
|
||||
TEST_ESP_OK(gptimer_start(gptimer));
|
||||
|
||||
struct timeval wait_time;
|
||||
@@ -258,6 +259,7 @@ TEST_CASE("eventfd signal from ISR", "[vfs][eventfd]")
|
||||
TEST_ASSERT(FD_ISSET(fd, &read_fds));
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
TEST_ESP_OK(gptimer_disable(gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(gptimer));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user