Peripherals

[中文]

Peripheral Clock Gating

As usual, peripheral clock gating is still handled by driver itself, users do not 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 & Continuous Mode Drivers

The ADC oneshot mode driver has been redesigned.

  • The new driver is in esp_adc component and the include path is esp_adc/adc_oneshot.h.

  • The legacy driver is still available in the previous include path driver/adc.h.

The ADC continuous mode driver has been moved from driver component to esp_adc component.

  • The include path has been changed from driver/adc.h to esp_adc/adc_continuous.h.

Attempting to use the legacy include path driver/adc.h of either driver triggers the build warning below by default. However, the warning can be suppressed by enabling the CONFIG_ADC_SUPPRESS_DEPRECATE_WARN Kconfig option.

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

ADC Calibration Driver

The ADC calibration driver has been redesigned.

  • The new driver is in esp_adc component and the include path is esp_adc/adc_cali.h and esp_adc/adc_cali_scheme.h.

Legacy driver is still available by including esp_adc_cal.h. However, if users still would like to use the include path of the legacy driver, users should add esp_adc component to the list of component requirements in CMakeLists.txt.

Attempting to use the legacy include path esp_adc_cal.h triggers the build warning below by default. However, the warning can be suppressed by enabling the CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN Kconfig option.

legacy adc calibration driver is deprecated, please migrate to use esp_adc/adc_cali.h and esp_adc/adc_cali_scheme.h

API Changes

  • The ADC power management APIs adc_power_acquire and adc_power_release have made private and moved to esp_private/adc_share_hw_ctrl.h.

    • The two APIs were previously made public due to a HW errata workaround.

    • Now, ADC power management is completely handled internally by drivers.

    • Users who still require this API can include esp_private/adc_share_hw_ctrl.h to continue using these functions.

  • driver/adc2_wifi_private.h has been moved to esp_private/adc_share_hw_ctrl.h.

  • Enums ADC_UNIT_BOTH, ADC_UNIT_ALTER, and ADC_UNIT_MAX in adc_unit_t have been removed.

  • The following enumerations have been removed as some of their enumeration values are not supported on all chips. This would lead to the driver triggering a runtime error if an unsupported value is used.

    • Enum ADC_CHANNEL_MAX

    • Enum ADC_ATTEN_MAX

    • Enum ADC_CONV_UNIT_MAX

  • API hall_sensor_read on ESP32 has been removed. Hall sensor is no longer supported on ESP32.

  • API adc_set_i2s_data_source and adc_i2s_mode_init have been deprecated. Related enum adc_i2s_source_t has been deprecated. Please migrate to use esp_adc/adc_continuous.h.

  • API adc_digi_filter_reset, adc_digi_filter_set_config, adc_digi_filter_get_config and adc_digi_filter_enable have been removed. These APIs behaviours are not guaranteed. Enum adc_digi_filter_idx_t, adc_digi_filter_mode_t and structure adc_digi_iir_filter_t have been removed as well.

  • API esp_adc_cal_characterize has been deprecated, please migrate to adc_cali_create_scheme_curve_fitting or adc_cali_create_scheme_line_fitting instead.

  • API esp_adc_cal_raw_to_voltage has been deprecated, please migrate to adc_cali_raw_to_voltage instead.

  • API esp_adc_cal_get_voltage has been deprecated, please migrate to adc_oneshot_get_calibrated_result instead.

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.

  • The user callback of a GPIO interrupt should no longer read the GPIO interrupt status register to get the GPIO's pin number of triggering the interrupt. You should use the callback argument to determine the GPIO's pin number instead.

    • Previously, when a GPIO interrupt occurs, the GPIO's interrupt status register is cleared after calling the user callbacks. Thus, it was possible for users to read the GPIO's interrupt status register inside the callback to determine which GPIO was used to trigger the interrupt.

    • However, clearing the interrupt status register after calling the user callbacks can potentially cause edge-triggered interrupts to be lost. For example, if an edge-triggered interrupt is triggered/retriggered while the user callbacks are being called, that interrupt will be cleared without its registered user callback being handled.

    • Now, the GPIO's interrupt status register is cleared before invoking the user callbacks. Thus, users can no longer read the GPIO interrupt status register to determine which pin has triggered the interrupt. Instead, users should use the callback argument to pass the pin number.

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 is recommended to use 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 triggers the build warning below. The warning can be suppressed by the Kconfig option CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN.

legacy timer group driver is deprecated, please migrate to driver/gptimer.h

The major breaking changes in concept and usage are listed as follows:

Breaking Changes in Concepts

  • timer_group_t and timer_idx_t which used to identify the hardware timer are removed from user's code. In the new driver, a timer is represented by gptimer_handle_t.

  • Definition of timer clock source is moved to gptimer_clock_source_t, the previous timer_src_clk_t is not used.

  • Definition of timer count direction is moved to gptimer_count_direction_t, the previous timer_count_dir_t is not used.

  • Only level interrupt is supported, timer_intr_t and timer_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 in gptimer_config_t. Note that, specific configurations of alarm events are not needed during the installation stage of the driver.

  • Alarm event is configured by gptimer_set_alarm_action(), with parameters set in the gptimer_alarm_config_t.

  • Setting and getting count value are done by gptimer_get_raw_count() and gptimer_set_raw_count(). The driver does not help convert the raw value into UTC time-stamp. Instead, the conversion should be done from 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, users do not have to deal with the low level registers (like "clear interrupt status", "re-enable alarm event" and so on). So functions like timer_group_get_intr_status_in_isr and timer_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

uart_isr_register()

None

UART interrupt handling is implemented by driver itself.

uart_isr_free()

None

UART interrupt handling is implemented by driver itself.

use_ref_tick in uart_config_t

uart_config_t::source_clk

Select the clock source.

uart_enable_pattern_det_intr()

uart_enable_pattern_det_baud_intr()

Enable pattern detection interrupt.

I2C

Removed/Deprecated items

Replacement

Remarks

i2c_isr_register()

None

I2C interrupt handling is implemented by driver itself.

i2c_isr_register()

None

I2C interrupt handling is implemented by driver itself.

i2c_opmode_t

None

It is not used anywhere in ESP-IDF.

SPI

Removed/Deprecated items

Replacement

Remarks

spi_cal_clock()

spi_get_actual_clock()

Get SPI real working frequency.

  • The internal header file spi_common_internal.h has been moved to esp_private/spi_common_internal.h.

LEDC

Removed/Deprecated items

Replacement

Remarks

bit_num in ledc_timer_config_t

ledc_timer_config_t::duty_resolution

Set resolution of the duty cycle.

Temperature Sensor Driver

The temperature sensor driver has been redesigned and it is recommended to use the new driver. However, the old driver is still available but cannot be used with the new driver simultaneously.

The new driver can be included via driver/temperature_sensor.h. The old driver is still available in the previous include path driver/temp_sensor.h. However, including driver/temp_sensor.h triggers the build warning below by default. The warning can be suppressed by enabling the menuconfig option CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN.

legacy temperature sensor driver is deprecated, please migrate to driver/temperature_sensor.h

Configuration contents has been changed. In the old version, users need to configure clk_div and dac_offset. While in the new version, users only need to choose tsens_range.

The process of using temperature sensor has been changed. In the old version, users can use config->start->read_celsius to get value. In the new version, users should install the temperature sensor driver firstly, by temperature_sensor_install and uninstall it when finished. For more information, please refer to Temperature Sensor .

LCD

  • The LCD panel initialization flow is slightly changed. Now the esp_lcd_panel_init() will not turn on the display automatically. User needs to call esp_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 flash 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 use esp_lcd_panel_disp_on_off() instead.

  • dc_as_cmd_phase is removed. The SPI LCD driver currently does not support a 9-bit 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 API esp_lcd_rgb_panel_register_event_callbacks(). However, the event callback signature is not changed.

  • Previous relax_on_idle flag in esp_lcd_rgb_panel_config_t has been renamed into esp_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 will not start a refresh in the esp_lcd_panel_draw_bitmap(). Now users have to call esp_lcd_rgb_panel_refresh() to refresh the screen by themselves.

  • esp_lcd_color_space_t is deprecated, please use lcd_color_space_t to describe the color space, and use lcd_rgb_element_order_t to describe the data order of RGB color.

Dedicated GPIO Driver

  • All of the dedicated GPIO related Low Level (LL) functions in cpu_ll.h have been moved to dedic_gpio_cpu_ll.h and renamed.

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, bits, mask);

In ESP-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, bits, mask);
uint32_t new_val = REG_READ(reg);