1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/cryptoauthlib/contrib/atca.c
2023-08-31 14:38:50 +02:00

217 lines
5.3 KiB
C

/*
* Copyright (C) 2019 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup pkg_cryptoauthlib
* @{
*
* @file
* @brief HAL implementation for the library Microchip CryptoAuth devices
*
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
*
* @}
*/
#include <stdio.h>
#include <stdint.h>
#include "timex.h"
#include "ztimer.h"
#include "periph/i2c.h"
#include "periph/gpio.h"
#include "atca.h"
#include "atca_params.h"
/* Timer functions */
void atca_delay_us(uint32_t delay)
{
ztimer_sleep(ZTIMER_USEC, delay);
}
void atca_delay_10us(uint32_t delay)
{
ztimer_sleep(ZTIMER_USEC, delay * 10);
}
void atca_delay_ms(uint32_t delay)
{
ztimer_sleep(ZTIMER_USEC, delay * US_PER_MS);
}
/* Hal I2C implementation */
ATCA_STATUS hal_i2c_init(ATCAIface iface, ATCAIfaceCfg *cfg)
{
(void)iface;
if (cfg->iface_type != ATCA_I2C_IFACE) {
return ATCA_BAD_PARAM;
}
atcab_wakeup();
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_post_init(ATCAIface iface)
{
(void)iface;
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t word_address, uint8_t *txdata, int txlength)
{
(void)word_address;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
int ret;
i2c_acquire(cfg->atcai2c.bus);
ret = i2c_write_bytes(cfg->atcai2c.bus, (cfg->atcai2c.address >> 1),
txdata, txlength, 0);
i2c_release(cfg->atcai2c.bus);
if (ret != 0) {
return ATCA_TX_FAIL;
}
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t word_address, uint8_t *rxdata,
uint16_t *rxlength)
{
(void)word_address;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t retries = cfg->rx_retries;
int ret = -1;
/* read rest of output and insert into rxdata array after first byte */
i2c_acquire(cfg->atcai2c.bus);
while (retries-- > 0 && ret != 0) {
ret = i2c_read_bytes(cfg->atcai2c.bus,
(cfg->atcai2c.address >> 1), (rxdata),
*rxlength, 0);
}
i2c_release(cfg->atcai2c.bus);
if (ret != 0) {
return ATCA_RX_TIMEOUT;
}
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_wake(ATCAIface iface)
{
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t data[4] = { 0 };
#if IS_USED(MODULE_PERIPH_I2C_RECONFIGURE)
/* switch I2C peripheral to GPIO function */
i2c_deinit_pins(cfg->atcai2c.bus);
gpio_init(i2c_pin_sda(cfg->atcai2c.bus), GPIO_OUT);
/* send wake pulse of 100us (t_WOL) */
gpio_clear(i2c_pin_sda(cfg->atcai2c.bus));
atca_delay_us(100);
/* reinit I2C peripheral */
i2c_init_pins(cfg->atcai2c.bus);
#else
/* send wake pulse by sending byte 0x00 */
/* this requires the I2C clock to be 100kHz at a max */
i2c_acquire(cfg->atcai2c.bus);
i2c_write_byte(cfg->atcai2c.bus, ATCA_WAKE_ADDR, data[0], 0);
i2c_release(cfg->atcai2c.bus);
#endif
atca_delay_us(cfg->wake_delay);
uint8_t retries = cfg->rx_retries;
int status = -1;
i2c_acquire(cfg->atcai2c.bus);
while (retries-- > 0 && status != 0) {
status = i2c_read_bytes(cfg->atcai2c.bus,
(cfg->atcai2c.address >> 1),
&data[0], 4, 0);
}
i2c_release(cfg->atcai2c.bus);
if (status != ATCA_SUCCESS) {
return ATCA_COMM_FAIL;
}
return hal_check_wake(data, 4);
}
ATCA_STATUS hal_i2c_idle(ATCAIface iface)
{
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
i2c_acquire(cfg->atcai2c.bus);
i2c_write_byte(cfg->atcai2c.bus, (cfg->atcai2c.address >> 1),
ATCA_IDLE_ADDR, 0);
i2c_release(cfg->atcai2c.bus);
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_sleep(ATCAIface iface)
{
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
i2c_acquire(cfg->atcai2c.bus);
i2c_write_byte(cfg->atcai2c.bus, (cfg->atcai2c.address >> 1),
ATCA_SLEEP_ADDR, 0);
i2c_release(cfg->atcai2c.bus);
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_control(ATCAIface iface, uint8_t option, void *param, size_t paramlen)
{
(void)param;
(void)paramlen;
switch (option) {
case ATCA_HAL_CONTROL_WAKE:
return hal_i2c_wake(iface);
case ATCA_HAL_CONTROL_IDLE:
return hal_i2c_idle(iface);
case ATCA_HAL_CONTROL_SLEEP:
return hal_i2c_sleep(iface);
case ATCA_HAL_CHANGE_BAUD:
return ATCA_UNIMPLEMENTED;
case ATCA_HAL_CONTROL_SELECT:
case ATCA_HAL_CONTROL_DESELECT:
return ATCA_SUCCESS;
default:
return ATCA_BAD_PARAM;
}
return ATCA_UNIMPLEMENTED;
}
ATCA_STATUS hal_i2c_release(void *hal_data)
{
(void)hal_data;
/* This function is unimplemented, because currently the bus gets acquired
and released before and after each read or write operation. It returns
a success code, in case it gets called somewhere in the library. */
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses)
{
(void)i2c_buses;
(void)max_buses;
return ATCA_UNIMPLEMENTED;
}
ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg *cfg, int *found)
{
(void)bus_num;
(void)cfg;
(void)found;
return ATCA_UNIMPLEMENTED;
}