wifi + timer interrupt = PANIC [esp32]

NIXIE_123
Posts: 32
Joined: Fri Aug 02, 2019 9:51 am

wifi + timer interrupt = PANIC [esp32]

Postby NIXIE_123 » Tue Aug 03, 2021 8:25 am

Hello

I have two working codes separately:
-ISR triggering with 111us period by timer
-Wifi station mode from example

Problem:
When I join these codes together i have panic. It hangs already on nvs_flash_init()
ISR takes 5us to realize. Measured with esp_timer_get_time()
  1. /*
  2. esp-idf 4.2
  3. 04-2021
  4. */
  5. #include "sdkconfig.h"
  6. #include "freertos/FreeRTOS.h"
  7. #include "freertos/task.h"
  8. #include "freertos/event_groups.h"
  9. #include "esp_wifi.h"
  10. #include "driver/rmt.h"
  11. #include "driver/timer.h"
  12. #include "driver/i2c.h"
  13. #include "driver/adc.h"
  14. #include "esp_intr_alloc.h"
  15. #include "esp_log.h"
  16. #include "esp_sntp.h"
  17. #include "nvs_flash.h"
  18. #include "esp_event.h"
  19. #include "lwip/err.h"
  20. #include "lwip/sys.h"
  21.  
  22. #define EXAMPLE_ESP_WIFI_SSID      "ssid"
  23. #define EXAMPLE_ESP_WIFI_PASS      "password"
  24. #define EXAMPLE_ESP_MAXIMUM_RETRY  5
  25.  
  26.  
  27. volatile uint8_t ktora_anoda=0, przyciemnij=0, crossfade_etap=16;
  28. uint8_t bufor0[6]={0,0,0,0,0,0};
  29. uint8_t bufor1[6]={0,0,0,0,0,0};
  30. static EventGroupHandle_t s_wifi_event_group;
  31. #define WIFI_CONNECTED_BIT BIT0
  32. #define WIFI_FAIL_BIT      BIT1
  33. static const char *TAG = "wifi station";
  34. static int s_retry_num = 0;
  35. static void event_handler(void* arg, esp_event_base_t event_base,
  36.                                 int32_t event_id, void* event_data)
  37. {
  38.     if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
  39.         esp_wifi_connect();
  40.     } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
  41.         if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
  42.             esp_wifi_connect();
  43.             s_retry_num++;
  44.             ESP_LOGI(TAG, "retry to connect to the AP");
  45.         } else {
  46.             xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
  47.         }
  48.         ESP_LOGI(TAG,"connect to the AP fail");
  49.     } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
  50.         ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
  51.         ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
  52.         s_retry_num = 0;
  53.         xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
  54.     }
  55. }
  56. void IRAM_ATTR ustaw_katode(uint8_t katoda){
  57.  
  58.     switch(katoda){
  59.     case 0: gpio_set_level(GPIO_NUM_27,0);
  60.     gpio_set_level(GPIO_NUM_26,0);
  61.     gpio_set_level(GPIO_NUM_33,0);
  62.     gpio_set_level(GPIO_NUM_32,0);
  63.     break;
  64.     case 1: gpio_set_level(GPIO_NUM_27,1);
  65.     gpio_set_level(GPIO_NUM_26,0);
  66.     gpio_set_level(GPIO_NUM_33,0);
  67.     gpio_set_level(GPIO_NUM_32,0);
  68.     break;
  69.     case 2: gpio_set_level(GPIO_NUM_27,0);
  70.     gpio_set_level(GPIO_NUM_26,1);
  71.     gpio_set_level(GPIO_NUM_33,0);
  72.     gpio_set_level(GPIO_NUM_32,0);
  73.     break;
  74.     case 3: gpio_set_level(GPIO_NUM_27,1);
  75.     gpio_set_level(GPIO_NUM_26,1);
  76.     gpio_set_level(GPIO_NUM_33,0);
  77.     gpio_set_level(GPIO_NUM_32,0);
  78.     break;
  79.     case 4: gpio_set_level(GPIO_NUM_27,0);
  80.     gpio_set_level(GPIO_NUM_26,0);
  81.     gpio_set_level(GPIO_NUM_33,1);
  82.     gpio_set_level(GPIO_NUM_32,0);
  83.     break;
  84.     case 5: gpio_set_level(GPIO_NUM_27,1);
  85.     gpio_set_level(GPIO_NUM_26,0);
  86.     gpio_set_level(GPIO_NUM_33,1);
  87.     gpio_set_level(GPIO_NUM_32,0);
  88.     break;
  89.     case 6: gpio_set_level(GPIO_NUM_27,0);
  90.     gpio_set_level(GPIO_NUM_26,1);
  91.     gpio_set_level(GPIO_NUM_33,1);
  92.     gpio_set_level(GPIO_NUM_32,0);
  93.     break;
  94.     case 7: gpio_set_level(GPIO_NUM_27,1);
  95.     gpio_set_level(GPIO_NUM_26,1);
  96.     gpio_set_level(GPIO_NUM_33,1);
  97.     gpio_set_level(GPIO_NUM_32,0);
  98.     break;
  99.     case 8: gpio_set_level(GPIO_NUM_27,0);
  100.     gpio_set_level(GPIO_NUM_26,0);
  101.     gpio_set_level(GPIO_NUM_33,0);
  102.     gpio_set_level(GPIO_NUM_32,1);
  103.     break;
  104.     case 9: gpio_set_level(GPIO_NUM_27,1);
  105.     gpio_set_level(GPIO_NUM_26,0);
  106.     gpio_set_level(GPIO_NUM_33,0);
  107.     gpio_set_level(GPIO_NUM_32,1);
  108.     break;
  109.     case 10: gpio_set_level(GPIO_NUM_17,0);
  110.     gpio_set_level(GPIO_NUM_16,0);
  111.     gpio_set_level(GPIO_NUM_4,0);
  112.     gpio_set_level(GPIO_NUM_23,0);
  113.     gpio_set_level(GPIO_NUM_15,0);
  114.     gpio_set_level(GPIO_NUM_13,0);
  115.     break;
  116.     }
  117. }
  118. void IRAM_ATTR przerwanie_od_timer_mux(){
  119.     timer_spinlock_take(TIMER_GROUP_0);
  120.     static uint16_t j_crossfade=0;
  121.     static uint8_t i_crossfade=0, i_multiplexowanie=0;
  122.     if(i_multiplexowanie>=15){
  123.         i_multiplexowanie=0;
  124.         ustaw_katode(10);   //zgaszenie
  125.         static unsigned char i_przyciemnianie=0;
  126.         if(!przyciemnij || (++i_przyciemnianie >= 6)){
  127.             i_przyciemnianie=0;
  128.             if(++ktora_anoda > 5) ktora_anoda=0;
  129.             if(ktora_anoda == 0){
  130.                 gpio_set_level(GPIO_NUM_17,1);
  131.             }
  132.             if(ktora_anoda == 1){
  133.                 gpio_set_level(GPIO_NUM_16,1);
  134.             }
  135.             if(ktora_anoda == 2){
  136.                 gpio_set_level(GPIO_NUM_4,1);
  137.             }
  138.             if(ktora_anoda == 3){
  139.                 gpio_set_level(GPIO_NUM_23,1);
  140.             }
  141.             if(ktora_anoda == 4){
  142.                 gpio_set_level(GPIO_NUM_15,1);
  143.             }
  144.             if(ktora_anoda == 5){
  145.                 gpio_set_level(GPIO_NUM_13,1);
  146.             }
  147.         }
  148.     }
  149.     else{
  150.         i_multiplexowanie++;
  151.     }
  152.  
  153.  
  154.     if(przyciemnij){
  155.         j_crossfade+=35;
  156.     }
  157.     else{
  158.         j_crossfade+=111;                   //  1 - 62ms
  159.     }                                       //  2 - 124ms
  160.                                             //  3 - 186ms
  161.     if(j_crossfade >= 3885){                //  4 - 248ms
  162.         j_crossfade=0;                      //  5 - 310ms
  163.         if(++i_crossfade >= 11){            //  6 - 373ms
  164.             if(crossfade_etap <= 15){       //  7 - 435ms
  165.                 crossfade_etap++;           //  8 - 497ms
  166.             }                               //  9 - 559ms
  167.             i_crossfade=0;                  // 10 - 621ms
  168.         }                                   // 11 - 683ms
  169.     }                                       // 12 - 746ms
  170.                                             // 13 - 808ms
  171.  
  172.     if(i_multiplexowanie>=crossfade_etap){
  173.         ustaw_katode(bufor0[ktora_anoda]);
  174.     }
  175.     else{
  176.         ustaw_katode(bufor1[ktora_anoda]);
  177.     }
  178.  
  179.     TIMERG0.int_clr_timers.t0 = 1;
  180.     TIMERG0.hw_timer[TIMER_0].config.alarm_en = 1;
  181.     timer_spinlock_give(TIMER_GROUP_0);
  182. }
  183.  
  184.  
  185. void app_main(void){
  186.     gpio_pad_select_gpio(GPIO_NUM_4);
  187.         gpio_pad_select_gpio(GPIO_NUM_12);
  188.         gpio_pad_select_gpio(GPIO_NUM_13);
  189.         gpio_pad_select_gpio(GPIO_NUM_14);
  190.         gpio_pad_select_gpio(GPIO_NUM_15);
  191.         gpio_pad_select_gpio(GPIO_NUM_16);
  192.         gpio_pad_select_gpio(GPIO_NUM_17);
  193.         gpio_pad_select_gpio(GPIO_NUM_18);
  194.         gpio_pad_select_gpio(GPIO_NUM_23);
  195.         gpio_pad_select_gpio(GPIO_NUM_26);
  196.         gpio_pad_select_gpio(GPIO_NUM_27);
  197.         gpio_pad_select_gpio(GPIO_NUM_32);
  198.         gpio_pad_select_gpio(GPIO_NUM_33);
  199.         gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
  200.         gpio_set_direction(GPIO_NUM_12, GPIO_MODE_OUTPUT);
  201.         gpio_set_direction(GPIO_NUM_13, GPIO_MODE_OUTPUT);
  202.         gpio_set_direction(GPIO_NUM_15, GPIO_MODE_OUTPUT);
  203.         gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT);
  204.         gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT);
  205.         gpio_set_direction(GPIO_NUM_23, GPIO_MODE_OUTPUT);
  206.         gpio_set_direction(GPIO_NUM_26, GPIO_MODE_OUTPUT);
  207.         gpio_set_direction(GPIO_NUM_27, GPIO_MODE_OUTPUT);
  208.         gpio_set_direction(GPIO_NUM_32, GPIO_MODE_OUTPUT);
  209.         gpio_set_direction(GPIO_NUM_33, GPIO_MODE_OUTPUT);
  210.     timer_config_t config_timer_mux = {
  211.                 .divider = 80,
  212.                 .counter_dir = TIMER_COUNT_UP,
  213.                 .counter_en = TIMER_PAUSE,
  214.                 .alarm_en = TIMER_ALARM_EN,
  215.                 .auto_reload = TIMER_AUTORELOAD_EN,
  216.             }; // default clock source is APB
  217.  
  218.         timer_init(TIMER_GROUP_0, TIMER_0, &config_timer_mux);
  219.         timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 111);
  220.         timer_enable_intr(TIMER_GROUP_0, TIMER_0);
  221.         timer_isr_register(TIMER_GROUP_0, TIMER_0, przerwanie_od_timer_mux, NULL, ESP_INTR_FLAG_IRAM, NULL);
  222.         timer_start(TIMER_GROUP_0, TIMER_0);
  223.  
  224.  
  225. vTaskDelay(5000/portTICK_PERIOD_MS);
  226.     esp_err_t ret = nvs_flash_init();
  227.         if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  228.           ESP_ERROR_CHECK(nvs_flash_erase());
  229.           ret = nvs_flash_init();
  230.         }
  231.         ESP_ERROR_CHECK(ret);
  232.         ESP_LOGI("wifi", "ESP_WIFI_MODE_STA");
  233.  
  234.         s_wifi_event_group = xEventGroupCreate();
  235.         ESP_ERROR_CHECK(esp_netif_init());
  236.         ESP_ERROR_CHECK(esp_event_loop_create_default());
  237.         esp_netif_create_default_wifi_sta();
  238.         wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  239.         ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  240.         esp_event_handler_instance_t instance_any_id;
  241.         esp_event_handler_instance_t instance_got_ip;
  242.         ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
  243.                 ESP_EVENT_ANY_ID,
  244.                 &event_handler,
  245.                 NULL,
  246.                 &instance_any_id));
  247.         ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
  248.                                                                 IP_EVENT_STA_GOT_IP,
  249.                                                                 &event_handler,
  250.                                                                 NULL,
  251.                                                                 &instance_got_ip));
  252.         wifi_config_t wifi_config = {
  253.                 .sta = {
  254.                     .ssid = EXAMPLE_ESP_WIFI_SSID,
  255.                     .password = EXAMPLE_ESP_WIFI_PASS,
  256.                     /* Setting a password implies station will connect to all security modes including WEP/WPA.
  257.                      * However these modes are deprecated and not advisable to be used. Incase your Access point
  258.                      * doesn't support WPA2, these mode can be enabled by commenting below line */
  259.                  .threshold.authmode = WIFI_AUTH_WPA2_PSK,
  260.  
  261.                     .pmf_cfg = {
  262.                         .capable = true,
  263.                         .required = false
  264.                     },
  265.                 },
  266.             };
  267.         ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
  268.         ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
  269.         ESP_ERROR_CHECK(esp_wifi_start() );
  270.  
  271.         ESP_LOGI(TAG, "wifi_init_sta finished.");
  272.         EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
  273.                     WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
  274.                     pdFALSE,
  275.                     pdFALSE,
  276.                     portMAX_DELAY);
  277.  
  278.         if (bits & WIFI_CONNECTED_BIT) {
  279.                 ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
  280.                          EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
  281.             } else if (bits & WIFI_FAIL_BIT) {
  282.                 ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
  283.                          EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
  284.             } else {
  285.                 ESP_LOGE(TAG, "UNEXPECTED EVENT");
  286.             }
  287.         ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
  288.         ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
  289.         vEventGroupDelete(s_wifi_event_group);
  290.  
  291. }

ESP_Sprite
Posts: 8921
Joined: Thu Nov 26, 2015 4:08 am

Re: wifi + timer interrupt = PANIC [esp32]

Postby ESP_Sprite » Wed Aug 04, 2021 1:42 am

Does it work if you don't specify ESP_INTR_FLAG_IRAM ? Also, what specifically is the panic?

NIXIE_123
Posts: 32
Joined: Fri Aug 02, 2019 9:51 am

Re: wifi + timer interrupt = PANIC [esp32]

Postby NIXIE_123 » Wed Aug 04, 2021 9:14 am

Does it work if you don't specify ESP_INTR_FLAG_IRAM ?
Yes. It works! If I pass 0 instead of ESP_INTR_FLAG_IRAM
Is this correct solution or just a workaround?
what specifically is the panic?

Code: Select all

  #0  0x400d1dc9:0x3ffb0880 in event_handler at src/main.c:55
  #1  0x4008273d:0x3ffb08a0 in _xt_lowint1 at /home/mariusz/.platformio/packages/framework-espidf/components/freertos/port/xtensa/xtensa_vectors.S:1105
  #2  0x4008cb3c:0x3ffba840 in spi_flash_hal_poll_cmd_done at /home/mariusz/.platformio/packages/framework-espidf/components/hal/spi_flash_hal_common.inc:37
  #3  0x4008c8da:0x3ffba860 in spi_flash_hal_read at /home/mariusz/.platformio/packages/framework-espidf/components/hal/spi_flash_hal_common.inc:188
  #4  0x40094c41:0x3ffba890 in spi_flash_chip_generic_read at /home/mariusz/.platformio/packages/framework-espidf/components/spi_flash/spi_flash_chip_generic.c:206
  #5  0x40083f7b:0x3ffba910 in esp_flash_read at /home/mariusz/.platformio/packages/framework-espidf/components/spi_flash/esp_flash_api.c:663 (discriminator 4)
  #6  0x400ee47e:0x3ffba950 in esp_partition_read at /home/mariusz/.platformio/packages/framework-espidf/components/spi_flash/partition.c:347
  #7  0x400ebd57:0x3ffba980 in nvs::NVSPartition::read(unsigned int, void*, unsigned int) at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_partition.cpp:45
  #8  0x400ec8a5:0x3ffba9a0 in nvs::Page::readEntry(unsigned int, nvs::Item&) const at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_page.cpp:797
  #9  0x400ecc19:0x3ffba9c0 in nvs::Page::findItem(unsigned char, nvs::ItemType, char const*, unsigned int&, nvs::Item&, unsigned char, nvs::VerOffset) at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_page.cpp:841
  #10 0x400eadbf:0x3ffbaa20 in nvs::Storage::eraseOrphanDataBlobs(intrusive_list<nvs::Storage::BlobIndexNode>&) at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_storage.cpp:80
  #11 0x400eb00f:0x3ffbab20 in nvs::Storage::init(unsigned int, unsigned int) at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_storage.cpp:140
  #12 0x400ebf21:0x3ffbab80 in nvs::NVSPartitionManager::init_custom(nvs::Partition*, unsigned int, unsigned int) at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_partition_manager.cpp:99
  #13 0x400ebf9d:0x3ffbaba0 in nvs::NVSPartitionManager::init_partition(char const*) at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_partition_manager.cpp:61
  #14 0x400ea772:0x3ffbabd0 in nvs_flash_init_partition at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_api.cpp:135
  #15 0x400ea792:0x3ffbabf0 in nvs_flash_init at /home/mariusz/.platformio/packages/framework-espidf/components/nvs_flash/src/nvs_api.cpp:171
  #16 0x400d205f:0x3ffbac10 in app_main at src/main.c:226
  #17 0x40143bb9:0x3ffbadb0 in main_task at /home/mariusz/.platformio/packages/framework-espidf/components/freertos/port/port_common.c:133 (discriminator 2)
  #18 0x4008bf29:0x3ffbadd0 in vPortTaskWrapper at /home/mariusz/.platformio/packages/framework-espidf/components/freertos/port/xtensa/port.c:168
Image

ESP_Sprite
Posts: 8921
Joined: Thu Nov 26, 2015 4:08 am

Re: wifi + timer interrupt = PANIC [esp32]

Postby ESP_Sprite » Wed Aug 04, 2021 1:43 pm

The thing is flash (write) accesses. An interrupt marked as in IRAM will keep functioning when a flash write happens (which in this case is what happens when you initialize NVS), a non-IRAM interrupt will be disabled for as long as the flash write takes. However, you must guarantee that the interrupt handler plus all data it accesses are in internal memory for you to be able to mark it as in IRAM, otherwise you'll get crashes like this.

As far as it's a workaround: it depends. If it's acceptable for the interrupt not to fire during flash writes, you're okay, if not you'll need to hunt for the bits that are not in IRAM.

NIXIE_123
Posts: 32
Joined: Fri Aug 02, 2019 9:51 am

Re: wifi + timer interrupt = PANIC [esp32]

Postby NIXIE_123 » Sat Aug 07, 2021 3:24 pm

Thank you for your response

If I make an empty ISR it works with IRAM flag set on.
But even if I add simple gpio_set_level() it panics.

I want to move ISR to core 1. I have below code:

Code: Select all

static void task(){
	timer_config_t config_timer_mux = {
	                .divider = 80,
	                .counter_dir = TIMER_COUNT_UP,
	                .counter_en = TIMER_PAUSE,
	                .alarm_en = TIMER_ALARM_EN,
	                .auto_reload = TIMER_AUTORELOAD_EN,
	            }; // default clock source is APB

	        timer_init(TIMER_GROUP_0, TIMER_0, &config_timer_mux);
	        timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 111);
	        timer_enable_intr(TIMER_GROUP_0, TIMER_0);
	        timer_isr_register(TIMER_GROUP_0, TIMER_0, przerwanie_od_timer_mux, NULL, ESP_INTR_FLAG_IRAM, NULL);
	        timer_start(TIMER_GROUP_0, TIMER_0);
	        while(1){
	              vTaskDelay(1);
	          }
//vTaskDelete(xHandle);
}
app_main(){
xTaskCreatePinnedToCore(task, "task", 4096, NULL, 1, NULL, 1);
}
But the ISR is not firing. Even if I pass 0, so it should be pinned to core 0

NIXIE_123
Posts: 32
Joined: Fri Aug 02, 2019 9:51 am

Re: wifi + timer interrupt = PANIC [esp32]

Postby NIXIE_123 » Mon Aug 09, 2021 12:39 pm

Do you know what is going on?

NIXIE_123
Posts: 32
Joined: Fri Aug 02, 2019 9:51 am

Re: wifi + timer interrupt = PANIC [esp32]

Postby NIXIE_123 » Mon Aug 09, 2021 7:32 pm

Ok, i got it. It was some stupid mistake.

Who is online

Users browsing this forum: No registered users and 126 guests