Part Number: AM3358
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