Wifi Driver Receive Buffer Access/Interrupt

danyo93
Posts: 10
Joined: Sat May 15, 2021 5:56 pm

Wifi Driver Receive Buffer Access/Interrupt

Postby danyo93 » Sun May 16, 2021 6:26 pm

Hi All,

I'm currently trying to implement a synchronization Protocol called 'SyncTSF', where the core idea is to always keep the System time adjusted to the Wi-Fi TSF-Timer value. Now, as per standard, the local TSF timer of an STA is automatically synched to the AP's TSF timer value by applying an offset contained in a beacons Timestamp field. To eliminate skew-related synchronization errors, the System time should be updated asap after the TSF timer has been updated. To achieve that, I would like to trigger an interrupt every time a frame was received and update my system clock. Is there any way to achieve this behavior while not using promiscuous mode? I couldn't find anything in the docs or the Wi-Fi drivers source code.

Cheers,
Dennis

david@millares.se
Posts: 5
Joined: Wed Mar 31, 2021 6:40 am

Re: Wifi Driver Receive Buffer Access/Interrupt

Postby david@millares.se » Tue May 25, 2021 9:03 am


danyo93
Posts: 10
Joined: Sat May 15, 2021 5:56 pm

Re: Wifi Driver Receive Buffer Access/Interrupt

Postby danyo93 » Wed Jun 02, 2021 9:23 pm

Hi David,

first of all, thank you for your answer! It definitely pointed me into the right direction. I have now tried to install an interrupt using the ETS_WIFI_MAC_INTR_SOURCE in the following fashion:

1.) I created a freeRTOS Event group to handle some events of my SyncTSF service. The only thing the interrupt is supposed to do at the moment is to set an event bit when it's triggered, which will then in turn signal the event handler to print a message on the console. Here is how I create the task:

Code: Select all

void syncTSF_init(void){
    syncTSF_event_group = xEventGroupCreate();
    syncTSF_event_group_mutex = xSemaphoreCreateMutex();
    xTaskCreatePinnedToCore(&syncTSF, 
                            "SyncTSF", 
                            2048, 
                            &syncTSF_interrupt_handle, 
                            4, 
                            syncTSF_task, 
                            0);
}
2.) The interrupt is allocated and started within that same task if the SyncTSF start function sets the dedicated bit. In that way I make sure the interrupt is created on the same core the task is running. The code of this specific section looks like this:

Code: Select all

static void syncTSF(void *pvParameters){
    const EventBits_t xBitsToWaitFor  = ( SYNC_TSF_STARTED | SYNC_TSF_STOPPED | SYNC_TSF_WIFI_PROBE_RCVD );
    EventBits_t xEventGroupValue;
    const TickType_t xTicksToWait = 200 / portTICK_PERIOD_MS;

    for(;;){
        xEventGroupValue  = xEventGroupWaitBits(syncTSF_event_group, xBitsToWaitFor, pdFALSE, pdFALSE, xTicksToWait);
	
	/* Print the Event Bits for debugging */
	ESP_LOGI(TAG, "Event Bits value: %d", (uint32_t) xEventGroupValue);
	
	/* This is where the message gets printed in case the interrupt handler sets the SYNC_TSF_WIFI_PROBE_RCVD Bit */
        if((xEventGroupValue & ( SYNC_TSF_RUNNING | SYNC_TSF_WIFI_PROBE_RCVD )) == 
        	( SYNC_TSF_RUNNING | SYNC_TSF_WIFI_PROBE_RCVD )){
		ESP_LOGI(TAG, "Interupt triggered");
            }
        }

        else if((xEventGroupValue & SYNC_TSF_STARTED) && syncTSF_intr_handle == NULL){
            ESP_LOGI(TAG, "SyncTSF Service Started");
            
	    /* Allocate Interrupt */
            esp_intr_alloc( ETS_WIFI_MAC_INTR_SOURCE, 
                            ESP_INTR_FLAG_SHARED, 
                            &syncTSF_interrupt_handle, 
                            NULL,
                            &syncTSF_intr_handle);
	    /* Set the Service in running state */
            xEventGroupSetBits(syncTSF_event_group, SYNC_TSF_RUNNING);
            xEventGroupClearBits(syncTSF_event_group, SYNC_TSF_STARTED);
            esp_intr_enable(syncTSF_intr_handle);
        }
    }
}
3.) Finally, as I said, the interrupt handler which sets the SYNC_TSF_WIFI_PROBE_RCVD Bit to trigger the Event:

Code: Select all

void syncTSF_interrupt_handle(void *arg){
    xEventGroupClearBitsFromISR(syncTSF_event_group, SYNC_TSF_WIFI_PROBE_RCVD); 
}
4.) Now, when I do everything as described, I immediately get a core panic with the following message after the interrupt is entered for the first time:

Code: Select all

␛[0;32mI (3153) SyncTSF: Event Bits value: 2␛[0m
␛[0;32mI (3163) SyncTSF: SyncTSF Service Started␛[0m
Guru Meditation Error: Core  0 panic'ed (Interrupt wdt timeout on CPU0).
This only happens when I create my event handler task on core 0. If I try to create it on core 1, the interrupt handler is never entered. I also tried to increase the watchdog timeout value, but that didn't help either. When I try the functions provided in the rom/ets_sys.h library, it has the same effect (nothing happens basically == the interrupt is either never entered or not created at all). I know that what I'm doing isn't thread safe but that shouldn't be the reason for the core panic. Since this interrupt source is probably used also by the WiFi PHY driver, could that be the reason for this kind of behavior? What am I missing here?

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: Wifi Driver Receive Buffer Access/Interrupt

Postby WiFive » Thu Jun 03, 2021 2:55 am

You didn't clear the interrupt

danyo93
Posts: 10
Joined: Sat May 15, 2021 5:56 pm

Re: Wifi Driver Receive Buffer Access/Interrupt

Postby danyo93 » Thu Jun 03, 2021 12:52 pm

Hi WiFive,

thanks for taking a look into it. Can you explain what you mean by 'clearing' the interrupt? I haven't encountered this terminus in the context of the ESP32 and I can't find a reference to this anywhere in the api or the technical reference manual.

Thanks a lot!
Dennis

david@millares.se
Posts: 5
Joined: Wed Mar 31, 2021 6:40 am

Re: Wifi Driver Receive Buffer Access/Interrupt

Postby david@millares.se » Wed Jun 16, 2021 9:17 am

One way is to let the wifi driver setup the interrupt handler. Then you could replace it with your own and call the "original" wmac handler. Assuming it to clear/acknowledge the interrupt properly.

Example:

Code: Select all

#include <freertos/FreeRTOS.h>
#include <esp_intr_alloc.h>


static xt_handler wmac_xt_handler;

/*
 * My ISR routine for WMAC interuppt
 */
void IRAM_ATTR m_isr_wmac(void* param)
{  
  // Do stuff here

  /*
   * Call previous configured interrupt handler
   * Assume it will enable the interrupt properly.
   */  
  wmac_xt_handler(param);
}

/*
 * m_isr_init must be called after the wifi module has ben configured.
 * In order to get the correct interrupt handler
 */
void m_isr_init(void)
{
  if (xt_int_has_handler(ETS_WMAC_INUM, xPortGetCoreID()))
  {
    ESP_INTR_DISABLE(ETS_WMAC_INUM);
    wmac_xt_handler = xt_set_interrupt_handler(ETS_WMAC_INUM, &m_isr_wmac, NULL);
    ESP_INTR_ENABLE(ETS_WMAC_INUM);
  }
  else
  {
    printf("m_isr_init: wmac_isr not set\n");
  }
}

void m_isr_deinit(void)
{
  if (wmac_xt_handler)
  {
    ESP_INTR_DISABLE(ETS_WMAC_INUM);
    xt_set_interrupt_handler(ETS_WMAC_INUM, wmac_xt_handler, NULL);
    ESP_INTR_ENABLE(ETS_WMAC_INUM);
  }
}

danyo93
Posts: 10
Joined: Sat May 15, 2021 5:56 pm

Re: Wifi Driver Receive Buffer Access/Interrupt

Postby danyo93 » Mon Jul 12, 2021 6:36 am

So, I finally had the time to come back to this and try your example. Worked like a charm. Thanks, David!

cyberman54
Posts: 27
Joined: Sun Jan 14, 2018 7:47 pm

Re: Wifi Driver Receive Buffer Access/Interrupt

Postby cyberman54 » Sun Feb 05, 2023 3:53 pm

I can't find ETS_WIFI_MAC_INTR_SOURCE in the linked technical documentation pdf. Where can i find a description of this interrupt source?

Who is online

Users browsing this forum: No registered users and 69 guests