Other Parts Discussed in Thread: AM6548, SEGGER
Dear experts,
we have issues in realtime behaviour when polling status register of a serial NOR flash:
the interrupts are disabled for a long period (250µs) which impacts realtime behavior heavily.
Our environment is:
- Sitara AM6548 with a custom board
- AM65xx processor SDK v6.3 (in v8.02 seem to have the same issue)
- TI-RTOS on A53, but I think with FreeRtos at R5 it would have the same issue
- Quad SPI interface accessing an ISSI NOR flash IS25LP256E
- An embedded filesystem accessing the NOR flash (Segger emFile)
The issue is that during polling NOR flash status register, the global interrupts are disabled and polling needs up to 250µs (!).
I located the root cause of the issue in PDK\packages\ti\drv\spi\src\v0\OSPI_v0.c in the function OSPI_transfer_v0()
key = SPI_osalHardwareIntDisable(); ... else { /* Save the pointer to the transaction */ object->transaction = transaction; /* Acquire the lock for this particular I2C handle */ (void)SPI_osalPendLock(object->mutex, SemaphoreP_WAIT_FOREVER); /* Book keeping of transmit and receive buffers. */ object->writeBufIdx = (uint8_t *)transaction->txBuf; object->writeCountIdx = (uint32_t)transaction->count; object->readBufIdx = (uint8_t *)transaction->rxBuf; object->readCountIdx = (uint32_t)transaction->count; /* * OSPI_primeTransfer_v0 is a longer process and * protection is needed from the OSPI interrupt */ if ((uint32_t)SPI_OPER_MODE_POLLING != object->intrPollMode) { SPI_osalHardwareIntrEnable((int32_t)hwAttrs->intrNum, (int32_t)hwAttrs->eventId); } xferRet = OSPI_primeTransfer_v0(handle, transaction); SPI_osalHardwareIntRestore(key);
This section has even 2 issues:
- during disabled interrupts, a call to SPI_osalPendLock() is done, which is generally not a good idea, since disabling interrupts blocks normal behavior of the scheduler. Just the task with the next lower priority would be executed.
- during disabled interrupts, a call to OSPI_primeTransfer_v0() is done, which takes in our case up to 250µs !
My fix is now to first re-enable interrupts, then call OSPI_primeTransfer_v0():
// R.Wurth 2022-04-01: re-enable interrupt BEFORE the transfer,
// because a transfer to poll ISSI flash status register takes sometimes up to 250us
SPI_osalHardwareIntRestore(key);
xferRet = OSPI_primeTransfer_v0(handle, transaction);
//SPI_osalHardwareIntRestore(key);
(The call to SPI_osalPendLock() is not a issue for us since we have already a mutex at a higher level (file system API), therefore the call to SPI_osalPendLock() does never block)
I could post some oscilloscope pictures with debug-GPIOs were we can see the timing behavior, including what happens in OSPI_flashExecCmd()
Questions:
- Why can OSPI_primeTransfer_v0() take so long for just polling a status register?
In our case the Software-Triggered Instruction Generator (STIG) of the AM6548 is used, via OSPI_flashExecCmd() - Is there a real reason why TI disabled globally interrupts before calling OSPI_primeTransfer_v0() ?
Best regards,
Ruediger