SPI communication halt on cypress FX3

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
haa_4305841
Level 2
Level 2

Hi,

I am using the Cypress Fx3 (CYUSB3014) for my application.

1.  The data flow and interface as follows

        FX3 --> SPI --> MAX3140 --> RS485 (RS485 bus is shared among other cards as well)

2.  For every byte received from the RS485 bus to the MAX3140 an interrupt is triggered to FX3(SPI)

3.  FX3 reads data from MAX3140, this continues until all the bytes received.

4.  Sometime upon receiving the interrupt the SPI controller goes out of control unable to read the data from RS485 from there on.

Exercise Performed:

1.  Tried to reset the SPI controller after identifying this case, by sending command through control endpoint, which works for us.

2.  Triggered an event and in the Task tried to reset the SPI controller, failed to send event from interrupt.

3.  Started a timer and tried to reset SPI controller, was not able to coming to this timer expiry handler.

We have few question regarding the issue:

1. What is the best possible method that will make SPI controller alone deinit and init during this case and make it work again without resetting the FX3 controller.

2. It is allowed to do SPI deinit & init in interrupt routine.

FX3 SPI frequency is configured to 100Khz

Please provide the feedback ASAP.

Best Regards,

Harsha

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

Hello Harsha,

1) The CY_U3P_ERROR_MUTEX_FAILURE occurs when the CyU3PSpiSetConfig API fails as the CyU3PMutexGet API fails. If you only initialize the SPI block using CyU3PSpiInit API which will initialize the SPI block but will not set the configuration settings as done in CyU3PSpiSetConfig API. Calling only CyU3PSpiInit API in the GPIO interrupt callback will not return an error (as done in the gpioapp firmware shared in my previous response)

- Please note that this GPIO interrupt call is made in interrupt context, which means that any blocking API calls cannot be made from this callback.

2) Similarly, if CyU3PSpiSetConfig is called from a timer callback the same error will be returned by the API.

This is my understanding after going through the code that you shared. Please correct me if I am wrong.

- Whenever GPIO interrupt occurs, under case GPIO21_RS485_IRQ if readBuffer[0] != 0  SPI RS485DataRecvIntrHandle is called

- RS485DataRecvIntrHandle then calls the RS485ErrHandler which sets CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1 event to reinitialize the SPI block.

- I found this event is set twice 1)  MsgTimerHandling2 (gTimerEvent)  2) RS485ErrHandler (DataRxEvent)

These are my questions:

- Why multiple threads and events are used to reinitialize SPI block?

- Are other events working properly or as expected? Events from the same event group (DataRxEvent)

Tests :

- Please try using a single event  CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1(DataRxEvent) by commenting out the second event (CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1) in MsgTimerHandling2

- Can you try adding one more event to DataRxEvent #define TEST_EVENT( 1<<3) and try setting the event in the interrupt callback

case GPIO21_RS485_IRQ:

      CyU3PEventSet(&DataRxEvent, TEST_EVENT, CYU3P_EVENT_OR);  ///before the SPI transfers

        .......

And check for the event in the for{}

status = CyU3PEventGet (&DataRxEvent,

                    (CY_FX_GPIOAPP_GPIO_HIGH_EVENT | CY_FX_GPIOAPP_GPIO_LOW_EVENT| CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1 | TEST_EVENT), CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

if (status == CY_U3P_SUCCESS)

            {

              if(eventFlag & TEST_EVENT)

                {

                      DEBUG_LOG(DBG1, 0xFF, 0);

                }

            }

Please let me know how to fix "CY_U3P_ERROR_MUTEX_FAILURE"  error.

>> As mentioned earlier in this post, the CY_U3P_ERROR_MUTEX_FAILURE error is returned by  CyU3PMutexGet API while it is called inside CyU3PSpiSetConfig. You can try calling CyU3PSpiDeInit in the GPIO callback and then later by setting event the SPI block can be initialized  CyU3PSpiInit as well as configured using CyU3PSpiSetConfig API.

I have attached the modified gpioapp firmware which checks the initialization of SPI block as well as communication using multiple events.

terterm.PNG

Please let me know the results of the above-mentioned tests

Regards,

Rashi

Regards,
Rashi

View solution in original post

0 Likes
11 Replies
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello Harsha,

- Please let me know which firmware are you using in your application.

- Is the SPI in DMA mode or reg mode?

- Please send the SPI configuration which is set using CyU3PSpiSetConfig API

Sometime upon receiving the interrupt the SPI controller goes out of control unable to read the data from RS485 from there on.

>>  Which interrupt will be generated when you need to disable the SPI block. Is it through some GPIO interrupt?

Triggered an event and in the Task tried to reset the SPI controller, failed to send event from interrupt.

>> This should work. Please share the code snippet when you try setting an event in the interrupt service routine. Also let me know hoe many events group are used in the firmware

Regards,

Rashi

Regards,
Rashi
0 Likes

Hi Rashi,

Thanks for the replay.

1. Please let me know which firmware are you using in your application.

- "USBBulkSourceSink" firmware is modified and used for our application

2. Is the SPI in DMA mode or reg mode?

- Reg mode

3. Please send the SPI configuration which is set using CyU3PSpiSetConfig API

-

    CyU3PMemSet ((uint8_t *)&spiConfig, 0, sizeof(spiConfig));

    spiConfig.isLsbFirst = CyFalse;

    spiConfig.cpol       = CyFalse;

    spiConfig.ssnPol     = CyFalse;

    spiConfig.cpha       = CyFalse;

    spiConfig.leadTime   = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK;

    spiConfig.lagTime    = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK;

    spiConfig.ssnCtrl    = CY_U3P_SPI_SSN_CTRL_FW;

    spiConfig.clock      = 100000;

    spiConfig.wordLen    = 8;

    status = CyU3PSpiSetConfig (&spiConfig, NULL);

4. Which interrupt will be generated when you need to disable the SPI block. Is it through some GPIO interrupt?

- Yes we are using the GPIO interrupt (GPIO [21]  /  CTL [4] ) is configured as GPIO interrupt.

5. Please share the code snippet when you try setting an event in the interrupt service routine. Also let me know hoe many events group are used in the firmware

- There are 2 events in the event group:

CyU3PEvent      gTimerEvent;

CyU3PEvent      DataRxEvent;

And these events are used for normal working case.

And it is tested working event triggering and as well as task switching also happening.

/**this functional is called upon receiving invalid data*/

void RS485ErrHandler()

{

RS485ErrThreadentry = 0xA2; //Rs485 Error thread invoke.

CyU3PEventSet(&DataRxEvent, CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1,CYU3P_EVENT_OR);

}

-----------------------------------------------------------------------------------------------------------------------------------------------

/**Function to perform task set by an event (Event get)*/

CyU3PReturnStatus_t

DataRxHandlerThread_Entry (

        uint32_t input)

{

gControlStruct_t = (gControlStruct *)GetStructPtr();

    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    uint32_t eventFlag;

    CyU3PThreadSleep (100);

    for (;;)

    {

        status = CyU3PEventGet (&DataRxEvent,

                (CY_FX_GPIOAPP_GPIO_HIGH_EVENT | CY_FX_GPIOAPP_GPIO_LOW_EVENT | CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1),

                CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

        if (status == CY_U3P_SUCCESS)

        {

        if(eventFlag & CY_FX_GPIOAPP_GPIO_LOW_EVENT)

        {

                   gControlStruct_t = (gControlStruct *)GetStructPtr();

                   DataHandler(gControlStruct_t->gFwHandle_t.gSystemInfo_t.gEventType, NULL);

        }

        else if(eventFlag & CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1) // event to reset SPI

        {

        RS485ErrThreadentry = 0xA3; //Rs485 Error thread entry.

            CyU3PSpiDeInit();  // SPI de-initialization

            CyU3PBusyWait(10000);

             CyFxSPIInit (1);      // SPI initilization

            CyU3PBusyWait(10000);

            RS485DeviceInit();  // RS485 initialization

            RS485ErrThreadentry = 0xA4; //Rs485 Error thread exit.

        }

        }

    }

    CyU3PDebugPrint (4, "%x: Application failed to initialize. Error code: %d.\n", status);

    while (1);

}

As we are maintaining global variable for reading the status through control endpoint

RS485ErrThreadentry = 0xA2; // to log the thread is invoked in RS485ErrHandler function (event set)

RS485ErrThreadentry = 0xA3; // to log the thread entry in DataRxHandlerThread_Entry function (event get before SPI reset)

RS485ErrThreadentry = 0xA4; // to log the thread entry in DataRxHandlerThread_Entry function (event get after SPI reset)

If we read the value of "RS485ErrThreadentry"  we are getting value "0XA2" which indicated only thread event is set and what may be the reason for not entering the event get function ?

Best Regards,

Harsha

0 Likes

Hello Harsha,

Is RS485ErrHandler called from GPIO interrupt callback function? Is that right?

Can you set the value of RS485ErrThreadentry after CyU3PEventSet API call and checking the return status of the API. This will confirm that an event has been SET. CyU3PEventSet API returns 0 if success

void RS485ErrHandler()

{

status = CyU3PEventSet(&DataRxEvent, CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1,CYU3P_EVENT_OR);

if (status == CY_U3P_SUCCESS) (

RS485ErrThreadentry = 0xA2; //Rs485 Error thread invoke.

}

}

You can also check whether the API is returning success and let me know the results

    status = CyU3PEventGet (&DataRxEvent,

                (CY_FX_GPIOAPP_GPIO_HIGH_EVENT | CY_FX_GPIOAPP_GPIO_LOW_EVENT | CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1),

                CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

        if (status == CY_U3P_SUCCESS)

        {

         RS485ErrThreadentry = 0xA5;

          if .......

Regards,

Rashi

Regards,
Rashi
0 Likes

Hi Rashi,

1.Is RS485ErrHandler called from GPIO interrupt callback function? Is that right?

- Yes, In InterruptCb an SPI data is read and based on the status, RS485ErrHandler will be called.

As per your suggestion we have verified the CyU3PEventSet API is executing successfully without error.

/**

  *This function is called upon receiving invalid data.

*/

void RS485ErrHandler()

{

CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

RS485ErrThreadentry = 0xB1; //Rs485 Error thread invoke.

DEBUG_LOG(DBG1, 0xA2, 0);

Status = CyU3PEventSet(&DataRxEvent, CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1,CYU3P_EVENT_OR);

if(Status != CY_U3P_SUCCESS)

{

DEBUG_LOG(DBG1, 0xA3, Status);

}

DEBUG_LOG(DBG1, 0xA4, 0);

}

-Yes, EventSet is success.

1. But we are facing the problem in switching the task after setting the particular event we are unable to get the receive event to perform the SPI re-initialization operation. The EventGet is neither success nor failed.

2. Actually, My main objective is to Deinit and Init the SPI module when i enetered to error condition, So I thought to perform this in Task.

3. Do you recommend that I can perform this Deinit and Init in InterruptCb(), and what is the minimum time delay required between SPI Deinit and Init.

But after this scenario, same task is being triggered from another interrupt receiving to InterruptCb and task switching is not happenng.

CY_U3P_DMA_CB_PROD_EVENT is also generating when I tried to send the data from host and able to log the data in  "CyFxBulkLpDmaCallback"

-> By analyzing the above data collectively. I think FW is not hung. Only the respective task is in Unknown state, Let us know your thought.

Question:

1. How I can analyze the above condition ?

2. Do we have any provision to check the status of task ?

3. For this respective task, We are allocating 8K Stack size. Do we have a provision to check any stack overflow ?

"CyU3PThreadStackErrorNotify" I found in "cyu3os.h", But it is masked. Whether this would be helpful. If so how it can be used ?

Best Regards,

Harsha

0 Likes
lock attach
Attachments are accessible only for community members.

Hello Harsha,

Yes, In InterruptCb an SPI data is read and based on the status, RS485ErrHandler will be called.

>> Please share the code snippet for us to understand.

I have modified the GpioApp example of the SDK to initialize and de initialize SPI block on getting GPIO interrupt. It works fine. (attached)

To analyze whether the thread switching is happening or not you can check whether the program control gets into the for{} loop or not (i.e. updating the variable before event get is called)

Yes, CyU3PThreadStackErrorNotify API can be used for checking stack overflow. This function is only provided in debug builds of the firmware and allows the application to register a callback function that will be called to notify when any thread in the system has encountered a stack overflow. This API must be called before any user thread is created. It is recommended to invoke this API from CyFxApplicationDefine().

It will be good if you can share the firmware files here so that we can get better understanding of the problem.

Regards,

Rashi

Regards,
Rashi
0 Likes

Hi Rashi,

1. Please share the code snippet for us to understand.

-

/*GPIO Interrupt calback function */

if (!gpioValue)

{

switch(gControlStruct_t->gFwHandle_t.gSystemInfo_t.gEventType)

{

case GPIO21_RS485_RECV_INTR: /*Interrupt received from the RS485 block, get the data over SPI*/

SPI->lpp_spi_config &= ~CY_U3P_LPP_SPI_SSN_BIT; //Set SS Line Low

readBuffer[0] = RS485_READ_DATA;

apiRetStatus = RecvSpiWords (&readBuffer[0], 2);

SPI->lpp_spi_config |= CY_U3P_LPP_SPI_SSN_BIT; //Set SS Line High

if(readBuffer[0]!= 0)

lSetEvent = RS485DataRecvIntrHandle(readBuffer);

break;

default:

break;

}

if(lSetEvent)

{

gControlStruct_t = (gControlStruct *)GetStructPtr();

switch(lSetEvent)

{

case 0x01:

gControlStruct_t->gFwHandle_t.gSystemInfo_t.gEventType = gpioId;

CyU3PEventSet(&DataRxEvent, CY_FX_GPIOAPP_GPIO_LOW_EVENT,

CYU3P_EVENT_OR);

break;

case 0xFF:/*Error Handler Event Set*/

DEBUG_LOG(DBG1, 0xA2, 0);

RS485ErrThreadentry = 0xB1; //Rs485 Error thread invoke.

apiRetStatus = CyU3PEventSet(&DataRxEvent, CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1,CYU3P_EVENT_OR);

if(apiRetStatus != CY_U3P_SUCCESS)

{

DEBUG_LOG(DBG1, 0xA3, apiRetStatus);

}

DEBUG_LOG(DBG1, 0xA4, 0);

break;

default:

break;

}

}

}

2.To analyze whether the thread switching is happening or not you can check whether the program control gets into the for{} loop or not (i.e. updating the variable before event get is called)

- In event get function we are logging the particular variable with "0XD1" only once, if it enters into error mode.And we are able to log the value as well.

    for (;;)

    {

    if(RS485ErrThreadentry && ErrorStatus)

    {

    DEBUG_LOG(DBG1, 0xD1, 0);

    ErrorStatus = 0x00;

    }

3. I am using Below function to set the thread and event activity and profiling build is enabled.

CyU3PThreadSetActivityGpio(); and CyU3PEventSetActivityGpio();

And when the issue occurred the state of the Thread is Active and the Event is also active.

After that also i continue to receive the interrupts but task switching is not happening.

4. I have used "CyU3PThreadPerfGet" and "CyU3PEventPerfGet" to read the status of DataRxThread and DataRxEvent respectively.

-

Event status of DataRxEvent:

0x0001A80C -- number of event set operations

0x0001A7FF -- number of event get operations

0x0001A7EF -- number of thread suspensions due to event get operations.

0x00000000 -- number of event get timeouts

Thread status of DataRxThread:

0x0001FD81 -- thread resume count

0x0001FD80 -- thread suspend count

0x00000016 -- thread pre-emptions count due to an RTOS API call.

0x00002C3E -- thread pre-emptions count due to interrupts

0x00000001 -- thread priority inversions count

0x00000000 -- count of thread relinquish calls

0x00000000 -- count of thread suspension timeouts

5. It will be good if you can share the firmware files here so that we can get better understanding of the problem.

- About sharing source code is not a problem. You won't be able reproduce using DVK kit. It is custom design board with RS485 communication.

So, If you can suggest what else I can try. Please let me know.

Best Regards,

Harsha,

0 Likes

Hello Harsha,

Please share the definition of the macros used for the events.

- Also, try setting another event (not from any callbacks) from the same event group (DataRxEvent) and let me know if that event is being received by the event get API.

- Please confirm how did you check that CyU3PEventGet is not returning success. Did you follow the code as mentioned in the previous reply?

    status = CyU3PEventGet (&DataRxEvent,

                (CY_FX_GPIOAPP_GPIO_HIGH_EVENT | CY_FX_GPIOAPP_GPIO_LOW_EVENT | CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1),

                CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

        if (status == CY_U3P_SUCCESS)

        {

         RS485ErrThreadentry = 0xA5;

....

Regards,

Rashi

Regards,
Rashi
0 Likes

Hi Rashi,

1. Please share the definition of the macros used for the events.

-

#define CY_FX_GPIOAPP_GPIO_HIGH_EVENT    (1 << 0)   /* GPIO high event */

#define CY_FX_GPIOAPP_GPIO_LOW_EVENT     (1 << 1)   /* GPIO low event */

#define CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1  (1 << 2)   /* GPIO high event 1*/

2. Please confirm how did you check that CyU3PEventGet is not returning success.

-

I used that "CyU3PEventSetActivityGpio" to get the status of the event and that GPIO went high and didn't cleared. So If Eventget happened means that event activity GPIO must go low. (ie CyU3PEventSetActivityGpio(&DataRxEvent,GPIO13_LED4_S_C))

And to get thread status we are using "CyU3PThreadSetActivityGpio" call. And the thread is in active state as the particular GPIO is driven high (ie CyU3PThreadSetActivityGpio(&DataRxThread,GPIO12_LED3_S_C))

Yes, we also verified the method you have mentioned in get event function as per code snippet shared below if the "CyU3PEventGet" is success then it should return "0xA5" once after RS485 error or else it should return "0xA6" for "CyU3PEventGet" failure.

But in our case it not return neither "0xA5" nor "0xA6".

        status = CyU3PEventGet (&DataRxEvent,

                    (CY_FX_GPIOAPP_GPIO_HIGH_EVENT | CY_FX_GPIOAPP_GPIO_LOW_EVENT | CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1),

                    CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

            if (status == CY_U3P_SUCCESS)

            {

            if(RS485ErrThreadentry)

            DEBUG_LOG(DBG1, 0xA5, 0);

            gFunctStruct_t = (gFunctStruct *)GetStructPtr();

            if(eventFlag & CY_FX_GPIOAPP_GPIO_LOW_EVENT)

            {

            if(RS485ErrThreadentry)

            DEBUG_LOG(DBG1, 0xA7, 0);

           /*Other operation is performed*/*/

            }

            else if(eventFlag & CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1)

            {

            DEBUG_LOG(DBG1, 0xA9, 0);

                    CyU3PSpiDeInit();  // SPI de-initialization

                   CyU3PBusyWait(10000);

                    CyFxSpiInit (1);   //SPI initialization

                    CyU3PBusyWait(10000);

                    RS485DeviceInit();  // RS485 initialization

            DEBUG_LOG(DBG1, 0xAA, 0);

            }

            }

            else

            {

            DEBUG_LOG(DBG1, 0xA6, status);

            }

Best Regards,

Harsha,

   

0 Likes

Hello Harsha,

As mentioned in my previous response can you please try this and let me know the results.

- Also, try setting another event (not from any callbacks) from the same event group (DataRxEvent) and let me know if that event is being received by the event get API.

It would be good if you share the firmware for us to check the possible reason for the issue.

Regards,

Rashi

Regards,
Rashi
0 Likes
lock attach
Attachments are accessible only for community members.

Hi Rashi,

Exersice 1:

1. During Re-initialization of SPI (When We tried to re-initialize when the issue occurred)we are getting"CY_U3P_ERROR_MUTEX_FAILURE" (i.e, 0x1D).

   Below is the sequence that we followed for SPI module re-initialization, And this function is being called from GpioInterruptCb()

   CyU3PSpiDeInit() returned with SUCCESS

void RS485ErrHandler()

{

    DEBUG_LOG(DBG1, 0xA9, 0);

Status = CyU3PSpiDeInit();  // SPI de-initialization

    if (Status != CY_U3P_SUCCESS)

    {

    DEBUG_LOG(DBG1, 0xF1, Status);

    }

    status = CyFxSpiInit (1);   //SPI initialization

if (status != CY_U3P_SUCCESS)

{

DEBUG_LOG(DBG1, 0xF2, status);

}

DEBUG_LOG(DBG1, 0xA9, 0);

}

Exersice 2:

2. Sequence 1 is tried for Performing Deinit() in InterruptCb and then a timer is started and in timer expiry handler doing SPIInit()

Still I got the CY_U3P_ERROR_MUTEX_FAILURE error status. .And in timer expiry I tried to set an Event group, Event is set successfully.

But Task Switching i snot happening.

Exersice 3:

3. Also, try setting another event (not from any callbacks) from the same event group (DataRxEvent) and let me know if that

event is being received by the event get API

-  Actually for performing the SPI re-initialization apart from "DataRxThread" we have moved to "BulkLpAppThread" but it was also not helpful the task switching is not happening.

Below i my snippet for SPI Initialization

/* SPI initialization for application. */

CyU3PReturnStatus_t

CyFxSpiInit (uint16_t pageLen)

{

    CyU3PSpiConfig_t spiConfig;

    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    /* Start the SPI module and configure the master. */

    status = CyU3PSpiInit();

    if (status != CY_U3P_SUCCESS)

    {

    CyU3PDebugPrint (2, "CyU3PSpiInit Failed\r\n");

        return status;

    }

    /* Start the SPI master block. Run the SPI clock at 4MHz

     * and configure the word length to 8 bits. Also configure

     * the slave select using FW. */

    CyU3PMemSet ((uint8_t *)&spiConfig, 0, sizeof(spiConfig));

    spiConfig.isLsbFirst = CyFalse;

    //spiConfig.cpol       = CyTrue;

    spiConfig.cpol       = CyFalse;

    spiConfig.ssnPol     = CyFalse;

    //spiConfig.cpha       = CyTrue;

    spiConfig.cpha       = CyFalse;

    spiConfig.leadTime   = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK;

    spiConfig.lagTime    = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK;

    spiConfig.ssnCtrl    = CY_U3P_SPI_SSN_CTRL_FW;

    spiConfig.clock      = 100000;//16000000;

    spiConfig.wordLen    = 8;

    status = CyU3PSpiSetConfig (&spiConfig, NULL);

    return status;

}

Please let me know how to fix "CY_U3P_ERROR_MUTEX_FAILURE"  error.

Please find the attachment source code and refer to Note.

Also if offline analysis is not yield any result, i can provide remote access for further debugging.

Best regards,

Harsha

0 Likes
lock attach
Attachments are accessible only for community members.

Hello Harsha,

1) The CY_U3P_ERROR_MUTEX_FAILURE occurs when the CyU3PSpiSetConfig API fails as the CyU3PMutexGet API fails. If you only initialize the SPI block using CyU3PSpiInit API which will initialize the SPI block but will not set the configuration settings as done in CyU3PSpiSetConfig API. Calling only CyU3PSpiInit API in the GPIO interrupt callback will not return an error (as done in the gpioapp firmware shared in my previous response)

- Please note that this GPIO interrupt call is made in interrupt context, which means that any blocking API calls cannot be made from this callback.

2) Similarly, if CyU3PSpiSetConfig is called from a timer callback the same error will be returned by the API.

This is my understanding after going through the code that you shared. Please correct me if I am wrong.

- Whenever GPIO interrupt occurs, under case GPIO21_RS485_IRQ if readBuffer[0] != 0  SPI RS485DataRecvIntrHandle is called

- RS485DataRecvIntrHandle then calls the RS485ErrHandler which sets CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1 event to reinitialize the SPI block.

- I found this event is set twice 1)  MsgTimerHandling2 (gTimerEvent)  2) RS485ErrHandler (DataRxEvent)

These are my questions:

- Why multiple threads and events are used to reinitialize SPI block?

- Are other events working properly or as expected? Events from the same event group (DataRxEvent)

Tests :

- Please try using a single event  CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1(DataRxEvent) by commenting out the second event (CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1) in MsgTimerHandling2

- Can you try adding one more event to DataRxEvent #define TEST_EVENT( 1<<3) and try setting the event in the interrupt callback

case GPIO21_RS485_IRQ:

      CyU3PEventSet(&DataRxEvent, TEST_EVENT, CYU3P_EVENT_OR);  ///before the SPI transfers

        .......

And check for the event in the for{}

status = CyU3PEventGet (&DataRxEvent,

                    (CY_FX_GPIOAPP_GPIO_HIGH_EVENT | CY_FX_GPIOAPP_GPIO_LOW_EVENT| CY_FX_GPIOAPP_GPIO_HIGH_EVENT_1 | TEST_EVENT), CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

if (status == CY_U3P_SUCCESS)

            {

              if(eventFlag & TEST_EVENT)

                {

                      DEBUG_LOG(DBG1, 0xFF, 0);

                }

            }

Please let me know how to fix "CY_U3P_ERROR_MUTEX_FAILURE"  error.

>> As mentioned earlier in this post, the CY_U3P_ERROR_MUTEX_FAILURE error is returned by  CyU3PMutexGet API while it is called inside CyU3PSpiSetConfig. You can try calling CyU3PSpiDeInit in the GPIO callback and then later by setting event the SPI block can be initialized  CyU3PSpiInit as well as configured using CyU3PSpiSetConfig API.

I have attached the modified gpioapp firmware which checks the initialization of SPI block as well as communication using multiple events.

terterm.PNG

Please let me know the results of the above-mentioned tests

Regards,

Rashi

Regards,
Rashi
0 Likes