/*! \brief Write device register content. * * \param reg_index Register address. Use macros as defined in the header file. * \param data Data that should be written to the device register. */ void PCA9952_write_reg(unsigned char topBotn, uint8_t reg_index, uint8_t data) { uint8_t pack[2]; twihs_packet_t twi_package; pack[0] = reg_index; pack[1] = data; //7apr15 twi_package.chip = PCA9952_TWI_ADDRESS; if (topBotn == LED_TOP) { twi_package.chip = PCA9952_U7_TOPDRIVE_TWI_ADDRESS; } else if (topBotn == LED_BOTTOM) { twi_package.chip = PCA9952_U8_BOTDRIVE_TWI_ADDRESS; } twi_package.addr[0] = 0; //is this right? 8feb16 twi_package.addr[1] = 0; //is this right? 8feb16 twi_package.addr[2] = 0; //is this right? 8feb16 twi_package.addr_length = 0; twi_package.buffer = &pack; twi_package.length = sizeof(pack); while(twihs_master_write(PCA9952_TWI, &twi_package)!=TWIHS_SUCCESS); return; }
/** * \brief Test if a chip answers a given I2C address. * * \param p_twihs Pointer to a TWIHS instance. * \param uc_slave_addr Address of the remote chip to search for. * * \return TWIHS_SUCCESS if a chip was found, error code otherwise. */ uint32_t twihs_probe(Twihs *p_twihs, uint8_t uc_slave_addr) { twihs_packet_t packet; uint8_t data = 0; /* Data to send */ packet.buffer = &data; /* Data length */ packet.length = 1; /* Slave chip address */ packet.chip = (uint32_t) uc_slave_addr; /* Internal chip address */ packet.addr[0] = 0; /* Address length */ packet.addr_length = 0; /* Perform a master write access */ return (twihs_master_write(p_twihs, &packet)); }
static sint8 nm_i2c_write(uint8 *b, uint16 sz) { sint8 result = M2M_SUCCESS; twihs_packet_t packet_tx; uint16_t timeout = 0; /* Configure the data packet to be transmitted */ packet_tx.chip = SLAVE_ADDRESS; packet_tx.addr[0] = 0; packet_tx.addr[1] = 0; packet_tx.addr[2] = 0; packet_tx.addr_length = 0; packet_tx.buffer = b; packet_tx.length = sz; while(twihs_master_write(CONF_WINC_I2C, &packet_tx) != TWIHS_SUCCESS) { if (timeout++ == I2C_TIMEOUT) { break; } } return result; }
/*! \brief Read device register content. * * \param reg_index Register address. * \returns Register content. */ uint8_t PCA9952_read_reg(unsigned char topBotn, uint8_t reg_index) { uint8_t data; twihs_packet_t twi_package; //7apr15 twi_package.chip = PCA9952_TWI_ADDRESS; if (topBotn == LED_TOP) { twi_package.chip = PCA9952_U7_TOPDRIVE_TWI_ADDRESS; } else if (topBotn == LED_BOTTOM) { twi_package.chip = PCA9952_U8_BOTDRIVE_TWI_ADDRESS; } twi_package.addr[0] = 0; //is this right? 8feb16 twi_package.addr[1] = 0; //is this right? 8feb16 twi_package.addr[2] = 0; //is this right? 8feb16 twi_package.addr_length = 0; twi_package.buffer = ®_index; twi_package.length = 1; while(twihs_master_write(PCA9952_TWI, &twi_package)!=TWIHS_SUCCESS); /* We need a delay here to make this work although this is not * specified in the datasheet. * Also there seems to be a bug in the TWI module or the driver * since some delay here (code or real delay) adds about 500us * between the write and the next read cycle. */ mdelay(20); //7apr15 this was set above, no need to reassign twi_package.chip = PCA9952_TWI_ADDRESS; twi_package.addr_length = 0; twi_package.buffer = &data; twi_package.length = 1; while(twihs_master_read(PCA9952_TWI, &twi_package)!=TWIHS_SUCCESS); return data; }
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; }
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; }
/** * \brief Application entry point for TWI EEPROM example. * * \return Unused (ANSI-C compatibility). */ int main(void) { uint32_t i; twihs_options_t opt; twihs_packet_t packet_tx, packet_rx; /* Initialize the SAM system */ sysclk_init(); /* Initialize the board */ board_init(); /* Turn off LEDs */ LED_Off(LED0); /* Initialize the console UART */ configure_console(); /* Output example information */ puts(STRING_HEADER); /* Configure systick for 1 ms */ puts("Configure system tick to get 1ms tick period.\r"); if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) { puts("-E- Systick configuration error\r"); while (1) { /* Capture error */ } } /* Enable the peripheral clock for TWI */ pmc_enable_periph_clk(BOARD_ID_TWIHS_EEPROM); /* Configure the options of TWI driver */ opt.master_clk = sysclk_get_cpu_hz(); opt.speed = TWIHS_CLK; /* Configure the data packet to be transmitted */ packet_tx.chip = AT24C_ADDRESS; packet_tx.addr[0] = EEPROM_MEM_ADDR >> 8; packet_tx.addr[1] = EEPROM_MEM_ADDR; packet_tx.addr_length = EEPROM_MEM_ADDR_LENGTH; packet_tx.buffer = (uint8_t *) test_data_tx; packet_tx.length = TEST_DATA_LENGTH; /* Configure the data packet to be received */ packet_rx.chip = packet_tx.chip; packet_rx.addr[0] = packet_tx.addr[0]; packet_rx.addr[1] = packet_tx.addr[1]; packet_rx.addr_length = packet_tx.addr_length; packet_rx.buffer = gs_uc_test_data_rx; packet_rx.length = packet_tx.length; if (twihs_master_init(BOARD_BASE_TWIHS_EEPROM, &opt) != TWIHS_SUCCESS) { puts("-E-\tTWI master initialization failed.\r"); while (1) { /* Capture error */ } } /* Send test pattern to EEPROM */ if (twihs_master_write(BOARD_BASE_TWIHS_EEPROM, &packet_tx) != TWIHS_SUCCESS) { puts("-E-\tTWI master write packet failed.\r"); while (1) { /* Capture error */ } } puts("Write:\tOK!\n\r"); /* Wait at least 10 ms */ mdelay(WAIT_TIME); /* Get memory from EEPROM*/ if (twihs_master_read(BOARD_BASE_TWIHS_EEPROM, &packet_rx) != TWIHS_SUCCESS) { puts("-E-\tTWI master read packet failed.\r"); while (1) { /* Capture error */ } } puts("Read:\tOK!\r"); /* Compare the sent and the received */ for (i = 0; i < TEST_DATA_LENGTH; i++) { if (test_data_tx[i] != gs_uc_test_data_rx[i]) { /* No match */ puts("Data comparison:\tUnmatched!\r"); while (1) { /* Capture error */ } } } /* Match */ puts("Data comparison:\tMatched!\r"); LED_On(LED0); while (1) { } }