Hello,
I am new to the max32660 so please forgive me if I am missing something silly.
I am trying to develop and application where both I2C interfaces of the max32660 will be used: one as cotroller (I2C0), one as client (I2C1).
To begin with, I started by modifying the I2C example program, removing everything linked to the controller (see code below). I am then using an external mcu to as i2c controller to write 4 bytes to the max32660.
The problem I am facing is that on the first communication, the max32660 acknowledges the first byte and then holds the clock low, missing the remaining 7 bytes. After this first "failed" attempt, the communication happens without problems (see image below). The clock being held low happens even if I disable the clock stretching functionality (as in the code below). I have also tried checking the program flow by debugging, but I don't see differences between the first run and successive ones.
My setup is the following:
- Eclipse Version: 2022-12 (4.26.0)
- Maxim Micros SDK 1.0.1 (Windows)
- Max32660 Evsys Rev. B
- 10k pullup resistors to 3.3V on SDA and SCL (P0.3 and P0.2)
I am really lost at this point. Any help would be greatly appreciated.
/** * @file main.c * @brief I2C Master-Slave Transaction Demo * @details This example uses the I2C Master to read/write from/to the I2C Slave. * For this example, user must connect I2C Master SCL pin to I2C Slave SCL * pin and I2C Master SDA pin to I2C Slave SDA pin. User must also connect * the pull-up jumpers to the proper I/O voltage. Refer UART messages for * more information. * @note Other devices on the EvKit might be using the same I2C bus. While * combining this example with other examples, make sure I2C pins are not * being used in other examples of any other function (like GPIO). */ /***** Includes *****/ #include <stdio.h> #include <stdint.h> #include <string.h> #include "mxc_device.h" #include "mxc_delay.h" #include "mxc_errors.h" #include "nvic_table.h" #include "i2c.h" #include "dma.h" /***** Definitions *****/ //#define MASTERDMA //Comment this line out if standard I2C transaction is required #define I2C_SLAVE MXC_I2C1 #define I2C_FREQ 100000 #define I2C_SLAVE_ADDR (0x51) #define I2C_BYTES 8 /***** Globals *****/ static uint8_t Stxdata[I2C_BYTES]; static uint8_t Srxdata[I2C_BYTES]; volatile int I2C_FLAG = 0; volatile int txnum = 0; volatile int txcnt = 0; volatile int rxnum = 0; /***** Functions *****/ //Slave interrupt handler void I2C1_IRQHandler(void) { MXC_I2C_AsyncHandler(I2C_SLAVE); } //I2C callback function void I2C_Callback(mxc_i2c_req_t *req, int error) { I2C_FLAG = error; } int slaveHandler(mxc_i2c_regs_t *i2c, mxc_i2c_slave_event_t event, void *data) { switch (event) { case MXC_I2C_EVT_MASTER_WR: // If we're being written to // Clear bytes written rxnum = 0; break; case MXC_I2C_EVT_MASTER_RD: txnum = I2C_BYTES; txcnt = 0; i2c->intfl0 = MXC_F_I2C_INTFL0_TXLOI | MXC_F_I2C_INTFL0_AMI; break; case MXC_I2C_EVT_RX_THRESH: case MXC_I2C_EVT_OVERFLOW: rxnum += MXC_I2C_ReadRXFIFO(i2c, &Srxdata[rxnum], MXC_I2C_GetRXFIFOAvailable(i2c)); if (rxnum == I2C_BYTES) { i2c->inten0 |= MXC_F_I2C_INTEN0_AMIE; } break; case MXC_I2C_EVT_TX_THRESH: case MXC_I2C_EVT_UNDERFLOW: // Write as much data as possible into TX FIFO // Unless we're at the end of the transaction (only write what's needed) if (txcnt >= txnum) { break; } int num = MXC_I2C_GetTXFIFOAvailable(i2c); num = (num > (txnum - txcnt)) ? (txnum - txcnt) : num; txcnt += MXC_I2C_WriteTXFIFO(i2c, &Stxdata[txcnt], num); break; default: if (*((int *)data) == E_COMM_ERR) { printf("I2C Slave Error!\n"); printf("i2c->intfl0 = 0x%08x\n", i2c->intfl0); printf("i2c->status = 0x%08x\n", i2c->status); I2C_Callback(NULL, E_COMM_ERR); return 1; } else if (*((int *)data) == E_NO_ERROR) { rxnum += MXC_I2C_ReadRXFIFO(i2c, &Srxdata[rxnum], MXC_I2C_GetRXFIFOAvailable(i2c)); I2C_Callback(NULL, E_NO_ERROR); return 1; } } return 0; } // ***************************************************************************** int main() { int error; //Setup the I2CS error = MXC_I2C_Init(I2C_SLAVE, 0, I2C_SLAVE_ADDR); if (error != E_NO_ERROR) { return error; } error=MXC_I2C_SetClockStretching(I2C_SLAVE, 0); if (error != E_NO_ERROR) { return error; } MXC_NVIC_SetVector(I2C1_IRQn, I2C1_IRQHandler); NVIC_EnableIRQ(I2C1_IRQn); __enable_irq(); MXC_I2C_SetFrequency(I2C_SLAVE, I2C_FREQ); I2C_FLAG = 1; //Setup slave async. The function internally sets RXThreshold = 1 if ((error = MXC_I2C_SlaveTransactionAsync(I2C_SLAVE, slaveHandler)) != 0) { return error; } if (error != E_NO_ERROR) { return error; } while(1){ // Resetting slave async if previous communication ended ok if(I2C_FLAG != 1){ if(I2C_FLAG != E_NO_ERROR){ break; } I2C_FLAG=1; if ((error = MXC_I2C_SlaveTransactionAsync(I2C_SLAVE, slaveHandler)) != 0) { break; } } } MXC_I2C_Shutdown(I2C_SLAVE); return E_NO_ERROR; }