ASF4 i2c async slave how to get bus status

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I am developing an I2C Bootloader, and I am using Microchip/Atmel Studio. I want to use the i2c slave async driver, so the whole callback implementation is ready to use.

The Hardware I am using is a SAMD21G18A MCU on an Arduino MKR ZERO Board.

 

My question is:

Is there a flag or some simple way to check if the slave device is receiving messages? I want to know if the Master/Primary is done sending data to the Slave/Secondary.

 

There is the Function "i2c_s_async_get_status" but after some reading my guess is, that this returns the device status and not the state of the Bus.

 

 

I hope that this minimal code segment can help in understanding my problem.

#include <atmel_start.h>
#include "driver_examples.h"
/*Global Var*/
static struct io_descriptor *io;

/*Functions*/

static void i2c_startmsg(const struct i2c_s_async_descriptor *const descr){
	uint8_t c;
	io_read(io, &c, 1);
}

void i2c_setup(void){
	i2c_s_async_get_io_descriptor(&I2C_0, &io);
	i2c_s_async_register_callback(&I2C_0, I2C_S_RX_COMPLETE, i2c_startmsg);
	i2c_s_async_enable(&I2C_0);
}

int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
	i2c_setup();
	while (1) {
		gpio_toggle_pin_level(LED_BUILTIN);
		delay_ms(1000);
		if( HERE SOME CONDITION TO CHECK BUS STATUS ){

		}
	}
}

I am a new player in programming the big boy MCUs, so please be kind and imply that there can be fundamental flaws in my approach.

 

Thank you in advance.

Last Edited: Thu. Feb 18, 2021 - 11:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

only from registers    in your callback

 

/* Master on bus interrupt checking */
    if (SERCOM2->I2CM.INTFLAG.bit.MB)
    {
        if (i == BUF_SIZE)
        { /* After transferring the last byte stop condition will be sent */
            SERCOM2->I2CM.CTRLB.bit.CMD = 0x3;
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
            txi2_done = true;
            i = 0;
        }
        else
        { /* placing the data from transmitting buffer to DATA register*/
            SERCOM2->I2CM.DATA.reg = tx_buf[i++];
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
        }
    }
    /* Slave on bus interrupt checking */
    if (SERCOM2->I2CM.INTFLAG.bit.SB)
    {
        if (i == (BUF_SIZE-1))
        { /* NACK should be sent before reading the last byte */
            SERCOM2->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
            SERCOM2->I2CM.CTRLB.bit.CMD = 0x3;
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
            rx_buf[i++] = SERCOM2->I2CM.DATA.reg;
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
            rxi2_done = true;
        }
        else
        {
            SERCOM2->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
            rx_buf[i++] = SERCOM2->I2CM.DATA.reg;
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
            /* sending ACK after reading each byte */
            SERCOM2->I2CM.CTRLB.bit.CMD = 0x2;
            while(SERCOM2->I2CM.SYNCBUSY.bit.SYSOP);
        }
    }

 

 

static void _sercom_i2c_s_irq_handler(struct _i2c_s_async_device *device)
{
	void *  hw  = device->hw;
	uint32_t flags = hri_sercomi2cs_read_INTFLAG_reg(hw);

	if (flags & SERCOM_I2CS_INTFLAG_DRDY) {
		if (!hri_sercomi2cs_get_STATUS_DIR_bit(hw)) {
			ASSERT(device->cb.rx_done);
			device->cb.rx_done(device, hri_sercomi2cs_read_DATA_reg(hw));
		} else {
			ASSERT(device->cb.tx);
			device->cb.tx(device);
		}
		hri_sercomi2cs_clear_INTFLAG_DRDY_bit(hw);
	}
	// clear AMATCH interrupt flag
	else if (flags & SERCOM_I2CS_INTFLAG_AMATCH) {
		hri_sercomi2cs_clear_INTFLAG_AMATCH_bit(hw);
	}

	// clear OREC interrupt flag
	else if (flags & SERCOM_I2CS_INTFLAG_PREC) {
		hri_sercomi2cs_clear_INTFLAG_PREC_bit(hw);
	}
}

 

Last Edited: Thu. Jun 10, 2021 - 02:23 PM