Other Parts Discussed in Thread: UNIFLASH
Hi,
I'm trying to use the SPI driver from pdk_am335x_1_0_16 in my application. In my use case I need to make a 12 byte SPI transaction as part of an interrupt.
Looking at the example code from the PDK, I set up my SPI params like this:
SPI_Params_init(&spiParams); spiParams.frameFormat = SPI_POL0_PHA0; spiParams.bitRate = 1000000; spiParams.transferMode = SPI_MODE_CALLBACK; spiParams.transferCallbackFxn = MCSPICallbackFxn;
And then open the SPI instance like this:
spi_handle = SPI_open(1, &spiParams); /* '1' comes from the MCSPI instance we want to open */
This all seems to work out just fine. However, when I call SPI_transfer within a Hwi I get a crash and ROV tells me:
Looking into the MCSPI driver code, I see the crash happens here:
static bool MCSPI_transfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction) { SPI_Handle handle; SPI_v1_Object *object; SPI_v1_chObject *chObj; SPI_v1_HWAttrs const *hwAttrs; uint32_t chNum, clrInt = 0U;; bool ret_val = (bool)false; SemaphoreP_Status semStatus = SemaphoreP_OK; /* Input parameter validation */ if ((mcHandle != NULL) && (transaction != NULL)) { /* Get the pointer to the object and hwAttrs */ handle = mcHandle->handle; chNum = mcHandle->chnNum; object = (SPI_v1_Object *)handle->object; chObj = &(object->chObject[chNum]); hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs; /* Acquire the lock for the SPI transfer on this instance */ (void)SPI_osalPendLock(object->mutex, SemaphoreP_WAIT_FOREVER); if (chObj->spiParams.transferTimeout == 0U) { /* timeout cannot be NO_WAIT, set it to default value */ chObj->spiParams.transferTimeout = SPI_WAIT_FOREVER; } if ((uint32_t)transaction->count != 0U) { transaction->status = SPI_TRANSFER_STARTED;
SPI_osalPendLock is the culprit (assuming you cannot wait forever inside a Hwi which makes sense).
According to the comments in header file SPI.h, I can call SPI_transfer within the context of an Hwi:
* In ::SPI_MODE_CALLBACK, SPI_transfer() does not block task execution and * calls a ::SPI_CallbackFxn. This makes the SPI_tranfer() safe to be used * within a Task, Swi, or Hwi context. The ::SPI_Transaction structure must * stay persistent until the SPI_transfer function has completed!
So, am I doing something wrong or are the comments incorrect in the header file and I cannot actually call SPI_transfer from an Hwi? I have tried calling SPI_transfer outside of the Hwi in a task and it works OK.
Kind regards,
Simon