Ejemplo n.º 1
0
/**
 * \brief Initialize TWIHS master mode.
 *
 * \param p_twihs Pointer to a TWIHS instance.
 * \param p_opt Options for initializing the TWIHS module (see \ref twihs_options_t).
 *
 * \return TWIHS_SUCCESS if initialization is complete, error code otherwise.
 */
uint32_t twihs_master_init(Twihs *p_twihs, const twihs_options_t *p_opt)
{
	uint32_t status = TWIHS_SUCCESS;

	/* Disable TWIHS interrupts */
	p_twihs->TWIHS_IDR = ~0UL;

	/* Dummy read in status register */
	p_twihs->TWIHS_SR;

	/* Reset TWIHS peripheral */
	twihs_reset(p_twihs);

	twihs_enable_master_mode(p_twihs);

	/* Select the speed */
	if (twihs_set_speed(p_twihs, p_opt->speed, p_opt->master_clk) == FAIL) {
		/* The desired speed setting is rejected */
		status = TWIHS_INVALID_ARGUMENT;
	}

	return status;
}
Ejemplo n.º 2
0
ATCA_STATUS hal_i2c_wake(ATCAIface iface)
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	int bus = cfg->atcai2c.bus;
	int retries = cfg->rx_retries, rxlength;
	uint32_t bdrt = cfg->atcai2c.baud;
	int status = !STATUS_OK;
	uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 };
	volatile Twihs * twihs_device;

	twihs_device = i2c_hal_data[bus]->twi_module;

	if ( bdrt != 100000 )  // if not already at 100KHz, change it

		if (twihs_set_speed(twihs_device, 100000, sysclk_get_cpu_hz() / CONFIG_SYSCLK_DIV) == FAIL)
			return ATCA_COMM_FAIL;

	twihs_packet_t packet = {
		.addr[0]        = 0,
		.addr[1]        = 0,
		.addr_length	= 0,                              //very important, since cryptoauthdevices do not require addressing;
		.chip			= cfg->atcai2c.slave_address >> 1,
		.buffer			=  &data[0],
		.length			= 1
	};

	twihs_master_write(twihs_device, &packet);

	atca_delay_us(cfg->wake_delay);   // wait tWHI + tWLO which is configured based on device type and configuration structure

	// look for wake response
	rxlength = 4;
	memset(data, 0x00, rxlength);
	status = hal_i2c_receive(iface, data, &rxlength );

	// if necessary, revert baud rate to what came in.
	if ( bdrt != 100000)
		if (twihs_set_speed(twihs_device, bdrt, sysclk_get_cpu_hz() / CONFIG_SYSCLK_DIV) == FAIL)
			return ATCA_COMM_FAIL;

	if ( status != STATUS_OK )
		return ATCA_COMM_FAIL;

	if ( memcmp( data, expected, 4 ) == 0 )
		return ATCA_SUCCESS;

	return ATCA_COMM_FAIL;
}


/** \brief idle CryptoAuth device using I2C bus
 * \param[in] iface  interface to logical device to idle
 */

ATCA_STATUS hal_i2c_idle(ATCAIface iface)
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	int bus = cfg->atcai2c.bus;
	uint8_t data[4];
	int length;
	uint32_t twihs_device;
	uint16_t status;

	data[0] = 0x02;  // idle word address value

	twihs_device = i2c_hal_data[bus]->twi_module;

	twihs_packet_t packet = {
		.addr[0]        = 0,
		.addr[1]        = 0,
		.addr_length	= 0,                              //very important, since cryptoauthdevices do not require addressing;
		.chip			= cfg->atcai2c.slave_address >> 1,
		.buffer			= data,
	};

	packet.length = 1;

	if (twihs_master_write( twihs_device, &packet) != STATUS_OK)
		return ATCA_COMM_FAIL;

	return ATCA_SUCCESS;
}

/** \brief sleep CryptoAuth device using I2C bus
 * \param[in] iface  interface to logical device to sleep
 */

ATCA_STATUS hal_i2c_sleep(ATCAIface iface)
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	int bus = cfg->atcai2c.bus;
	uint8_t data[4];
	int length;
	uint32_t twihs_device;
	uint16_t status;

	data[0] = 0x01;  // sleep word address value

	twihs_device = i2c_hal_data[bus]->twi_module;

	twihs_packet_t packet = {
		.addr[0]        = 0,
		.addr[1]        = 0,
		.addr_length	= 0,                              //very important, since cryptoauthdevices do not require addressing;
		.chip			= cfg->atcai2c.slave_address >> 1,
		.buffer			= data,
	};

	packet.length = 1;

	if (twihs_master_write( twihs_device, &packet) != STATUS_OK)
		return ATCA_COMM_FAIL;

	return ATCA_SUCCESS;
}

/** \brief manages reference count on given bus and releases resource if no more refences exist
 * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation
 */

ATCA_STATUS hal_i2c_release( void *hal_data )
{
	ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data;

	i2c_bus_ref_ct--;  // track total i2c bus interface instances for consistency checking and debugging

	// if the use count for this bus has gone to 0 references, disable it.  protect against an unbracketed release
	if ( hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL ) {
		twihs_disable_master_mode( i2c_hal_data[hal->bus_index]->twi_module );
		free(i2c_hal_data[hal->bus_index]);
		i2c_hal_data[hal->bus_index] = NULL;
	}

	return ATCA_SUCCESS;
}
Ejemplo n.º 3
0
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength)
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	int bus = cfg->atcai2c.bus;
	uint32_t twihs_device;
	uint16_t status;

	twihs_device = i2c_hal_data[bus]->twi_module;

	twihs_packet_t packet = {
		.addr[0]        = 0,
		.addr[1]        = 0,
		.addr_length	= 0,                              //very important, since cryptoauthdevices do not require addressing;
		.chip			= cfg->atcai2c.slave_address >> 1,
		.buffer			= txdata,
	};

	// for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format

	// other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one
	// this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet
	// txdata[0] is using _reserved byte of the ATCAPacket
	txdata[0] = 0x03;   // insert the Word Address Value, Command token
	txlength++;         // account for word address value byte.
	packet.length = txlength;

	if (twihs_master_write( twihs_device, &packet) != STATUS_OK)
		return ATCA_COMM_FAIL;

	return ATCA_SUCCESS;
}

/** \brief HAL implementation of I2C receive function for ASF I2C
 * \param[in] iface     instance
 * \param[in] rxdata    pointer to space to receive the data
 * \param[in] rxlength  ptr to expected number of receive bytes to request
 * \return ATCA_STATUS
 */

ATCA_STATUS hal_i2c_receive( ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength)
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	int bus = cfg->atcai2c.bus;
	int retries = cfg->rx_retries;
	int status = !STATUS_OK;
	Twihs *twihs_device;

	twihs_packet_t packet = {
		.chip	= cfg->atcai2c.slave_address >> 1, // use 7-bit address
		.buffer = rxdata,
		.length = *rxlength
	};

	twihs_device = i2c_hal_data[bus]->twi_module;

	while ( retries-- > 0 && status != STATUS_OK ) {
		if ( twihs_master_read(twihs_device, &packet) != TWIHS_SUCCESS )
			status = ATCA_COMM_FAIL;
		else
			status = ATCA_SUCCESS;
	}

	if ( status != STATUS_OK )
		return ATCA_COMM_FAIL;

	return ATCA_SUCCESS;
}

/** \brief method to change the bus speed of I2C
 * \param[in] iface  interface on which to change bus speed
 * \param[in] speed  baud rate (typically 100000 or 400000)
 */

ATCA_STATUS change_i2c_speed( ATCAIface iface, uint32_t speed )
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	int bus = cfg->atcai2c.bus;

	// if necessary, revert baud rate to what came in.
	if (twihs_set_speed(i2c_hal_data[bus]->twi_module, speed, sysclk_get_cpu_hz() / CONFIG_SYSCLK_DIV) == FAIL)
		return ATCA_COMM_FAIL;
}