ATCA_STATUS hal_swi_wake(ATCAIface iface) { #ifdef DEBUG_HAL printf("hal_swi_wake()\r\n"); #endif ATCA_STATUS status = ATCA_COMM_FAIL; ATCAIfaceCfg *cfg = atgetifacecfg(iface); int bus = cfg->atcaswi.bus; int retries = cfg->rx_retries; uint16_t datalength = 4; uint8_t data[4] = { 0x00, 0x00, 0x00, 0x00 }, expected[4] = { 0x04, 0x11, 0x33, 0x43 }; while ((status != ATCA_SUCCESS) && (retries >= 0x00)) { retries--; // Change baudrate to 115200 to get low signal more than 60us swi_uart_setbaud(swi_hal_data[bus], 115200); // Send byte 0x00 status = swi_uart_send_byte(swi_hal_data[bus], SWI_WAKE_TOKEN); // Change baudrate back to 230400 swi_uart_setbaud(swi_hal_data[bus], 230400); } if (!status) { atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure status = hal_swi_receive(iface, data, &datalength); } if ((retries == 0x00) && (status != ATCA_SUCCESS) ) return ATCA_TIMEOUT; if ( memcmp( data, expected, 4 ) == 0 ) return ATCA_SUCCESS; return ATCA_COMM_FAIL; }
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_wake(ATCAIface iface) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); int bus = cfg->atcai2c.bus; int retries = cfg->rx_retries; uint32_t bdrt = cfg->atcai2c.baud; int status = !STATUS_OK; uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; if ( bdrt != 100000 ) // if not already at 100KHz, change it change_i2c_speed( iface, 100000 ); // Send the wake by writing to an address of 0x00 twi_package_t packet = { .addr_length = 0, // TWI slave memory address data size .chip = 0x00, // TWI slave bus address .buffer = &data[0], // transfer data source buffer .length = 0 // transfer data size (bytes) }; // Send the 00 address as the wake pulse twi_master_write(i2c_hal_data[bus]->i2c_master_instance, &packet ); // part will NACK, so don't check for status atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure packet.chip = cfg->atcai2c.slave_address >> 1; packet.length = 4; packet.buffer = data; 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; // if necessary, revert baud rate to what came in. if ( bdrt != 100000 ) change_i2c_speed( iface, bdrt ); 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]; twi_package_t packet = { .addr_length = 0, // TWI slave memory address data size .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address .buffer = &data[0], // transfer data source buffer .length = 1 // transfer data size (bytes) }; data[0] = 0x02; // idle word address value if ( twi_master_write((i2c_hal_data[bus]->i2c_master_instance), &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]; twi_package_t packet = { .addr_length = 0, // TWI slave memory address data size .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address .buffer = &data[0], // transfer data source buffer .length = 1 // transfer data size (bytes) }; data[0] = 0x01; // sleep word address value if ( twi_master_write((i2c_hal_data[bus]->i2c_master_instance), &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 ) { twi_master_disable(hal->i2c_master_instance); free(i2c_hal_data[hal->bus_index]); i2c_hal_data[hal->bus_index] = NULL; } return ATCA_SUCCESS; }
ATCA_STATUS hal_swi_receive( ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) { #ifdef DEBUG_HAL printf("hal_swi_receive()\r\n"); #endif ATCA_STATUS status = ATCA_COMM_FAIL; ATCAIfaceCfg *cfg = atgetifacecfg(iface); int bus = cfg->atcaswi.bus; int retries = cfg->rx_retries; uint8_t bit_mask, *head_buff, bit_data; uint16_t i = 0; while ((status != ATCA_SUCCESS) && (retries >= 0x00)) { retries--; head_buff = rxdata; status = hal_swi_send_flag(iface, SWI_FLAG_TX); // Set SWI to receive mode. swi_uart_mode(swi_hal_data[bus], RECEIVE_MODE); #ifdef SAMD21_ASF RX_DELAY #else atca_delay_us(RX_DELAY); // Must be configured to sync with response from device #endif if (status == ATCA_SUCCESS) { for (i = 0; i < *rxlength; i++) { *head_buff = 0x00; for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { bit_data = 0; status = swi_uart_receive_byte(swi_hal_data[bus], &bit_data); if ((i == 0) && (bit_mask == 1) && (status != ATCA_SUCCESS)) break; // Sometimes bit data from device is stretched // When the device sends a "one" bit, it is read as 0x7E or 0x7F. // When the device sends a "zero" bit, it is read as 0x7A, 0x7B, or 7D. if ((bit_data ^ 0x7F) < 2) // Received "one" bit. *head_buff |= bit_mask; } if ((i == 0) && (bit_mask == 1) && (status != ATCA_SUCCESS)) break; head_buff++; } // Set SWI to transmit mode. swi_uart_mode(swi_hal_data[bus], TRANSMIT_MODE); atca_delay_us(TX_DELAY); // Must be configured to sync with response from device } // The Response shorter than expected if ((i >= 4) && (status = ATCA_TIMEOUT)) status = ATCA_SUCCESS; } #ifdef DEBUG_HAL printf("\r\nResponse Packet (size:0x%.4x)\r\n", *rxlength); printf("Count : %.2x\r\n", rxdata[0]); if (rxdata[0] > 3) { printf("Data : "); print_array(&rxdata[1], rxdata[0] - 3); printf("CRC : "); print_array(&rxdata[rxdata[0] - 2], 2); } printf("\r\n"); #endif return status; }
/** \brief wake up CryptoAuth device using I2C bus * \param[in] interface to logical device to wakeup */ ATCA_STATUS hal_i2c_wake(ATCAIface iface) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); int bus = cfg->atcai2c.bus; int retries = cfg->rx_retries; uint32_t bdrt = cfg->atcai2c.baud; uint8_t data[4], expected[4] = { 0x04,0x11,0x33,0x43 }; int status = !TWI_SUCCESS; // if not already at 100KHz, change it if (bdrt != 100000) { change_i2c_speed(iface, 100000); } // Send 0x00 as wake pulse switch(bus) { //case 0: twi_write_byte(TWI0, 0x00); break; case 0: twi_write_byte(TWI_Channel0,0);break; case 1: twi_write_byte(TWI_Channel1,0); break; } atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure //twi_package_t packet = { twi_packet_t packet = { .chip = cfg->atcai2c.slave_address >> 1, .addr[0] = NULL, .addr_length = 0, .buffer = (void *)data, .length = 4 }; // if necessary, revert baud rate to what came in. if (bdrt != 100000) { change_i2c_speed(iface, bdrt); } switch(bus) { case 0: //if (twi_master_read(TWI0, &packet) != TWI_SUCCESS) while (retries-- > 0 && status != TWI_SUCCESS) status = twi_master_read(TWI_Channel0, &packet); /*if (twi_master_read(TWI_Channel0, &packet) != TWI_SUCCESS) { return ATCA_COMM_FAIL; }*/ break; case 1: /* if (twi_master_read(TWI_Channel1, &packet) != TWI_SUCCESS) { return ATCA_COMM_FAIL; }*/ break; } if (memcmp(data, expected, 4) == 0) { return ATCA_SUCCESS; } return ATCA_COMM_FAIL; } /** \brief idle CryptoAuth device using I2C bus * \param[in] 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]; data[0] = 0x02; // idle word address value //twi_package_t packet = { twi_packet_t packet = { .chip = cfg->atcai2c.slave_address >> 1, .addr[0] = NULL, .addr_length = 0, .buffer = (void *)data, .length = 1 }; switch(bus) { case 0: //if (twi_master_write(TWI0, &packet) != TWI_SUCCESS) if (twi_master_write(TWI_Channel0, &packet) != TWI_SUCCESS) { return ATCA_COMM_FAIL; } break; case 1: if (twi_master_write(TWI_Channel1, &packet) != TWI_SUCCESS) { return ATCA_COMM_FAIL; } break; } return ATCA_SUCCESS; } /** \brief sleep CryptoAuth device using I2C bus * \param[in] 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]; data[0] = 0x01; // sleep word address value //twi_package_t packet = { twi_packet_t packet = { .chip = cfg->atcai2c.slave_address >> 1, .addr[0] = NULL, .addr_length = 0, .buffer = (void *)data, .length = 1 }; switch(bus) { case 0: //if (twi_master_write(TWI0, &packet) != TWI_SUCCESS) if (twi_master_write(TWI_Channel0, &packet) != TWI_SUCCESS) { return ATCA_COMM_FAIL; } break; case 1: if (twi_master_write(TWI_Channel1, &packet) != TWI_SUCCESS) { return ATCA_COMM_FAIL; } break; } 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) { switch(hal->bus_index) { //case 0: twi_reset(TWI0); break; case 0: twi_reset(TWI_Channel0);break; case 1: twi_reset(TWI_Channel1);break; } free(i2c_hal_data[hal->bus_index]); i2c_hal_data[hal->bus_index] = NULL; } return ATCA_SUCCESS; }