Lpspi_Ip_SyncTransmitHalfDuplex TIMEOUT issue

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Lpspi_Ip_SyncTransmitHalfDuplex TIMEOUT issue

834 次查看
MehmetFatih
Contributor I

* Project : RTD AUTOSAR 4.7
* Platform : CORTEXM
* Peripheral : LPSPI
* Dependencies :
*
* Autosar Version : 4.7.0
* Autosar Revision : ASR_REL_4_7_REV_0000
* Autosar Conf.Variant :
* SW Version : 3.0.0
* Build Version : S32K3_RTD_3_0_0_D2303_ASR_REL_4_7_REV_0000_20230331


I am using the Lpspi_Ip_SyncTransmitHalfDuplex function with the TIMEOUT parameter and TransferType = LPSPI_IP_HALF_DUPLEX_RECEIVE. However, I believe there is an issue in this function.

Inside the while loop, the line ElapsedTicks = 0u; is executed in each iteration until ExpectedFifoReads == State->RxIndex.

For the TIMEOUT condition, the following code is used:

ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, LPSPI_IP_TIMEOUT_METHOD);
if (ElapsedTicks >= TimeoutTicks)
{
Status = LPSPI_IP_TIMEOUT;
}

Here, the OsIf_GetElapsed function uses CurrentTicks, which is set before the loop as shown below:

CurrentTicks = OsIf_GetCounter(LPSPI_IP_TIMEOUT_METHOD);

If CurrentTicks were truly initialized before the loop and OsIf_GetElapsed measured the time elapsed since that point, everything would work as expected.

However, the OsIf_GetElapsed function internally calls OsIf_Timer_System_GetElapsed, which then calls OsIf_Timer_System_Internal_GetElapsed. In this last function, I believe something unintended happens:

uint32 OsIf_Timer_System_Internal_GetElapsed(uint32 * const CurrentRef)
{
...
*CurrentRef = CurrentVal;
...
}

Here, CurrentRef is updated. As a result, instead of measuring the time elapsed since the beginning of the loop, the function measures the time elapsed since the last OsIf_GetElapsed call. This causes the SPI transfer to fail to timeout as expected, and it ends up stuck.

When the line ElapsedTicks = 0u; inside the while loop is removed, the function behaves as expected.

Could you clarify if this is a known issue or if there’s an intended use case I might be missing?

 

标记 (1)
0 项奖励
回复
3 回复数

526 次查看
Flagello
Contributor I

We are using "The S32 Real-Time Drivers Version 4.0.0 is AUTOSAR 4.4.0 compliant. " on S32K314 target.

I have faced a similar issue. But im my case using FreeRTOS and during an operation:

Gmac_Ip_MDIORead()

There were unexpected timeouts executing many operartions.
I have investigated the OsIf_Timer_System_Internal_GetElapsed() and I think I could individuate the root cause:
The default configuration is done in 
source\RTD\src\OsIf_Timer_System_Internal_Systick.c/OsIf_Timer_System_Internal_Init()

S32_SysTick->RVR = S32_SysTick_RVR_RELOAD(SYSTICK_MAX);


The SysTick is configured differently if the FreeRTOS is configured:
In port.c/vPortSetupTimerInterrupt()

portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;


But in the OsIf_Timer_System_Internal_GetElapsed() always the 
SYSTICK_MAX used when the counter was overflowed:

if (SYSTICK_OVERFLOWED((CurrentVal), (*CurrentRef)))
{
/* overflow occurred */
dif = SYSTICK_DELTA_OUTER(CurrentVal, *CurrentRef, SYSTICK_MAX);

The below alternative solution for me has resolved the problem:

/*---------------------------------------------------------------------
    Function:   OsIf_Timer_System_Internal_GetElapsed
    Purpose:    The original implementation was fixed using the LOAD_VALUE instead of SYSTICK_MAX
    Arguments:  uint32 * const CurrentRef   The tick counter of the last interrogation
                                            The value is updated
    Return:     The number of elapsed ticks since last *CurrentRef
---------------------------------------------------------------------*/
uint32 OsIf_Timer_System_Internal_GetElapsed(uint32 * const CurrentRef)
{
    uint32 CurrentVal = SYSTICK_GET_COUNTER();
    uint32 dif = 0U;

    if (SYSTICK_OVERFLOWED((CurrentVal), (*CurrentRef)))
    {
        /* overflow occurred */
        dif = SYSTICK_DELTA_OUTER(CurrentVal, *CurrentRef, SYSTICK_GET_LOAD_VALUE());
    }
    else
    {
        /* overflow did not occur */
        dif = SYSTICK_DELTA_INNER(*CurrentRef, CurrentVal);
    }
    *CurrentRef = CurrentVal;
    return dif;
}

 

0 项奖励
回复

524 次查看
Flagello
Contributor I

We are using "The S32 Real-Time Drivers Version 4.0.0 is AUTOSAR 4.4.0 compliant. " on S32K314 target.

I have faced a similar issue. But im my case using FreeRTOS and during an operation:

Gmac_Ip_MDIORead()
There were unexpected timeouts executing many operations.
I have investogated the OsIf_Timer_System_Internal_GetElapsed() and I think I could individuate the root cause:
The default configuration is done in 
source\RTD\src\OsIf_Timer_System_Internal_Systick.c/OsIf_Timer_System_Internal_Init()

 

    S32_SysTick->RVR = S32_SysTick_RVR_RELOAD(SYSTICK_MAX);

 

The SysTick is configured differently if the FreeRTOS is configured:
In port.c/vPortSetupTimerInterrupt()

 

portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;

 

But in the OsIf_Timer_System_Internal_GetElapsed() always the 
SYSTICK_MAX used when the counter was overflowed:

 

    if (SYSTICK_OVERFLOWED((CurrentVal), (*CurrentRef)))
    {
        /* overflow occurred */
        dif = SYSTICK_DELTA_OUTER(CurrentVal, *CurrentRef, SYSTICK_MAX);

 

The below alternative solution for me has resolved the issue:

 

uint32 OsIf_Timer_System_Internal_GetElapsed(uint32 * const CurrentRef)
{
    uint32 CurrentVal = SYSTICK_GET_COUNTER();
    uint32 dif = 0U;

    if (SYSTICK_OVERFLOWED((CurrentVal), (*CurrentRef)))
    {
        /* overflow occurred */
        dif = SYSTICK_DELTA_OUTER(CurrentVal, *CurrentRef, SYSTICK_GET_LOAD_VALUE());
    }
    else
    {
        /* overflow did not occur */
        dif = SYSTICK_DELTA_INNER(*CurrentRef, CurrentVal);
    }
    *CurrentRef = CurrentVal;

    return dif;
}

 

0 项奖励
回复

785 次查看
IsaulO
NXP Employee
NXP Employee

Hi @MehmetFatih ,

The value ElapsedTicks is reset in each iteration to isolate and measure the duration of data transmission or reception. By updating this value within the loop we ensure that only the time spent on receiving or transmitting the information is measured. This allows for accurate comparison with the proposed Timeout value, ensuring the system behaves as expected and can handle timeouts appropriately.

Please let us know if our understanding of your question is incorrect.

Have a nice day!

IsaulO.

0 项奖励
回复