コード例 #1
0
// Supporting function implementation
Accelerometer::Accelerometer() {

	// Initialize variables
	uint8_t value;
	
	// Configure VDDIO, SDA and SCL pins
	ioport_set_pin_dir(ACCELEROMETER_VDDIO_PIN, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(ACCELEROMETER_VDDIO_PIN, IOPORT_PIN_LEVEL_HIGH);
	ioport_set_pin_mode(ACCELEROMETER_SDA_PIN, IOPORT_MODE_WIREDANDPULL);
	ioport_set_pin_mode(ACCELEROMETER_SCL_PIN, IOPORT_MODE_WIREDANDPULL);
	
	// Configure interface
	twi_options_t options;
	options.speed = BUS_SPEED;
	options.chip = MASTER_ADDRESS;
	options.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), BUS_SPEED);
	
	// Initialize interface
	sysclk_enable_peripheral_clock(&TWI_MASTER);
	twi_master_init(&TWI_MASTER, &options);
	twi_master_enable(&TWI_MASTER);

	// Create packet
	twi_package_t packet;
	packet.addr[0] = WHO_AM_I;
	packet.addr_length = 1;
	packet.chip = ACCELEROMETER_ADDRESS;
	packet.buffer = &value;
	packet.length = 1;
	packet.no_wait = false;
	
	// Check if transmitting or receiving failed
	if(twi_master_read(&TWI_MASTER, &packet) != TWI_SUCCESS || value != DEVICE_ID)
	
		// Clear is working
		isWorking = false;
	
	// Otherwise
	else {
	
		// Reset the accelerometer
		writeValue(CTRL_REG2, CTRL_REG2_RST);
		
		// Wait enough time for accelerometer to initialize
		delay_ms(1);
		
		// Initialize settings
		initializeSettings();
		
		// Calibrate
		//calibrate();
	
		// Set is working
		isWorking = true;
	}
}
コード例 #2
0
/**
 * \internal
 * \brief This test sends a packet from the master, and checks
 * that the sending happens without errors.
 *
 * \param test Current test case.
 */
static void run_twi_master_send_test(
		const struct test_case *test)
{
	status_code_t master_status;
	// Package to send
	twi_package_t packet = {
		// No address or command
		.addr_length = 0,
		// issue to slave
		.chip        = TWI_SLAVE_ADDR,
		.buffer      = (void *)test_pattern,
		.length      = PATTERN_TEST_LENGTH,
		// Wait if bus is busy
		.no_wait     = false
	};

	// TWI master options
	twi_options_t m_options = {
		.speed = TWI_SPEED,
		.chip  = TWI_MASTER_ADDR,
		.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), TWI_SPEED)
	};

	irq_initialize_vectors();

	// Initialize TWI_MASTER
	sysclk_enable_peripheral_clock(&TWI_MASTER);
	twi_master_init(&TWI_MASTER, &m_options);
	twi_master_enable(&TWI_MASTER);

	// Initialize TWI_SLAVE
	sysclk_enable_peripheral_clock(&TWI_SLAVE);
	TWI_SlaveInitializeDriver(&slave, &TWI_SLAVE, *slave_process);
	TWI_SlaveInitializeModule(&slave, TWI_SLAVE_ADDR,
			TWI_SLAVE_INTLVL_MED_gc);

	cpu_irq_enable();

	// Send package to slave
	master_status = twi_master_write(&TWI_MASTER, &packet);

	test_assert_true(test, master_status == STATUS_OK,
			"Master write not ok");
}

/**
 * \internal
 * \brief This test sends a packet from the master to the slave,
 * and checks that the correct packet is received.
 *
 * \param test Current test case.
 */
static void run_twi_slave_recv_test(
		const struct test_case *test)
{
	uint8_t i = 0;

	// Package to send
	twi_package_t packet = {
		// No address or command to issue to slave
		.addr_length = 0,
		.chip        = TWI_SLAVE_ADDR,
		.buffer      = (void *)test_pattern,
		.length      = PATTERN_TEST_LENGTH,
		// Wait if bus is busy
		.no_wait      = false
	};

	// TWI master options
	twi_options_t m_options = {
		.speed = TWI_SPEED,
		.chip  = TWI_MASTER_ADDR,
		.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), TWI_SPEED)
	};

	irq_initialize_vectors();

	// Initialize TWI_MASTER
	sysclk_enable_peripheral_clock(&TWI_MASTER);
	twi_master_init(&TWI_MASTER, &m_options);
	twi_master_enable(&TWI_MASTER);

	// Initialize TWI_SLAVE
	for (i = 0; i < TWIS_SEND_BUFFER_SIZE; i++) {
		slave.receivedData[i] = 0;
	}
	sysclk_enable_peripheral_clock(&TWI_SLAVE);
	TWI_SlaveInitializeDriver(&slave, &TWI_SLAVE, *slave_process);
	TWI_SlaveInitializeModule(&slave, TWI_SLAVE_ADDR,
			TWI_SLAVE_INTLVL_MED_gc);

	cpu_irq_enable();

	// Send package to slave
	twi_master_write(&TWI_MASTER, &packet);

	// Wait for slave to receive packet and check that packet is correct
	do {} while (slave.result != TWIS_RESULT_OK);
	for (i = 0; i < PATTERN_TEST_LENGTH; i++) {
		test_assert_true(test, slave.receivedData[i] == test_pattern[i],
				"Wrong data[%d] received, %d != %d", i,
				slave.receivedData[i],
				test_pattern[i]);
	}
}

/**
 * \internal
 * \brief This test requests a packet to be sent from the slave,
 * and checks that the correct packet is received by the master.
 *
 * \param test Current test case.
 */
static void run_twi_master_recv_test(const struct test_case *test)
{
	uint8_t i = 0;
	uint8_t recv_pattern[TWIS_SEND_BUFFER_SIZE] = {0};

	// Package to send
	twi_package_t packet = {
		// No address or command to issue to slave
		.addr_length = 0,
		.chip        = TWI_SLAVE_ADDR,
		.buffer      = (void *)recv_pattern,
		// Wait if bus is busy
		.length      = PATTERN_TEST_LENGTH,
		.no_wait     = false
	};
	// TWI master options
	twi_options_t m_options = {
		.speed = TWI_SPEED,
		.chip  = TWI_MASTER_ADDR,
		.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), TWI_SPEED)
	};

	// Data for slave to send, same as test_pattern
	slave.sendData[0] = 0x55;
	slave.sendData[1] = 0xA5;
	slave.sendData[2] = 0x5A;
	slave.sendData[3] = 0x77;
	slave.sendData[4] = 0x99;

	irq_initialize_vectors();

	// Initialize TWI_MASTER
	sysclk_enable_peripheral_clock(&TWI_MASTER);
	twi_master_init(&TWI_MASTER, &m_options);
	twi_master_enable(&TWI_MASTER);

	// Initialize TWI_SLAVE
	for (i = 0; i < TWIS_SEND_BUFFER_SIZE; i++) {
		slave.receivedData[i] = 0;
	}
	sysclk_enable_peripheral_clock(&TWI_SLAVE);
	TWI_SlaveInitializeDriver(&slave, &TWI_SLAVE, *slave_process);
	TWI_SlaveInitializeModule(&slave, TWI_SLAVE_ADDR,
			TWI_SLAVE_INTLVL_MED_gc);

	cpu_irq_enable();

	// Send package to slave
	twi_master_read(&TWI_MASTER, &packet);

	// Wait for slave to send packet
	do {} while (slave.result != TWIS_RESULT_OK);

	for (i = 0; i < PATTERN_TEST_LENGTH; i++) {
		test_assert_true(test, recv_pattern[i] == test_pattern[i],
				"Wrong data[%d] received, %d != %d", i,
				recv_pattern[i],
				test_pattern[i]);
	}
}

//@}

/**
 * \brief Run TWI unit tests
 *
 * Initializes the clock system, board and serial output, then sets up the
 * TWI unit test suite and runs it.
 */
int main(void)
{
	const usart_serial_options_t usart_serial_options = {
		.baudrate   = CONF_TEST_BAUDRATE,
		.charlength = CONF_TEST_CHARLENGTH,
		.paritytype = CONF_TEST_PARITY,
		.stopbits   = CONF_TEST_STOPBITS,
	};

	sysclk_init();
	board_init();
	stdio_serial_init(CONF_TEST_USART, &usart_serial_options);

	// Use the internal pullups for SDA and SCL
	TWI_MASTER_PORT.PIN0CTRL = PORT_OPC_WIREDANDPULL_gc;
	TWI_MASTER_PORT.PIN1CTRL = PORT_OPC_WIREDANDPULL_gc;

	// Define single ended conversion test cases
	DEFINE_TEST_CASE(twi_master_send_test, NULL,
			run_twi_master_send_test, NULL,
			"Sending packet from master test");
	DEFINE_TEST_CASE(twi_slave_recv_test, NULL,
			run_twi_slave_recv_test, NULL,
			"Receiving packet from master test");
	DEFINE_TEST_CASE(twi_master_recv_test, NULL,
			run_twi_master_recv_test, NULL,
			"Receiving packet from slave test");

	// Put test case addresses in an array
	DEFINE_TEST_ARRAY(twi_tests) = {
		&twi_master_send_test,
		&twi_slave_recv_test,
		&twi_master_recv_test,
	};

	// Define the test suite
	DEFINE_TEST_SUITE(twi_suite, twi_tests,
			"XMEGA TWI driver test suite");

	// Run all tests in the suite
	test_suite_run(&twi_suite);

	while (1) {
		// Intentionally left empty.
	}
}
コード例 #3
0
ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found )
{
	ATCAIfaceCfg *head = cfg;
	uint8_t slaveAddress = 0x01;
	ATCADevice device;
	ATCAIface discoverIface;
	ATCACommand command;
	ATCAPacket packet;
	uint32_t execution_time;
	ATCA_STATUS status;
	uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } };
	uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } };
	uint8_t revs204[2][4] = { { 0x00, 0x02, 0x00, 0x08 },
							  { 0x00, 0x04, 0x05, 0x00 } };
	int i;

	/** \brief default configuration, to be reused during discovery process */
	ATCAIfaceCfg discoverCfg = {
		.iface_type				= ATCA_I2C_IFACE,
		.devtype				= ATECC508A,
		.atcai2c.slave_address	= 0x07,
		.atcai2c.bus			= busNum,
		.atcai2c.baud			= 400000,
		//.atcai2c.baud = 100000,
		.wake_delay				= 800,
		.rx_retries				= 3
	};

	// build an info command
	packet.param1 = INFO_MODE_REVISION;
	packet.param2 = 0;

	device = newATCADevice( &discoverCfg );
	discoverIface = atGetIFace( device );
	command = atGetCommands( device );

	// iterate through all addresses on given i2c bus
	// all valid 7-bit addresses go from 0x07 to 0x78
	for ( slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++ ) {
		discoverCfg.atcai2c.slave_address = slaveAddress << 1;  // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent

		// wake up device
		// If it wakes, send it a dev rev command.  Based on that response, determine the device type
		// BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a)

		if ( hal_i2c_wake( discoverIface ) == ATCA_SUCCESS ) {
			(*found)++;
			memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg));

			memset( packet.info, 0x00, sizeof(packet.info));

			// get devrev info and set device type accordingly
			atInfo( command, &packet );
			execution_time = atGetExecTime(command, CMD_INFO) + 1;

			// send the command
			if ( (status = atsend( discoverIface, (uint8_t*)&packet, packet.txsize )) != ATCA_SUCCESS ) {
				printf("packet send error\r\n");
				continue;
			}

			// delay the appropriate amount of time for command to execute
			atca_delay_ms(execution_time);

			// receive the response
			if ( (status = atreceive( discoverIface, &(packet.info[0]), &(packet.rxsize) )) != ATCA_SUCCESS )
				continue;

			if ( (status = isATCAError(packet.info)) != ATCA_SUCCESS ) {
				printf("command response error\r\n");
				continue;
			}

			// determine device type from common info and dev rev response byte strings
			for ( i = 0; i < sizeof(revs508) / 4; i++ ) {
				if ( memcmp( &packet.info[1], &revs508[i], 4) == 0 ) {
					discoverCfg.devtype = ATECC508A;
					break;
				}
			}

			for ( i = 0; i < sizeof(revs204) / 4; i++ ) {
				if ( memcmp( &packet.info[1], &revs204[i], 4) == 0 ) {
					discoverCfg.devtype = ATSHA204A;
					break;
				}
			}

			for ( i = 0; i < sizeof(revs108) / 4; i++ ) {
				if ( memcmp( &packet.info[1], &revs108[i], 4) == 0 ) {
					discoverCfg.devtype = ATECC108A;
					break;
				}
			}

			atca_delay_ms(15);
			// now the device type is known, so update the caller's cfg array element with it
			head->devtype = discoverCfg.devtype;
			head++;
		}

		hal_i2c_idle(discoverIface);
	}

	deleteATCADevice(&device);

	return ATCA_SUCCESS;
}


/** \brief
    - this HAL implementation assumes you've included the ASF I2C libraries in your project, otherwise,
    the HAL layer will not compile because the ASF I2C drivers are a dependency *
 */

/** \brief hal_i2c_init manages requests to initialize a physical interface.  it manages use counts so when an interface
 * has released the physical layer, it will disable the interface for some other use.
 * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on
 * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details.
 */

/** \brief initialize an I2C interface using given config
 * \param[in] hal - opaque ptr to HAL data
 * \param[in] cfg - interface configuration
 */
ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg)
{
	int bus = cfg->atcai2c.bus;   // 0-based logical bus number
	ATCAHAL_t *phal = (ATCAHAL_t*)hal;

	if ( i2c_bus_ref_ct == 0 )     // power up state, no i2c buses will have been used
		for ( int i = 0; i < MAX_I2C_BUSES; i++ )
			i2c_hal_data[i] = NULL;

	i2c_bus_ref_ct++;  // total across buses

	if ( bus >= 0 && bus < MAX_I2C_BUSES ) {
		// if this is the first time this bus and interface has been created, do the physical work of enabling it
		if ( i2c_hal_data[bus] == NULL ) {
			i2c_hal_data[bus] = malloc( sizeof(ATCAI2CMaster_t) );
			i2c_hal_data[bus]->ref_ct = 1;  // buses are shared, this is the first instance

			config_i2c_master.speed = cfg->atcai2c.baud;
			config_i2c_master.chip  = 0x50;
			config_i2c_master.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), cfg->atcai2c.baud);
			switch (bus) {
			case 0: i2c_hal_data[bus]->i2c_master_instance = &TWIC; break;
			//case 1: i2c_hal_data[bus]->i2c_master_instance = &TWID; break;	// for XMEGA-A1
			case 2: i2c_hal_data[bus]->i2c_master_instance = &TWIE; break;
				//case 3: i2c_hal_data[bus]->i2c_master_instance = &TWIF; break;	// for XMEGA-A1
			}

			twi_master_setup((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master);
			// store this for use during the release phase
			i2c_hal_data[bus]->bus_index = bus;
			twi_master_enable(i2c_hal_data[bus]->i2c_master_instance);
		}  else{
			// otherwise, another interface already initialized the bus, so this interface will share it and any different
			// cfg parameters will be ignored...first one to initialize this sets the configuration
			i2c_hal_data[bus]->ref_ct++;
		}

		phal->hal_data = i2c_hal_data[bus];

		return ATCA_SUCCESS;
	}

	return ATCA_COMM_FAIL;
}
コード例 #4
0
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength)
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	int bus = cfg->atcai2c.bus;

	twi_package_t packet = {
		.addr_length	= 0,                                // TWI slave memory address data size
		.chip			= cfg->atcai2c.slave_address >> 1,  // TWI slave bus address
		.buffer			= txdata,                           // transfer data source buffer
		.length			= txlength,                         // transfer data size (bytes)
	};

	// 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 ( twi_master_write(i2c_hal_data[bus]->i2c_master_instance, &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;

	twi_package_t packet = {
		.addr_length	= 0,                                // TWI slave memory address data size
		.chip			= cfg->atcai2c.slave_address >> 1,  // TWI slave bus address
		.buffer			= rxdata,                           // transfer data source buffer
		.length			= *rxlength,                        // transfer data size (bytes)
	};

	while ( retries-- > 0 && status != STATUS_OK )
		status = twi_master_read(i2c_hal_data[bus]->i2c_master_instance, &packet);

	if ( status != STATUS_OK )
		return ATCA_COMM_FAIL;

	return ATCA_SUCCESS;
}

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

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

	config_i2c_master.speed = speed;
	config_i2c_master.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), speed);

	twi_master_disable(i2c_hal_data[bus]->i2c_master_instance);

	switch (bus) {
	case 0: i2c_hal_data[bus]->i2c_master_instance = &TWIC; break;
	case 2: i2c_hal_data[bus]->i2c_master_instance = &TWIE; break;
	}

	twi_master_setup((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master);

	twi_master_enable(i2c_hal_data[bus]->i2c_master_instance);
}