ATSAMR34-XPRO - I2C Callback

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

I have created a new ASF project for my ATSAMR34-XPRO and added SERCOM I2C - Master Mode I2C driver callback. The ASF created the skeleton code simply sets the LED to the state of the button. While creating the I2C code I was inspired by the I2C_UNIT_TEST2 code.
.

My goal is to set the GPS (u-blox ZOE-M8Q) internal register (pointer) to 0xFD and than read two bytes (0xFD, 0x FE) which represents how many bytes of data (GPS reply to command) are waiting. If no data are ready the return value is 0 in Big Endian.
.

That's why I set I2C_MASTER_CALLBACK_WRITE_COMPLETE function which should be run after the first write to GPS i.e. w: 0x84 ACK 0xFD ACK but the callback function is not called after WRITE. Any advice what I am doing wrong? LED is working well wink.
.

main.c

/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/**
 * \mainpage User Application template doxygen documentation
 *
 * \par Empty user application template
 *
 * This is a bare minimum user application template.
 *
 * For documentation of the board, go \ref group_common_boards "here" for a link
 * to the board-specific documentation.
 *
 * \par Content
 *
 * -# Include the ASF header files (through asf.h)
 * -# Minimal main function that starts with a call to system_init()
 * -# Basic usage of on-board LED and button
 * -# "Insert application code here" comment
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
 */
#include <asf.h>

void i2c_write_complete_callback(struct i2c_master_module *const module);
void configure_i2c_callbacks(void);

/* master packet_data */
static struct i2c_master_packet master_packet;

static struct i2c_master_module i2c_master_instance;

#define SLAVE_ADDRESS 0x42

// UBX-NAV-POSLLH command for u-blox ZOE-M8Q GPS to get LAT, LON
static uint8_t master_write_buffer[8] = {
	0xB5, 0x62, 0x01, 0x02, 0x00, 0x00, 0x03, 0x0A,
};
static uint8_t master_write_register[1] = {0xfd};
static uint8_t master_read_buffer[36] = {0};
static uint8_t master_read_len[2] = {0};

/* master sercom pinmux setting */
#define CONF_I2C_MASTER_MODULE    SERCOM5
#define CONF_MASTER_SDA_PINMUX    PINMUX_PB02D_SERCOM5_PAD0
#define CONF_MASTER_SCK_PINMUX    PINMUX_PA23D_SERCOM5_PAD1

enum status_code OK;

static void run_i2c_init(void){
	enum status_code status;
	struct i2c_master_config config_i2c_master;
	i2c_master_get_config_defaults(&config_i2c_master);
	config_i2c_master.buffer_timeout = 10000;
	config_i2c_master.pinmux_pad0    = CONF_MASTER_SDA_PINMUX;
	config_i2c_master.pinmux_pad1    = CONF_MASTER_SCK_PINMUX;
	status = i2c_master_init(&i2c_master_instance, CONF_I2C_MASTER_MODULE, &config_i2c_master);
	/* Check for successful initialization */
	i2c_master_enable(&i2c_master_instance);
}

static void run_i2c_master_transfer(void){
	uint32_t timeout_cycles = 1000;
	master_packet.address = SLAVE_ADDRESS;
	master_packet.data_length = 1;
	master_packet.data = master_write_register;	// Bylo master_write_buffer
	master_packet.ten_bit_address = false;
	master_packet.high_speed = false;
	master_packet.hs_master_code = 0x0;
	timeout_cycles = 1000;
	do {

		timeout_cycles--;
		if (i2c_master_write_packet_wait_no_stop(&i2c_master_instance, &master_packet) ==
		STATUS_OK) {
			break;
		}
	} while (timeout_cycles > 0);
	i2c_master_send_stop(&i2c_master_instance);
}

// Callback function for write complete:
//void i2c_write_complete_callback(struct i2c_master_module *const module)
void i2c_write_complete_callback(struct i2c_master_module *const module)
{
	asm("nop");
	master_packet.data_length = 2;
	master_packet.data = master_read_len;
	/* Initiate new packet read */
	i2c_master_read_packet_job(&i2c_master_instance,&master_packet);
}

void configure_i2c_callbacks(void)
{
	/* Register callback function. */
	i2c_master_register_callback(&i2c_master_instance, i2c_write_complete_callback,
	I2C_MASTER_CALLBACK_WRITE_COMPLETE);
	i2c_master_enable_callback(&i2c_master_instance,
	I2C_MASTER_CALLBACK_WRITE_COMPLETE);
}

int main (void)
{
	system_init();

	run_i2c_init();
	configure_i2c_callbacks();
	run_i2c_master_transfer();
	asm("nop");

	/* Insert application code here, after the board has been initialized. */

	/* This skeleton code simply sets the LED to the state of the button. */
	while (1) {
		/* Is button pressed? */
		if (port_pin_get_input_level(BUTTON_0_PIN) == BUTTON_0_ACTIVE) {
			/* Yes, so turn LED on. */
			port_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
		} else {
			/* No, so turn LED off. */
			port_pin_set_output_level(LED_0_PIN, !LED_0_ACTIVE);
		}
	}
}

 

Last Edited: Sat. May 9, 2020 - 09:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
i2c_master_write_packet_job_no_stop

is the function to use if you need the callback.

API doc is here:

https://asf.microchip.com/docs/latest/saml21/html/group__asfdoc__sam0__sercom__i2c__group.html

 

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lars,

 

Thank you for your advice. I will modify my code, test it and let you know.