• AVR Freaks

AnsweredHot!I2C Harmony receive buffer issue

Author
vibhu
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2019/02/25 05:37:34
  • Location: 0
  • Status: offline
2019/04/23 00:50:40 (permalink)
0

I2C Harmony receive buffer issue

Hi Guys,

I am using PIC32mz1024EFE100 custom board.

I am trying to use I2C1 to write and read from EEPROM.

I have already written data(0x99) into the EEPROM with slave address A0 and register address 0x1122.

When I am trying to read back the value there is no data on the receive buffer. The receive buffer is zero always.

I am attaching the code here.



/*******************************************************************************
MPLAB Harmony Application Source File

Company:
Microchip Technology Inc.

File Name:
app.c

Summary:
This file contains the source code for the MPLAB Harmony application.

Description:
This file contains the source code for the MPLAB Harmony application. It
implements the logic of the application's state machine and it may call
API routines of other MPLAB Harmony modules in the system, such as drivers,
system services, and middleware. However, it does not call any of the
system interfaces (such as the "Initialize" and "Tasks" functions) of any of
the modules in the system or make any assumptions about when those functions
are called. That is the responsibility of the configuration-specific system
files.
*******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc. All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
// DOM-IGNORE-END

/*******************************************************************************
Application Information and Set-up

* This demo illustrates the an I2C module that acts as a Master talking to
* to an external slave device.
* The external slave device used is a Real Time Clock Calendar (RTCC) chip.
* The data from the Master is written into an SRAM location in the RTCC chip.
*
* The I2C Master writes and reads data from I2C Slave and RTCC chip. The RTCC
* chip sends back the data that was written to it by the I2C Master. The data
* written by the I2C Master is stored in the SRAM of RTCC.
*
* This demo uses uses a Buffer model of I2C transfer. The APIs are matched to
* the buffer static implementation of I2C driver. The operation to write, read
* and read-after-write is demonstrated. The read-after-write allows
* random access of a register in a slave device, in this case RTCC.
*
* Refer to Applications Help > Driver Demonstrations > I2C Driver Demonstrations
> Demonstrations > i2c_rtcc_loopback
* for more information on this demo
*******************************************************************************/


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "app.h"

static uint32_t ReadCoreTimer(void);

static uint32_t ReadCoreTimer()
{
volatile uint32_t timer;

// get the count reg
asm volatile("mfc0 %0, $9" : "=r"(timer));

return(timer);
}


#define GetSystemClock() (SYS_CLK_FREQ)
#define us_SCALE (GetSystemClock()/2000000)
#define ms_SCALE (GetSystemClock()/2000)

/* Address of slave devices */
unsigned char ControlByte = 0b10100000; // Write mode, A2, A1, P0 = 0
unsigned char ControlByte1 = 0b10100001; // Write mode, A2, A1, P0 = 0

// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

Summary:
Holds application data

Description:
This structure holds the application's data.

Remarks:
This structure should be initialized by the APP_Initialize function.

Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;

// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

uint8_t operationStatus;

uint8_t numOfRXBytes = 1;

uint8_t numOfTXBytes = 3;

uint8_t indexRegByteSize = 2;

unsigned char Tx_Buffer[3]={0x11,0x22,0x44};

/* I2C driver RX Buffer */
unsigned char RXbuffer[1];

DRV_I2C_BUFFER_EVENT appBufferEvent[MAX_NUMBER_OF_BUFFERS];

uint32_t appNumberOfBytesTransferred[MAX_NUMBER_OF_BUFFERS];


// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* callback to Master indicating a change in Buffer Status of transmit
OR receive buffer */

void I2C_MasterBufferStatusCallback ( DRV_I2C_BUFFER_EVENT event,
DRV_I2C_BUFFER_HANDLE bufferHandle,
uintptr_t context);

/* callback to slave after a read or write */

void I2C_SlaveCbAfterByteReadorWrite ( DRV_I2C_BUFFER_EVENT event,
DRV_I2C_BUFFER_HANDLE bufferHandle,
uintptr_t context);



// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************

DRV_I2C_BUFFER_EVENT APP_Check_Transfer_Status(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle);

uint32_t APP_Number_Of_Bytes_Transferred(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle);

void DelayMs(unsigned long int msDelay );

void DelayMs(unsigned long int msDelay );

// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/* State Machine for Master Write */
bool APP_Write_Tasks(void);

/* State Machine for Master Read */
bool APP_Read_Tasks(void);


typedef enum{

TxRx_OPEN = 0,
TxRx_TO_EXTERNAL_SLAVE_1,
TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1,
TxRx_TO_EXTERNAL_SLAVE_2,
TxRx_EXTERNAL_SLAVE_STATUS_CHECK_2,
TxRx_STATUS_CHECK,
TxRx_COMPLETED

}APP_EEPROM_WR_STATES;

static APP_EEPROM_WR_STATES appWriteState = TxRx_OPEN;

/*******************************************************************************
Function:
void APP_Initialize ( void )

Remarks:
See prototype in app.h.
*/

void APP_Initialize ( void )
{
/* Place the App state machine in its initial state. */
appData.state = APP_STATE_INIT;

/* TODO: Initialize your application's state machine and other
* parameters.
*/
}


/******************************************************************************
Function:
void APP_Tasks ( void )

Remarks:
See prototype in app.h.
*/

void APP_Tasks ( void )
{
/* Check the application's current state. */
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
{
appData.state = APP_WRITE_DATA;

break;
}
case APP_WRITE_DATA:
{

/* completes write task to the slave */
if(APP_Write_Tasks())
{

appData.state = APP_STATE_IDLE;
}
break;
}
case APP_STATE_IDLE:
{
Nop();
break;
}
default:
{
/* TODO: Handle error in application's state machine. */
break;
}
}
}

DRV_I2C_BUFFER_EVENT Transaction;
unsigned int ErrorDetection = 0;

bool APP_Write_Tasks(void)
{
switch (appWriteState)
{
case TxRx_OPEN:
{
/* Open the I2C Driver for Master */
appData.drvI2CHandle_Master = DRV_I2C_Open( DRV_I2C_INDEX_0,
DRV_IO_INTENT_READWRITE );

if(appData.drvI2CHandle_Master != DRV_HANDLE_INVALID)
{
ErrorDetection = 0;
appWriteState = TxRx_TO_EXTERNAL_SLAVE_1;
}
else
{
appData.state = APP_STATE_ERROR;
}

break;
}
case TxRx_TO_EXTERNAL_SLAVE_1:
{
if ( (appData.appI2CWriteBufferHandle[0] == DRV_I2C_BUFFER_HANDLE_INVALID) ||
(APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_COMPLETE) ||
(APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_ERROR) )
{
appData.appI2CWriteBufferHandle[0] = DRV_I2C_Transmit (appData.drvI2CHandle_Master,
ControlByte,
Tx_Buffer ,2, NULL);
SYS_PRINT("TX_buffer %x \n",Tx_Buffer[0]);
SYS_PRINT("TX_buffer %x \n",Tx_Buffer[1]);

DelayMs(1000);
}

appWriteState = TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1;

break;
}
case TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1:
{
Transaction = APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]);
if ( Transaction == DRV_I2C_BUFFER_EVENT_COMPLETE)
{
appWriteState =TxRx_TO_EXTERNAL_SLAVE_2;
}
else if (Transaction == DRV_I2C_BUFFER_EVENT_ERROR)
{
ErrorDetection = 1;
appWriteState =TxRx_TO_EXTERNAL_SLAVE_2;
}

break;
}
case TxRx_TO_EXTERNAL_SLAVE_2:
{
if ( (appData.appI2CWriteBufferHandle[0] == DRV_I2C_BUFFER_HANDLE_INVALID) ||
(APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_COMPLETE) ||
(APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_ERROR) )
{
appData.appI2CWriteBufferHandle[0] = DRV_I2C_Receive (appData.drvI2CHandle_Master,
ControlByte1,
RXbuffer ,1, NULL);
SYS_PRINT("RX_buffer %x \n",RXbuffer[0]);

DelayMs(1000);
}

appWriteState = TxRx_EXTERNAL_SLAVE_STATUS_CHECK_2;

break;
}
case TxRx_EXTERNAL_SLAVE_STATUS_CHECK_2:
{
Transaction = APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]);
if ( Transaction == DRV_I2C_BUFFER_EVENT_COMPLETE)
{
appWriteState =TxRx_STATUS_CHECK;
}
else if (Transaction == DRV_I2C_BUFFER_EVENT_ERROR)
{
ErrorDetection = 1;
appWriteState =TxRx_STATUS_CHECK;
}

break;
}
case TxRx_STATUS_CHECK:
{

// Only defined for dynamic driver.
#ifdef DRV_I2C_CLIENTS_NUMBER
extern const DRV_I2C_INIT drvI2C0InitData;
DRV_I2C_Close( appData.drvI2CHandle_Master );
DRV_I2C_Deinitialize (sysObj.drvI2C0);
#endif

DelayMs(800);
#ifdef DRV_I2C_CLIENTS_NUMBER
sysObj.drvI2C0 = DRV_I2C_Initialize(DRV_I2C_INDEX_0, (SYS_MODULE_INIT *)&drvI2C0InitData);
#endif

/* to run the application only once,
* set next state to TxRx_COMPLETED */
appWriteState = TxRx_COMPLETED;
break;
}
case TxRx_COMPLETED:
{
return true;
break;
}
}

return false;
}

//****************************************************************************/
// Function: APP_Check_Transfer_Status
//
// Returns the status of Buffer operation from the driver; The application
// can probe this function to see if the status of a particular I2C
// transfer is in its execution
//****************************************************************************/
DRV_I2C_BUFFER_EVENT APP_Check_Transfer_Status(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle)
{
return (DRV_I2C_TransferStatusGet (appData.drvI2CHandle_Master, drvBufferHandle));
}

//****************************************************************************/
// Function: APP_Check_Transfer_Status
//
// Returns the number of bytes that was transferred in a particular I2C
// transaction. The application can identify the transfer using the
// appropriate driver handle
//****************************************************************************/

uint32_t APP_Number_Of_Bytes_Transferred(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle)
{
return (DRV_I2C_BytesTransferred (appData.drvI2CHandle_Master,drvBufferHandle));
}

/***********************************************************
* Millisecond Delay function using the Count register
* in coprocessor 0 in the MIPS core.
* When running 200 MHz, CoreTimer frequency is 100 MHz
* CoreTimer increments every 2 SYS_CLK, CoreTimer period = 10ns
* 1 ms = N x CoreTimer_period;
* To count 1ms, N = 100000 counts of CoreTimer
* 1 ms = 10 ns * 100000 = 10e6 ns = 1 ms
* When running 80 MHz, CoreTimer frequency is 40 MHz
* CoreTimer increments every 2 SYS_CLK, CoreTimer period = 25ns
* To count 1ms, N = 40000 counts of CoreTimer
* 1ms = 25 ns * 40000 = 10e6 ns = 1 ms
* ms_SCALE = (GetSystemClock()/2000) @ 200 MHz = 200e6/2e3 = 100e3 = 100000
* ms_SCLAE = (GetSystemClock()/2000) @ = 80e6/2e3 = 40e3 = 40000
*/

void DelayMs(unsigned long int msDelay )
{
register unsigned int startCntms = ReadCoreTimer();
register unsigned int waitCntms = msDelay * ms_SCALE;

while( ReadCoreTimer() - startCntms < waitCntms );
}

/***********************************************************
* Microsecond Delay function using the Count register
* in coprocessor 0 in the MIPS core.
* When running 200 MHz, CoreTimer frequency is 100 MHz
* CoreTimer increments every 2 SYS_CLK, CoreTimer period = 10ns
* 1 us = N x CoreTimer_period;
* To count 1us, N = 100 counts of CoreTimer
* 1 us = 10 ns * 100 = 1000 ns = 1us
* When running 80 MHz, CoreTimer frequency is 40 MHz
* CoreTimer increments every 2 SYS_CLK, CoreTimer period = 25ns
* To count 1us, N = 40 counts of CoreTimer
* 1us = 25 ns * 40 = 1000 ns = 1 us
* us_SCALE = (GetSystemClock()/2000) @ 200 MHz = 200e6/2e6 = 100
* us_SCLAE = (GetSystemClock()/2000) @ 80 MHz = 80e6/2e6 = 40
*/

void DelayUs(unsigned long int usDelay )
{
register unsigned int startCnt = ReadCoreTimer();
register unsigned int waitCnt = usDelay * us_SCALE;

while( ReadCoreTimer() - startCnt < waitCnt );
}

/*******************************************************************************
End of File
*/



In the code



appData.appI2CWriteBufferHandle[0] = DRV_I2C_Receive (appData.drvI2CHandle_Master,
ControlByte1,
RXbuffer ,1, NULL);
SYS_PRINT("RX_buffer %x \n",RXbuffer[0]);



The RXbuffer is always zero.

So I included print statements in the I2CxRCV register itself and there I am getting the correct values.



PLIB_TEMPLATE uint8_t I2C_ReceivedByteGet_Default( I2C_MODULE_ID index )
{
volatile i2c_register_t *regs = (i2c_register_t *)index;
SYS_PRINT("regs->I2CxRCV %x \n",regs->I2CxRCV);

return (uint8_t)regs->I2CxRCV;
}



Can anyone help me on where I could have possibly gone wrong ?

I am also getting correct waveform in CRO.

Attached Image(s)

#1
NKurzman
A Guy on the Net
  • Total Posts : 17248
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: offline
Re: I2C Harmony receive buffer issue 2019/04/23 06:48:23 (permalink)
0
Are you waiting for the write to complete?
Do you get back 0xFF if you read a location you did not write too?
#2
vibhu
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2019/02/25 05:37:34
  • Location: 0
  • Status: offline
Re: I2C Harmony receive buffer issue 2019/04/23 21:36:17 (permalink)
0
NKurzman
Are you waiting for the write to complete?

I guess so because I am getting the value in the I2CxRCV register.
If the write is not complete then I wont get that I suppose.
 
NKurzman
Do you get back 0xFF if you read a location you did not write too?

I did not try reading the location that I did not write to.
I will try that.
#3
GDA
Junior Member
  • Total Posts : 74
  • Reward points : 0
  • Joined: 2015/08/31 16:46:40
  • Location: 0
  • Status: offline
Re: I2C Harmony receive buffer issue 2019/04/24 10:50:28 (permalink) ☼ Best Answerby vibhu 2019/04/24 21:26:50
5 (2)
This code:
appData.appI2CWriteBufferHandle[0] = DRV_I2C_Receive (appData.drvI2CHandle_Master,
ControlByte1,
RXbuffer ,1, NULL);
SYS_PRINT("RX_buffer %x \n",RXbuffer[0]);

Tells the I2C driver to begin receiving data (placing it in RXbuffer).
The SYS_PRINT them immediately prints out the buffer.
No time has occured to allow the I2C to communicate with the EEPROM.
Try moving your print inside this if statement:
case TxRx_EXTERNAL_SLAVE_STATUS_CHECK_2:
{
Transaction = APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]);
if ( Transaction == DRV_I2C_BUFFER_EVENT_COMPLETE)
{
- Add print out here.
appWriteState =TxRx_STATUS_CHECK;
}
#4
vibhu
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2019/02/25 05:37:34
  • Location: 0
  • Status: offline
Re: I2C Harmony receive buffer issue 2019/04/24 21:26:42 (permalink)
0
gary.attarian
This code:
appData.appI2CWriteBufferHandle[0] = DRV_I2C_Receive (appData.drvI2CHandle_Master,
ControlByte1,
RXbuffer ,1, NULL);
SYS_PRINT("RX_buffer %x \n",RXbuffer[0]);

Tells the I2C driver to begin receiving data (placing it in RXbuffer).
The SYS_PRINT them immediately prints out the buffer.
No time has occured to allow the I2C to communicate with the EEPROM.
Try moving your print inside this if statement:
case TxRx_EXTERNAL_SLAVE_STATUS_CHECK_2:
{
Transaction = APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]);
if ( Transaction == DRV_I2C_BUFFER_EVENT_COMPLETE)
{
- Add print out here.
appWriteState =TxRx_STATUS_CHECK;
}




Thank You so much It worked !!
#5
Jump to:
© 2019 APG vNext Commercial Version 4.5