ESP interrupt latency

mculibrk
Posts: 22
Joined: Mon Feb 09, 2015 3:35 am

ESP interrupt latency

Postby mculibrk » Tue Apr 14, 2015 11:02 pm

Any information about the latency of peripheral (HSPI) interrupts related to the ETS_SPI_INTR_ATTACH(); API function?

Or what is the interrupt latency in general for the ESP?

cross posted here: http://bbs.espressif.com/viewtopic.php?f=6&t=359#p1323

Best regards,
mculibrk

raz123
Posts: 13
Joined: Tue Feb 24, 2015 9:14 am

Re: ESP interrupt latency

Postby raz123 » Wed Apr 15, 2015 4:45 am

Excellent question. I'd like to know as well.

netlook
Posts: 4
Joined: Wed Apr 08, 2015 6:38 pm

Re: ESP interrupt latency

Postby netlook » Thu Apr 16, 2015 1:43 pm

We test the normal latency is about 1~1.2us , Now the API "ETS_SPI_INTR_ATTACH(isr_handler, void *)" is directly attached on the interrupt vector.

mculibrk
Posts: 22
Joined: Mon Feb 09, 2015 3:35 am

Re: ESP interrupt latency

Postby mculibrk » Thu Apr 16, 2015 4:08 pm

Thanks for your info!

Can you tell me which interrupt you checked? SPI? Other peripheral?
1-1.2uS is still quite a looong time for interrupt latency... that's some 80+ instructions... but, OK, this is still reasonable. 80 instructions for INT handler, mask check, clear.. So... acceptable.

I'll try to toggle a gpio to see if it's the SPI that's so slow - that it needs 4uS to start sending data after setting the "start transfer" bit... seems very odd to me.

The loading and re-firing the SPI takes 2750nS on average - counted by CCOUNT register (instruction count). Attached is a scope-shot of the SPI output stream. The SPI module is configured to trigger a interrupt when a transfer is complete. ISR should just reload the FIFO and start the transfer as soon as possible - ideally there should be no "gaps" in the SPI output but that won't be possible as the INT is triggered only after the antire fifo is send and you need time to reload the fifo.
An option would be to use a timer to trigger before the fifo is emptied (~140uS) to reload it and doing a busy loop waiting for SPI to finish and re-trigger it immediately. But giving the ONE timer and the "timer list" system I doubt it will be fast and constant enough to keep the fifo full.

Here is part of my ISR for any comments on what am I doing wrong, if it's my fault:

Code: Select all


// worker
void wspi_spi_engine(volatile isrState_t *S) {
   uint32            *dst;
   uint32            tmr;
   register uint32    idx;

   // if anything is waiting in the fifo shadow load it and re-trigger transfer & interrupt
   if (S->spiFIFObits) {
      dst = (uint32 *)SPI_W0(ESP_SPI_HSPI);
      src = (uint32 *)&S->spiFIFO[0];
      for (idx = 0; idx < 16; idx++)
         dst[idx] = S->spiFIFO[idx];
         
      CLEAR_PERI_REG_MASK(SPI_USER1(ESP_SPI_HSPI), SPI_USR_MOSI_BITLEN << SPI_USR_MOSI_BITLEN_S);
      SET_PERI_REG_MASK(SPI_USER1(ESP_SPI_HSPI), S->spiFIFObits << SPI_USR_MOSI_BITLEN_S);

      SET_PERI_REG_MASK(SPI_CMD(ESP_SPI_HSPI), SPI_USR);      // start new transfer

   }

   // some other stuff here, taking approx 1 uS
}


// ISR handler registered via ETS_SPI_INTR_ATTACH()
void esp_spi_isr_handler(void *ptr) {
   uint32      tmr;
   volatile isrState_t *S;

   S = (isrState_t *)ptr;

   PROFILE(tmr = get_ccount());
   if (READ_PERI_REG(PERI_INT_FLAGS) & PERI_INTF_HSPI) {
      CLEAR_PERI_REG_MASK(SPI_SLAVE(ESP_SPI_HSPI), (SLV_SPI_INT_EN<<SLV_SPI_INT_EN_S)|SLV_SPI_INT_EN);   // clear all en & events

      wspi_spi_engine(S);

      SET_PERI_REG_MASK(SPI_SLAVE(ESP_SPI_HSPI), SLV_SPI_INT_EN<<SLV_SPI_INT_EN_S);   // enable all?
      S->dbg.intSPI++;
      // record no of inst for chunk load
      PROFILE(S->dbg.tmrLoad = get_ccount() - tmr);
   }
   if (READ_PERI_REG(PERI_INT_FLAGS) & PERI_INTF_SPI) {
      CLEAR_PERI_REG_MASK(SPI_SLAVE(ESP_SPI_SPI), (SLV_SPI_INT_EN<<SLV_SPI_INT_EN_S)|SLV_SPI_INT_EN);   // 0x3FF
   }
}


// SPI config

   CLEAR_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_DUMMY|SPI_USR_MISO|SPI_USR_MOSI_HIGHPART|SPI_USR_MISO_HIGHPART|
         SPI_SIO|SPI_FWRITE_DIO|SPI_FWRITE_QIO|SPI_FWRITE_DUAL|SPI_FWRITE_QUAD|SPI_WR_BYTE_ORDER|SPI_RD_BYTE_ORDER|SPI_CK_I_EDGE|SPI_CK_OUT_EDGE|SPI_FLASH_MODE);

   SET_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_USR_MOSI|    /* only data part */
         SPI_WR_BYTE_ORDER |SPI_CK_OUT_EDGE);   // little endian out, rising clock edge

   CLEAR_PERI_REG_MASK(SPI_CTRL(ESP_SPI_HSPI), SPI_WR_BIT_ORDER|SPI_RD_BIT_ORDER|      /* MSB bit order for I/O */
         SPI_QIO_MODE|SPI_DIO_MODE|SPI_QOUT_MODE|SPI_DOUT_MODE|SPI_FASTRD_MODE);         // disable multi bit IN options

   WRITE_PERI_REG(SPI_CTRL2(ESP_SPI_HSPI), 1<<SPI_MOSI_DELAY_MODE_S);               // 1/2 spi_clk delay

   SET_PERI_REG_MASK(SPI_PIN(ESP_SPI_HSPI), SPI_CS0_DIS|SPI_CS1_DIS|SPI_CS2_DIS);      // no CS needed
   CLEAR_PERI_REG_MASK(SPI_SLAVE(ESP_SPI_HSPI), SPI_SLAVE_MODE|                  /* enable master mode */
         (SLV_SPI_INT_EN<<SLV_SPI_INT_EN_S)|                                    /* disable interrupts */
         SPI_SLV_CMD_DEFINE|SPI_TRANS_DONE|SPI_SLV_WR_STA_DONE|SPI_SLV_RD_STA_DONE|SPI_SLV_WR_BUF_DONE|SPI_SLV_RD_BUF_DONE); // clear flags
   SET_PERI_REG_MASK(SPI_SLAVE(ESP_SPI_HSPI), SPI_SYNC_RESET);                     // reset SPI module?

   WRITE_PERI_REG(SPI_CLOCK(ESP_SPI_HSPI), (0<<SPI_CLKDIV_PRE_S) | (24<<SPI_CLKCNT_N_S) | (12<<SPI_CLKCNT_H_S) | (0<<SPI_CLKCNT_L_S));


   ETS_INTR_DISABLE(ETS_SPI_INUM);
   ETS_SPI_INTR_ATTACH(esp_spi_isr_handler, (void *)&SPIstate);
   //enable level2 isr, which contains spi, hspi and i2s events
   ETS_INTR_ENABLE(ETS_SPI_INUM);

   SET_PERI_REG_MASK(SPI_SLAVE(ESP_SPI_HSPI), SPI_TRANS_DONE_EN|SPI_SLV_WR_BUF_DONE_EN);


Attachments
DS2_QuickPrint1.png
SPI output stream
DS2_QuickPrint1.png (68.82 KiB) Viewed 8639 times

netlook
Posts: 4
Joined: Wed Apr 08, 2015 6:38 pm

Re: ESP interrupt latency

Postby netlook » Mon Apr 20, 2015 2:04 pm

1.With some setting, the SPI clock may start after CS or may stop before CS. Can you catch the waveform of SPI CS for reference?
2.Do you try to change the SPI clock frequency to check whether the interval is 7uS ?
Would you send the bin file for our further study?

mculibrk
Posts: 22
Joined: Mon Feb 09, 2015 3:35 am

Re: ESP interrupt latency

Postby mculibrk » Mon Apr 20, 2015 4:24 pm

netlook wrote:1.With some setting, the SPI clock may start after CS or may stop before CS. Can you catch the waveform of SPI CS for reference?


I know about various settings of the CS pin/functions.... but to be honest did not think about the possible correlation... ie that the SPI CLK will be delayed for the CS setup time etc.
I actually not use/need the CS whatsoever... and did not actually configure CS pin. Also, set all the CS delays to 0:

Code: Select all

//SET_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_MOSI|    /* only data part */
SET_PERI_REG_MASK(SPI_USER(ESP_SPI_HSPI), SPI_USR_MOSI|    /* only data part */

WRITE_PERI_REG(SPI_CTRL2(ESP_SPI_HSPI), 1<<SPI_MOSI_DELAY_MODE_S);               // mosi has 1/2 spi_clk delay -> data out change/valid on clock fall


but I'm not sure if the measurements was done with or without the "SPI_CS_SETUP|SPI_CS_HOLD"...

Anyway good point and thanks for this!


2.Do you try to change the SPI clock frequency to check whether the interval is 7uS ?
Would you send the bin file for our further study?


Hmm... did not think about that (also related to the previous mentioned CS setup/hold times)
I'll re-try the measurements to see what's going on...

regarding the bin... no problem... but it's currently not a "upload and start" thing... it needs some "interactive" parameter configuration and "manual" starting.
let me try/check the issues you pointed out and I'll prepare a "standalone bin" it I'll still have issues.

Thanks!

mculibrk
Posts: 22
Joined: Mon Feb 09, 2015 3:35 am

Re: ESP interrupt latency

Postby mculibrk » Sun Apr 26, 2015 11:36 pm

After a lot of trial/errors I can confirm the problem is/was not the Interrupt latecy alone...

The thing is the SPI module "takes quite some time" to generate the interrupt... I tried a lot of options with the SPI module but nothing changes... the delay depends on the SPI CLK so a variable delay is generated after the transfer is completed to the interrupt firing.
And yes... the "master ISR" it takes around 1.2uS before it manages to call the user specified function.

There are mentions in the .h files (RTOS SDK) that the ESP has high priority interrupts.
Is there any infor on how to configure a high priority interrupt handler and have it handle some "peripheral" interrupts (SPI or other)?

netlook
Posts: 4
Joined: Wed Apr 08, 2015 6:38 pm

Re: ESP interrupt latency

Postby netlook » Wed Apr 29, 2015 3:41 pm

Regarding the SPI config, we have following suggestion for your reference, it can reduce the delay time on CS line.
Actually there are many SPI registers that support flexible config for different application mode.
But some of the registers is not open to user now, So would you send the detail requirement to us , then we can prepare a special SPI config for you.

Code: Select all

1.Update the spi_register.h,add another control registers
#define SPI_CTRL1(i)                         (REG_SPI_BASE(i)  + 0xc)
#define  SPI_CS_HOLD_DELAY  0xf   
#define  SPI_CS_HOLD_DELAY_S   28
#define  SPI_CS_HOLD_DELAY_RES  0xfff 
#define  SPI_CS_HOLD_DELAY_RES_S   16

2.Reduce the delay on CS line: set SPI_CS_HOLD_DELAY in SPI_CTRL1 to 0
SET_PERI_REG_BITS(SPI_CTRL1(HSPI), SPI_CS_HOLD_DELAY, 0, SPI_CS_HOLD_DELAY_S); //test spi cs config

3.Some suggestions for SPI_MOSI_DELAY_MODE setting:
#define SPI_MOSI_DELAY_MODE 0x00000003 
//mode 0 : posedge; data set at positive edge of clk
//mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk
//mode 2 : Do not use this mode.

#define SPI_MOSI_DELAY_NUM 0x00000007   
//mode == 0 and freq<=40Mhz ,can be set to 0 or 1 ; 
//freq==80MHz :0 ,must set to 0;

mculibrk
Posts: 22
Joined: Mon Feb 09, 2015 3:35 am

Re: ESP interrupt latency

Postby mculibrk » Wed Apr 29, 2015 4:29 pm

Hi there!

Yeah.... I "noticed" there are a lot of "grey areas" regarding configuration "bits" of the ESP... ;)

Should I send/communicate via PM/support@espressif.com or post "public" here?

Anyway, I would like to have a "as constant as possible" SPI data stream (with the largest SPI FIFO that can be used) using interrupts to "re trigger/refill" the SPI FIFO. The "gap" should be less than 2,5uS, SPI CLK is set to 4MHz.


Code: Select all

data definitions

uint32  dataBuffer[2047];                        8KB work buffer
uint32  dataIndex;

//pseudo code for HSPI interrupt handler
HSPI_int_handler() {
    if (dataIndex < 2032) {
        // copy 16 (or more?) dwords from RAM buffer to HSPI FIFO (W0..15, ..31?)
        for (i=0;i<16;i++)
            SPI_W(i) = dataBuffer[dataIndex + i]

        // restart HSPI
        SET_PERI_REG_MASK(SPI_CMD, SPI_USR)
    }
}


setup code:

Code: Select all

configure HSPI INT handler (possibly high-level int)
enable HSPI ints


I already have similar code working but with the mentioned "gaps" in spi data which I need to avoid.

regards,
mculibrk

netlook
Posts: 4
Joined: Wed Apr 08, 2015 6:38 pm

Re: ESP interrupt latency

Postby netlook » Wed Apr 29, 2015 6:33 pm

Ok , please communicate via support@espressif.com & feedback@espressif.com .

Who is online

Users browsing this forum: No registered users and 11 guests