• AVR Freaks

AnsweredHow wait the read value after DRV_I2C_WriteReadTransferAdd() call?

Author
thoraz
Junior Member
  • Total Posts : 100
  • Reward points : 0
  • Joined: 2013/06/01 18:37:43
  • Location: 0
  • Status: offline
2020/06/25 02:47:27 (permalink)
0

How wait the read value after DRV_I2C_WriteReadTransferAdd() call?

I have a problem with the asynchronous I2C driver on my PIC32MZ. I want to use the DRV_I2C_WriteReadTransferAdd() function to read a register from my slave device and wait for the value. I've created a read function:
 
static bool i2cTransferComplete;

void ADAU1961_I2C_Transfer_Event_Handler( DRV_I2C_TRANSFER_EVENT event, DRV_I2C_TRANSFER_HANDLE transferHandle, uintptr_t context )
{
    switch( event )
    {
        case DRV_I2C_TRANSFER_EVENT_COMPLETE:
            
            i2cTransferComplete = true;
        
            break;
            
        case DRV_I2C_TRANSFER_EVENT_ERROR:
            
            break;
        
        default:
            
            break;
    }
}



SYSTEM_ERROR_TYPE ADAU1961_Read_Register( uint16_t registerAddr, uint8_t *registerValue )
{
    i2cTxBuff[ 0 ] = ( uint8_t )( ( registerAddr >> 8 ) & 0x00FF );
    i2cTxBuff[ 1 ] = ( uint8_t )( registerAddr & 0x00FF );
    i2cRxBuff[ 0 ] = 0;
    
    DRV_I2C_WriteReadTransferAdd( codecData.codecDrvI2CHandle, ADAU1961_I2C_ADDRESS, ( void * )i2cTxBuff, 2, ( void * )i2cRxBuff, 1, &codecData.codecDrvI2CTransferHandle );
    if( codecData.codecDrvI2CTransferHandle == DRV_I2C_TRANSFER_HANDLE_INVALID )
    {
        SYSTEM_DBG_PRINT( SYSTEM_DBG_LEVEL_ERROR, "\nERROR: ADAU1961 read DRV_I2C_WriteReadTransferAdd" );
        return SYSTEM_ERROR;
    }
    else
    {
        i2cTransferComplete = false;
    }
    
    while ( i2cTransferComplete == false )
    {

    }
    
    *registerValue = i2cRxBuff[ 0 ];
    
    return SYSTEM_NO_ERROR;
}

 
When I call my function, it blocks on while cycle because the i2cTransferComplete variable seems to never become true. If I put in the while cycle a random print on the PMP (I have a parallel serial/usb converter)
 
while ( i2cTransferComplete == false )
{
    SYSTEM_PRINT( "o" );
}

 
it works! The call is
 
if ( SYSTEM_ERROR == ADAU1961_Read_Register( ADAU1961_REG_R39_SERPP, &value ) )
    SYSTEM_PRINT( "\nERROR read ADAU1961_REG_R39_SERPP register" );
else
    SYSTEM_PRINT( "\nvalue: %X", value );

 
and in the terminal I have (the value 0xAA is what I'm waiting for)
 
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
value: AA

 
I don't understant this behaviour. I'm sure that the i2cTransferComplete variable is processed in the I2C transfer event handler cause I've tested it by toggling a led and also printing its value one time.
 
Can anyone explain me what is happening in the code?
#1
vgandhi
Senior Member
  • Total Posts : 36
  • Reward points : 0
  • Joined: 2016/10/24 21:28:35
  • Location: 0
  • Status: offline
Re: How wait the read value after DRV_I2C_WriteReadTransferAdd() call? 2020/06/25 04:13:54 (permalink) ☼ Best Answerby thoraz 2020/06/25 04:39:34
0
I believe the i2cTransferComplete variable is set to false after the callback is given out. You may want to first set the i2cTransferComplete variable to false and then call the I2C driver API. Also, consider defining the i2cTransferComplete flag with "volatile" qualifier, since it is updated from the interrupt/callback context.
 
i2cTransferComplete = false;

DRV_I2C_WriteReadTransferAdd( codecData.codecDrvI2CHandle, ADAU1961_I2C_ADDRESS, ( void * )i2cTxBuff, 2, ( void * )i2cRxBuff, 1, &codecData.codecDrvI2CTransferHandle );
    if( codecData.codecDrvI2CTransferHandle == DRV_I2C_TRANSFER_HANDLE_INVALID )
    {
        SYSTEM_DBG_PRINT( SYSTEM_DBG_LEVEL_ERROR, "\nERROR: ADAU1961 read DRV_I2C_WriteReadTransferAdd" );
        return SYSTEM_ERROR;
    }
    else
    {
        //i2cTransferComplete = false;
    }

#2
thoraz
Junior Member
  • Total Posts : 100
  • Reward points : 0
  • Joined: 2013/06/01 18:37:43
  • Location: 0
  • Status: offline
Re: How wait the read value after DRV_I2C_WriteReadTransferAdd() call? 2020/06/25 04:44:15 (permalink)
0
vgandhi
I believe the i2cTransferComplete variable is set to false after the callback is given out. You may want to first set the i2cTransferComplete variable to false and then call the I2C driver API. Also, consider defining the i2cTransferComplete flag with "volatile" qualifier, since it is updated from the interrupt/callback context.
 
i2cTransferComplete = false;

DRV_I2C_WriteReadTransferAdd( codecData.codecDrvI2CHandle, ADAU1961_I2C_ADDRESS, ( void * )i2cTxBuff, 2, ( void * )i2cRxBuff, 1, &codecData.codecDrvI2CTransferHandle );
    if( codecData.codecDrvI2CTransferHandle == DRV_I2C_TRANSFER_HANDLE_INVALID )
    {
        SYSTEM_DBG_PRINT( SYSTEM_DBG_LEVEL_ERROR, "\nERROR: ADAU1961 read DRV_I2C_WriteReadTransferAdd" );
        return SYSTEM_ERROR;
    }
    else
    {
        //i2cTransferComplete = false;
    }





Thanks! The problem was just the qualifier "volatile". My code now works. Thanks again.
#3
Jump to:
© 2020 APG vNext Commercial Version 4.5