Add Atmel CryptoAuthLib to extras

This is Atmel/Microchip's official library for interfacing
to the Atmel ATECC508 chip.  The submodule points to their
repository in GitHub.

Additionally, this includes the HAL necessary to use this library
in esp_open_rtos using the i2c library in extras/i2c.  I have also
included a tool I wrote to play with the chip as an example under
examples/atcatool.

The extras module currently overrides atca_iface.h to fix bug in
cryptoauthlib (c11-only feature, which breaks c++ builds that want
to use cryptoauthlib)
This commit is contained in:
Peter Dunshee 2017-11-22 09:21:59 -06:00
parent 8f378b41c8
commit e66e87aa8e
18 changed files with 1466 additions and 0 deletions

View file

@ -0,0 +1,6 @@
# cryptoauthlib
Note: The file atca_iface.h is copied from cryptoauthlib/lib/atca_iface.h. The difference is, the anonymous struct names have been commented out, since they are not valid in c++ (only c11). Otherwise this file is exactly the same. Its presence here overrides the
one in cryptoauthlib. See <https://github.com/MicrochipTech/cryptoauthlib/issues/43>.
Also see <https://github.com/Petezah/CryptoAuthLib-Tools> for some tools which aid in generating config data for the ECC module.

View file

@ -0,0 +1,173 @@
/**
* \file
*
* \brief Microchip Crypto Auth hardware interface object
*
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip software
* and any derivatives exclusively with Microchip products. It is your
* responsibility to comply with third party license terms applicable to your
* use of third party software (including open source software) that may
* accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
* THIS SOFTWARE.
*/
#ifndef ATCA_IFACE_H
#define ATCA_IFACE_H
/** \defgroup interface ATCAIface (atca_)
* \brief Abstract interface to all CryptoAuth device types. This interface
* connects to the HAL implementation and abstracts the physical details of the
* device communication from all the upper layers of CryptoAuthLib
@{ */
#ifdef __cplusplus
extern "C" {
#endif
#include "atca_command.h"
typedef enum
{
ATCA_I2C_IFACE,
ATCA_SWI_IFACE,
ATCA_UART_IFACE,
ATCA_SPI_IFACE,
ATCA_HID_IFACE,
ATCA_CUSTOM_IFACE,
// additional physical interface types here
ATCA_UNKNOWN_IFACE,
} ATCAIfaceType;
/* ATCAIfaceCfg is a mediator object between a completely abstract notion of a
physical interface and an actual physical interface.
The main purpose of it is to keep hardware specifics from bleeding into the
higher levels - hardware specifics could include things like framework
specific items (ASF SERCOM) vs a non-Microchip I2C library constant that
defines an I2C port. But I2C has roughly the same parameters regardless of
architecture and framework.
*/
typedef struct
{
ATCAIfaceType iface_type; // active iface - how to interpret the union below
ATCADeviceType devtype; // explicit device type
union // each instance of an iface cfg defines a single type of interface
{
struct //ATCAI2C
{
uint8_t slave_address; // 8-bit slave address
uint8_t bus; // logical i2c bus number, 0-based - HAL will map this to a pin pair for SDA SCL
uint32_t baud; // typically 400000
} atcai2c;
struct //ATCASWI
{
uint8_t bus; // logical SWI bus - HAL will map this to a pin or uart port
} atcaswi;
struct //ATCAUART
{
int port; // logic port number
uint32_t baud; // typically 115200
uint8_t wordsize; // usually 8
uint8_t parity; // 0 == even, 1 == odd, 2 == none
uint8_t stopbits; // 0,1,2
} atcauart;
struct //ATCAHID
{
int idx; // HID enumeration index
uint32_t vid; // Vendor ID of kit (0x03EB for CK101)
uint32_t pid; // Product ID of kit (0x2312 for CK101)
uint32_t packetsize; // Size of the USB packet
uint8_t guid[16]; // The GUID for this HID device
} atcahid;
struct //ATCACUSTOM
{
ATCA_STATUS (*halinit)(void *hal, void *cfg);
ATCA_STATUS (*halpostinit)(void *iface);
ATCA_STATUS (*halsend)(void *iface, uint8_t *txdata, int txlength);
ATCA_STATUS (*halreceive)(void *iface, uint8_t* rxdata, uint16_t* rxlength);
ATCA_STATUS (*halwake)(void *iface);
ATCA_STATUS (*halidle)(void *iface);
ATCA_STATUS (*halsleep)(void *iface);
ATCA_STATUS (*halrelease)(void* hal_data);
} atcacustom;
};
uint16_t wake_delay; // microseconds of tWHI + tWLO which varies based on chip type
int rx_retries; // the number of retries to attempt for receiving bytes
void * cfg_data; // opaque data used by HAL in device discovery
} ATCAIfaceCfg;
typedef struct atca_iface * ATCAIface;
/** \brief atca_iface is the C object backing ATCAIface. See the atca_iface.h file for
* details on the ATCAIface methods
*/
struct atca_iface
{
ATCAIfaceType mType;
ATCAIfaceCfg *mIfaceCFG; // points to previous defined/given Cfg object, caller manages this
ATCA_STATUS (*atinit)(void *hal, ATCAIfaceCfg *);
ATCA_STATUS (*atpostinit)(ATCAIface hal);
ATCA_STATUS (*atsend)(ATCAIface hal, uint8_t *txdata, int txlength);
ATCA_STATUS (*atreceive)(ATCAIface hal, uint8_t *rxdata, uint16_t *rxlength);
ATCA_STATUS (*atwake)(ATCAIface hal);
ATCA_STATUS (*atidle)(ATCAIface hal);
ATCA_STATUS (*atsleep)(ATCAIface hal);
// treat as private
void *hal_data; // generic pointer used by HAL to point to architecture specific structure
// no ATCA object should touch this except HAL, HAL manages this pointer and memory it points to
};
ATCA_STATUS initATCAIface(ATCAIfaceCfg *cfg, ATCAIface ca_iface);
ATCAIface newATCAIface(ATCAIfaceCfg *cfg);
ATCA_STATUS releaseATCAIface(ATCAIface ca_iface);
void deleteATCAIface(ATCAIface *ca_iface);
// IFace methods
ATCA_STATUS atinit(ATCAIface ca_iface);
ATCA_STATUS atpostinit(ATCAIface ca_iface);
ATCA_STATUS atsend(ATCAIface ca_iface, uint8_t *txdata, int txlength);
ATCA_STATUS atreceive(ATCAIface ca_iface, uint8_t *rxdata, uint16_t *rxlength);
ATCA_STATUS atwake(ATCAIface ca_iface);
ATCA_STATUS atidle(ATCAIface ca_iface);
ATCA_STATUS atsleep(ATCAIface ca_iface);
// accessors
ATCAIfaceCfg * atgetifacecfg(ATCAIface ca_iface);
void* atgetifacehaldat(ATCAIface ca_iface);
#ifdef __cplusplus
}
#endif
/** @} */
#endif

View file

@ -0,0 +1,41 @@
#
# esp_open_rtos build system component Makefile
#
CRYPTOAUTHLIB_MODULE_DIR = $(cryptoauthlib_ROOT)cryptoauthlib/
CRYPTOAUTHLIB_DIR = $(CRYPTOAUTHLIB_MODULE_DIR)lib/
INC_DIRS += $(cryptoauthlib_ROOT) $(CRYPTOAUTHLIB_DIR) $(CRYPTOAUTHLIB_DIR)basic $(CRYPTOAUTHLIB_DIR)hal
# args for passing into compile rule generation
cryptoauthlib_INC_DIR = $(CRYPTOAUTHLIB_DIR) $(CRYPTOAUTHLIB_DIR)basic
cryptoauthlib_SRC_DIR = \
$(cryptoauthlib_ROOT) \
$(CRYPTOAUTHLIB_DIR) \
$(CRYPTOAUTHLIB_DIR)basic \
$(CRYPTOAUTHLIB_DIR)crypto \
$(CRYPTOAUTHLIB_DIR)crypto/hashes \
$(CRYPTOAUTHLIB_DIR)host
cryptoauthlib_EXTRA_SRC_FILES = $(CRYPTOAUTHLIB_DIR)hal/atca_hal.c $(cryptoauthlib_ROOT)/hal/atca_hal_espfreertos_i2c.c
# default define variable values
CRYPTOAUTHLIB_ROOT_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(CRYPTOAUTHLIB_ROOT_DIR)defaults.mk
ATEC_DEBUG_FLAGS = \
-DATEC_HAL_DEBUG=$(ATEC_HAL_DEBUG) \
-DATEC_HAL_VERBOSE_DEBUG=$(ATEC_HAL_VERBOSE_DEBUG) \
-DATEC_I2C_HAL_DEBUG=$(ATEC_I2C_HAL_DEBUG)
cryptoauthlib_CFLAGS += -DATCA_HAL_I2C -std=gnu11 $(ATEC_DEBUG_FLAGS)
ifeq ($(ATEC_PRINTF_ENABLE), 1)
cryptoauthlib_CFLAGS += -DATCAPRINTF
cryptoauthlib_CXXFLAGS += -DATCAPRINTF
endif
$(eval $(call component_compile_rules,cryptoauthlib))
# Helpful error if git submodule not initialised
$(CRYPTOAUTHLIB_MODULE_DIR):
$(error "cryptoauthlib git submodule not installed. Please run 'git submodule update --init'")

@ -0,0 +1 @@
Subproject commit f86b9dbb1e805d85a435456ca03450342dbdc43e

View file

@ -0,0 +1,83 @@
#include "cryptoauthlib.h"
#include "lwip/def.h"
#include <stdio.h>
#include <malloc.h>
#define ATEC_DEBUG
#ifdef ATEC_DEBUG
#define DBG(...) printf("%s:%d ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\r\n");
#define DBGX(...) printf(__VA_ARGS__);
#else
#define DBGV(...) {};
#define DBGVX(...) {};
#endif
void init_cryptoauthlib(uint8_t i2c_addr)
{
uint32_t revision;
uint32_t serial[(ATCA_SERIAL_NUM_SIZE + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
bool config_is_locked, data_is_locked;
ATCA_STATUS status;
const ATCAIfaceCfg *atca_cfg;
/*
* Allow for addresses either in 7-bit format (0-7F) or in Atmel 8-bit shifted-by-one format.
* If user specifies address > 0x80, it must be already shifted since I2C bus addresses > 0x7f are invalid.
*/
if (i2c_addr < 0x7f) i2c_addr <<= 1;
atca_cfg = &cfg_ateccx08a_i2c_default;
if (atca_cfg->atcai2c.slave_address != i2c_addr)
{
ATCAIfaceCfg *cfg = (ATCAIfaceCfg *) calloc(1, sizeof(*cfg));
memcpy(cfg, &cfg_ateccx08a_i2c_default, sizeof(*cfg));
cfg->atcai2c.slave_address = i2c_addr;
atca_cfg = cfg;
}
status = atcab_init(atca_cfg);
if (status != ATCA_SUCCESS)
{
DBG("ATCA: Library init failed");
goto out;
}
status = atcab_info((uint8_t *) &revision);
if (status != ATCA_SUCCESS)
{
DBG("ATCA: Failed to get chip info");
goto out;
}
status = atcab_read_serial_number((uint8_t *) serial);
if (status != ATCA_SUCCESS)
{
DBG("ATCA: Failed to get chip serial number");
goto out;
}
status = atcab_is_locked(LOCK_ZONE_CONFIG, &config_is_locked);
status = atcab_is_locked(LOCK_ZONE_DATA, &data_is_locked);
if (status != ATCA_SUCCESS)
{
DBG("ATCA: Failed to get chip zone lock status");
goto out;
}
DBG("ATECC508 @ 0x%02x: rev 0x%04x S/N 0x%04x%04x%02x, zone "
"lock status: %s, %s",
i2c_addr >> 1, htonl(revision), htonl(serial[0]), htonl(serial[1]),
*((uint8_t *) &serial[2]), (config_is_locked ? "yes" : "no"),
(data_is_locked ? "yes" : "no"));
out:
/*
* We do not free atca_cfg in case of an error even if it was allocated
* because it is referenced by ATCA basic object.
*/
if (status != ATCA_SUCCESS)
{
DBG("ATCA: Chip is not available");
/* In most cases the device can still work, so we continue anyway. */
}
}

View file

@ -0,0 +1,15 @@
#ifndef CRYPTOAUTHLIB_INIT_H
#define CRYPTOAUTHLIB_INIT_H
#ifdef __cplusplus
extern "C" {
#endif
void init_cryptoauthlib(uint8_t i2c_addr);
#ifdef __cplusplus
} //extern "C" {
#endif
#endif //CRYPTOAUTHLIB_INIT_H

View file

@ -0,0 +1,15 @@
#########################################
# Default define variables
#########################################
# Enable/disable debug output from HAL
ATEC_HAL_DEBUG ?= 0
# Enable/disable verbose debug output from HAL
ATEC_HAL_VERBOSE_DEBUG ?= 0
# Enable/disable i2c debug output from HAL
ATEC_I2C_HAL_DEBUG ?= 0
# Enable/disable printf from library
ATEC_PRINTF_ENABLE ?= 0

View file

@ -0,0 +1,372 @@
#include <inttypes.h>
#include <espressif/esp_misc.h> // sdk_os_delay_us
#include "i2c/i2c.h"
#include "cryptoauthlib.h"
#include "FreeRTOS.h"
#include "task.h"
// Move to config if ever necessary
#define I2C_BUS (0)
#define vTaskDelayMs(ms) vTaskDelay((ms)/portTICK_PERIOD_MS)
#if ATEC_HAL_DEBUG || ATEC_HAL_VERBOSE_DEBUG
#define DBG(...) printf("%s:%d ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\r\n");
#define DBGX(...) printf(__VA_ARGS__);
#if ATEC_HAL_VERBOSE_DEBUG
#define DEBUG_HAL
#define DBGV(...) printf("%s:%d ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\r\n");
#define DBGVX(...) printf(__VA_ARGS__);
#else
#define DBGV(...) {};
#define DBGVX(...) {};
#endif
#ifdef DEBUG_HAL
static void print_array(uint8_t *data, uint32_t data_size)
{
uint32_t n;
for (n = 0; n < data_size; n++)
{
printf("%.2x ", data[n]);
if (((n + 1) % 16) == 0)
{
printf("\r\n");
if ((n + 1) != data_size)
printf(" ");
}
}
if (data_size % 16 != 0)
printf("\r\n");
}
#endif
#else
#define DBG(...) {};
#define DBGX(...) {};
#define DBGV(...) {};
#define DBGVX(...) {};
#endif
#if ATEC_I2C_HAL_DEBUG
#define I2C_DBG(...) printf(__VA_ARGS__); printf("\r\n");
#else
#define I2C_DBG(...) {};
#endif
ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg)
{
(void)hal;
(void)cfg;
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_post_init(ATCAIface iface)
{
(void)iface;
return ATCA_SUCCESS;
}
static bool hal_internal_i2c_write(ATCAIface iface, uint8_t *txdata, int len)
{
const ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t slave_addr = (cfg->atcai2c.slave_address >> 1);
int result = i2c_slave_write(I2C_BUS, slave_addr, NULL, txdata, len);
if (result != 0)
{
I2C_DBG("I2C write Error: %d len data: %d first byte: %x", result, len, len > 0 ? txdata[0] : 0);
return false;
}
return true;
}
static bool hal_internal_i2c_read(ATCAIface iface, uint8_t *rxdata, int len)
{
const ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t slave_addr = (cfg->atcai2c.slave_address >> 1);
int result = i2c_slave_read(I2C_BUS, slave_addr, NULL, rxdata, len);
if (result != 0)
{
I2C_DBG("I2C read Error: %d len data: %d", result, len);
return false;
}
return true;
}
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength)
{
ATCA_STATUS status = ATCA_TX_TIMEOUT;
#ifdef DEBUG_HAL
// shamelessly taken from hal_sam4s_i2c_asf.c
printf("hal_i2c_send()\r\n");
printf("\r\nCommand Packet (size:0x%.8x)\r\n", (uint32_t)txlength);
printf("Count : %.2x\r\n", txdata[1]);
printf("Opcode : %.2x\r\n", txdata[2]);
printf("Param1 : %.2x\r\n", txdata[3]);
printf("Param2 : "); print_array(&txdata[4], 2);
if (txdata[1] > 7) {
printf("Data : "); print_array(&txdata[6], txdata[1] - 7);
}
printf("CRC : "); print_array(&txdata[txdata[1] - 1], 2);
printf("\r\n");
#endif
DBG("Send len %d, sending command", txlength);
txdata[0] = 0x03; /* Word Address Value = Command */
txlength++; /* Include Word Address value in txlength */
if (hal_internal_i2c_write(iface, txdata, txlength))
{
DBGV("ATCA_SUCCESS");
status = ATCA_SUCCESS;
}
else
{
DBGV("ATCA_TX_FAIL");
status = ATCA_TX_FAIL;
}
return status;
}
ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength)
{
DBGV("hal_i2c_receive()");
const ATCAIfaceCfg *cfg = atgetifacecfg(iface);
ATCA_STATUS status = ATCA_RX_TIMEOUT;
int retries = cfg->rx_retries;
while (retries-- > 0)
{
if (!hal_internal_i2c_read(iface, rxdata, *rxlength))
{
DBGV("ATCA_RX_FAIL--retry %d", retries);
continue;
}
DBGV("ATCA_SUCCESS");
status = ATCA_SUCCESS;
break;
}
#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
/*
* rxlength is a pointer, which suggests that the actual number of bytes
* received should be returned in the value pointed to, but none of the
* existing HAL implementations do it.
*/
return status;
}
ATCA_STATUS hal_i2c_wake(ATCAIface iface)
{
const ATCAIfaceCfg *cfg = atgetifacecfg(iface);
ATCA_STATUS status = ATCA_WAKE_FAILED;
uint8_t response[4] = { 0x00, 0x00, 0x00, 0x00 };
uint8_t expected_response[4] = { 0x04, 0x11, 0x33, 0x43 };
/*
* ATCA devices define "wake up" token as START, 80 us of SDA low, STOP.
*/
DBGV("Sending wake");
i2c_start(I2C_BUS);
atca_delay_us(80);
i2c_stop(I2C_BUS);
/* After wake signal we need to wait some time for device to init. */
atca_delay_us(cfg->wake_delay);
/* Receive the wake response. */
uint16_t len = sizeof(response);
status = hal_i2c_receive(iface, response, &len);
if (status == ATCA_SUCCESS) {
DBGV("Response %x %x %x %x", response[0], response[1], response[2], response[3]);
if (memcmp(response, expected_response, 4) != 0) {
DBGV("Wake failed");
status = ATCA_WAKE_FAILED;
}
}
return status;
}
ATCA_STATUS hal_i2c_idle(ATCAIface iface)
{
uint8_t idle_cmd = 0x02;
DBG("Sending idle");
return hal_internal_i2c_write(iface, &idle_cmd, 1) ? ATCA_SUCCESS : ATCA_TX_FAIL;
}
ATCA_STATUS hal_i2c_sleep(ATCAIface iface)
{
uint8_t sleep_cmd = 0x01;
DBG("Sending sleep");
return hal_internal_i2c_write(iface, &sleep_cmd, 1) ? ATCA_SUCCESS : ATCA_TX_FAIL;
}
ATCA_STATUS hal_i2c_release(void *hal_data)
{
(void)hal_data;
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses)
{
i2c_buses[0] = 0; // There is just one bus on our esp8266 i2c implementation
return ATCA_SUCCESS;
}
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;
uint16_t rxsize;
uint32_t execution_or_wait_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;
discoverCfg.iface_type = ATCA_I2C_IFACE;
discoverCfg.devtype = ATECC508A;
discoverCfg.atcai2c.slave_address = 0x07;
discoverCfg.atcai2c.bus = busNum;
discoverCfg.atcai2c.baud = 400000;
//discoverCfg.atcai2c.baud = 100000;
discoverCfg.wake_delay = 800;
discoverCfg.rx_retries = 3;
ATCAHAL_t hal;
hal_i2c_init( &hal, &discoverCfg );
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.data, 0x00, sizeof(packet.data));
// get devrev info and set device type accordingly
atInfo( command, &packet );
#ifdef ATCA_NO_POLL
if ((status = atGetExecTime(packet->opcode, device->mCommands)) != ATCA_SUCCESS)
{
return status;
}
execution_or_wait_time = device->mCommands->execution_time_msec;
#else
execution_or_wait_time = 1;//ATCA_POLLING_INIT_TIME_MSEC;
#endif
// 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_or_wait_time);
// receive the response
if ( (status = atreceive( discoverIface, &(packet.data[0]), &rxsize )) != ATCA_SUCCESS )
continue;
if ( (status = isATCAError(packet.data)) != 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 < (int)sizeof(revs508) / 4; i++ ) {
if ( memcmp( &packet.data[1], &revs508[i], 4) == 0 ) {
discoverCfg.devtype = ATECC508A;
break;
}
}
for ( i = 0; i < (int)sizeof(revs204) / 4; i++ ) {
if ( memcmp( &packet.data[1], &revs204[i], 4) == 0 ) {
discoverCfg.devtype = ATSHA204A;
break;
}
}
for ( i = 0; i < (int)sizeof(revs108) / 4; i++ ) {
if ( memcmp( &packet.data[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);
}
hal_i2c_release(&hal);
return ATCA_SUCCESS;
}
void atca_delay_us(uint32_t us)
{
DBG("atca_delay_us: %d", us);
/*
* configTICK_RATE_HZ is 100, implying 10 ms ticks.
* But we run CPU at 160 and tick timer is not updated, hence / 2 below.
* https://github.com/espressif/ESP8266_RTOS_SDK/issues/90
*/
#define USECS_PER_TICK (1000000 / configTICK_RATE_HZ / 2)
uint32_t ticks = us / USECS_PER_TICK;
us = us % USECS_PER_TICK;
if (ticks > 0) vTaskDelay(ticks);
sdk_os_delay_us(us);
}
void atca_delay_ms(uint32_t ms)
{
atca_delay_us(ms * 1000);
}