app_main.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * In this example, we show you a way to make an ISR-based callback work during Flash operations, when the ISR-based
  8. * callback is put in Flash.
  9. *
  10. * Please read the README.md to know more details about this feature!
  11. */
  12. #include <stdbool.h>
  13. #include <stdio.h>
  14. #include <inttypes.h>
  15. #include "sdkconfig.h"
  16. #include "esp_log.h"
  17. #include "esp_attr.h"
  18. #include "esp_cpu.h"
  19. #include "esp_partition.h"
  20. #include "driver/gptimer.h"
  21. #include "esp_flash.h"
  22. #define TIMER_RESOLUTION_HZ (1 * 1000 * 1000) // 1MHz resolution
  23. #define TIMER_ALARM_PERIOD_S 1 // Alarm period 1s
  24. #define RECORD_TIME_PREPARE() uint32_t __t1, __t2
  25. #define RECORD_TIME_START() do {__t1 = esp_cpu_get_cycle_count();} while(0)
  26. #define RECORD_TIME_END(p_time) do{__t2 = esp_cpu_get_cycle_count(); p_time = (__t2 - __t1);} while(0)
  27. #define GET_US_BY_CCOUNT(t) ((double)(t)/CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
  28. const static char *TAG = "Example";
  29. DRAM_ATTR static uint32_t s_t1;
  30. DRAM_ATTR static uint32_t s_flash_func_t2;
  31. DRAM_ATTR static uint32_t s_iram_func_t2;
  32. static NOINLINE_ATTR void s_function_in_flash(void)
  33. {
  34. /**
  35. * - Here we will have few instructions in .flash.text
  36. * - Cache will read from Flash to get the instructions synchronized.
  37. * - CPU will execute around 400 times.
  38. */
  39. for (int i = 0; i < 100; i++) {
  40. asm volatile("nop");
  41. }
  42. s_flash_func_t2 = esp_cpu_get_cycle_count();
  43. }
  44. static IRAM_ATTR NOINLINE_ATTR void s_function_in_iram(void)
  45. {
  46. /**
  47. * - Here we will have few instructions in .iram0.text
  48. * - CPU will execute around 400 times.
  49. */
  50. for (int i = 0; i < 100; i++) {
  51. asm volatile("nop");
  52. }
  53. s_iram_func_t2 = esp_cpu_get_cycle_count();
  54. }
  55. static bool IRAM_ATTR on_gptimer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
  56. {
  57. bool is_flash = *(bool *)user_ctx;
  58. s_t1 = esp_cpu_get_cycle_count();
  59. if (is_flash) {
  60. s_function_in_flash();
  61. } else {
  62. s_function_in_iram();
  63. }
  64. return false;
  65. }
  66. static const esp_partition_t *s_get_partition(void)
  67. {
  68. //Find the "storage1" partition defined in `partitions.csv`
  69. const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1");
  70. if (!result) {
  71. ESP_LOGE(TAG, "Can't find the partition, please define it correctly in `partitions.csv`");
  72. abort();
  73. }
  74. return result;
  75. }
  76. void app_main(void)
  77. {
  78. //Get the partition used for SPI1 erase operation
  79. const esp_partition_t *part = s_get_partition();
  80. ESP_LOGI(TAG, "found partition '%s' at offset 0x%"PRIx32" with size 0x%"PRIx32, part->label, part->address, part->size);
  81. //Erase whole region
  82. ESP_ERROR_CHECK(esp_flash_erase_region(part->flash_chip, part->address, part->size));
  83. gptimer_handle_t gptimer = NULL;
  84. gptimer_config_t timer_config = {
  85. .clk_src = GPTIMER_CLK_SRC_DEFAULT,
  86. .direction = GPTIMER_COUNT_UP,
  87. .resolution_hz = TIMER_RESOLUTION_HZ,
  88. };
  89. ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
  90. gptimer_alarm_config_t alarm_config = {
  91. .reload_count = 0,
  92. .alarm_count = 1 * 1000 * 1000,
  93. .flags.auto_reload_on_alarm = false,
  94. };
  95. ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
  96. gptimer_event_callbacks_t cbs = {
  97. .on_alarm = on_gptimer_alarm_cb,
  98. };
  99. bool is_flash = true;
  100. ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, &is_flash));
  101. ESP_ERROR_CHECK(gptimer_enable(gptimer));
  102. ESP_ERROR_CHECK(gptimer_start(gptimer));
  103. uint32_t erase_time = 0;
  104. RECORD_TIME_PREPARE();
  105. RECORD_TIME_START();
  106. ESP_ERROR_CHECK(esp_flash_erase_region(part->flash_chip, part->address, part->size));
  107. RECORD_TIME_END(erase_time);
  108. ESP_ERROR_CHECK(gptimer_stop(gptimer));
  109. ESP_LOGI(TAG, "Flash Driver Erase Operation finishes, duration:\n\t\t%0.2f us", GET_US_BY_CCOUNT(erase_time));
  110. ESP_LOGI(TAG, "During Erase, ISR callback function(in flash) response time:\n\t\t%0.2f us", GET_US_BY_CCOUNT(s_flash_func_t2 - s_t1));
  111. //Let the timer alarm callback to run code reside in .iram0.text
  112. is_flash = false;
  113. ESP_ERROR_CHECK(gptimer_set_raw_count(gptimer, 0));
  114. ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
  115. ESP_ERROR_CHECK(gptimer_start(gptimer));
  116. RECORD_TIME_START();
  117. //Erase whole region
  118. ESP_ERROR_CHECK(esp_flash_erase_region(part->flash_chip, part->address, part->size));
  119. RECORD_TIME_END(erase_time);
  120. ESP_ERROR_CHECK(gptimer_stop(gptimer));
  121. ESP_LOGI(TAG, "Flash Driver Erase Operation finishes, duration:\n\t\t%0.2f us", GET_US_BY_CCOUNT(erase_time));
  122. ESP_LOGI(TAG, "During Erase, ISR callback function(in iram) response time:\n\t\t%0.2f us", GET_US_BY_CCOUNT(s_iram_func_t2 - s_t1));
  123. ESP_LOGI(TAG, "Finish");
  124. ESP_ERROR_CHECK(gptimer_disable(gptimer));
  125. ESP_ERROR_CHECK(gptimer_del_timer(gptimer));
  126. }