Peripherals
Peripheral Clock Gating
As usual, peripheral clock gating is still handled by driver itself, users don’t need to take care of the peripheral module clock gating.
However, for advanced users who implement their own drivers based on hal
and soc
components, the previous clock gating include path has been changed from driver/periph_ctrl.h
to esp_private/periph_ctrl.h
.
RTC Subsystem Control
RTC control APIs have been moved from driver/rtc_cntl.h
to esp_private/rtc_ctrl.h
.
ADC
ADC oneshot mode driver has been redesigned. New driver is in
esp_adc
component and the include path isesp_adc/adc_oneshot.h
. Legacy driver is still available in the previous include pathdriver/adc.h
. However, by default, includingdriver/adc.h
will bring a build warning like legacy adc driver is deprecated, please migrate to use esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode drivers respectively. The warning can be suppressed by the Kconfig option CONFIG_ADC_SUPPRESS_DEPRECATE_WARN.ADC continuous mode driver has been moved from
driver
component toesp_adc
component. Include path has been changed fromdriver/adc.h
toesp_adc/adc_continuous.h
. Legacy driver is still available in the previous include pathdriver/adc.h
. Similarly, including it will bring a build warning, and it can be suppressed by the Kconfig option CONFIG_ADC_SUPPRESS_DEPRECATE_WARN.ADC calibration driver has been redesigned. New driver is in
esp_adc
component and the include path isesp_adc/adc_cali.h
andesp_adc/adc_cali_scheme.h
. Legacy driver is still available by includingesp_adc_cal.h
. However, by default, includingesp_adc_cal.h
will bring a build warning like legacy adc calibration driver is deprecated, please migrate to use esp_adc/adc_cali.h and esp_adc/adc_cali_scheme.h. The warning can be suppressed by the Kconfig option CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN.API
adc_power_acquire
andadc_power_release
have been deprecated. These two are used by other drivers to maintain ADC power due to hardware limitation. After this change, ADC power will still be handled by the drivers. However, for users who are interested in this, the include path has been changed fromdriver/adc.h
toesp_private/adc_private.h
.Previous
driver/adc2_wifi_private.h
has been moved toesp_private/adc2_wifi.h
.Enums
ADC_UNIT_BOTH
,ADC_UNIT_ALTER
andADC_UNIT_MAX
inadc_unit_t
have been removed.Enum
ADC_CHANNEL_MAX
inadc_channel_t
has been removed. Some channels are not supported on some chips, driver will give a dynamic error if an unsupported channels are used.Enum
ADC_ATTEN_MAX
has been removed. Some attenuations are not supported on some chips, driver will give a dynamic error if an unsupported attenuation is used.Enum
ADC_CONV_UNIT_MAX
has been removed. Some convert mode are not supported on some chips, driver will give a dynamic error if an unsupported convert mode is used.API
hall_sensor_read
on ESP32 has been removed. Hall sensor is no more supported on ESP32.API
adc_set_i2s_data_source
andadc_i2s_mode_init
have been deprecated. Related enumadc_i2s_source_t
has been deprecated. Please migrate to useesp_adc/adc_continuous.h
.
GPIO
The previous Kconfig option RTCIO_SUPPORT_RTC_GPIO_DESC has been removed, thus the rtc_gpio_desc
array is unavailable. Please use rtc_io_desc
array instead.
Sigma-Delta Modulator
The Sigma-Delta Modulator driver has been redesigned into SDM. The new driver implements a factory pattern, where the SDM channels are managed in a pool internally, thus you don’t have to fix a SDM channel to a GPIO manually. All SDM channels can be allocated dynamically. Although it’s recommended to use the new driver APIs, the legacy driver is still available in the previous include path driver/sigmadelta.h
. However, by default, including driver/sigmadelta.h
will bring a build warning like The legacy sigma-delta driver is deprecated, please use driver/sdm.h
. The warning can be suppressed by Kconfig option CONFIG_SDM_SUPPRESS_DEPRECATE_WARN.
The major breaking changes in concept and usage are listed as follows:
Breaking Changes in Concepts
SDM channel representation has changed from
sigmadelta_channel_t
tosdm_channel_handle_t
, which is an opaque pointer.SDM channel configurations are stored in
sdm_config_t
now, instead the previoussigmadelta_config_t
.In the legacy driver, you don’t have to set the clock source for SDM channel. But in the new driver, you need to set a proper one in the
sdm_config_t::clk_src
. The available clock sources are listed in thesoc_periph_sdm_clk_src_t
.In the legacy driver, you need to set a
prescale
for the channel, which will reflected into the frequency the modulator output a pulse. In the new driver, you should usesdm_config_t::sample_rate_hz
.
Breaking Changes in Usage
Channel configuration was done by channel allocation, in
sdm_new_channel()
. In the new driver, only theduty
can be changed at runtime, bysdm_channel_set_duty()
. Other parameters likegpio number
andprescale
are only allowed to set during channel allocation.Before further channel operations, you should enable the channel in advance, by calling
sdm_channel_enable()
. This function will help to manage some system level services, like Power Management.
Timer Group Driver
Timer Group driver has been redesigned into GPTimer, which aims to unify and simplify the usage of general purpose timer. Although it’s recommended to use the the new driver APIs, the legacy driver is still available in the previous include path driver/timer.h
. However, by default, including driver/timer.h
will bring a build warning like legacy timer group driver is deprecated, please migrate to driver/gptimer.h
. The warning can be suppressed by the Kconfig option CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN.
The major breaking changes in concept and usage are listed as follows:
Breaking Changes in Concepts
timer_group_t
andtimer_idx_t
which used to identify the hardware timer are removed from user’s code. In the new driver, a timer is represented bygptimer_handle_t
.Definition of timer source clock is moved to
gptimer_clock_source_t
, the previoustimer_src_clk_t
is not used.Definition of timer count direction is moved to
gptimer_count_direction_t
, the previoustimer_count_dir_t
is not used.Only level interrupt is supported,
timer_intr_t
andtimer_intr_mode_t
are not used.Auto-reload is enabled by set the
gptimer_alarm_config_t::auto_reload_on_alarm
flag.timer_autoreload_t
is not used.
Breaking Changes in Usage
Timer initialization is done by creating a timer instance from
gptimer_new_timer()
. Basic configurations like clock source, resolution and direction should be set ingptimer_config_t
. Note that, alarm event specific configurations are not needed during the driver install stage.Alarm event is configured by
gptimer_set_alarm_action()
, with parameters set in thegptimer_alarm_config_t
.Setting and getting count value are done by
gptimer_get_raw_count()
andgptimer_set_raw_count()
. The driver doesn’t help convert the raw value into UTC time-stamp. Instead, the conversion should be done form user’s side as the timer resolution is also known to the user.The driver will install the interrupt service as well if
gptimer_event_callbacks_t::on_alarm
is set to a valid callback function. In the callback, user doesn’t have to deal with the low level registers (like “clear interrupt status”, “re-enable alarm event” and so on). So functions liketimer_group_get_intr_status_in_isr
andtimer_group_get_auto_reload_in_isr
are not used anymore.To update the alarm configurations when alarm event happens, one can call
gptimer_set_alarm_action()
in the interrupt callback, then the alarm will be re-enabled again.Alarm will always be re-enabled by the driver if
gptimer_alarm_config_t::auto_reload_on_alarm
is set to true.
UART
Removed/Deprecated items |
Replacement |
Remarks |
---|---|---|
|
None |
UART interrupt handling is implemented by driver itself. |
|
None |
UART interrupt handling is implemented by driver itself. |
|
Select the clock source. |
|
|
Enable pattern detection interrupt. |
I2C
Removed/Deprecated items |
Replacement |
Remarks |
---|---|---|
|
None |
I2C interrupt handling is implemented by driver itself. |
|
None |
I2C interrupt handling is implemented by driver itself. |
|
None |
It’s not used anywhere in esp-idf. |
SPI
Removed/Deprecated items |
Replacement |
Remarks |
---|---|---|
|
Get SPI real working frequency. |
The internal header file
spi_common_internal.h
has been moved toesp_private/spi_common_internal.h
.
SDMMC
Removed/Deprecated items |
Replacement |
Remarks |
---|---|---|
|
set |
Enable internal pull up. |
LEDC
Removed/Deprecated items |
Replacement |
Remarks |
---|---|---|
|
Set resolution of the duty cycle. |
Pulse Counter Driver
Pulse counter driver has been redesigned (see PCNT), which aims to unify and simplify the usage of PCNT peripheral. Although it’s recommended to use the new driver APIs, the legacy driver is still available in the previous include path driver/pcnt.h
. However, by default, including driver/pcnt.h
will bring a build warning like legacy pcnt driver is deprecated, please migrate to use driver/pulse_cnt.h. The warning can be suppressed by the Kconfig option CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN.
The major breaking changes in concept and usage are listed as follows:
Breaking Changes in Concepts
pcnt_port_t
,pcnt_unit_t
andpcnt_channel_t
which used to identify the hardware unit and channel are removed from user’s code. In the new driver, PCNT unit is represented bypcnt_unit_handle_t
, likewise, PCNT channel is represented bypcnt_channel_handle_t
. Both of them are opaque pointers.pcnt_evt_type_t
is not used any more, they have been replaced by a universal Watch Point Event. In the event callbackpcnt_watch_cb_t
, it’s still possible to distinguish different watch points frompcnt_watch_event_data_t
.pcnt_count_mode_t
is replaced bypcnt_channel_edge_action_t
, andpcnt_ctrl_mode_t
is replaced bypcnt_channel_level_action_t
.
Breaking Changes in Usage
In the legacy driver, the PCNT unit configuration and channel configuration were combined into a single function:
pcnt_unit_config
. Now this is split into two factory APIs:pcnt_new_unit()
andpcnt_new_channel()
. Only the count range is necessary for initializing a PCNT unit. GPIO number assignment has been moved topcnt_new_channel()
. High/Low control mode and positive/negative edge count mode are set by stand-alone functions:pcnt_channel_set_edge_action()
andpcnt_channel_set_level_action()
.pcnt_get_counter_value
is replaced bypcnt_unit_get_count()
.pcnt_counter_pause
is replaced bypcnt_unit_stop()
.pcnt_counter_resume
is replaced bypcnt_unit_start()
.pcnt_counter_clear
is replaced bypcnt_unit_clear_count()
.pcnt_intr_enable
andpcnt_intr_disable
are removed. In the new driver, the interrupt is enabled by registering event callbackspcnt_unit_register_event_callbacks()
.pcnt_event_enable
andpcnt_event_disable
are removed. In the new driver, the PCNT events are enabled/disabled by adding/removing watch pointspcnt_unit_add_watch_point()
,pcnt_unit_remove_watch_point()
.pcnt_set_event_value
is removed. In the new driver, event value is also set when adding watch point bypcnt_unit_add_watch_point()
.pcnt_get_event_value
andpcnt_get_event_status
are removed. In the new driver, these information are provided by event callbackpcnt_watch_cb_t
in thepcnt_watch_event_data_t
.pcnt_isr_register
andpcnt_isr_unregister
are removed. Register of the ISR handler from user code is no longer permitted. Users should register event callbacks instead by callingpcnt_unit_register_event_callbacks()
.pcnt_set_pin
is removed and the new driver no longer allows the switching of the GPIO at runtime. If you want to change to other GPIOs, please delete the existing PCNT channel bypcnt_del_channel()
and reinstall with the new GPIO number bypcnt_new_channel()
.pcnt_filter_enable
,pcnt_filter_disable
, andpcnt_set_filter_value
are replaced bypcnt_unit_set_glitch_filter()
. Meanwhile,pcnt_get_filter_value
has been removed.pcnt_set_mode
is replaced bypcnt_channel_set_edge_action()
andpcnt_channel_set_level_action()
.pcnt_isr_service_install
,pcnt_isr_service_uninstall
,pcnt_isr_handler_add
andpcnt_isr_handler_remove
are replaced bypcnt_unit_register_event_callbacks()
. The default ISR handler is lazy installed in the new driver.
RMT Driver
RMT driver has been redesigned (see RMT transceiver), which aims to unify and extend the usage of RMT peripheral. Although it’s recommended to use the new driver APIs, the legacy driver is still available in the previous include path driver/rmt.h
. However, by default, including driver/rmt.h
will bring a build warning like The legacy RMT driver is deprecated, please use driver/rmt_tx.h and/or driver/rmt_rx.h. The warning can be suppressed by the Kconfig option CONFIG_RMT_SUPPRESS_DEPRECATE_WARN.
The major breaking changes in concept and usage are listed as follows:
Breaking Changes in Concepts
rmt_channel_t
which used to identify the hardware channel are removed from user space. In the new driver, RMT channel is represented byrmt_channel_handle_t
. The channel is dynamic allocated by the driver, instead of designated by user.rmt_item32_t
is replaced byrmt_symbol_word_t
, which avoids a nested union inside a struct.rmt_mem_t
is removed, as we don’t allow users to access RMT memory block (a.k.an RMTMEM) directly. Direct access to RMTMEM doesn’t make sense but make mistakes, especially when the RMT channel also connected with a DMA channel.rmt_mem_owner_t
is removed, as the ownership is controller by driver, not by user anymore.rmt_source_clk_t
is replaced byrmt_clock_source_t
, note they’re not binary compatible.rmt_data_mode_t
is removed, the RMT memory access mode is configured to always use Non-FIFO and DMA mode.rmt_mode_t
is removed, as the driver has stand alone install functions for TX and RX channels.rmt_idle_level_t
is removed, setting IDLE level for TX channel is available inrmt_transmit_config_t::eot_level
.rmt_carrier_level_t
is removed, setting carrier polarity is available inrmt_carrier_config_t::polarity_active_low
.rmt_channel_status_t
andrmt_channel_status_result_t
are removed, they’re not used anywhere.transmitting by RMT channel doesn’t expect user to prepare the RMT symbols, instead, user needs to provide an RMT Encoder to tell the driver how to convert user data into RMT symbols.
Breaking Changes in Usage
Channel installation has been separated for TX and RX channels into
rmt_new_tx_channel()
andrmt_new_rx_channel()
.rmt_set_clk_div
andrmt_get_clk_div
are removed. Channel clock configuration can only be done during channel installation.rmt_set_rx_idle_thresh
andrmt_get_rx_idle_thresh
are removed. In the new driver, the RX channel IDLE threshold is redesigned into a new conceptrmt_receive_config_t::signal_range_max_ns
.rmt_set_mem_block_num
andrmt_get_mem_block_num
are removed. In the new driver, the memory block number is determined byrmt_tx_channel_config_t::mem_block_symbols
andrmt_rx_channel_config_t::mem_block_symbols
.rmt_set_tx_carrier
is removed, the new driver usesrmt_apply_carrier()
to set carrier behavior.rmt_set_mem_pd
andrmt_get_mem_pd
are removed. The memory power is managed by the driver automatically.rmt_memory_rw_rst
,rmt_tx_memory_reset
andrmt_rx_memory_reset
are removed. Memory reset is managed by the driver automatically.rmt_tx_start
andrmt_rx_start
are merged into a single functionrmt_enable()
, for both TX and RX channels.rmt_tx_stop
andrmt_rx_stop
are merged into a single functionrmt_disable()
, for both TX and RX channels.rmt_set_memory_owner
andrmt_get_memory_owner
are removed. RMT memory owner guard is added automatically by the driver.rmt_set_tx_loop_mode
andrmt_get_tx_loop_mode
are removed. In the new driver, the loop mode is configured inrmt_transmit_config_t::loop_count
.rmt_set_source_clk
andrmt_get_source_clk
are removed. Configuring clock source is only possible during channel installation byrmt_tx_channel_config_t::clk_src
andrmt_rx_channel_config_t::clk_src
.rmt_set_rx_filter
is removed. In the new driver, the filter threshold is redesigned into a new conceptrmt_receive_config_t::signal_range_min_ns
.rmt_set_idle_level
andrmt_get_idle_level
are removed. Setting IDLE level for TX channel is available inrmt_transmit_config_t::eot_level
.rmt_set_rx_intr_en
,rmt_set_err_intr_en
,rmt_set_tx_intr_en
,rmt_set_tx_thr_intr_en
andrmt_set_rx_thr_intr_en
are removed. The new driver doesn’t allow user to turn on/off interrupt from user space. Instead, it provides callback functions.rmt_set_gpio
andrmt_set_pin
are removed. The new driver doesn’t support to switch GPIO dynamically at runtime.rmt_config
is removed. In the new driver, basic configuration is done during the channel installation stage.rmt_isr_register
andrmt_isr_deregister
are removed, the interrupt is allocated by the driver itself.rmt_driver_install
is replaced byrmt_new_tx_channel()
andrmt_new_rx_channel()
.rmt_driver_uninstall
is replaced byrmt_del_channel()
.rmt_fill_tx_items
,rmt_write_items
andrmt_write_sample
are removed. In the new driver, user needs to provide an encoder to “translate” the user data into RMT symbols.rmt_get_counter_clock
is removed, as the channel clock resolution is configured by user fromrmt_tx_channel_config_t::resolution_hz
.rmt_wait_tx_done
is replaced byrmt_tx_wait_all_done()
.rmt_translator_init
,rmt_translator_set_context
andrmt_translator_get_context
are removed. In the new driver, the translator has been replaced by the RMT encoder.rmt_get_ringbuf_handle
is removed. The new driver doesn’t use Ringbuffer to save RMT symbols. Instead, the incoming data are saved to the user provided buffer directly. The user buffer can even be mounted to DMA link internally.rmt_register_tx_end_callback
is replaced byrmt_tx_register_event_callbacks()
, where user can registerrmt_tx_event_callbacks_t::on_trans_done
event callback.rmt_set_intr_enable_mask
andrmt_clr_intr_enable_mask
are removed, as the interrupt is handled by the driver, user doesn’t need to take care of it.rmt_add_channel_to_group
andrmt_remove_channel_from_group
are replaced by RMT sync manager. Please refer tormt_new_sync_manager()
.rmt_set_tx_loop_count
is removed. The loop count in the new driver is configured inrmt_transmit_config_t::loop_count
.rmt_enable_tx_loop_autostop
is removed. In the new driver, TX loop auto stop is always enabled if available, it’s not configurable anymore.
LCD
The LCD panel initialization flow is slightly changed. Now the
esp_lcd_panel_init()
won’t turn on the display automatically. User needs to callesp_lcd_panel_disp_on_off()
to manually turn on the display. Note, this is different from turning on backlight. With this breaking change, user can flush a predefined pattern to the screen before turning on the screen. This can help avoid random noise on the screen after a power on reset.esp_lcd_panel_disp_off()
is deprecated, please useesp_lcd_panel_disp_on_off()
instead.dc_as_cmd_phase
is removed. The SPI LCD driver currently doesn’t support a 9bit SPI LCD. Please always use a dedicated GPIO to control the LCD D/C line.The way to register RGB panel event callbacks has been moved from the
esp_lcd_rgb_panel_config_t
into a separate APIesp_lcd_rgb_panel_register_event_callbacks()
. However, the event callback signature is not changed.Previous
relax_on_idle
flag inesp_lcd_rgb_panel_config_t
has been renamed intoesp_lcd_rgb_panel_config_t::refresh_on_demand
, which expresses the same meaning but with a clear name.If the RGB LCD is created with the
refresh_on_demand
flag enabled, the driver won’t start a refresh in theesp_lcd_panel_draw_bitmap()
. Now you have to callesp_lcd_rgb_panel_refresh()
to refresh the screen by yourself.
MCPWM
MCPWM driver was redesigned (see MCPWM), meanwhile, the legacy driver is deprecated. The new driver’s aim is to make each MCPWM submodule independent to each other, and give the freedom of resource connection back to users. Although it’s recommended to use the new driver APIs, the legacy driver is still available in the previous include path driver/mcpwm.h
. However, by default, using legacy driver will bring compile warnings like legacy MCPWM driver is deprecated, please migrate to the new driver (include driver/mcpwm_prelude.h)
. This warning can be suppressed by the Kconfig option CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN.
The major breaking changes in concept and usage are listed as follows:
Breaking Changes in Concepts
The new MCPWM driver is object-oriented, where most of the MCPWM submodule has a driver object associated with it. The driver object is created by factory function like mcpwm_new_timer()
. IO control function always needs an object handle, in the first place.
The legacy driver has an inappropriate assumption, that is the MCPWM operator should be connected to different MCPWM timer. In fact, the hardware doesn’t have such limitation. In the new driver, a MCPWM timer can be connected to multiple operators, so that the operators can achieve the best synchronization performance.
The legacy driver preset the way to generate a PWM waveform into a so called mcpwm_duty_type_t
, however, the duty cycle modes listed there are far from sufficient. Likewise, legacy driver has several preset mcpwm_deadtime_type_t
, which also doesn’t cover all the use cases. What’s more, user usually gets confused by the name of the duty cycle mode and dead-time mode. In the new driver, there’re no such limitation, but user has to construct the generator behavior from scratch.
In the legacy driver, the ways to synchronize the MCPWM timer by GPIO, software and other timer module are not unified. It increased learning costs for users. In the new driver, the synchronization APIs are unified.
The legacy driver has mixed the concepts of “Fault detector” and “Fault handler”. Which make the APIs very confusing to users. In the new driver, the fault object just represents a failure source, and we introduced a new concept – brake to express the concept of “Fault handler”. What’s more, the new driver supports software fault.
The legacy drive only provides callback functions for the capture submodule. The new driver provides more useful callbacks for various MCPWM submodules, like timer stop, compare match, fault enter, brake, etc.
mcpwm_io_signals_t
andmcpwm_pin_config_t
are not used. GPIO configuration has been moved into submodule’s configuration structure.mcpwm_timer_t
,mcpwm_generator_t
are not used. Timer and generator are represented bymcpwm_timer_handle_t
andmcpwm_gen_handle_t
.mcpwm_fault_signal_t
andmcpwm_sync_signal_t
are not used. Fault and sync source are represented bymcpwm_fault_handle_t
andmcpwm_sync_handle_t
.mcpwm_capture_signal_t
is not used. A capture channel is represented bymcpwm_cap_channel_handle_t
.
Breaking Changes in Usage
mcpwm_gpio_init
andmcpwm_set_pin
: GPIO configurations are moved to submodule’s own configuration. e.g. set the PWM GPIO inmcpwm_generator_config_t::gen_gpio_num
.mcpwm_init
: To get an expected PWM waveform, you need to allocated at least one MCPWM timer and MCPWM operator, then connect them by callingmcpwm_operator_connect_timer()
. After that, you should set the generator’s actions on various events by calling e.g.mcpwm_generator_set_actions_on_timer_event()
,mcpwm_generator_set_actions_on_compare_event()
.mcpwm_group_set_resolution
: in the new driver, the group resolution is fixed to the maximum, usually it’s 80MHz.mcpwm_timer_set_resolution
: MCPWM Timer resolution is set inmcpwm_timer_config_t::resolution_hz
.mcpwm_set_frequency
: PWM frequency is determined bymcpwm_timer_config_t::resolution_hz
,mcpwm_timer_config_t::count_mode
andmcpwm_timer_config_t::period_ticks
.mcpwm_set_duty
: To set the PWM duty cycle, you should callmcpwm_comparator_set_compare_value()
to change comparator’s threshold.mcpwm_set_duty_type
: There won’t be any preset duty types, the duty type is configured by setting different generator actions. e.g.mcpwm_generator_set_actions_on_timer_event()
.mcpwm_set_signal_high
andmcpwm_set_signal_low
are replaced bymcpwm_generator_set_force_level()
. In the new driver, it’s implemented by setting force action for the generator, instead of changing the duty cycle to 0% or 100% at the background.mcpwm_start
andmcpwm_stop
are replaced bymcpwm_timer_start_stop()
. You have more modes to start and stop the MCPWM timer, seemcpwm_timer_start_stop_cmd_t
.mcpwm_carrier_init
: It’s replaced bymcpwm_operator_apply_carrier()
.mcpwm_carrier_enable
andmcpwm_carrier_disable
: Enabling and disabling carrier submodule is done automatically by checking whether the carrier configuration structuremcpwm_carrier_config_t
is NULL.mcpwm_carrier_set_period
is replaced bymcpwm_carrier_config_t::frequency_hz
.mcpwm_carrier_set_duty_cycle
is replaced bymcpwm_carrier_config_t::duty_cycle
.mcpwm_carrier_oneshot_mode_enable
is replaced bymcpwm_carrier_config_t::first_pulse_duration_us
.mcpwm_carrier_oneshot_mode_disable
is removed. Disabling the first pulse (a.k.a the one-shot pulse) in the carrier is never supported by the hardware.mcpwm_carrier_output_invert
is replaced bymcpwm_carrier_config_t::invert_before_modulate
andmcpwm_carrier_config_t::invert_after_modulate
.mcpwm_deadtime_enable
andmcpwm_deadtime_disable
are replaced bymcpwm_generator_set_dead_time()
.mcpwm_fault_init
is replaced bymcpwm_new_gpio_fault()
.mcpwm_fault_set_oneshot_mode
,mcpwm_fault_set_cyc_mode
are replaced bymcpwm_operator_set_brake_on_fault()
andmcpwm_generator_set_actions_on_brake_event()
.mcpwm_capture_enable
is removed. It’s duplicated tomcpwm_capture_enable_channel()
.mcpwm_capture_disable
is removed. It’s duplicated tomcpwm_capture_capture_disable_channel()
.mcpwm_capture_enable_channel
andmcpwm_capture_disable_channel
are replaced bymcpwm_new_capture_channel()
andmcpwm_del_capture_channel()
.mcpwm_capture_signal_get_value
andmcpwm_capture_signal_get_edge
: Capture timer count value and capture edge are provided in the capture event callback, viamcpwm_capture_event_data_t
. Capture data are only valuable when capture event happens. Providing single API to fetch capture data is meaningless.mcpwm_sync_enable
is removed. It’s duplicated tomcpwm_sync_configure()
.mcpwm_sync_configure
is replaced bymcpwm_timer_set_phase_on_sync()
.mcpwm_sync_disable
is equivalent to settingmcpwm_timer_sync_phase_config_t::sync_src
toNULL
.mcpwm_set_timer_sync_output
is replaced bymcpwm_new_timer_sync_src()
.mcpwm_timer_trigger_soft_sync
is replaced bymcpwm_soft_sync_activate()
.mcpwm_sync_invert_gpio_synchro
is equivalent to settingmcpwm_gpio_sync_src_config_t::active_neg
.mcpwm_isr_register
is removed. You can register various event callbacks instead. For example, to register capture event callback, you can usemcpwm_capture_channel_register_event_callbacks()
.
I2S driver
Shortcomings are exposed when supporting all the new features of ESP32-C3 & ESP32-S3 by the old I2S driver, so it is re-designed to make it more compatible and flexible to all the communication modes. New APIs are available by including corresponding mode header files driver/include/driver/i2s_std.h, driver/include/driver/i2s_pdm.h or driver/include/driver/i2s_tdm.h. Meanwhile, the old APIs in driver/deprecated/driver/i2s.h are still supported for backward compatibility. But there will be warnings if you keep using the old APIs in your project, these warnings can be suppressed by the Kconfig option CONFIG_I2S_SUPPRESS_DEPRECATE_WARN. Here is the general overview of the current I2S files:
Breaking changes in Concepts
The minimum control unit in new I2S driver will be tx/rx channel instead of a whole I2S controller.
The tx/rx channel in a same I2S controller can be controlled separately, that means they will be initialized, started or stopped separately. Especially for ESP32-C3 and ESP32-S3, tx and rx channels in one controller can be configured to different clocks or modes now, they are able to work in a totally separate way which can help to save the resources of I2S controller. But for ESP32 and ESP32-S2, though their tx/rx can be controlled separately, some hardware resources are still shared by tx and rx, they might affect each other if they are configured to different configurations;
The channels can be registered to an available I2S controller automatically by setting
i2s_port_t::I2S_NUM_AUTO
as I2S port id. The driver will help you to search for the available tx/rx channel. Of cause, driver can still support to be installed by a specific port;i2s_chan_handle_t
is the handle that used for identifying the I2S channels. All the APIs will require the channel handle, users need to maintain the channel handles by themselves;In order to distinguish tx/rx channel and sound channel, now the word ‘channel’ is only stand for the tx/rx channel in new driver, meanwhile the sound channel will be called ‘slot’.
I2S communication modes are extracted into three modes.
Standard mode: Standard mode always has two slots, it can support Philip, MSB and PCM(short sync) format, please refer to driver/include/driver/i2s_std.h for details;
PDM mode: PDM mode only support two slots with 16 bits data width, but the configurations of PDM TX and PDM RX are little bit different. For PDM TX, the sample rate can be set by
i2s_pdm_tx_clk_config_t::sample_rate
, and its clock frequency is depended on the up-sampling configuration. For PDM RX, the sample rate can be set byi2s_pdm_rx_clk_config_t::sample_rate
, and its clock frequency is depended on the down-sampling configuration. Please refer to driver/include/driver/i2s_pdm.h for details;TDM mode: TDM mode can support upto 16 slots. It can work in Philip, MSB, PCM(short sync) and PCM(long sync) format, please refer to driver/include/driver/i2s_tdm.h for details;
When allocating a new channel in a specific mode, must initialize this channel by corresponding function. It is strongly recommended to use the helper macros to generate the default configurations, in case the default values will be changed one day.
States and state-machine are adopted in the new I2S driver to avoid APIs called in wrong state.
The slot configurations and clock configurations can be configured separately.
Calling
i2s_channel_init_std_mode()
,i2s_channel_init_pdm_rx_mode()
,i2s_channel_init_pdm_tx_mode()
ori2s_channel_init_tdm_mode()
to initialize the slot/clock/gpio_pin configurations;Calling
i2s_channel_reconfig_std_slot()
,i2s_channel_reconfig_pdm_rx_slot()
,i2s_channel_reconfig_pdm_tx_slot()
ori2s_channel_reconfig_tdm_slot()
can change the slot configurations after initialization;Calling
i2s_channel_reconfig_std_clock()
,i2s_channel_reconfig_pdm_rx_clock()
,i2s_channel_reconfig_pdm_tx_clock()
ori2s_channel_reconfig_tdm_clock()
can change the clock configurations after initialization;Calling
i2s_channel_reconfig_std_gpio()
,i2s_channel_reconfig_pdm_rx_gpio()
,i2s_channel_reconfig_pdm_tx_gpio()
ori2s_channel_reconfig_tdm_gpio()
can change the gpio configurations after initialization.
ADC and DAC modes are removed. They will only be supported in their own driver and legacy I2S driver.
i2s_channel_write()
andi2s_channel_read()
can be aborted byi2s_channel_abort_reading_writing()
now.
Breaking Changes in Usage
To use the new I2S driver, please follow these steps:
Calling
i2s_new_channel()
to aquire the channel handles. We should specify the work role and I2S port in this step. Besides, the tx or rx channel handles will be generated by the driver. Inputting both two tx and rx handles is not necessary but at least one handle is needed. In the case of inputting both two handles, the driver will work at duplex mode, both tx and rx channel will be avaliable on a same port, and they will share the MCLK, BCLK and WS signal. But if only one of the tx or rx handle is inputted, this channel will only work in simplex mode.Calling
i2s_channel_init_std_mode()
,i2s_channel_init_pdm_rx_mode()
,i2s_channel_init_pdm_tx_mode()
ori2s_channel_init_tdm_mode()
to initialize the channel to the specified mode. Corresponding slot, clock and gpio configurations are needed in this step.(Optional) Calling
i2s_channel_register_event_callback()
to register the ISR event callback functions. I2S events now can be received by the callback function synchronously, instead of from event queue asynchronously.Calling
i2s_channel_enable()
to start the hardware of I2S channel. In the new driver, I2S won’t start automatically after installed anymore, users are supposed to know clearly whether the channel has started or not.Reading or writing data by
i2s_channel_read()
ori2s_channel_write()
. Certainly, only rx channel handle is suppoesd to be inputted ini2s_channel_read()
and tx channel handle ini2s_channel_write()
.(Optional) The slot, clock and gpio configurations can be changed by corresponding ‘reconfig’ functions, but
i2s_channel_disable()
must be called before updating the configurations.Calling
i2s_channel_disable()
to stop the hardware of I2S channel.Calling
i2s_del_channel()
to delete and release the resources of the channel if it is not needed any more, but the channel must be disabled before deleting it.
Register access macros
Previously, all register access macros could be used as expressions, so the following was allowed:
uint32_t val = REG_SET_BITS(reg, mask);
In IDF v5.0, register access macros which write or read-modify-write the register can no longer be used as expressions, and can only be used as statements. This applies to the following macros: REG_WRITE
, REG_SET_BIT
, REG_CLR_BIT
, REG_SET_BITS
, REG_SET_FIELD
, WRITE_PERI_REG
, CLEAR_PERI_REG_MASK
, SET_PERI_REG_MASK
, SET_PERI_REG_BITS
.
To store the value which would have been written into the register, split the operation as follows:
uint32_t new_val = REG_READ(reg) | mask;
REG_WRITE(reg, new_val);
To get the value of the register after modification (which may be different from the value written), add an explicit read:
REG_SET_BITS(reg, mask);
uint32_t new_val = REG_READ(reg);