ESP interrupt latency
ESP interrupt latency
Postby mculibrk » Tue Apr 14, 2015 11:02 pm
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
Re: ESP interrupt latency
Postby mculibrk » Thu Apr 16, 2015 4:08 pm
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
-
- SPI output stream
- DS2_QuickPrint1.png (68.82 KiB) Viewed 16646 times
Re: ESP interrupt latency
Postby netlook » Mon Apr 20, 2015 2:04 pm
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?
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!
Re: ESP interrupt latency
Postby mculibrk » Sun Apr 26, 2015 11:36 pm
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)?
Re: ESP interrupt latency
Postby netlook » Wed Apr 29, 2015 3:41 pm
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;
Re: ESP interrupt latency
Postby mculibrk » Wed Apr 29, 2015 4:29 pm
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
Re: ESP interrupt latency
Postby netlook » Wed Apr 29, 2015 6:33 pm
Who is online
Users browsing this forum: No registered users and 60 guests
Login
Newbies Start Here
Are you new to ESP8266?
Unsure what to do?
Dunno where to start?
Start right here!
Latest SDK
Documentation
Complete listing of the official ESP8266 related documentation release by ESPRESSIF!
Must read here!
- All times are UTC+08:00
- Top
- Delete all board cookies
About Us
Espressif Systems is a fabless semiconductor company providing cutting-edge low power WiFi SoCs and wireless solutions for wireless communications and Internet of Things applications. We are the manufacturer of ESP8266EX.