|
19 | 19 | #include "esp_private/cache_utils.h"
|
20 | 20 | #include "esp_private/spi_common_internal.h"
|
21 | 21 | #include "esp_private/esp_clk.h"
|
| 22 | +#include "esp_private/sleep_cpu.h" |
| 23 | +#include "esp_private/esp_sleep_internal.h" |
| 24 | +#include "esp_private/esp_pmu.h" |
22 | 25 | #include "esp_heap_caps.h"
|
23 | 26 | #include "esp_clk_tree.h"
|
24 | 27 | #include "esp_timer.h"
|
@@ -1788,3 +1791,135 @@ TEST_CASE("test_bus_free_safty_to_remain_devices", "[spi]")
|
1788 | 1791 | TEST_ESP_OK(spi_bus_remove_device(dev1));
|
1789 | 1792 | TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
|
1790 | 1793 | }
|
| 1794 | + |
| 1795 | +TEST_CASE("test_spi_master_sleep_retention", "[spi]") |
| 1796 | +{ |
| 1797 | + // Prepare a TOP PD sleep |
| 1798 | + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); |
| 1799 | +#if ESP_SLEEP_POWER_DOWN_CPU |
| 1800 | + TEST_ESP_OK(sleep_cpu_configure(true)); |
| 1801 | +#endif |
| 1802 | + esp_sleep_context_t sleep_ctx; |
| 1803 | + esp_sleep_set_sleep_context(&sleep_ctx); |
| 1804 | + |
| 1805 | + spi_device_handle_t dev_handle; |
| 1806 | + spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG(); |
| 1807 | + spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG(); |
| 1808 | + buscfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS; |
| 1809 | + buscfg.flags |= SPICOMMON_BUSFLAG_SLP_ALLOW_PD; |
| 1810 | + uint8_t send[16] = "hello spi x\n"; |
| 1811 | + uint8_t recv[16]; |
| 1812 | + spi_transaction_t trans_cfg = { |
| 1813 | + .length = 8 * sizeof(send), |
| 1814 | + .tx_buffer = send, |
| 1815 | + .rx_buffer = recv, |
| 1816 | + }; |
| 1817 | + |
| 1818 | + for (int periph = SPI2_HOST; periph < SPI_HOST_MAX; periph ++) { |
| 1819 | + for (int test_dma = 0; test_dma <= 1; test_dma ++) { |
| 1820 | + int use_dma = SPI_DMA_DISABLED; |
| 1821 | +#if SOC_GDMA_SUPPORT_SLEEP_RETENTION // TODO: IDF-11317 test dma on esp32 and s2 |
| 1822 | + use_dma = test_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED; |
| 1823 | +#endif |
| 1824 | + printf("Retention on GPSPI%d with dma: %d\n", periph + 1, use_dma); |
| 1825 | + TEST_ESP_OK(spi_bus_initialize(periph, &buscfg, use_dma)); |
| 1826 | + // set spi "self-loop" after bus initialized |
| 1827 | + spitest_gpio_output_sel(buscfg.miso_io_num, FUNC_GPIO, spi_periph_signal[periph].spid_out); |
| 1828 | + TEST_ESP_OK(spi_bus_add_device(periph, &devcfg, &dev_handle)); |
| 1829 | + |
| 1830 | + for (uint8_t cnt = 0; cnt < 3; cnt ++) { |
| 1831 | + printf("Going into sleep...\n"); |
| 1832 | + TEST_ESP_OK(esp_light_sleep_start()); |
| 1833 | + printf("Waked up!\n"); |
| 1834 | + |
| 1835 | + // check if the sleep happened as expected |
| 1836 | + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); |
| 1837 | +#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP |
| 1838 | + // check if the power domain also is powered down |
| 1839 | + TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); |
| 1840 | +#endif |
| 1841 | + memset(recv, 0, sizeof(recv)); |
| 1842 | + send[10] = cnt + 'A'; |
| 1843 | + TEST_ESP_OK(spi_device_transmit(dev_handle, &trans_cfg)); |
| 1844 | + printf("%s", recv); |
| 1845 | + spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, sizeof(send)); |
| 1846 | + } |
| 1847 | + |
| 1848 | + TEST_ESP_OK(spi_bus_remove_device(dev_handle)); |
| 1849 | + TEST_ESP_OK(spi_bus_free(periph)); |
| 1850 | + } |
| 1851 | + } |
| 1852 | + |
| 1853 | + esp_sleep_set_sleep_context(NULL); |
| 1854 | +#if ESP_SLEEP_POWER_DOWN_CPU |
| 1855 | + TEST_ESP_OK(sleep_cpu_configure(false)); |
| 1856 | +#endif |
| 1857 | +} |
| 1858 | + |
| 1859 | +#if 0 /* Temp disable, TODO: IDFCI-2455*/ |
| 1860 | +#if CONFIG_PM_ENABLE |
| 1861 | +TEST_CASE("test_spi_master_auto_sleep_retention", "[spi]") |
| 1862 | +{ |
| 1863 | + // Configure dynamic frequency scaling: |
| 1864 | + // maximum and minimum frequencies are set in sdkconfig, |
| 1865 | + // automatic light sleep is enabled if tickless idle support is enabled. |
| 1866 | + uint32_t xtal_hz = 0; |
| 1867 | + esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &xtal_hz); |
| 1868 | + esp_pm_config_t pm_config = { |
| 1869 | + .max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, |
| 1870 | + .min_freq_mhz = xtal_hz / 1000000, |
| 1871 | +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE |
| 1872 | + .light_sleep_enable = true, |
| 1873 | +#endif |
| 1874 | + }; |
| 1875 | + TEST_ESP_OK(esp_pm_configure(&pm_config)); |
| 1876 | + esp_sleep_context_t sleep_ctx; |
| 1877 | + esp_sleep_set_sleep_context(&sleep_ctx); |
| 1878 | + |
| 1879 | + for (uint8_t allow_pd = 0; allow_pd < 2; allow_pd ++) { |
| 1880 | + spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG(); |
| 1881 | + buscfg.flags = (allow_pd) ? SPICOMMON_BUSFLAG_SLP_ALLOW_PD : 0; |
| 1882 | + buscfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS; |
| 1883 | + TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_DISABLED)); |
| 1884 | + // set spi "self-loop" after bus initialized |
| 1885 | + spitest_gpio_output_sel(buscfg.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); |
| 1886 | + |
| 1887 | + spi_device_handle_t dev_handle; |
| 1888 | + spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG(); |
| 1889 | + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle)); |
| 1890 | + |
| 1891 | + uint8_t send[13] = "hello spi 0\n"; |
| 1892 | + uint8_t recv[13]; |
| 1893 | + spi_transaction_t trans_cfg = { |
| 1894 | + .length = 8 * sizeof(send), |
| 1895 | + .tx_buffer = send, |
| 1896 | + .rx_buffer = recv, |
| 1897 | + }; |
| 1898 | + |
| 1899 | + for (uint8_t cnt = 0; cnt < 3; cnt ++) { |
| 1900 | + printf("Going into Auto sleep with power %s ...\n", (buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? "down" : "hold"); |
| 1901 | + vTaskDelay(1000); //auto light sleep here |
| 1902 | + printf("Waked up!\n"); |
| 1903 | + |
| 1904 | + // check if the sleep happened as expected |
| 1905 | + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); |
| 1906 | +#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP |
| 1907 | + // check if the power domain also is powered down |
| 1908 | + TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); |
| 1909 | +#endif |
| 1910 | + memset(recv, 0, sizeof(recv)); |
| 1911 | + send[10] = cnt + '0'; |
| 1912 | + TEST_ESP_OK(spi_device_polling_transmit(dev_handle, &trans_cfg)); |
| 1913 | + printf("%s", recv); |
| 1914 | + spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, sizeof(send)); |
| 1915 | + } |
| 1916 | + |
| 1917 | + TEST_ESP_OK(spi_bus_remove_device(dev_handle)); |
| 1918 | + TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST)); |
| 1919 | + } |
| 1920 | + esp_sleep_set_sleep_context(NULL); |
| 1921 | + pm_config.light_sleep_enable = false; |
| 1922 | + TEST_ESP_OK(esp_pm_configure(&pm_config)); |
| 1923 | +} |
| 1924 | +#endif //CONFIG_PM_ENABLE |
| 1925 | +#endif // 0 |
0 commit comments