docs: provide CN translation for peripherals in migration guides

pull/9803/head
Linda 2022-08-31 17:53:33 +08:00
rodzic 4f1a9e436e
commit 31aa922d67
2 zmienionych plików z 802 dodań i 137 usunięć

Wyświetl plik

@ -1,6 +1,8 @@
Peripherals
===========
:link_to_translation:`zh_CN:[中文]`
Peripheral Clock Gating
-----------------------
@ -16,16 +18,57 @@ RTC control APIs have been moved from ``driver/rtc_cntl.h`` to ``esp_private/rtc
ADC
---
- ADC oneshot mode driver has been redesigned. New driver is in ``esp_adc`` component and the include path is ``esp_adc/adc_oneshot.h``. Legacy driver is still available in the previous include path ``driver/adc.h``. However, by default, including ``driver/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 :ref:`CONFIG_ADC_SUPPRESS_DEPRECATE_WARN`.
- ADC continuous mode driver has been moved from ``driver`` component to ``esp_adc`` component. Include path has been changed from ``driver/adc.h`` to ``esp_adc/adc_continuous.h``. Legacy driver is still available in the previous include path ``driver/adc.h``. Similarly, including it will bring a build warning, and it can be suppressed by the Kconfig option :ref:`CONFIG_ADC_SUPPRESS_DEPRECATE_WARN`.
- ADC calibration driver has been redesigned. 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, you should add ``esp_adc`` component to the list of component requirements in CMakeLists.txt. By default, including ``esp_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 :ref:`CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN`.
- API ``adc_power_acquire`` and ``adc_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 from ``driver/adc.h`` to ``esp_private/adc_share_hw_ctrl.h``.
- Previous ``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.
- Enum ``ADC_CHANNEL_MAX`` in ``adc_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.
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 will trigger the build warning below by default. However, the warning can be suppressed by enabling the :ref:`CONFIG_ADC_SUPPRESS_DEPRECATE_WARN` Kconfig option.
.. code-block:: text
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`` will trigger the build warning below by default. However, the warning can be suppressed by enabling the :ref:`CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN` Kconfig option.
.. code-block:: text
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``.
GPIO
@ -33,10 +76,10 @@ 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.
- GPIO interrupt users callbacks should no longer read the GPIO interrupt status register to get the triggered GPIO's pin number. Users should use the callback argument to determine the GPIO's pin number 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 triggered.
- However, clearing the interrupt status after the user callbacks can potentially cause edge-triggered interrupts to be lost. For example, if an edge-triggered interrupt (re)triggers while the user callbacks are being called, that interrupt will be cleared without its registered user callback being handled.
- 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 (re)is triggered 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.
.. only:: SOC_SDM_SUPPORTED
@ -44,86 +87,121 @@ GPIO
Sigma-Delta Modulator
---------------------
The Sigma-Delta Modulator driver has been redesigned into :doc:`SDM <../../api-reference/peripherals/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 :ref:`CONFIG_SDM_SUPPRESS_DEPRECATE_WARN`.
The Sigma-Delta Modulator driver has been redesigned into :doc:`SDM <../../api-reference/peripherals/sdm>`.
- The new driver implements a factory pattern, where the SDM channels are managed in a pool internally, thus users 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 trigger the build warning below. The warning can be suppressed by Kconfig option :ref:`CONFIG_SDM_SUPPRESS_DEPRECATE_WARN`.
.. code-block:: text
The legacy sigma-delta driver is deprecated, please use driver/sdm.h
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`` to :cpp:type:`sdm_channel_handle_t`, which is an opaque pointer.
- SDM channel configurations are stored in :cpp:type:`sdm_config_t` now, instead the previous ``sigmadelta_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 :cpp:member:`sdm_config_t::clk_src`. The available clock sources are listed in the :cpp:type:`soc_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 use :cpp:member:`sdm_config_t::sample_rate_hz`.
- In the legacy driver, users don't have to set the clock source for SDM channel. But in the new driver, users need to set a proper one in the :cpp:member:`sdm_config_t::clk_src`. The available clock sources are listed in the :cpp:type:`soc_periph_sdm_clk_src_t`.
- In the legacy driver, users need to set a ``prescale`` for the channel, which reflects the frequency in which the modulator outputs a pulse. In the new driver, users should use :cpp:member:`sdm_config_t::sample_rate_hz`.
Breaking Changes in Usage
~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^
- Channel configuration was done by channel allocation, in :cpp:func:`sdm_new_channel`. In the new driver, only the ``duty`` can be changed at runtime, by :cpp:func:`sdm_channel_set_duty`. Other parameters like ``gpio number`` and ``prescale`` are only allowed to set during channel allocation.
- Before further channel operations, you should **enable** the channel in advance, by calling :cpp:func:`sdm_channel_enable`. This function will help to manage some system level services, like **Power Management**.
- Before further channel operations, users should **enable** the channel in advance, by calling :cpp:func:`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 :doc:`GPTimer <../../api-reference/peripherals/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 :ref:`CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN`.
Timer Group driver has been redesigned into :doc:`GPTimer <../../api-reference/peripherals/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 trigger the build warning below. The warning can be suppressed by the Kconfig option :ref:`CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN`.
.. code-block:: text
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 :cpp:type:`gptimer_handle_t`.
- Definition of timer source clock is moved to :cpp:type:`gptimer_clock_source_t`, the previous ``timer_src_clk_t`` is not used.
- Definition of timer clock source is moved to :cpp:type:`gptimer_clock_source_t`, the previous ``timer_src_clk_t`` is not used.
- Definition of timer count direction is moved to :cpp:type:`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 :cpp:member:`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 :cpp:func:`gptimer_new_timer`. Basic configurations like clock source, resolution and direction should be set in :cpp:type:`gptimer_config_t`. Note that, alarm event specific configurations are not needed during the driver install stage.
- Timer initialization is done by creating a timer instance from :cpp:func:`gptimer_new_timer`. Basic configurations like clock source, resolution and direction should be set in :cpp:type:`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 :cpp:func:`gptimer_set_alarm_action`, with parameters set in the :cpp:type:`gptimer_alarm_config_t`.
- Setting and getting count value are done by :cpp:func:`gptimer_get_raw_count` and :cpp:func:`gptimer_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 :cpp:member:`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 like ``timer_group_get_intr_status_in_isr`` and ``timer_group_get_auto_reload_in_isr`` are not used anymore.
- Setting and getting count value are done by :cpp:func:`gptimer_get_raw_count` and :cpp:func:`gptimer_set_raw_count`. The driver doesn't 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 :cpp:member:`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 :cpp:func:`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 :cpp:member:`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 :cpp:type:`uart_config_t` | :cpp:member:`uart_config_t::source_clk` | Select the clock source. |
+-----------------------------------------------+-----------------------------------------------+----------------------------------------------------------+
| ``uart_enable_pattern_det_intr()`` | :cpp:func:`uart_enable_pattern_det_baud_intr` | Enable pattern detection interrupt. |
+-----------------------------------------------+-----------------------------------------------+----------------------------------------------------------+
.. list-table::
:width: 700 px
:header-rows: 1
* - 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 :cpp:type:`uart_config_t`
- :cpp:member:`uart_config_t::source_clk`
- Select the clock source.
* - ``uart_enable_pattern_det_intr()``
- :cpp:func:`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's not used anywhere in esp-idf. |
+--------------------------+-------------+---------------------------------------------------------+
.. list-table::
:width: 700 px
:header-rows: 1
* - 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's not used anywhere in esp-idf.
SPI
---
+--------------------------+----------------------------------+---------------------------------+
| Removed/Deprecated items | Replacement | Remarks |
+==========================+==================================+=================================+
| ``spi_cal_clock()`` | :cpp:func:`spi_get_actual_clock` | Get SPI real working frequency. |
+--------------------------+----------------------------------+---------------------------------+
.. list-table::
:width: 700 px
:header-rows: 1
* - Removed/Deprecated items
- Replacement
- Remarks
* - ``spi_cal_clock()``
- :cpp:func:`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``.
@ -132,42 +210,61 @@ SPI
SDMMC
-----
+----------------------------+----------------------------------------------+--------------------------+
| Removed/Deprecated items | Replacement | Remarks |
+============================+==============================================+==========================+
| ``sdmmc_host_pullup_en()`` | set ``SDMMC_SLOT_FLAG_INTERNAL_PULLUP`` flag | Enable internal pull up. |
| | in :cpp:member:`sdmmc_slot_config_t::flags` | |
+----------------------------+----------------------------------------------+--------------------------+
.. list-table::
:width: 700 px
:header-rows: 1
* - Removed/Deprecated items
- Replacement
- Remarks
* - ``sdmmc_host_pullup_en()``
- set ``SDMMC_SLOT_FLAG_INTERNAL_PULLUP`` flag in :cpp:member:`sdmmc_slot_config_t::flags`
- Enable internal pull up.
LEDC
-----
+------------------------------------------------+----------------------------------------------------+-----------------------------------+
| Removed/Deprecated items | Replacement | Remarks |
+================================================+====================================================+===================================+
| ``bit_num`` in :cpp:type:`ledc_timer_config_t` | :cpp:member:`ledc_timer_config_t::duty_resolution` | Set resolution of the duty cycle. |
+------------------------------------------------+----------------------------------------------------+-----------------------------------+
.. list-table::
:width: 700 px
:header-rows: 1
* - Removed/Deprecated items
- Replacement
- Remarks
* - ``bit_num`` in :cpp:type:`ledc_timer_config_t`
- :cpp:member:`ledc_timer_config_t::duty_resolution`
- Set resolution of the duty cycle.
.. only:: SOC_PCNT_SUPPORTED
Pulse Counter Driver
--------------------
Pulse counter driver has been redesigned (see :doc:`PCNT <../../api-reference/peripherals/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 :ref:`CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN`.
Pulse counter driver has been redesigned (see :doc:`PCNT <../../api-reference/peripherals/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, including ``driver/pcnt.h`` will trigger the build warning below by default. The warning can be suppressed by the Kconfig option :ref:`CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN`.
.. code-block:: text
legacy pcnt driver is deprecated, please migrate to use driver/pulse_cnt.h
The major breaking changes in concept and usage are listed as follows:
Breaking Changes in Concepts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ``pcnt_port_t``, ``pcnt_unit_t`` and ``pcnt_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 by :cpp:type:`pcnt_unit_handle_t`, likewise, PCNT channel is represented by :cpp:type:`pcnt_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 callback :cpp:type:`pcnt_watch_cb_t`, it's still possible to distinguish different watch points from :cpp:type:`pcnt_watch_event_data_t`.
- ``pcnt_count_mode_t`` is replaced by :cpp:type:`pcnt_channel_edge_action_t`, and ``pcnt_ctrl_mode_t`` is replaced by :cpp:type:`pcnt_channel_level_action_t`.
Breaking Changes in Usage
~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^
- Previously, the PCNT unit configuration and channel configuration were combined into a single function: ``pcnt_unit_config``. They are now split into the two factory APIs: :cpp:func:`pcnt_new_unit` and :cpp:func:`pcnt_new_channel` respectively.
- Only the count range is necessary for initializing a PCNT unit. GPIO number assignment has been moved to :cpp:func:`pcnt_new_channel`.
- High/Low control mode and positive/negative edge count mode are set by stand-alone functions: :cpp:func:`pcnt_channel_set_edge_action` and :cpp:func:`pcnt_channel_set_level_action`.
- 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: :cpp:func:`pcnt_new_unit` and :cpp:func:`pcnt_new_channel`. Only the count range is necessary for initializing a PCNT unit. GPIO number assignment has been moved to :cpp:func:`pcnt_new_channel`. High/Low control mode and positive/negative edge count mode are set by stand-alone functions: :cpp:func:`pcnt_channel_set_edge_action` and :cpp:func:`pcnt_channel_set_level_action`.
- ``pcnt_get_counter_value`` is replaced by :cpp:func:`pcnt_unit_get_count`.
- ``pcnt_counter_pause`` is replaced by :cpp:func:`pcnt_unit_stop`.
- ``pcnt_counter_resume`` is replaced by :cpp:func:`pcnt_unit_start`.
@ -176,9 +273,9 @@ LEDC
- ``pcnt_event_enable`` and ``pcnt_event_disable`` are removed. In the new driver, the PCNT events are enabled/disabled by adding/removing watch points :cpp:func:`pcnt_unit_add_watch_point`, :cpp:func:`pcnt_unit_remove_watch_point`.
- ``pcnt_set_event_value`` is removed. In the new driver, event value is also set when adding watch point by :cpp:func:`pcnt_unit_add_watch_point`.
- ``pcnt_get_event_value`` and ``pcnt_get_event_status`` are removed. In the new driver, these information are provided by event callback :cpp:type:`pcnt_watch_cb_t` in the :cpp:type:`pcnt_watch_event_data_t`.
- ``pcnt_isr_register`` and ``pcnt_isr_unregister`` are removed. Register of the ISR handler from user code is no longer permitted. Users should register event callbacks instead by calling :cpp:func:`pcnt_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 by :cpp:func:`pcnt_del_channel` and reinstall with the new GPIO number by :cpp:func:`pcnt_new_channel`.
- ``pcnt_filter_enable``, ``pcnt_filter_disable``, and ``pcnt_set_filter_value`` are replaced by :cpp:func:`pcnt_unit_set_glitch_filter`. Meanwhile, ``pcnt_get_filter_value`` has been removed.
- ``pcnt_isr_register`` and ``pcnt_isr_unregister`` are removed. Register of the ISR handler from user's code is no longer permitted. Users should register event callbacks instead by calling :cpp:func:`pcnt_unit_register_event_callbacks`.
- ``pcnt_set_pin`` is removed and the new driver no longer allows the switching of the GPIO at runtime. If users want to change to other GPIOs, please delete the existing PCNT channel by :cpp:func:`pcnt_del_channel` and reinstall with the new GPIO number by :cpp:func:`pcnt_new_channel`.
- ``pcnt_filter_enable``, ``pcnt_filter_disable`` and ``pcnt_set_filter_value`` are replaced by :cpp:func:`pcnt_unit_set_glitch_filter`. Meanwhile, ``pcnt_get_filter_value`` has been removed.
- ``pcnt_set_mode`` is replaced by :cpp:func:`pcnt_channel_set_edge_action` and :cpp:func:`pcnt_channel_set_level_action`.
- ``pcnt_isr_service_install``, ``pcnt_isr_service_uninstall``, ``pcnt_isr_handler_add`` and ``pcnt_isr_handler_remove`` are replaced by :cpp:func:`pcnt_unit_register_event_callbacks`. The default ISR handler is lazy installed in the new driver.
@ -187,38 +284,50 @@ LEDC
Temperature Sensor Driver
-------------------------
- Old API header ``temp_sensor.h`` has been redesigned as ``temperature_sensor.h``, it is recommended to use the new driver and the old driver is not allowed to be used at the same time.
- Although it's recommended to use the new driver APIs, the legacy driver is still available in the previous include path ``driver/temp_sensor.h``. However, by default, including ``driver/temp_sensor.h`` will bring a build warning like "legacy temperature sensor driver is deprecated, please migrate to driver/temperature_sensor.h". The warning can be suppressed by enabling the menuconfig option :ref:`CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN`.
- Configuration contents has been changed. In old version, user need to configure the ``clk_div`` and ``dac_offset``. While in new version, user only need to choose ``tsens_range``
- The process of using temperature sensor has been changed. In old version, user can use ``config->start->read_celsius`` to get value. In the new version, user must install the temperature sensor driver firstly, by ``temperature_sensor_install`` and uninstall it when finished. For more information, you can refer to :doc:`Temperature Sensor <../../api-reference/peripherals/temp_sensor>` .
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`` will trigger the build warning below by default. The warning can be suppressed by enabling the menuconfig option :ref:`CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN`.
.. code-block:: text
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 :doc:`Temperature Sensor <../../api-reference/peripherals/temp_sensor>` .
.. only:: SOC_RMT_SUPPORTED
RMT Driver
----------
RMT driver has been redesigned (see :doc:`RMT transceiver <../../api-reference/peripherals/rmt>`), 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 :ref:`CONFIG_RMT_SUPPRESS_DEPRECATE_WARN`.
RMT driver has been redesigned (see :doc:`RMT transceiver <../../api-reference/peripherals/rmt>`), 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, including ``driver/rmt.h`` will trigger the build warning below by default. The warning can be suppressed by the Kconfig option :ref:`CONFIG_RMT_SUPPRESS_DEPRECATE_WARN`.
.. code-block:: text
The legacy RMT driver is deprecated, please use driver/rmt_tx.h and/or driver/rmt_rx.h
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 by :cpp:type:`rmt_channel_handle_t`. The channel is dynamic allocated by the driver, instead of designated by user.
- ``rmt_channel_t`` which used to identify the hardware channel are removed from user space. In the new driver, RMT channel is represented by :cpp:type:`rmt_channel_handle_t`. The channel is dynamically allocated by the driver, instead of designated by user.
- ``rmt_item32_t`` is replaced by :cpp:type:`rmt_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 by :cpp:type:`rmt_clock_source_t`, note they're not binary compatible.
- ``rmt_mem_owner_t`` is removed, as the ownership is controlled by driver, not by user anymore.
- ``rmt_source_clk_t`` is replaced by :cpp:type:`rmt_clock_source_t`, and 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 in :cpp:member:`rmt_transmit_config_t::eot_level`.
- ``rmt_carrier_level_t`` is removed, setting carrier polarity is available in :cpp:member:`rmt_carrier_config_t::polarity_active_low`.
- ``rmt_channel_status_t`` and ``rmt_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.
- 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 :cpp:func:`rmt_new_tx_channel` and :cpp:func:`rmt_new_rx_channel`.
- ``rmt_set_clk_div`` and ``rmt_get_clk_div`` are removed. Channel clock configuration can only be done during channel installation.
@ -254,12 +363,12 @@ LEDC
LCD
---
- The LCD panel initialization flow is slightly changed. Now the :cpp:func:`esp_lcd_panel_init` won't turn on the display automatically. User needs to call :cpp:func:`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 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.
- The LCD panel initialization flow is slightly changed. Now the :cpp:func:`esp_lcd_panel_init` won't turn on the display automatically. User needs to call :cpp:func:`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.
- :cpp:func:`esp_lcd_panel_disp_off` is deprecated, please use :cpp:func:`esp_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.
- ``dc_as_cmd_phase`` is removed. The SPI LCD driver currently doesn't 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 :cpp:type:`esp_lcd_rgb_panel_config_t` into a separate API :cpp:func:`esp_lcd_rgb_panel_register_event_callbacks`. However, the event callback signature is not changed.
- Previous ``relax_on_idle`` flag in :cpp:type:`esp_lcd_rgb_panel_config_t` has been renamed into :cpp:member:`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 won't start a refresh in the :cpp:func:`esp_lcd_panel_draw_bitmap`. Now you have to call :cpp:func:`esp_lcd_rgb_panel_refresh` to refresh the screen by yourself.
- If the RGB LCD is created with the ``refresh_on_demand`` flag enabled, the driver won't start a refresh in the :cpp:func:`esp_lcd_panel_draw_bitmap`. Now users have to call :cpp:func:`esp_lcd_rgb_panel_refresh` to refresh the screen by themselves.
- :cpp:type:`esp_lcd_color_space_t` is deprecated, please use :cpp:type:`lcd_color_space_t` to describe the color space, and use :cpp:type:`lcd_color_rgb_endian_t` to describe the data order of RGB color.
.. only:: SOC_MCPWM_SUPPORTED
@ -267,18 +376,26 @@ LCD
MCPWM
-----
MCPWM driver was redesigned (see :doc:`MCPWM <../../api-reference/peripherals/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 :ref:`CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN`.
MCPWM driver was redesigned (see :doc:`MCPWM <../../api-reference/peripherals/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, using legacy driver will rigger the build warning below by default. This warning can be suppressed by the Kconfig option :ref:`CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN`.
.. code-block:: text
legacy MCPWM driver is deprecated, please migrate to the new driver (include driver/mcpwm_prelude.h)
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 :cpp:func:`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.
The legacy driver presets 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.
@ -292,18 +409,18 @@ LCD
- ``mcpwm_capture_signal_t`` is not used. A capture channel is represented by :cpp:type:`mcpwm_cap_channel_handle_t`.
Breaking Changes in Usage
~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^
- ``mcpwm_gpio_init`` and ``mcpwm_set_pin``: GPIO configurations are moved to submodule's own configuration. e.g. set the PWM GPIO in :cpp:member:`mcpwm_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 calling :cpp:func:`mcpwm_operator_connect_timer`. After that, you should set the generator's actions on various events by calling e.g. :cpp:func:`mcpwm_generator_set_actions_on_timer_event`, :cpp:func:`mcpwm_generator_set_actions_on_compare_event`.
- ``mcpwm_init``: To get an expected PWM waveform, users need to allocated at least one MCPWM timer and MCPWM operator, then connect them by calling :cpp:func:`mcpwm_operator_connect_timer`. After that, users should set the generator's actions on various events by calling e.g. :cpp:func:`mcpwm_generator_set_actions_on_timer_event`, :cpp:func:`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 in :cpp:member:`mcpwm_timer_config_t::resolution_hz`.
- ``mcpwm_set_frequency``: PWM frequency is determined by :cpp:member:`mcpwm_timer_config_t::resolution_hz`, :cpp:member:`mcpwm_timer_config_t::count_mode` and :cpp:member:`mcpwm_timer_config_t::period_ticks`.
- ``mcpwm_set_duty``: To set the PWM duty cycle, you should call :cpp:func:`mcpwm_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. :cpp:func:`mcpwm_generator_set_actions_on_timer_event`.
- ``mcpwm_set_duty``: To set the PWM duty cycle, users should call :cpp:func:`mcpwm_comparator_set_compare_value` to change comparator's threshold.
- ``mcpwm_set_duty_type``: There won't be any preset duty cycle types, the duty cycle type is configured by setting different generator actions. e.g. :cpp:func:`mcpwm_generator_set_actions_on_timer_event`.
- ``mcpwm_set_signal_high`` and ``mcpwm_set_signal_low`` are replaced by :cpp:func:`mcpwm_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`` and ``mcpwm_stop`` are replaced by :cpp:func:`mcpwm_timer_start_stop`. You have more modes to start and stop the MCPWM timer, see :cpp:type:`mcpwm_timer_start_stop_cmd_t`.
- ``mcpwm_carrier_init``: It's replaced by :cpp:func:`mcpwm_operator_apply_carrier`.
- ``mcpwm_carrier_init`` is replaced by :cpp:func:`mcpwm_operator_apply_carrier`.
- ``mcpwm_carrier_enable`` and ``mcpwm_carrier_disable``: Enabling and disabling carrier submodule is done automatically by checking whether the carrier configuration structure :cpp:type:`mcpwm_carrier_config_t` is NULL.
- ``mcpwm_carrier_set_period`` is replaced by :cpp:member:`mcpwm_carrier_config_t::frequency_hz`.
- ``mcpwm_carrier_set_duty_cycle`` is replaced by :cpp:member:`mcpwm_carrier_config_t::duty_cycle`.
@ -323,85 +440,94 @@ LCD
- ``mcpwm_set_timer_sync_output`` is replaced by :cpp:func:`mcpwm_new_timer_sync_src`.
- ``mcpwm_timer_trigger_soft_sync`` is replaced by :cpp:func:`mcpwm_soft_sync_activate`.
- ``mcpwm_sync_invert_gpio_synchro`` is equivalent to setting :cpp:member:`mcpwm_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 use :cpp:func:`mcpwm_capture_channel_register_event_callbacks`.
- ``mcpwm_isr_register`` is removed. You can register various event callbacks instead. For example, to register capture event callback, users can use :cpp:func:`mcpwm_capture_channel_register_event_callbacks`.
.. only:: SOC_DEDICATED_GPIO_SUPPORTED
Dedicated GPIO Driver
---------------------
- All of the dedicated GPIO related LL functionsn in ``cpu_ll.h`` have been moved to ``dedic_gpio_cpu_ll.h`` and renamed.
- 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.
.. only:: SOC_I2S_SUPPORTED
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 :component_file:`driver/include/driver/i2s_std.h`, :component_file:`driver/include/driver/i2s_pdm.h` or :component_file:`driver/include/driver/i2s_tdm.h`. Meanwhile, the old APIs in :component_file:`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 :ref:`CONFIG_I2S_SUPPRESS_DEPRECATE_WARN`. Here is the general overview of the current I2S files:
The I2S driver has been redesigned (see :doc:`I2S Driver <../../api-reference/peripherals/i2s>`), which aims to rectify the shortcomings of the driver that were exposed when supporting all the new features of ESP32-C3 & ESP32-S3. The new driver's APIs are available by including corresponding I2S mode's header files :component_file:`driver/include/driver/i2s_std.h`, :component_file:`driver/include/driver/i2s_pdm.h`, or :component_file:`driver/include/driver/i2s_tdm.h`.
Meanwhile, the old driver's APIs in :component_file:`driver/deprecated/driver/i2s.h` are still supported for backward compatibility. But there will be warnings if users keep using the old APIs in their projects, these warnings can be suppressed by the Kconfig option :ref:`CONFIG_I2S_SUPPRESS_DEPRECATE_WARN`.
Here is the general overview of the current I2S files:
.. figure:: ../../../_static/diagrams/i2s/i2s_file_structure.png
:align: center
:alt: I2S File Structure
Breaking changes in Concepts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The minimum control unit in new I2S driver will be tx/rx channel instead of a whole I2S controller.
Independent TX/RX channels
""""""""""""""""""""""""""
1. 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;
2. The channels can be registered to an available I2S controller automatically by setting :cpp:enumerator:`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;
3. :c:type:`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;
4. 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'.
The minimum control unit in new I2S driver are now individual TX/RX channels instead of an entire I2S controller (that consistes of multiple channels).
- I2S communication modes are extracted into three modes.
- The TX and RX channels of the same I2S controller can be controlled separately, meaning that they are configured such that they can be started or stopped separately.
- The c:type:`i2s_chan_handle_t` handle type is used to uniquely identify I2S channels. All the APIs will require the channel handle and users need to maintain the channel handles by themselves.
- On the ESP32-C3 and ESP32-S3, TX and RX channels in the same controller can be configured to different clocks or modes.
- However, on the ESP32 and ESP32-S2, the TX and RX channels of the same controller still share some hardware resources. Thus, configurations may cause one channel to affect another channel in the same controller.
- The channels can be registered to an available I2S controller automatically by setting :cpp:enumerator:`i2s_port_t::I2S_NUM_AUTO` as I2S port ID which will cause the driver to search for the available TX/RX channels. However, the driver also supports registering channels to a specific port.
- In order to distinguish between TX/RX channels and sound channels, the term 'channel' in the context of the I2S driver will only refer to TX/RX channels. Meanwhile, sound channels will be referred to as "slots".
1. **Standard mode**: Standard mode always has two slots, it can support Philip, MSB and PCM(short sync) format, please refer to :component_file:`driver/include/driver/i2s_std.h` for details;
2. **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 :cpp:member:`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 by :cpp:member:`i2s_pdm_rx_clk_config_t::sample_rate`, and its clock frequency is depended on the down-sampling configuration. Please refer to :component_file:`driver/include/driver/i2s_pdm.h` for details;
3. **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 :component_file:`driver/include/driver/i2s_tdm.h` for details;
4. 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.
I2S Mode Categorization
""""""""""""""""""""""""
I2S communication modes are categorized into the following three modes. Note that:
- **Standard mode**: Standard mode always has two slots, it can support Philips, MSB, and PCM (short frame sync) formats. Please refer to :component_file:`driver/include/driver/i2s_std.h` for more details.
- **PDM mode**: PDM mode only supports two slots with 16-bit data width, but the configurations of PDM TX and PDM RX are slightly different. For PDM TX, the sample rate can be set by :cpp:member:`i2s_pdm_tx_clk_config_t::sample_rate`, and its clock frequency depends on the up-sampling configuration. For PDM RX, the sample rate can be set by :cpp:member:`i2s_pdm_rx_clk_config_t::sample_rate`, and its clock frequency depends on the down-sampling configuration. Please refer to :component_file:`driver/include/driver/i2s_pdm.h` for details.
- **TDM mode**: TDM mode can support up to 16 slots. It can work in Philips, MSB, PCM (short frame sync), and PCM (long frame sync) formats. Please refer to :component_file:`driver/include/driver/i2s_tdm.h` for details.
When allocating a new channel in a specific mode, users should initialize that channel by its corresponding function. It is strongly recommended to use the helper macros to generate the default configurations in case the default values are changed in the future.
Independent Slot and Clock Configuration
""""""""""""""""""""""""""""""""""""""""
The slot configurations and clock configurations can be configured separately.
- Call :cpp:func:`i2s_channel_init_std_mode`, :cpp:func:`i2s_channel_init_pdm_rx_mode`, :cpp:func:`i2s_channel_init_pdm_tx_mode`, or :cpp:func:`i2s_channel_init_tdm_mode` to initialize the slot/clock/gpio_pin configurations.
- Calling :cpp:func:`i2s_channel_reconfig_std_slot`, :cpp:func:`i2s_channel_reconfig_pdm_rx_slot`, :cpp:func:`i2s_channel_reconfig_pdm_tx_slot`, or :cpp:func:`i2s_channel_reconfig_tdm_slot` can change the slot configurations after initialization.
- Calling :cpp:func:`i2s_channel_reconfig_std_clock`, :cpp:func:`i2s_channel_reconfig_pdm_rx_clock`, :cpp:func:`i2s_channel_reconfig_pdm_tx_clock`, or :cpp:func:`i2s_channel_reconfig_tdm_clock` can change the clock configurations after initialization.
- Calling :cpp:func:`i2s_channel_reconfig_std_gpio`, :cpp:func:`i2s_channel_reconfig_pdm_rx_gpio`, :cpp:func:`i2s_channel_reconfig_pdm_tx_gpio`, or :cpp:func:`i2s_channel_reconfig_tdm_gpio` can change the GPIO configurations after initialization.
Misc
""""
- 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.
1. Calling :cpp:func:`i2s_channel_init_std_mode`, :cpp:func:`i2s_channel_init_pdm_rx_mode`, :cpp:func:`i2s_channel_init_pdm_tx_mode` or :cpp:func:`i2s_channel_init_tdm_mode` to initialize the slot/clock/gpio_pin configurations;
2. Calling :cpp:func:`i2s_channel_reconfig_std_slot`, :cpp:func:`i2s_channel_reconfig_pdm_rx_slot`, :cpp:func:`i2s_channel_reconfig_pdm_tx_slot` or :cpp:func:`i2s_channel_reconfig_tdm_slot` can change the slot configurations after initialization;
3. Calling :cpp:func:`i2s_channel_reconfig_std_clock`, :cpp:func:`i2s_channel_reconfig_pdm_rx_clock`, :cpp:func:`i2s_channel_reconfig_pdm_tx_clock` or :cpp:func:`i2s_channel_reconfig_tdm_clock` can change the clock configurations after initialization;
4. Calling :cpp:func:`i2s_channel_reconfig_std_gpio`, :cpp:func:`i2s_channel_reconfig_pdm_rx_gpio`, :cpp:func:`i2s_channel_reconfig_pdm_tx_gpio` or :cpp:func:`i2s_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.
- :cpp:func:`i2s_channel_write` and :cpp:func:`i2s_channel_read` can be aborted by :cpp:func:`i2s_channel_abort_reading_writing` now.
- ADC and DAC modes are removed. They will only be supported in their own drivers and the legacy I2S driver.
Breaking Changes in Usage
~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^
To use the new I2S driver, please follow these steps:
1. Calling :cpp:func:`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.
1. Call :cpp:func:`i2s_new_channel` to acquire channel handles. We should specify the work role and I2S port in this step. Besides, the TX or RX channel handle will be generated by the driver. Inputting both two TX and RX channel handles is not necessary but at least one handle is needed. In the case of inputting both two handles, the driver will work at the duplex mode. Both TX and RX channels 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 channel handle is inputted, this channel will only work in the simplex mode.
2. Call :func:`i2s_channel_init_std_mode`, :func:`i2s_channel_init_pdm_rx_mode`, :func:`i2s_channel_init_pdm_tx_mode` or :func:`i2s_channel_init_tdm_mode` to initialize the channel to the specified mode. Corresponding slot, clock and GPIO configurations are needed in this step.
3. (Optional) Call :cpp:func:`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 the event queue asynchronously.
4. Call :cpp:func:`i2s_channel_enable` to start the hardware of I2S channel. In the new driver, I2S won't start automatically after installed, and users are supposed to know clearly whether the channel has started or not.
5. Read or write data by :cpp:func:`i2s_channel_read` or :cpp:func:`i2s_channel_write`. Certainly, only the RX channel handle is suppoesd to be inputted in :cpp:func:`i2s_channel_read` and the TX channel handle in :cpp:func:`i2s_channel_write`.
6. (Optional) The slot, clock and GPIO configurations can be changed by corresponding 'reconfig' functions, but :cpp:func:`i2s_channel_disable` must be called before updating the configurations.
7. Call :cpp:func:`i2s_channel_disable` to stop the hardware of I2S channel.
8. Call :cpp:func:`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.
2. Calling :func:`i2s_channel_init_std_mode`, :func:`i2s_channel_init_pdm_rx_mode`, :func:`i2s_channel_init_pdm_tx_mode` or :func:`i2s_channel_init_tdm_mode` to initialize the channel to the specified mode. Corresponding slot, clock and gpio configurations are needed in this step.
3. (Optional) Calling :cpp:func:`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.
4. Calling :cpp:func:`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.
5. Reading or writing data by :cpp:func:`i2s_channel_read` or :cpp:func:`i2s_channel_write`. Certainly, only rx channel handle is suppoesd to be inputted in :cpp:func:`i2s_channel_read` and tx channel handle in :cpp:func:`i2s_channel_write`.
6. (Optional) The slot, clock and gpio configurations can be changed by corresponding 'reconfig' functions, but :cpp:func:`i2s_channel_disable` must be called before updating the configurations.
7. Calling :cpp:func:`i2s_channel_disable` to stop the hardware of I2S channel.
8. Calling :cpp:func:`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
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``.
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::
@ -411,4 +537,4 @@ To store the value which would have been written into the register, split the op
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);
uint32_t new_val = REG_READ(reg);

Wyświetl plik

@ -1 +1,540 @@
.. include:: ../../../en/migration-guides/release-5.x/peripherals.rst
外设
============
:link_to_translation:`en:[English]`
外设时钟门控
------------------------------
与更新之前相同,外设的时钟仍由驱动处理,用户无需对外设模块的时钟门控进行设置。
但是,如果用户想基于组件 ``hal````soc`` 开发自己的驱动,请注意时钟门控的头文件引用路径已由 ``driver/periph_ctrl.h`` 更新为 ``esp_private/periph_ctrl.h``
RTC 子系统控制
----------------------------------
RTC 控制 API 已经从 ``driver/rtc_cntl.h`` 移动到了 ``esp_private/rtc_ctrl.h``
ADC
-----------------
ADC 单次模式及连续模式驱动
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ADC 单次模式的驱动已更新。
- 新的驱动位于组件 ``esp_adc`` 中,头文件引用路径为 ``esp_adc/adc_oneshot.h``
- 旧版驱动仍然可用,其头文件引用路径为 ``driver/adc.h``
对于 ADC 连续模式驱动,其位置已由组件 ``driver`` 更新为 ``esp_adc``
- 头文件引用路径由 ``driver/adc.h`` 更新为 ``esp_adc/adc_continuous.h``
但是,引用两种模式的旧版路径 ``driver/adc.h`` 会默认触发如下编译警告,可通过配置 Kconfig 选项 :ref:`CONFIG_ADC_SUPPRESS_DEPRECATE_WARN` 关闭该警告。
.. code-block:: text
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 校准驱动
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ADC 校准驱动已更新。
- 新的驱动位于组件 ``esp_adc`` 中,头文件引用路径为 ``esp_adc/adc_cali.h````esp_adc/adc_cali_scheme.h``
旧版驱动仍然可用,其头文件引用路径为 ``esp_adc_cal.h``。如果用户要使用旧版路径,需要将组件 ``esp_adc`` 添加到文件 CMakeLists.txt 的组件需求表中。
默认情况下,引用路径 ``esp_adc_cal.h`` 会默认触发如下编译警告,可通过配置 Kconfig 选项 :ref:`CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN` 关闭该警告。
.. code-block:: text
legacy adc calibration driver is deprecated, please migrate to use esp_adc/adc_cali.h and esp_adc/adc_cali_scheme.h
API 更新
^^^^^^^^^^^^^^^^^^^^^
- ADC 电源管理 API ``adc_power_acquire````adc_power_release`` 已被移至 ``esp_private/adc_share_hw_ctrl.h``,用于内部功能。
- 更新前,由于硬件勘误表的工作原理,这两个 API 可以被用户调用。
- 更新后ADC 电源管理完全由驱动在内部实现。
- 如果用户仍需调用这个 API可以通过引用路径 ``esp_private/adc_share_hw_ctrl.h`` 来调用它。
- 更新后, ``driver/adc2_wifi_private.h`` 已被移至 ``esp_private/adc_share_hw_ctrl.h``
- ``adc_unit_t`` 中的枚举 ``ADC_UNIT_BOTH`` ``ADC_UNIT_ALTER````ADC_UNIT_MAX`` 已被删除。
- 由于只有部分芯片支持下列枚举的某些取值,因此将下列枚举删除。如果用户使用了不支持的取值,会造成驱动运行错误。
- 枚举 ``ADC_CHANNEL_MAX``
- 枚举 ``ADC_ATTEN_MAX``
- 枚举 ``ADC_CONV_UNIT_MAX``
- ESP32 中的 API ``hall_sensor_read`` 已被删除,因此 ESP32 不再支持霍尔传感器。
- API ``adc_set_i2s_data_source````adc_i2s_mode_init`` 已被弃用,相关的枚举 ``adc_i2s_source_t`` 也已被弃用,请使用 ``esp_adc/adc_continuous.h`` 进行迁移。
GPIO
----------
- 之前的 Kconfig 选项 `RTCIO_SUPPORT_RTC_GPIO_DESC` 已被删除,因此数组 ``rtc_gpio_desc`` 已不可用,请使用替代数组 ``rtc_io_desc``
- 更新后,用户回调函数无法再通过读取 GPIO 中断的状态寄存器来获取用于触发中断的 GPIO 管脚的编号。但是,用户可以通过使用回调函数变量来确定该管脚编号。
- 更新前GPIO 中断发生时GPIO 中断状态寄存器调用用户回调函数之后,会被清空。因此,用户可以在回调函数中读取 GPIO 中断状态寄存器,以便确定触发中断的 GPIO 管脚。
- 但是,在调用回调函数后清空中断状态寄存器可能会导致边沿触发的中断丢失。例如,在调用用户回调函数时,如果某个边沿触发的中断 (re) 被触发,该中断会被清除,并且其注册的用户回调函数还未被处理。
- 更新后GPIO 的中断状态寄存器在调用用户回调函数 **之前** 被清空。因此,用户无法读取 GPIO 中断状态寄存器来确定哪个管脚触发了中断。但是,用户可以通过回调函数变量来传递被触发的管脚编号。
.. only:: SOC_SDM_SUPPORTED
Sigma-Delta 调制器
---------------------------------
Sigma-Delta 调制器的驱动现已更新为 :doc:`SDM <../../api-reference/peripherals/sdm>`
- 新驱动中实现了工厂模式SDM 通道都位于内部通道池中,因此用户无需手动将 SDM 通道配置到 GPIO 管脚。
- SDM 通道会被自动分配。
尽管我们推荐用户使用新的驱动 API旧版驱动仍然可用位于头文件引用路径 ``driver/sigmadelta.h`` 中。但是,引用 ``driver/sigmadelta.h`` 会默认触发如下编译警告,可通过配置 Kconfig 选项 :ref:`CONFIG_SDM_SUPPRESS_DEPRECATE_WARN` 关闭该警告。
.. code-block:: text
The legacy sigma-delta driver is deprecated, please use driver/sdm.h
概念与使用方法上的主要更新如下所示:
主要概念更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- SDM 通道名称已由 ``sigmadelta_channel_t`` 更新为 :cpp:type:`sdm_channel_handle_t`,后者为一个不透明指针。
- SDM 通道配置原来存放于 ``sigmadelta_config_t``,现存放于 :cpp:type:`sdm_config_t`
- 旧版驱动中,用户无需为 SDM 通道设置时钟源。但是在新驱动中,用户需要在 :cpp:member:`sdm_config_t::clk_src` 为 SDM 通道设置合适的时钟源,:cpp:type:`soc_periph_sdm_clk_src_t` 中列出了可用的时钟源。
- 旧版驱动中,用户需要为通道设置 ``prescale``,该参数会影响调制器输出脉冲的频率。在新的驱动中,用户需要使用 :cpp:member:`sdm_config_t::sample_rate_hz` 实现该功能。
主要使用方法更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 更新前,通道配置由通道分配在 :cpp:func:`sdm_new_channel` 完成。在新驱动中,只有 ``duty`` 可在运行时由 :cpp:func:`sdm_channel_set_duty` 更新。其他参数如 ``gpio number````prescale`` 只能在通道分配时进行设置。
- 在进行下一步通道操作前,用户应通过调用 :cpp:func:`sdm_channel_enable` 提前 **使能** 该通道。该函数有助于管理一些系统级服务,如 **电源管理**
定时器组驱动
-----------------------------------------
为统一和简化通用定时器的使用,定时器组驱动已更新为 :doc:`GPTimer <../../api-reference/peripherals/gptimer>`
尽管我们推荐使用新的驱动 API 旧版驱动仍然可用,其头文件引用路径为 ``driver/timer.h``。但是,引用 ``driver/timer.h`` 会默认触发如下编译警告,可通过配置 Kconfig 选项 :ref:`CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN` 关闭该警告。
.. code-block:: text
legacy timer group driver is deprecated, please migrate to driver/gptimer.h
概念和使用方法上的主要更新如下所示:
主要概念更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 用于识别定时器的 ``timer_group_t````timer_idx_t`` 已被删除。在新驱动中,定时器用参数 :cpp:type:`gptimer_handle_t` 表示。
- 更新后,定时器的时钟源由 :cpp:type:`gptimer_clock_source_t` 定义,之前的时钟源参数 ``timer_src_clk_t`` 不再使用。
- 更新后,定时器计数方向由 :cpp:type:`gptimer_count_direction_t` 定义,之前的计数方向参数 ``timer_count_dir_t`` 不再使用。
- 更新后,仅支持电平触发的中断, ``timer_intr_t````timer_intr_mode_t`` 不再使用。
- 更新后,通过设置标志位 :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` 可以使能自动加载。 ``timer_autoreload_t`` 不再使用。
主要使用方法更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 更新后,通过从 :cpp:func:`gptimer_new_timer` 创建定时器示例可以初始化定时器。用户可以在 :cpp:type:`gptimer_config_t` 进行一些基本设置,如时钟源,分辨率和计数方向。请注意,无需在驱动安装阶段进行报警事件的特殊设置。
- 更新后,报警事件在 :cpp:func:`gptimer_set_alarm_action` 中进行设置,参数在 :cpp:type:`gptimer_alarm_config_t` 中进行设置。
- 更新后,通过 :cpp:func:`gptimer_get_raw_count` 设置计数数值,通过 :cpp:func:`gptimer_set_raw_count` 获取计数数值。驱动不会自动将原始数据同步到 UTC 时间戳。由于定时器的分辨率已知,用户可以自行转换数据。
- 更新后,如果 :cpp:member:`gptimer_event_callbacks_t::on_alarm` 被设置为有效的回调函数,驱动程序也会安装中断服务。在回调函数中,用户无需配置底层寄存器,如用于“清除中断状态”,“重新使能事件”的寄存器等。因此, ``timer_group_get_intr_status_in_isr````timer_group_get_auto_reload_in_isr`` 这些函数不再使用。
- 更新后,当报警事件发生时,为更新报警配置,用户可以在中断回调中调用 :cpp:func:`gptimer_set_alarm_action`,这样报警事件会被重新使能。
- 更新后,如果用户将 :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` 设置为 true报警事件将会一直被驱动程序使能。
UART
------------
.. list-table::
:width: 700 px
:header-rows: 1
* - 删除/弃用项目
- 替代
- 备注
* - ``uart_isr_register()``
- 无
- 更新后UART 中断由驱动处理。
* - ``uart_isr_free()``
- 无
- 更新后UART 中断由驱动处理。
* - :cpp:type:`uart_config_t` 中的 ``use_ref_tick``
- :cpp:member:`uart_config_t::source_clk`
- 选择时钟源。
* - ``uart_enable_pattern_det_intr()``
- :cpp:func:`uart_enable_pattern_det_baud_intr`
- 使能模式检测中断。
I2C
-------
.. list-table::
:width: 700 px
:header-rows: 1
* - 删除/弃用项目
- 替代
- 备注
* - ``i2c_isr_register()``
- 无
- 更新后I2C 中断由驱动处理。
* - ``i2c_isr_register()``
- 无
- 更新后I2C 中断由驱动处理。
* - ``i2c_opmode_t``
- 无
- 更新后,该项不再在 esp-idf 中使用。
SPI
---
.. list-table::
:width: 700 px
:header-rows: 1
* - 删除/弃用项目
- 替代
- 备注
* - ``spi_cal_clock()``
- :cpp:func:`spi_get_actual_clock`
- 获取 SPI 真实的工作频率。
- 内部头文件 ``spi_common_internal.h`` 已被移至 ``esp_private/spi_common_internal.h``
.. only:: SOC_SDMMC_HOST_SUPPORTED
SDMMC
-----
.. list-table::
:width: 700 px
:header-rows: 1
* - 删除/弃用项目
- 替代
- 备注
* - ``sdmmc_host_pullup_en()``
- 在 :cpp:member:`sdmmc_slot_config_t::flags` 设置标志位 ``SDMMC_SLOT_FLAG_INTERNAL_PULLUP``
- 使能内部上拉。
LEDC
-----
.. list-table::
:width: 700 px
:header-rows: 1
* - 删除/弃用项目
- 替代
- 备注
* - :cpp:type:`ledc_timer_config_t` 中的 ``bit_num``
- :cpp:member:`ledc_timer_config_t::duty_resolution`
- 设置占空比分辨率。
.. only:: SOC_PCNT_SUPPORTED
脉冲计数器 (PCNT) 驱动
----------------------------------
为统一和简化 PCNT 外设PCNT 驱动已更新,详见 :doc:`PCNT <../../api-reference/peripherals/pcnt>`
尽管我们推荐使用新的驱动 API旧版驱动仍然可用保留在头文件引用路径 ``driver/pcnt.h`` 中。但是,引用路径 ``driver/pcnt.h`` 会默认触发如下编译警告,可通过配置 Kconfig 选项 :ref:`CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN` 来关闭该警告。
.. code-block:: text
legacy pcnt driver is deprecated, please migrate to use driver/pulse_cnt.h
主要概念和使用方法上的更新如下所示:
主要概念更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 更新后, ``pcnt_port_t````pcnt_unit_t````pcnt_channel_t`` 这些用于识别 PCNT 单元和通道的参数已被删除。在新的驱动中PCNT 单元由参数 :cpp:type:`pcnt_unit_handle_t` 表示PCNT 通道由参数 :cpp:type:`pcnt_channel_handle_t` 表示,这两个参数都是不透明指针。
- 更新后,不再使用 ``pcnt_evt_type_t``,它们由统一的 **观察点事件** 表示。在事件回调函数 :cpp:type:`pcnt_watch_cb_t` 中,通过 :cpp:type:`pcnt_watch_event_data_t` 可以分辨不同观察点。
- ``pcnt_count_mode_t`` 更新为:cpp:type:`pcnt_channel_edge_action_t` ``pcnt_ctrl_mode_t`` 更新为 :cpp:type:`pcnt_channel_level_action_t`
主要使用方法更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 更新前PCNT 的单元配置和通道配置都通过函数 ``pcnt_unit_config`` 实现。更新后PCNT 的单元配置通过工厂 API :cpp:func:`pcnt_new_unit` 完成,通道配置通过工厂 API :cpp:func:`pcnt_new_channel` 完成。
- 只需配置计数范围即可初始化一个 PCNT 单元。更新后GPIO 管脚分配通过 :cpp:func:`pcnt_new_channel` 完成。
- 高/低电平控制模式和上升沿/下降沿计数模式分别通过函数 :cpp:func:`pcnt_channel_set_edge_action`:cpp:func:`pcnt_channel_set_level_action` 进行设置。
- ``pcnt_get_counter_value`` 更新为 :cpp:func:`pcnt_unit_get_count`
- ``pcnt_counter_pause`` 更新为 :cpp:func:`pcnt_unit_stop`
- ``pcnt_counter_resume`` 更新为 :cpp:func:`pcnt_unit_start`
- ``pcnt_counter_clear`` 更新为 :cpp:func:`pcnt_unit_clear_count`
- 更新后, ``pcnt_intr_enable````pcnt_intr_disable`` 已被删除。新的驱动中,通过注册时间回调函数 :cpp:func:`pcnt_unit_register_event_callbacks` 来使能中断。
- 更新后, ``pcnt_event_enable````pcnt_event_disable`` 已被删除。新的驱动中,可通过 :cpp:func:`pcnt_unit_add_watch_point`:cpp:func:`pcnt_unit_remove_watch_point` 来增加/删除观察点,以使能/停用 PCNT 事件。
- 更新后, ``pcnt_set_event_value`` 已被删除。新的驱动中,通过 :cpp:func:`pcnt_unit_add_watch_point` 增加观察点时,也同时设置了事件的数值。
- 更新后, ``pcnt_get_event_value````pcnt_get_event_status`` 已被删除。在新的驱动中,这些信息存储在 :cpp:type:`pcnt_watch_event_data_t` 的回调函数 :cpp:type:`pcnt_watch_cb_t` 中。
- 更新后, ``pcnt_isr_register````pcnt_isr_unregister`` 已被删除,不允许注册 ISR 句柄。 用户可以通过调用:cpp:func:`pcnt_unit_register_event_callbacks` 来注册事件回调函数。
- 更新后, ``pcnt_set_pin`` 已被删除,新的驱动不再允许在运行时切换 GPIO 管脚。如果用户想切换为其他 GPIO 管脚,可通过:cpp:func:`pcnt_del_channel` 删除当前的 PCNT 通道,然后通过:cpp:func:`pcnt_new_channel` 安装新的 GPIO 管脚。
- ``pcnt_filter_enable`` ``pcnt_filter_disable````pcnt_set_filter_value`` 更新为 :cpp:func:`pcnt_unit_set_glitch_filter`。同时, ``pcnt_get_filter_value`` 已被删除。
- ``pcnt_set_mode`` 更新为 :cpp:func:`pcnt_channel_set_edge_action`:cpp:func:`pcnt_channel_set_level_action`
- ``pcnt_isr_service_install`` ``pcnt_isr_service_uninstall`` ``pcnt_isr_handler_add````pcnt_isr_handler_remove`` 更新为 :cpp:func:`pcnt_unit_register_event_callbacks`。默认的 ISR 句柄已安装在新的驱动中。
.. only:: SOC_TEMP_SENSOR_SUPPORTED
温度传感器驱动
------------------------------------------------------------
温度传感器的驱动已更新,推荐用户使用新驱动。旧版驱动仍然可用,但是无法与新驱动同时使用。
新驱动的头文件引用路径为 ``driver/temperature_sensor.h``。旧版驱动仍然可用,保留在引用路径 ``driver/temp_sensor.h`` 中。但是,引用路径 ``driver/temp_sensor.h`` 会默认触发如下编译警告,可通过设置 Kconfig 选项 :ref:`CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN` 来关闭该警告。
.. code-block:: text
legacy temperature sensor driver is deprecated, please migrate to driver/temperature_sensor.h
配置内容已更新。更新前,用户需要设置 ``clk_div````dac_offset``。更新后,用户仅需设置 ``tsens_range``
温度传感器的使用过程也已更新。更新前,用户可通过 ``config->start->read_celsius`` 获取数据。更新后,用户需要通过 ``temperature_sensor_install`` 先安装温度传感器的驱动,测量完成后需卸载驱动,详情请参考 :doc:`Temperature Sensor <../../api-reference/peripherals/temp_sensor>`
.. only:: SOC_RMT_SUPPORTED
RMT 驱动
----------------------
为统一和扩展 RMT 外设的使用RMT 驱动已更新,详见 :doc:`RMT transceiver <../../api-reference/peripherals/rmt>`
尽管我们建议使用新的驱动 API旧版驱动仍然可用保留在头文件引用路径 ``driver/rmt.h``中。但是,引用路径 ``driver/rmt.h`` 会默认触发如下编译警告,可通过配置 Kconfig 选项 :ref:`CONFIG_RMT_SUPPRESS_DEPRECATE_WARN` 来关闭该警告。
.. code-block:: text
The legacy RMT driver is deprecated, please use driver/rmt_tx.h and/or driver/rmt_rx.h
主要概念和使用方法更新如下所示:
主要概念更新
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 更新后,用于识别硬件通道的 ``rmt_channel_t`` 已删除。在新的驱动中RMT 通道用参数 :cpp:type:`rmt_channel_handle_t` 表示,该通道由驱动程序动态分配,而不是由用户指定。
- ``rmt_item32_t`` 更新为 :cpp:type:`rmt_symbol_word_t`,以避免在结构体中出现嵌套的共用体。
- 更新后, ``rmt_mem_t`` 已被删除,因为我们不允许用户直接访问 RMT 内存块(即 RMTMEM。直接访问 RMTMEM 没有意义,反而会引发错误,特别是当 RMT 通道与 DMA 通道相连时。
- 更新后,由于 ``rmt_mem_owner_t`` 由驱动控制,而不是用户,因此 ``rmt_mem_owner_t`` 已被删除。
- ``rmt_source_clk_t`` 更新为 :cpp:type:`rmt_clock_source_t`,后者不支持二进制兼容。
- 更新后, ``rmt_data_mode_t`` 已被删除RMT 内存访问模式配置为始终使用 Non-FIFO 和 DMA 模式。
- 更新后,由于驱动有独立的发送和接收通道安装函数,因此 ``rmt_mode_t`` 已被删除。
- 更新后, ``rmt_idle_level_t`` 已被删除,在 :cpp:member:`rmt_transmit_config_t::eot_level` 中可为发送通道设置空闲状态电平。
- 更新后, ``rmt_carrier_level_t`` 已被删除,可在 :cpp:member:`rmt_carrier_config_t::polarity_active_low` 设置载流子极性。
- 更新后, ``rmt_channel_status_t````rmt_channel_status_result_t`` 已被删除,不再使用。
- 通过 RMT 通道发送并不需要用户提供 RMT 符号,但是用户需要提供一个 RMT 编码器用来告诉驱动如何将用户数据转换成 RMT 符号。
主要使用方法更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 更新后,分别通过 :cpp:func:`rmt_new_tx_channel`:cpp:func:`rmt_new_rx_channel` 安装发送通道和接收通道。
- 更新后, ``rmt_set_clk_div````rmt_get_clk_div`` 已被删除。通道时钟配置只能在通道安装时完成。
- 更新后, ``rmt_set_rx_idle_thresh````rmt_get_rx_idle_thresh`` 已被删除。新驱动中,接收通道的空闲状态阈值定义为 :cpp:member:`rmt_receive_config_t::signal_range_max_ns`
- 更新后, ``rmt_set_mem_block_num````rmt_get_mem_block_num`` 已被删除。新驱动中,内存块的数量由 :cpp:member:`rmt_tx_channel_config_t::mem_block_symbols`:cpp:member:`rmt_rx_channel_config_t::mem_block_symbols` 决定。
- 更新后, ``rmt_set_tx_carrier`` 已被删除。新驱动使用 :cpp:func:`rmt_apply_carrier` 来设置载波动作。
- 更新后, ``rmt_set_mem_pd````rmt_get_mem_pd`` 已被删除,驱动程序自动调整内存的功率。
- 更新后, ``rmt_memory_rw_rst`` ``rmt_tx_memory_reset````rmt_rx_memory_reset`` 已被删除,驱动程序自动进行内存重置。
- 更新后, ``rmt_tx_start````rmt_rx_start`` 被合并为函数 :cpp:func:`rmt_enable`,该函数同时适用于发射通道和接收通道。
- 更新后, ``rmt_tx_stop````rmt_rx_stop`` 被合并为函数 :cpp:func:`rmt_disable`,该函数同时适用于发射通道和接收通道。
- 更新后, ``rmt_set_memory_owner````rmt_get_memory_owner`` 已被删除,驱动程序自动添加 RMT 内存保护。
- 更新后, ``rmt_set_tx_loop_mode````rmt_get_tx_loop_mode`` 已被删除。新驱动中,在 :cpp:member:`rmt_transmit_config_t::loop_count` 中设置循环模式。
- 更新后, ``rmt_set_source_clk````rmt_get_source_clk`` 已被删除。仅能在通道安装时通过 :cpp:member:`rmt_tx_channel_config_t::clk_src`:cpp:member:`rmt_rx_channel_config_t::clk_src` 设置时钟源。
- 更新后, ``rmt_set_rx_filter`` 已被删除。新驱动中,过滤阈值定义为 :cpp:member:`rmt_receive_config_t::signal_range_min_ns`
- 更新后, ``rmt_set_idle_level````rmt_get_idle_level`` 已被删除,可在 :cpp:member:`rmt_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````rmt_set_rx_thr_intr_en`` 已被删除。新驱动不允许用户在用户端开启/关闭中断,而是提供了回调函数。
- 更新后, ``rmt_set_gpio````rmt_set_pin`` 已被删除。新驱动不支持运行时动态切换 GPIO 管脚。
- 更新后, ``rmt_config`` 已被删除。新驱动中,基础配置在通道安装阶段完成。
- 更新后, ``rmt_isr_register````rmt_isr_deregister`` 已被删除,驱动程序负责分配中断。
- ``rmt_driver_install`` 更新为 :cpp:func:`rmt_new_tx_channel`:cpp:func:`rmt_new_rx_channel`
- ``rmt_driver_uninstall`` 更新为 :cpp:func:`rmt_del_channel`
- 更新后, ``rmt_fill_tx_items`` ``rmt_write_items````rmt_write_sample`` 已被删除。新驱动中,用户需要提供一个编码器用来将用户数据“翻译”为 RMT 符号。
- 更新后,由于用户可以通过 :cpp:member:`rmt_tx_channel_config_t::resolution_hz` 配置通道的时钟分辨率, ``rmt_get_counter_clock`` 已被删除。
- ``rmt_wait_tx_done`` 更新为 :cpp:func:`rmt_tx_wait_all_done`
- 更新后, ``rmt_translator_init`` ``rmt_translator_set_context````rmt_translator_get_context`` 已被删除。新驱动中,翻译器更新为 RMT 译码器。
- 更新后, ``rmt_get_ringbuf_handle`` 已被删除。新驱动程序不再使用 Ringbuffer 来保存 RMT 符号。输入数据会直接保存到用户提供的缓冲区中,这些缓冲区甚至可以直接被挂载到 DMA 链接内部。
- ``rmt_register_tx_end_callback`` 更新为 :cpp:func:`rmt_tx_register_event_callbacks`,用户可以在这个参数里面注册事件回调函数 :cpp:member:`rmt_tx_event_callbacks_t::on_trans_done`
- 更新后, ``rmt_set_intr_enable_mask````rmt_clr_intr_enable_mask`` 已被删除。由于驱动程序负责处理中断,因此用户无需进行处理。
- ``rmt_add_channel_to_group````rmt_remove_channel_from_group`` 更新为 RMT 同步管理器,详见 :cpp:func:`rmt_new_sync_manager`
- 更新后, ``rmt_set_tx_loop_count`` 已被删除。新驱动中,循环计数在 :cpp:member:`rmt_transmit_config_t::loop_count` 进行配置。
- 更新后, ``rmt_enable_tx_loop_autostop`` 已被删除。新驱动中,发射循环自动终止一直使能,用户无法进行配置。
LCD
-----
- LCD 面板的初始化流程也有一些更新。更新后,:cpp:func:`esp_lcd_panel_init` 不再会自动打开显示器。用户需要调用 :cpp:func:`esp_lcd_panel_disp_on_off` 来手动打开显示器。请注意,打开显示器与打开背光是不同的。更新后,打开屏幕前,用户可以烧录一个预定义的图案,这可以避免开机复位后屏幕上的随机噪音。
- 更新后, :cpp:func:`esp_lcd_panel_disp_off` 已被弃用,请使用 :cpp:func:`esp_lcd_panel_disp_on_off` 作为替代。
- 更新后, ``dc_as_cmd_phase`` 已被删除SPI LCD 驱动不再支持 9-bit 的 SPI LCD。请使用专用的 GPIO 管脚来控制 LCD D/C 线。
- 更新后,用于注册 RGB 面板的事件回调函数已从 :cpp:type:`esp_lcd_rgb_panel_config_t` 更新为单独的 API :cpp:func:`esp_lcd_rgb_panel_register_event_callbacks`。但是,事件回调签名仍保持不变。
- 更新后, :cpp:type:`esp_lcd_rgb_panel_config_t` 中的标志位 ``relax_on_idle`` 被重命名为 :cpp:member:`esp_lcd_rgb_panel_config_t::refresh_on_demand`,后者虽表达了同样的含义,但是其命名更有意义。
- 更新后,如果创建 RGB LCD 时,标志位 ``refresh_on_demand`` 使能,驱动不会在 :cpp:func:`esp_lcd_panel_draw_bitmap` 中进行刷新,用户需要调用 :cpp:func:`esp_lcd_rgb_panel_refresh` 来刷新屏幕。
- 更新后,:cpp:type:`esp_lcd_color_space_t` 已被弃用,请使用 :cpp:type:`lcd_color_space_t` 来描述色彩空间,使用 :cpp:type:`lcd_color_rgb_endian_t` 来描述 RGB 颜色的排列顺序。
.. only:: SOC_MCPWM_SUPPORTED
MCPWM
-----
MCPWM 驱动已更新(详见 :doc:`MCPWM <../../api-reference/peripherals/mcpwm>`)。同时,旧版驱动已被弃用。
新驱动中,每个 MCPWM 子模块相互独立,用户可以自由进行资源连接。
尽管我们推荐使用新的驱动 API旧版驱动仍然可用其引用路径为 ``driver/mcpwm.h``。但是,使用旧版驱动会默认触发如下编译警告,可以通过配置 Kconfig 选项 :ref:`CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN` 来关闭该警告。
.. code-block:: text
legacy MCPWM driver is deprecated, please migrate to the new driver (include driver/mcpwm_prelude.h)
主要概念和使用方法上的更新如下所示:
主要概念更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
更新后MCPWM 驱动是面向对象的,大多数 MCPWM 子模块都有一个与之相关的驱动对象。驱动对象是由工厂函数创建的,如 :cpp:func:`mcpwm_new_timer`。IO 控制函数总是需要对象句柄。
旧版驱动有一个不恰当的假设,即 MCPWM 运算器应连接到不同的 MCPWM 定时器上。但是,硬件上并没有这样的限制。新驱动中,同一个 MCPWM 定时器可以连接多个运算器,这样运算器可以获得最佳的同步性能。
更新前,驱动将生成 PWM 波形的方法预设为所谓的 ``mcpwm_duty_type_t``,但是,列出的占空比模式远远不够。类似的,旧版驱动有一些预设的 ``mcpwm_deadtime_type_t`` 也没有包含所有的使用场景。更重要的是,用户通常会被占空比模式和死区时间模式的名称所迷惑。更新后,驱动没有这些限制,但是用户必须从头开始构建发生器的行为。
在旧版驱动中,通过 GPIO 管脚,软件和其他定时器模块同步 MCPWM 定时器的方法并不统一。这增加了用户的学习成本,因此新驱动统一了同步 API。
旧版驱动混淆了“故障检测器”和“故障处理器”的概念。这让用户对 API 感到非常困惑。新驱动中,故障对象只代表一个故障源,而且我们引入了一个新概念, **制动器**,来表示故障处理器。而且,新驱动支持软件故障。
旧版驱动只为获取子模块提供了回调函数,而新驱动为 MCPWM 子模块提供多种回调函数,如停止定时器,比较匹配,故障进入,紧急停止等。
- 更新后,不再使用 ``mcpwm_io_signals_t````mcpwm_pin_config_t`` GPIO 管脚配置被移至子模块的配置结构中。
- 更新后,不再使用 ``mcpwm_timer_t````mcpwm_generator_t``,定时器和发生器分别用 :cpp:type:`mcpwm_timer_handle_t` 和:cpp:type:`mcpwm_gen_handle_t` 表示。
- 更新后,不再使用 ``mcpwm_fault_signal_t````mcpwm_sync_signal_t``,故障和同步源分别用 :cpp:type:`mcpwm_fault_handle_t` 和:cpp:type:`mcpwm_sync_handle_t` 表示。
- 更新后,不再使用 ``mcpwm_capture_signal_t``,获取通道用 :cpp:type:`mcpwm_cap_channel_handle_t` 表示。
主要使用方法更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ``mcpwm_gpio_init````mcpwm_set_pin``GPIO 管脚配置在子模块配置中完成,例如在 :cpp:member:`mcpwm_generator_config_t::gen_gpio_num` 中设置 PWM GPIO 管脚。
- ``mcpwm_init``:为得到预期的 PWM 波形,用户需要至少分配一个 MCPWM 定时器和 MCPWM 运算器,然后通过调用 :cpp:func:`mcpwm_operator_connect_timer` 将二者连接起来。然后,用户需要调用如:cpp:func:`mcpwm_generator_set_actions_on_timer_event` :cpp:func:`mcpwm_generator_set_actions_on_compare_event` 来设置发生器对不同事件的动作。
- ``mcpwm_group_set_resolution``:新驱动中,群组分辨率固定为最大值,通常为 80 MHz。
- ``mcpwm_timer_set_resolution``MCPWM 定时器的分辨率在 :cpp:member:`mcpwm_timer_config_t::resolution_hz` 中进行设置。
- ``mcpwm_set_frequency``PWM 频率由 :cpp:member:`mcpwm_timer_config_t::resolution_hz` :cpp:member:`mcpwm_timer_config_t::count_mode` 和:cpp:member:`mcpwm_timer_config_t::period_ticks` 决定。
- ``mcpwm_set_duty``:为设置 PWM 占空比,用户应调用 :cpp:func:`mcpwm_comparator_set_compare_value` 来改变比较器的阈值。
- ``mcpwm_set_duty_type``:新驱动中没有预设的占空比模式,通过设置不同的发生器行为,如 :cpp:func:`mcpwm_generator_set_actions_on_timer_event`,来配置占空比模式。
- ``mcpwm_set_signal_high````mcpwm_set_signal_low`` 更新为 :cpp:func:`mcpwm_generator_set_force_level`。新驱动中,这是通过为发生器设置力作用来实现的,而不是在后台将占空比改为 0% 或 100%。
- ``mcpwm_start````mcpwm_stop`` 更新为 :cpp:func:`mcpwm_timer_start_stop`。用户可以用更多的模式来启动和停止 MCPWM 定时器,详见 :cpp:type:`mcpwm_timer_start_stop_cmd_t`
- ``mcpwm_carrier_init`` 更新为 :cpp:func:`mcpwm_operator_apply_carrier`
- ``mcpwm_carrier_enable````mcpwm_carrier_disable``:通过检查载波设置结构 :cpp:type:`mcpwm_carrier_config_t` 是否为空集来自动使能和停用载波子模块。
- ``mcpwm_carrier_set_period`` 更新为 :cpp:member:`mcpwm_carrier_config_t::frequency_hz`
- ``mcpwm_carrier_set_duty_cycle`` 更新为 :cpp:member:`mcpwm_carrier_config_t::duty_cycle`
- ``mcpwm_carrier_oneshot_mode_enable`` 更新为 :cpp:member:`mcpwm_carrier_config_t::first_pulse_duration_us`
- 更新后, ``mcpwm_carrier_oneshot_mode_disable`` 被删除。硬件不支持停用第一个载波脉冲(即一次性脉冲)。
- ``mcpwm_carrier_output_invert`` 更新为 :cpp:member:`mcpwm_carrier_config_t::invert_before_modulate`:cpp:member:`mcpwm_carrier_config_t::invert_after_modulate`
- ``mcpwm_deadtime_enable````mcpwm_deadtime_disable`` 更新为 :cpp:func:`mcpwm_generator_set_dead_time`
- ``mcpwm_fault_init`` 更新为 :cpp:func:`mcpwm_new_gpio_fault`
- ``mcpwm_fault_set_oneshot_mode````mcpwm_fault_set_cyc_mode`` 更新为 :cpp:func:`mcpwm_operator_set_brake_on_fault`:cpp:func:`mcpwm_generator_set_actions_on_brake_event`
- 由于 ``mcpwm_capture_enable``:cpp:func:`mcpwm_capture_enable_channel` 重复,因此在更新后被删除。
- 由于 ``mcpwm_capture_disable``:cpp:func:`mcpwm_capture_capture_disable_channel` 重复,因此在更新后被删除。
- ``mcpwm_capture_enable_channel````mcpwm_capture_disable_channel`` 更新为 :cpp:func:`mcpwm_capture_channel_enable`:cpp:func:`mcpwm_capture_channel_disable`
- ``mcpwm_capture_signal_get_value````mcpwm_capture_signal_get_edge``:通过 :cpp:type:`mcpwm_capture_event_data_t`,获取事件回调函数中提供了计时器的数值和边缘电平。只有获取事件发生时,获取数据才有意义,提供单一的 API 来获取捕获数据是没有意义的。
- 由于 ``mcpwm_sync_enable``:cpp:func:`mcpwm_sync_configure` 重复,因此更新后被删除。
- ``mcpwm_sync_configure`` 更新为 :cpp:func:`mcpwm_timer_set_phase_on_sync`
- ``mcpwm_sync_disable`` 相当于将 :cpp:member:`mcpwm_timer_sync_phase_config_t::sync_src` 设置为 ``NULL``
- ``mcpwm_set_timer_sync_output`` 更新为 :cpp:func:`mcpwm_new_timer_sync_src`
- ``mcpwm_timer_trigger_soft_sync`` 更新为 :cpp:func:`mcpwm_soft_sync_activate`
- ``mcpwm_sync_invert_gpio_synchro`` 与设置 :cpp:member:`mcpwm_gpio_sync_src_config_t::active_neg` 功能相同。
- 更新后, ``mcpwm_isr_register`` 已被删除。用户可以注册不同的事件回调函数来替代其功能,例如,可以使用 :cpp:func:`mcpwm_capture_channel_register_event_callbacks` 注册获取事件注册函数。
.. only:: SOC_DEDICATED_GPIO_SUPPORTED
专用的 GPIO 驱动
-------------------------------------
- 更新后,所有与专用 GPIO 管脚相关的底层 (LL) 函数从 ``cpu_ll.h`` 中被移至 ``dedic_gpio_cpu_ll.h``,并重新命名。
.. only:: SOC_I2S_SUPPORTED
I2S 驱动
-----------------------
旧版 I2S 驱动在支持 ESP32-C3 和 ESP32-S3 新功能时暴露了很多缺点为解决这些缺点I2S 驱动已更新(请参考:doc:`I2S Driver <../../api-reference/peripherals/i2s>`)。用户可以通过引用不同 I2S 模式对应的头文件来使用新版驱动的 API如 :component_file:`driver/include/driver/i2s_std.h` :component_file:`driver/include/driver/i2s_pdm.h` 以及 :component_file:`driver/include/driver/i2s_tdm.h`
为保证前向兼容,旧版驱动的 API 仍然在 :component_file:`driver/deprecated/driver/i2s.h` 中可用。但使用旧版 API 会触发编译警告,该警告可通过配置 Kconfig 选项 :ref:`CONFIG_I2S_SUPPRESS_DEPRECATE_WARN` 来关闭。
以下是更新后的 I2S 文件概况。
.. figure:: ../../../_static/diagrams/i2s/i2s_file_structure.png
:align: center
:alt: I2S File Structure
主要概念更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
独立的发送通道和接收通道
""""""""""""""""""""""""""""""""""""""""""""""""""""""""
更新后I2S 驱动的最小控制单元是发送/接收通道,而不是整个 I2S 控制器(控制器包括多个通道)。
- 用户可以分别控制同一个 I2S 控制器的发送通道和接收通道,即可以通过配置实现分别开启和关闭发送通道和接收通道。
- :c:type:`i2s_chan_handle_t` 句柄类型用于唯一地识别 I2S 通道。所有的 API 都需要该通道句柄,用户需要对这些通道句柄进行维护。
- 对于 ESP32-C3 和 ESP32-S3同一个控制器中的发送通道和接收通道可以配置为不同的时钟或不同的模式。
- 但是对于 ESP32 和 ESP32-S2 同一个控制器中的发送通道和接收通道共享某些硬件资源。因此,配置可能会造成一个通道影响同一个控制器中的另一个通道。
- 通过将 :cpp:enumerator:`i2s_port_t::I2S_NUM_AUTO` 设置为 I2S 端口 ID驱动会搜索可用的发送/接收通道,之后通道会被自动注册到可用的 I2S 控制器上。但是,驱动仍然支持将通道注册到一个特定的端口上。
- 为区分发送/接收通道和声音通道,在更新后的驱动中,“通道 (channel)”一词仅代表发送/接收通道,用“声道 (slot)”来表示声音通道。
I2S 模式分类
""""""""""""""""""""""""""""""""
I2S 通信模式包括以下三种模式,请注意:
- **标准模式**:标准模式通常包括两个声道,支持 PhilipMSB 和 PCM短帧同步格式详见 :component_file:`driver/include/driver/i2s_std.h`
- **PDM模式**PDM 模式仅支持两个声道16 bit 数据位宽,但是 PDM TX 和 PDM RX 的配置略有不同。对于 PDM TX采样率可通过 :cpp:member:`i2s_pdm_tx_clk_config_t::sample_rate` 进行设置,其时钟频率取决于上采样的配置。对于 PDM RX采样率可通过 :cpp:member:`i2s_pdm_rx_clk_config_t::sample_rate` 进行设置,其时钟频率取决于下采样的配置,详见 :component_file:`driver/include/driver/i2s_pdm.h`
- **TDM 模式**TDM 模式可支持高达 16 声道,该模式可工作在 PhilipMSBPCM短帧同步和PCM长帧同步格式下详见 :component_file:`driver/include/driver/i2s_tdm.h`
在某个模式下分配新通道时,必须通过相应的函数初始化这个通道。我们强烈建议使用辅助宏来生成默认配置,以避免默认值被改动。
独立的声道配置和时钟配置
""""""""""""""""""""""""""""""""""""""""""""""""""""
可以单独进行声道配置和时钟配置。
- 通过调用 :cpp:func:`i2s_channel_init_std_mode` :cpp:func:`i2s_channel_init_pdm_rx_mode` :cpp:func:`i2s_channel_init_pdm_tx_mode`:cpp:func:`i2s_channel_init_tdm_mode` 初始化声道/时钟/GPIO 管脚配置。
- 通过调用 :cpp:func:`i2s_channel_reconfig_std_slot` :cpp:func:`i2s_channel_reconfig_pdm_rx_slot` :cpp:func:`i2s_channel_reconfig_pdm_tx_slot`:cpp:func:`i2s_channel_reconfig_tdm_slot` 可以在初始化之后改变声道配置。
- 通过调用 :cpp:func:`i2s_channel_reconfig_std_clock` :cpp:func:`i2s_channel_reconfig_pdm_rx_clock` :cpp:func:`i2s_channel_reconfig_pdm_tx_clock`:cpp:func:`i2s_channel_reconfig_tdm_clock` 可以在初始化之后改变时钟配置。
- 通过调用 :cpp:func:`i2s_channel_reconfig_std_gpio` :cpp:func:`i2s_channel_reconfig_pdm_rx_gpio` :cpp:func:`i2s_channel_reconfig_pdm_tx_gpio`:cpp:func:`i2s_channel_reconfig_tdm_gpio` 可以在初始化之后改变 GPIO 管脚配置。
Misc
""""
- 更新后I2S 驱动利用状态和状态机避免在错误状态下调用 API。
- 更新后ADC 和 DAC 模式已被删除,只有它们各自专用的驱动及 I2S 旧版驱动还支持这两种模式。
主要使用方法更新
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
请参考以下步骤使用更新后的 I2S 驱动:
1. 通过调用 :cpp:func:`i2s_new_channel` 来获取通道句柄。我们应该在此步骤中指定外设为主机还是从机以及 I2S 端口。此外,驱动负责生成发送通道或接收通道的句柄。不需要同时输入发送通道和接收通道句柄,但需要输入至少一个句柄。输入两个句柄时,驱动会工作在双工模式。在同一端口上,发送通道和接收通道同时可用,并且共享 MCLKBCLK 和 WS 信号。如果只输入了发送通道句柄或接收通道句柄,该通道只能工作在单工模式。
2. 通过调用 :func:`i2s_channel_init_std_mode` :func:`i2s_channel_init_pdm_rx_mode` :func:`i2s_channel_init_pdm_tx_mode`:func:`i2s_channel_init_tdm_mode` 将通道初始化为指定模式。进行相应的声道、时钟和 GPIO 管脚配置。
3. (可选)通过调用 :cpp:func:`i2s_channel_register_event_callback` 注册 ISR 事件回调函数。I2S 事件由回调函数同步接收,而不是从事件队列中异步接收。
4. 通过调用 :cpp:func:`i2s_channel_enable` 来开启 I2S 通道的硬件资源。在更新后的驱动中I2S 在安装后不会再自动开启,用户需要确定通道是否已经开启。
5. 分别通过 :cpp:func:`i2s_channel_read`:cpp:func:`i2s_channel_write` 来读取和写入数据。当然,在 :cpp:func:`i2s_channel_read` 中只能输入接收通道句柄,在 :cpp:func:`i2s_channel_write` 中只能输入发送通道句柄。
6. (可选)通过相应的 'reconfig' 函数可以更改声道、时钟和 GPIO 管脚配置,但是更改配置前必须调用 :cpp:func:`i2s_channel_disable`
7. 通过调用 :cpp:func:`i2s_channel_disable` 可以停止使用 I2S 通道的硬件资源。
8. 不再使用某通道时,通过调用 :cpp:func:`i2s_del_channel` 可以删除和释放该通道资源,但是删除之前必须先停用该通道。
用于访问寄存器的宏
---------------------------------------------
更新前,所有用于访问寄存器的宏都可以作为表达式来使用,所以以下命令是允许的::
uint32_t val = REG_SET_BITS(reg, mask);
在 ESP-IDF v5.0 中,用于写入或读取-修改-写入寄存器的宏不能再作为表达式使用,而只能作为语句使用,这适用于以下宏: ``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``
为存储要写入寄存器的值,请按以下步骤完成操作::
uint32_t new_val = REG_READ(reg) | mask;
REG_WRITE(reg, new_val);
要获得修改后的寄存器的值(该值可能与写入的值不同),要增加一个显示的读取命令::
REG_SET_BITS(reg, mask);
uint32_t new_val = REG_READ(reg);