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;
}
