Merge branch 'feature/mcpwm_timer_change_freq' into 'master'

feat(mcpwm): support update timer period dynamically

Closes IDFGH-11145

See merge request espressif/esp-idf!26419
pull/12486/head
morris 2023-10-23 15:51:14 +08:00
commit 767595a22f
11 zmienionych plików z 88 dodań i 25 usunięć

Wyświetl plik

@ -69,6 +69,24 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
*/
esp_err_t mcpwm_del_timer(mcpwm_timer_handle_t timer);
/**
* @brief Set a new period for MCPWM timer
*
* @note If `mcpwm_timer_config_t::update_period_on_empty` and `mcpwm_timer_config_t::update_period_on_sync` are not set,
* the new period will take effect immediately.
* Otherwise, the new period will take effect when timer counts to zero or on sync event.
* @note You may need to use `mcpwm_comparator_set_compare_value` to set a new compare value for MCPWM comparator
* in order to keep the same PWM duty cycle.
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer`
* @param[in] period_ticks New period in count ticks
* @return
* - ESP_OK: Set new period for MCPWM timer successfully
* - ESP_ERR_INVALID_ARG: Set new period for MCPWM timer failed because of invalid argument
* - ESP_FAIL: Set new period for MCPWM timer failed because of other error
*/
esp_err_t mcpwm_timer_set_period(mcpwm_timer_handle_t timer, uint32_t period_ticks);
/**
* @brief Enable MCPWM timer
*

Wyświetl plik

@ -3,3 +3,4 @@ archive: libdriver.a
entries:
if MCPWM_CTRL_FUNC_IN_IRAM = y:
mcpwm_cmpr: mcpwm_comparator_set_compare_value (noflash)
mcpwm_timer: mcpwm_timer_set_period (noflash)

Wyświetl plik

@ -95,6 +95,12 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
ESP_GOTO_ON_FALSE(1 << (config->intr_priority) & MCPWM_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG, err,
TAG, "invalid interrupt priority:%d", config->intr_priority);
}
// check the peak ticks that the timer can reach to
uint32_t peak_ticks = config->period_ticks;
if (config->count_mode == MCPWM_TIMER_COUNT_MODE_UP_DOWN) {
peak_ticks /= 2; // in symmetric mode, peak_ticks = period_ticks / 2
}
ESP_GOTO_ON_FALSE(peak_ticks > 0 && peak_ticks < MCPWM_LL_MAX_COUNT_VALUE, ESP_ERR_INVALID_ARG, err, TAG, "invalid period ticks");
timer = heap_caps_calloc(1, sizeof(mcpwm_timer_t), MCPWM_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(timer, ESP_ERR_NO_MEM, err, TAG, "no mem for timer");
@ -125,10 +131,6 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
// set the peak tickes that the timer can reach to
timer->count_mode = config->count_mode;
uint32_t peak_ticks = config->period_ticks;
if (timer->count_mode == MCPWM_TIMER_COUNT_MODE_UP_DOWN) {
peak_ticks /= 2; // in symmetric mode, peak_ticks = period_ticks / 2
}
timer->peak_ticks = peak_ticks;
mcpwm_ll_timer_set_peak(hal->dev, timer_id, peak_ticks, timer->count_mode == MCPWM_TIMER_COUNT_MODE_UP_DOWN);
// set count direction
@ -174,6 +176,22 @@ esp_err_t mcpwm_del_timer(mcpwm_timer_handle_t timer)
return ESP_OK;
}
esp_err_t mcpwm_timer_set_period(mcpwm_timer_handle_t timer, uint32_t period_ticks)
{
ESP_RETURN_ON_FALSE_ISR(timer, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
mcpwm_group_t *group = timer->group;
int timer_id = timer->timer_id;
mcpwm_hal_context_t *hal = &group->hal;
uint32_t peak_ticks = period_ticks;
if (timer->count_mode == MCPWM_TIMER_COUNT_MODE_UP_DOWN) {
peak_ticks /= 2; // in symmetric mode, peak_ticks = period_ticks / 2
}
ESP_RETURN_ON_FALSE_ISR(peak_ticks > 0 && peak_ticks < MCPWM_LL_MAX_COUNT_VALUE, ESP_ERR_INVALID_ARG, TAG, "invalid period ticks");
mcpwm_ll_timer_set_peak(hal->dev, timer_id, peak_ticks, timer->count_mode == MCPWM_TIMER_COUNT_MODE_UP_DOWN);
timer->peak_ticks = peak_ticks;
return ESP_OK;
}
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");
@ -203,8 +221,8 @@ esp_err_t mcpwm_timer_register_event_callbacks(mcpwm_timer_handle_t timer, const
int isr_flags = MCPWM_INTR_ALLOC_FLAG;
isr_flags |= mcpwm_get_intr_priority_flag(group);
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),
mcpwm_timer_default_isr, timer, &timer->intr), TAG, "install interrupt service for timer failed");
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_TIMER_MASK(timer_id),
mcpwm_timer_default_isr, timer, &timer->intr), TAG, "install interrupt service for timer failed");
}
// enable/disable interrupt events

Wyświetl plik

@ -177,9 +177,26 @@ TEST_CASE("mcpwm_timer_event_callbacks", "[mcpwm]")
bits = xEventGroupWaitBits(event_group, TEST_MCPWM_TIMER_EVENT_BIT_STOP, pdTRUE, pdTRUE, pdMS_TO_TICKS(50));
TEST_ASSERT_EQUAL(TEST_MCPWM_TIMER_EVENT_BIT_STOP, bits);
printf("update timer period\r\n");
TEST_ESP_OK(mcpwm_timer_set_period(timer, 50 * 1000)); // period: 50ms, 20Hz
udata.accumulate_empty_counts = 0;
udata.accumulate_full_counts = 0;
printf("start timer\r\n");
TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));
printf("wait for full and empty events\r\n");
bits = xEventGroupWaitBits(event_group, TEST_MCPWM_TIMER_EVENT_BIT_FULL | TEST_MCPWM_TIMER_EVENT_BIT_EMPTY, pdTRUE, pdTRUE, pdMS_TO_TICKS(1500));
// because the timer period changed, the previous wait time is not sufficient, so timeout
TEST_ASSERT_EQUAL(0, bits);
bits = xEventGroupWaitBits(event_group, TEST_MCPWM_TIMER_EVENT_BIT_FULL | TEST_MCPWM_TIMER_EVENT_BIT_EMPTY, pdTRUE, pdTRUE, pdMS_TO_TICKS(1500));
TEST_ASSERT_EQUAL(TEST_MCPWM_TIMER_EVENT_BIT_FULL | TEST_MCPWM_TIMER_EVENT_BIT_EMPTY, bits);
printf("stop timer\r\n");
TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_STOP_EMPTY));
printf("disable timer\r\n");
TEST_ESP_OK(mcpwm_timer_disable(timer));
printf("delete timer\r\n");
TEST_ESP_OK(mcpwm_del_timer(timer));
vEventGroupDelete(event_group);

Wyświetl plik

@ -251,13 +251,12 @@ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int tim
* @param peak Peak value
* @param symmetric True to set symmetric peak value, False to set asymmetric peak value
*/
__attribute__((always_inline))
static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric)
{
if (!symmetric) { // in asymmetric mode, period = [0,peak-1]
HAL_ASSERT(peak > 0 && peak <= MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1);
} else { // in symmetric mode, period = [0,peak-1] + [peak,1]
HAL_ASSERT(peak < MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak);
}
}

Wyświetl plik

@ -249,13 +249,12 @@ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int tim
* @param peak Peak value
* @param symmetric True to set symmetric peak value, False to set asymmetric peak value
*/
__attribute__((always_inline))
static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric)
{
if (!symmetric) { // in asymmetric mode, period = [0,peak-1]
HAL_ASSERT(peak > 0 && peak <= MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1);
} else { // in symmetric mode, period = [0,peak-1] + [peak,1]
HAL_ASSERT(peak < MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak);
}
}

Wyświetl plik

@ -247,13 +247,12 @@ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int tim
* @param peak Peak value
* @param symmetric True to set symmetric peak value, False to set asymmetric peak value
*/
__attribute__((always_inline))
static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric)
{
if (!symmetric) { // in asymmetric mode, period = [0,peak-1]
HAL_ASSERT(peak > 0 && peak <= MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1);
} else { // in symmetric mode, period = [0,peak-1] + [peak,1]
HAL_ASSERT(peak < MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak);
}
}

Wyświetl plik

@ -307,13 +307,12 @@ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int tim
* @param peak Peak value
* @param symmetric True to set symmetric peak value, False to set asymmetric peak value
*/
__attribute__((always_inline))
static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric)
{
if (!symmetric) { // in asymmetric mode, period = [0,peak-1]
HAL_ASSERT(peak > 0 && peak <= MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1);
} else { // in symmetric mode, period = [0,peak-1] + [peak,1]
HAL_ASSERT(peak < MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak);
}
}

Wyświetl plik

@ -247,13 +247,12 @@ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int tim
* @param peak Peak value
* @param symmetric True to set symmetric peak value, False to set asymmetric peak value
*/
__attribute__((always_inline))
static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric)
{
if (!symmetric) { // in asymmetric mode, period = [0,peak-1]
HAL_ASSERT(peak > 0 && peak <= MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1);
} else { // in symmetric mode, period = [0,peak-1] + [peak,1]
HAL_ASSERT(peak < MCPWM_LL_MAX_COUNT_VALUE);
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak);
}
}

Wyświetl plik

@ -26,8 +26,8 @@ The main submodules are listed in the following diagram:
- **MCPWM Sync**: The sync module is used to synchronize the MCPWM timers, so that the final PWM signals generated by different MCPWM generators can have a fixed phase difference. The sync signal can be routed from the GPIO matrix or from an MCPWM Timer event.
- **Dead Time**: This submodule is used to insert extra delay to the existing PWM edges generated in the previous steps.
- **Carrier Modulation**: The carrier submodule can modulate a high-frequency carrier signal into PWM waveforms by the generator and dead time submodules. This capability is mandatory for controlling the power-switching elements.
- **Brake**: MCPWM operator can set how to brake the generators when a particular fault is detected. We can shut down the PWM output immediately or regulate the PWM output cycle by cycle, depending on how critical the fault is.
- **MCPWM Capture**: This is a standalone submodule that can work even without the above MCPWM operators. The capture consists one dedicated timer and several independent channels, with each channel connected to the GPIO. A pulse on the GPIO triggers the capture timer to store the time-base count value and then notify you by an interrupt. Using this feature, we can measure a pulse width precisely. What is more, the capture timer can also be synchronized by the MCPWM Sync submodule.
- **Brake**: MCPWM operator can set how to brake the generators when a particular fault is detected. You can shut down the PWM output immediately or regulate the PWM output cycle by cycle, depending on how critical the fault is.
- **MCPWM Capture**: This is a standalone submodule that can work even without the above MCPWM operators. The capture consists one dedicated timer and several independent channels, with each channel connected to the GPIO. A pulse on the GPIO triggers the capture timer to store the time-base count value and then notify you by an interrupt. Using this feature, you can measure a pulse width precisely. What is more, the capture timer can also be synchronized by the MCPWM Sync submodule.
Functional Overview
-------------------
@ -161,7 +161,7 @@ To allocate a GPIO sync source, you can call the :cpp:func:`mcpwm_new_gpio_sync_
- :cpp:member:`mcpwm_gpio_sync_src_config_t::group_id` sets the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range. Please note, the GPIO sync sources located in different groups are totally independent, i.e., GPIO sync source in group 0 can not be detected by the timers in group 1.
- :cpp:member:`mcpwm_gpio_sync_src_config_t::gpio_num` sets the GPIO number used by the sync source.
- :cpp:member:`mcpwm_gpio_sync_src_config_t::active_neg` sets whether the sync signal is active on negative edges.
- :cpp:member:`mcpwm_gpio_sync_src_config_t::active_neg` sets whether the sync signal is active on falling edges.
- :cpp:member:`mcpwm_gpio_sync_src_config_t::pull_up` and :cpp:member:`mcpwm_gpio_sync_src_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally.
- :cpp:member:`mcpwm_gpio_sync_src_config_t::io_loop_back` sets whether to enable the Loop-back mode. It is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral.
@ -204,7 +204,7 @@ Next, to allocate a capture channel, you can call the :cpp:func:`mcpwm_new_captu
- :cpp:member:`mcpwm_capture_channel_config_t::intr_priority` sets the priority of the interrupt. If it is set to ``0``, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.
- :cpp:member:`mcpwm_capture_channel_config_t::gpio_num` sets the GPIO number used by the capture channel.
- :cpp:member:`mcpwm_capture_channel_config_t::prescale` sets the prescaler of the input signal.
- :cpp:member:`mcpwm_capture_channel_config_t::pos_edge` and :cpp:member:`mcpwm_capture_channel_config_t::neg_edge` set whether to capture on the positive and/or negative edge of the input signal.
- :cpp:member:`mcpwm_capture_channel_config_t::pos_edge` and :cpp:member:`mcpwm_capture_channel_config_t::neg_edge` set whether to capture on the positive and/or falling edge of the input signal.
- :cpp:member:`mcpwm_capture_channel_config_t::pull_up` and :cpp:member:`mcpwm_capture_channel_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally.
- :cpp:member:`mcpwm_capture_channel_config_t::invert_cap_signal` sets whether to invert the capture signal.
- :cpp:member:`mcpwm_capture_channel_config_t::io_loop_back` sets whether to enable the Loop-back mode. It is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral.
@ -228,6 +228,11 @@ MCPWM allows configuring interrupts separately for timer, operator, comparator,
Timer Operations and Events
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Update Period
~~~~~~~~~~~~~
The timer period is initialized by the :cpp:member:`mcpwm_timer_config_t::period_ticks` parameter in :cpp:type:`mcpwm_timer_config_t`. You can update the period at runtime by calling :cpp:func:`mcpwm_timer_set_period` function. The new period will take effect based on how you set the :cpp:member:`mcpwm_timer_config_t::update_period_on_empty` and :cpp:member:`mcpwm_timer_config_t::update_period_on_sync` parameters in :cpp:type:`mcpwm_timer_config_t`. If none of them are set, the timer period will take effect immediately.
Register Timer Event Callbacks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -345,7 +350,7 @@ One generator can set action on fault based trigger events, by calling :cpp:func
When no free trigger slot is left in the operator to which the generator belongs, this function will return the :c:macro:`ESP_ERR_NOT_FOUND` error. [1]_
The trigger only support GPOI fault. when the input is not a GPIO fault, this function will return the :c:macro:`ESP_ERR_NOT_SUPPORTED` error.
The trigger only support GPIO fault. when the input is not a GPIO fault, this function will return the :c:macro:`ESP_ERR_NOT_SUPPORTED` error.
There is a helper macro :c:macro:`MCPWM_GEN_FAULT_EVENT_ACTION` to simplify the construction of a trigger event action entry.
@ -502,7 +507,7 @@ Dead Time
In power electronics, the rectifier and inverter are commonly used. This requires the use of a rectifier bridge and an inverter bridge. Each bridge arm has two power electronic devices, such as MOSFET, IGBT, etc. The two MOSFETs on the same arm can not conduct at the same time, otherwise there will be a short circuit. The fact is that, although the PWM wave shows it is turning off the switch, the MOSFET still needs a small time window to make that happen. This requires an extra delay to be added to the existing PWM wave generated by setting `Generator Actions on Events <#generator-actions-on-events>`__.
The dead time driver works like a **decorator**. This is also reflected in the function parameters of :cpp:func:`mcpwm_generator_set_dead_time`, where it takes the primary generator handle (``in_generator``), and returns a new generator (``out_generator``) after applying the dead time. Please note, if the ``out_generator`` and ``in_generator`` are the same, it means we are adding the time delay to the PWM waveform in an "in-place" fashion. In turn, if the ``out_generator`` and ``in_generator`` are different, it means we are deriving a new PWM waveform from the existing ``in_generator``.
The dead time driver works like a **decorator**. This is also reflected in the function parameters of :cpp:func:`mcpwm_generator_set_dead_time`, where it takes the primary generator handle (``in_generator``), and returns a new generator (``out_generator``) after applying the dead time. Please note, if the ``out_generator`` and ``in_generator`` are the same, it means you are adding the time delay to the PWM waveform in an "in-place" fashion. In turn, if the ``out_generator`` and ``in_generator`` are different, it means you are deriving a new PWM waveform from the existing ``in_generator``.
Dead time specific configuration is listed in the :cpp:type:`mcpwm_dead_time_config_t` structure:
@ -773,7 +778,7 @@ Faults and Brake Actions
The MCPWM operator is able to sense external signals with information about the failure of the motor, the power driver or any other device connected. These failure signals are encapsulated into MCPWM fault objects.
You should determine possible failure modes of the motor and what action should be performed on detection of a particular fault, e.g., drive all outputs low for a brushed motor, lock current state for a stepper motor, etc. As a result of this action, the motor should be put into a safe state to reduce the likelihood of damage caused by the fault.
You should determine possible failure modes of the motor and what action should be performed on detection of a particular fault, e.g., drive all outputs low for a brushed motor, lock current state for a stepper motor, etc. Because of this action, the motor should be put into a safe state to reduce the likelihood of damage caused by the fault.
Set Operator Brake Mode on Fault
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -896,7 +901,7 @@ Sync Timers by GPIO
Capture
^^^^^^^
The basic functionality of MCPWM capture is to record the time when any pulse edge of the capture signal turns active. Then you can get the pulse width and convert it into other physical quantities like distance or speed in the capture callback function. For example, in the BLDC (Brushless DC, see figure below) scenario, we can use the capture submodule to sense the rotor position from the Hall sensor.
The basic functionality of MCPWM capture is to record the time when any pulse edge of the capture signal turns active. Then you can get the pulse width and convert it into other physical quantities like distance or speed in the capture callback function. For example, in the BLDC (Brushless DC, see figure below) scenario, you can use the capture submodule to sense the rotor position from the Hall sensor.
.. figure:: ../../../_static/mcpwm-bldc-control.png
:align: center
@ -991,6 +996,7 @@ This allows the interrupt to run while the cache is disabled but comes at the co
There is another Kconfig option :ref:`CONFIG_MCPWM_CTRL_FUNC_IN_IRAM` that can put commonly used IO control functions into IRAM as well. So, these functions can also be executable when the cache is disabled. The IO control function is as follows:
- :cpp:func:`mcpwm_comparator_set_compare_value`
- :cpp:func:`mcpwm_timer_set_period`
.. _mcpwm-thread-safety:
@ -1003,6 +1009,7 @@ The factory functions like :cpp:func:`mcpwm_new_timer` are guaranteed to be thre
The following function is allowed to run under the ISR context, as the driver uses a critical section to prevent them from being called concurrently in the task and ISR.
- :cpp:func:`mcpwm_comparator_set_compare_value`
- :cpp:func:`mcpwm_timer_set_period`
Other functions that are not related to `Resource Allocation and Initialization <#resource-allocation-and-initialization>`__, are not thread-safe. Thus, you should avoid calling them in different tasks without mutex protection.

Wyświetl plik

@ -228,6 +228,11 @@ MCPWM 允许为 定时器、操作器、比较器、故障以及捕获事件分
定时器操作和事件
^^^^^^^^^^^^^^^^^^^^^^^^^^^
更新定时器周期
~~~~~~~~~~~~~~
定时器周期在创建定时器时就已经通过 :cpp:member:`mcpwm_timer_config_t::period_ticks` 被初始化过了。你还可以在运行期间,调用 :cpp:func:`mcpwm_timer_set_period` 函数来更新定时周期。新周期的生效时机由 :cpp:member:`mcpwm_timer_config_t::update_period_on_empty`:cpp:member:`mcpwm_timer_config_t::update_period_on_sync` 共同决定。如果他们两个参数都是 ``false`` 那么新的定时周期会立即生效。
注册定时器事件回调
~~~~~~~~~~~~~~~~~~~~~~~~
@ -991,6 +996,7 @@ IRAM 安全
另一个 Kconfig 选项 :ref:`CONFIG_MCPWM_CTRL_FUNC_IN_IRAM` 也支持将常用的 IO 控制函数存放在 IRAM 中,以保证在禁用 cache 时可以正常使用函数。IO 控制函数如下所示:
- :cpp:func:`mcpwm_comparator_set_compare_value`
- :cpp:func:`mcpwm_timer_set_period`
.. _mcpwm-thread-safety:
@ -1003,6 +1009,7 @@ IRAM 安全
驱动程序设置了临界区,以防函数同时在任务和 ISR 中调用。因此,以下函数支持在 ISR 上下文运行:
- :cpp:func:`mcpwm_comparator_set_compare_value`
- :cpp:func:`mcpwm_timer_set_period`
:ref:`mcpwm-resource-allocation-and-initialization` 中尚未提及的函数并非线程安全。在没有设置互斥锁保护的任务中,应避免调用这些函数。