From 3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 23 Aug 2018 17:08:59 +0200 Subject: o Initial import. --- .../external/infineon/include/Datatypes.h | 122 ++++ .../external/infineon/include/ifx_i2c.h | 90 +++ .../external/infineon/include/ifx_i2c_config.h | 296 ++++++++ .../infineon/include/ifx_i2c_data_link_layer.h | 103 +++ .../infineon/include/ifx_i2c_physical_layer.h | 110 +++ .../infineon/include/ifx_i2c_transport_layer.h | 84 +++ .../external/infineon/include/optiga_comms.h | 90 +++ .../external/infineon/include/pal.h | 60 ++ .../external/infineon/include/pal_gpio.h | 84 +++ .../external/infineon/include/pal_i2c.h | 92 +++ .../external/infineon/include/pal_ifx_i2c_config.h | 49 ++ .../external/infineon/include/pal_os_event.h | 61 ++ .../external/infineon/include/pal_os_timer.h | 76 +++ .../external/infineon/include/pal_socket.h | 182 +++++ .../infineon/optiga_comms/ifx_i2c/ifx_i2c.c | 419 ++++++++++++ .../infineon/optiga_comms/ifx_i2c/ifx_i2c_config.c | 68 ++ .../optiga_comms/ifx_i2c/ifx_i2c_data_link_layer.c | 568 ++++++++++++++++ .../optiga_comms/ifx_i2c/ifx_i2c_physical_layer.c | 742 +++++++++++++++++++++ .../optiga_comms/ifx_i2c/ifx_i2c_transport_layer.c | 502 ++++++++++++++ .../infineon/optiga_comms/optiga_comms_ifx_i2c.c | 250 +++++++ .../external/infineon/pal/nrf5x/pal_gpio.c | 97 +++ .../external/infineon/pal/nrf5x/pal_i2c.c | 314 +++++++++ .../infineon/pal/nrf5x/pal_ifx_i2c_config.c | 71 ++ .../external/infineon/pal/nrf5x/pal_os_event.c | 127 ++++ .../external/infineon/pal/nrf5x/pal_os_timer.c | 71 ++ 25 files changed, 4728 insertions(+) create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/Datatypes.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_config.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_data_link_layer.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_physical_layer.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_transport_layer.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/optiga_comms.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_gpio.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_i2c.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_ifx_i2c_config.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_event.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_timer.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_socket.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_config.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_data_link_layer.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_physical_layer.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_transport_layer.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/optiga_comms_ifx_i2c.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_gpio.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_i2c.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_ifx_i2c_config.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_event.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_timer.c (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon') diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/Datatypes.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/Datatypes.h new file mode 100644 index 0000000..2e056fe --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/Datatypes.h @@ -0,0 +1,122 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file contains the type definitions for the fundamental data types. +* +* +* +*/ + +#ifndef _DATATYPES_H_ +#define _DATATYPES_H_ + +/****************************************************************************** +* required includes +* Setup common include order for the used types and definitions +******************************************************************************/ +#include +#include +#include + +/****************************************************************************** +* DataTypes.h +******************************************************************************/ + +/****************************************************************************** +* defines +******************************************************************************/ + +/// @cond hidden +#ifndef _OPTIGA_EXPORTS_DLLEXPORT_H_ +#define _OPTIGA_EXPORTS_DLLEXPORT_H_ + +#if defined(WIN32) || defined(_WIN32) + +#ifdef OPTIGA_LIB_EXPORTS +#define LIBRARY_EXPORTS __declspec(dllexport) +#elif defined(OPTIGA_LIB_EXCLUDE_IMPORT) +#define LIBRARY_EXPORTS +#else +#define LIBRARY_EXPORTS __declspec(dllimport) +#endif // OPTIGA_LIB_EXPORTS + +#else +#define LIBRARY_EXPORTS +#endif //WIN32 + +#endif /*_OPTIGA_EXPORTS_DLLEXPORT_H_*/ +/// @endcond + +/// Definition for false +#ifndef FALSE +#define FALSE 0 +#endif + +/// Definition for true +#ifndef TRUE +#define TRUE 1 +#endif + +/****************************************************************************** +* fundamental typedefs +******************************************************************************/ + +/// Typedef for one byte integer +typedef char char_t; + +/// Typedef for native byte pointer +typedef uint8_t* puint8_t; + +/// Typedef for a 4 byte unsigned integer pointer +typedef uint32_t* puint32_t; + +/// Typedef for unsigned word pointer +typedef uint16_t* puint16_t ; + +/// Typedef for a void +typedef void Void; + +/// Typedef for a double word +typedef double double_t; + +/// Typedef for a float +typedef float float_t; + +/// Typedef for a boolean +typedef uint8_t bool_t; + +/// Typedef for Handle +typedef Void* hdl_t; + +/// typedef for host library status +typedef uint16_t host_lib_status_t; + +/** + * \brief Structure to specify a byte stream consisting of length and data + * pointer. + */ +typedef struct sbBlob_d +{ + /// Length of the byte stream + uint16_t wLen; + + /// Pointer to byte array which contains the data stream + uint8_t *prgbStream; +} sbBlob_d; + +/// typedef for application event handler +typedef void (*app_event_handler_t)(void* upper_layer_ctx, host_lib_status_t event); + +#ifndef _STATIC_H +#define _STATIC_H static +#endif +#endif /* __DATATYPES_H__ */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c.h new file mode 100644 index 0000000..0a3b586 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c.h @@ -0,0 +1,90 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c.h +* +* \brief This file defines the API prototype for IFX I2C protocol v1.65 wrapper. +* +* \addtogroup grIFXI2C +* @{ +*/ + +#ifndef _IFXI2C_H_ +#define _IFXI2C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************************************************************** + * HEADER FILES + **********************************************************************************************************************/ +#include "Datatypes.h" +#include "ifx_i2c_config.h" +/*********************************************************************************************************************** +* MACROS +***********************************************************************************************************************/ + +/*********************************************************************************************************************** + +* ENUMS +***********************************************************************************************************************/ + +/** @brief IFX I2C Reset types */ +typedef enum ifx_i2c_reset_type +{ + /// Cold reset. Both reset pin and vdd pin are toggled low and then high + IFX_I2C_COLD_RESET = 0U, + /// Soft reset. 0x0000 is written to IFX-I2C Soft reset register + IFX_I2C_SOFT_RESET = 1U, + /// Warm reset. Only reset pin is toggled low and then high + IFX_I2C_WARM_RESET = 2U +} ifx_i2c_reset_type_t; +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ + +/** + * \brief Initializes the IFX I2C protocol stack for a given context. + */ +host_lib_status_t ifx_i2c_open(ifx_i2c_context_t *p_ctx); + +/** + * \brief Resets the I2C slave. + */ +host_lib_status_t ifx_i2c_reset(ifx_i2c_context_t *p_ctx, ifx_i2c_reset_type_t reset_type); + +/** + * \brief Sends a command and receives a response for the command. + */ +host_lib_status_t ifx_i2c_transceive(ifx_i2c_context_t *p_ctx,const uint8_t* p_data, const uint16_t* p_data_length, + uint8_t* p_buffer, uint16_t* p_buffer_len); + +/** + * \brief Closes the IFX I2C protocol stack for a given context. + */ +host_lib_status_t ifx_i2c_close(ifx_i2c_context_t *p_ctx); + +/** + * \brief Sets the slave address of the target device. + */ +host_lib_status_t ifx_i2c_set_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t persistent); + +#ifdef __cplusplus +} +#endif +#endif /* _IFXI2C_H_ */ +/** + * @} + **/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_config.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_config.h new file mode 100644 index 0000000..bf1fa2f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_config.h @@ -0,0 +1,296 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_config.h +* +* \brief This file defines the structures and macros for the Infineon I2C Protocol. +* +* \addtogroup grIFXI2C +* @{ +*/ + +#ifndef _IFX_I2C_CONFIG_H_ +#define _IFX_I2C_CONFIG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +// Protocol Stack Includes +#include +#include "pal_i2c.h" +#include "pal_gpio.h" +#include "pal_os_timer.h" + +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ + +/** @brief I2C slave address of the Infineon device */ +#define IFX_I2C_BASE_ADDR (0x30) + +/** @brief Physical Layer: polling interval in microseconds */ +#define PL_POLLING_INVERVAL_US (1000) +/** @brief Physical layer: maximal attempts */ +#define PL_POLLING_MAX_CNT (200) +/** @brief Physical Layer: data register polling interval in microseconds */ +#define PL_DATA_POLLING_INVERVAL_US (5000) +/** @brief Physical Layer: guard time interval in microseconds */ +#define PL_GUARD_TIME_INTERVAL_US (50) + +/** @brief Data link layer: maximum frame size */ +#define DL_MAX_FRAME_SIZE (300) +/** @brief Data link layer: header size */ +#define DL_HEADER_SIZE (5) +/** @brief Data link layer: maximum number of retries in case of transmission error */ +#define DL_TRANS_REPEAT (3) +/** @brief Data link layer: Trans timeout in milliseconds*/ +#define PL_TRANS_TIMEOUT_MS (10) + +/** @brief Transport layer: Maximum exit timeout in seconds */ +#define TL_MAX_EXIT_TIMEOUT (6) + +/** @brief Reset low time for GPIO pin toggling */ +#define RESET_LOW_TIME_MSEC (2000) +/** @brief Start up time */ +#define STARTUP_TIME_MSEC (12000) + +/** @brief Protocol Stack: Status codes for success */ +#define IFX_I2C_STACK_SUCCESS (0x00) +/** @brief Protocol Stack: Status codes for error */ +#define IFX_I2C_STACK_ERROR (0x01) +/** @brief Protocol Stack: Status codes busy */ +#define IFX_I2C_STACK_BUSY (0x02) +/** @brief Protocol Stack: Memory insufficient */ +#define IFX_I2C_STACK_MEM_ERROR (0x03) +/** @brief Protocol Stack: Fatal error. Used internal to IFX I2C Stack */ +#define IFX_I2C_FATAL_ERROR (0x04) + +/** @brief Offset of Datalink header in tx_frame_buffer */ +#define IFX_I2C_DL_HEADER_OFFSET (0) +/** @brief Offset of Transport header in tx_frame_buffer */ +#define IFX_I2C_TL_HEADER_OFFSET (IFX_I2C_DL_HEADER_OFFSET+3) + +/** @brief Protocol Stack debug switch for physical layer (set to 0 or 1) */ +#define IFX_I2C_LOG_PL 0 +/** @brief Protocol Stack debug switch for data link layer (set to 0 or 1) */ +#define IFX_I2C_LOG_DL 0 +/** @brief Protocol Stack debug switch for transport layer (set to 0 or 1) */ +#define IFX_I2C_LOG_TL 0 + +/** @brief Log ID number for physical layer */ +#define IFX_I2C_LOG_ID_PL 0x00 +/** @brief Log ID number for data link layer */ +#define IFX_I2C_LOG_ID_DL 0x01 +/** @brief Log ID number for transport layer */ +#define IFX_I2C_LOG_ID_TL 0x02 +/** @brief Log ID number for platform abstraction layer */ +#define IFX_I2C_LOG_ID_PAL 0x04 + +/*********************************************************************************************************************** +* ENUMS +***********************************************************************************************************************/ + + +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +typedef struct ifx_i2c_context ifx_i2c_context_t; + +/** @brief Event handler function prototype */ +typedef void (*ifx_i2c_event_handler_t)(struct ifx_i2c_context* ctx, host_lib_status_t event, const uint8_t* data, uint16_t data_len); + +/** @brief Physical layer structure */ +typedef struct ifx_i2c_pl +{ + // Physical Layer low level interface variables + + /// Physical layer buffer + uint8_t buffer[DL_MAX_FRAME_SIZE+1]; + /// Tx length + uint16_t buffer_tx_len; + /// Rx length + uint16_t buffer_rx_len; + /// Action on register, read/write + uint8_t register_action; + /// i2c read/i2c write + uint8_t i2c_cmd; + /// Retry counter + uint16_t retry_counter; + + // Physical Layer high level interface variables + + /// Action of frame. Tx/Rx + uint8_t frame_action; + /// Frame state + uint8_t frame_state ; + /// Pointer to data to be sent + uint8_t * p_tx_frame; + /// Length of data to be sent + uint16_t tx_frame_len; + // Upper layer handler + ifx_i2c_event_handler_t upper_layer_event_handler; + + // Physical Layer negotiation/soft reset variables + + /// Negotiation state + uint8_t negotiate_state; + /// Soft reset requested + uint8_t request_soft_reset; +} ifx_i2c_pl_t; + +/** @brief Datalink layer structure */ +typedef struct ifx_i2c_dl +{ + // Data Link layer internal state variables + + /// Datalink layer state + uint8_t state; + /// Tx sequence number + uint8_t tx_seq_nr; + // Rx sequence number + uint8_t rx_seq_nr; + /// Indicate only Rx required + uint8_t action_rx_only; + /// Retransmit counter + uint8_t retransmit_counter; + /// Error occured + uint8_t error; + /// Resynced + uint8_t resynced; + /// Timeout value + uint32_t data_poll_timeout; + /// Transmit buffer size + uint16_t tx_buffer_size; + /// Receive buffer size + uint16_t rx_buffer_size; + /// Pointer to main transmit buffers + uint8_t* p_tx_frame_buffer; + /// Pointer to main receive buffers + uint8_t* p_rx_frame_buffer; + ///Start time of sending frame + uint32_t frame_start_time; + // Upper layer Event handler + ifx_i2c_event_handler_t upper_layer_event_handler; +} ifx_i2c_dl_t; + +/** @brief Transport layer structure */ +typedef struct ifx_i2c_tl +{ + // Transport Layer state and buffer + + /// Transport layer state + uint8_t state; + /// Pointer to packet provided by user + uint8_t* p_actual_packet; + /// Total received data + uint16_t total_recv_length; + /// Actual length of user provided packet + uint16_t actual_packet_length; + /// Offset till which data is sent from p_actual_packet + uint16_t packet_offset; + /// Maximum length of packet at transport layer + uint16_t max_packet_length; + /// Pointer to user provided receive buffer + uint8_t* p_recv_packet_buffer; + /// Length of receive buffer + uint16_t* p_recv_packet_buffer_length; + /// Start time of the transport layer API + uint32_t api_start_time; + ///Chaining error coutn from slave + uint8_t chaining_error_count; + ///Chaining error count for master + uint8_t master_chaining_error_count; + ///State to check last chaining state + uint8_t previous_chaining; + /// transmission done + uint8_t transmission_completed; + /// Error event state + uint8_t error_event; + + /// Upper layer event handler + ifx_i2c_event_handler_t upper_layer_event_handler; +} ifx_i2c_tl_t; + +/** @brief IFX I2C context structure */ +struct ifx_i2c_context +{ + /// I2C Slave address + uint8_t slave_address; + /// Frequency of i2c master + uint16_t frequency; + /// Data link layer frame size + uint16_t frame_size; + /// Pointer to pal gpio context for vdd + pal_gpio_t* p_slave_vdd_pin; + /// Pointer to pal gpio context for reset + pal_gpio_t* p_slave_reset_pin; + /// Pointer to pal i2c context + pal_i2c_t* p_pal_i2c_ctx; + + /// Upper layer event handler + app_event_handler_t upper_layer_event_handler; + /// Upper layer context + void* p_upper_layer_ctx; + /// Pointer to upper layer rx buffer + uint8_t* p_upper_layer_rx_buffer; + /// Pointer to length of upper layer rx buffer + uint16_t* p_upper_layer_rx_buffer_len; + + /// Protocol variables + /// ifx i2c wrapper apis state + uint8_t state; + /// ifx i2c wrapper api status + uint8_t status; + /// reset states + uint8_t reset_state; + /// type of reset + uint8_t reset_type; + /// init pal + uint8_t do_pal_init; + + /// Transport layer context + ifx_i2c_tl_t tl; + /// Datalink layer context + ifx_i2c_dl_t dl; + /// Physical layer context + ifx_i2c_pl_t pl; + + /// IFX I2C tx frame of max length + uint8_t tx_frame_buffer[DL_MAX_FRAME_SIZE]; + /// IFX I2C rx frame of max length + uint8_t rx_frame_buffer[DL_MAX_FRAME_SIZE]; + +}; + +/*********************************************************************************************************************** +* GLOBAL +***********************************************************************************************************************/ + +/** @brief IFX I2C Instance */ +extern ifx_i2c_context_t ifx_i2c_context_0; + +/*********************************************************************************************************************** +* LOCAL ROUTINES +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ + +/** + * @} + **/ +#ifdef __cplusplus +} +#endif +#endif /* _IFX_I2C_CONFIG_H_ */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_data_link_layer.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_data_link_layer.h new file mode 100644 index 0000000..ae89ff3 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_data_link_layer.h @@ -0,0 +1,103 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_data_link_layer.h +* +* \brief This file defines the API prototype for data link layer of the Infineon I2C Protocol Stack library. +* +* \addtogroup grIFXI2C +* @{ +*/ + +#ifndef _IFX_I2C_DATA_LINK_LAYER_H_ +#define _IFX_I2C_DATA_LINK_LAYER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +#include "ifx_i2c_config.h" + +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ +/** @brief Error event propagated to upper layer */ +#define IFX_I2C_DL_EVENT_ERROR (0x01) +/** @brief Transmit success event propagated to upper layer (bit field 1) */ +#define IFX_I2C_DL_EVENT_TX_SUCCESS (0x02) +/** @brief Receive success event propagated to upper layer (bit field 3)*/ +#define IFX_I2C_DL_EVENT_RX_SUCCESS (0x04) + +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ +/** + * @brief Function for initializing the module. + * + * Function initializes and enables the module and registers + * an event handler to receive events from this module. + * @attention This function must be called before using the module. + * + * @param[in,out] p_ctx Pointer to ifx i2c context. + * @param[in] handler Function pointer to the event handler of the upper layer. + * + * @retval IFX_I2C_STACK_SUCCESS If initialization was successful. + * @retval IFX_I2C_STACK_ERROR If the module is already initialized. + */ +host_lib_status_t ifx_i2c_dl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler); + +/** + * @brief Function for sending a frame. + * + * Asynchronous function to send a frame. The function returns immediately. + * One of the following events is propagated to the event handler registered + * with @ref ifx_i2c_dl_init. + * + * @param[in,out] p_ctx Pointer to ifx i2c context. + * @param[in] frame_len Frame length. + * + * @retval IFX_I2C_STACK_SUCCESS If function was successful. + * @retval IFX_I2C_STACK_ERROR If the module is busy. + */ +host_lib_status_t ifx_i2c_dl_send_frame(ifx_i2c_context_t *p_ctx,uint16_t frame_len); + +/** + * @brief Function for receiving a frame. + * + * Asynchronous function to receive a frame. The function returns immediately. + * One of the following events is propagated to the event handler registered + * with @ref ifx_i2c_dl_init. + * + * @param[in,out] p_ctx Pointer to ifx i2c context. + * + * @retval IFX_I2C_STACK_SUCCESS If function was successful. + * @retval IFX_I2C_STACK_ERROR If the module is busy. + */ +host_lib_status_t ifx_i2c_dl_receive_frame(ifx_i2c_context_t *p_ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* _IFX_I2C_DATA_LINK_LAYER_H_ */ + + +/** + * @} + **/ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_physical_layer.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_physical_layer.h new file mode 100644 index 0000000..18366f7 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_physical_layer.h @@ -0,0 +1,110 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_physical_layer.h +* +* \brief This file defines the API prototype for physical layer of the Infineon I2C Protocol Stack library. +* +* \addtogroup grIFXI2C +* @{ +*/ + +#ifndef _IFX_I2C_PHYSICAL_LAYER_H_ +#define _IFX_I2C_PHYSICAL_LAYER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +#include "ifx_i2c_config.h" + +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ +/** + * @brief Function for initializing the module. + * + * Function initializes and enables the module and registers + * an event handler to receive events from this module. + * @attention This function must be called before using the module. + * + * @param[in,out] p_ctx Pointer to ifx i2c context. + * @param[in] handler Function pointer to the event handler of the upper layer. + * + * @retval IFX_I2C_STACK_SUCCESS If initialization was successful. + * @retval IFX_I2C_STACK_ERROR If the module is already initialized. + */ +host_lib_status_t ifx_i2c_pl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler); + +/** + * @brief Function for sending a frame. + * + * Asynchronous function to send a frame. The function returns immediately. + * One of the following events is propagated to the event handler registered + * with @ref ifx_i2c_pl_init + * + * @param[in,out] p_ctx Pointer to ifx i2c context. + * @param[in] p_frame Buffer containing the frame. + * @param[in] frame_len Frame length. + * + * @retval IFX_I2C_STACK_SUCCESS If function was successful. + * @retval IFX_I2C_STACK_ERROR If the module is busy. + */ +host_lib_status_t ifx_i2c_pl_send_frame(ifx_i2c_context_t *p_ctx,uint8_t* p_frame, uint16_t frame_len); + +/** + * @brief Function for receiving a frame. + * + * Asynchronous function to receive a frame. The function returns immediately. + * One of the following events is propagated to the event handler registered + * with @ref ifx_i2c_pl_init + * + * @param[in] p_ctx Pointer to ifx i2c context. + * + * @retval IFX_I2C_STACK_SUCCESS If function was successful. + * @retval IFX_I2C_STACK_ERROR If the module is busy. + */ +host_lib_status_t ifx_i2c_pl_receive_frame(ifx_i2c_context_t *p_ctx); + + +/** + * @brief Function for setting slave address. + * + * Synchronous function to set slave address. + * + * @param[in] p_ctx Pointer to ifx i2c context. + * @param[in] slave_address Holds new slave address[7 Bit] to be set. + * @param[in] storage_type 0 - To set the Slave address until next reset.
+ * Non-zero - To set the slave address to persistent memory. + * + * @retval IFX_I2C_STACK_SUCCESS If function was successful. + * @retval IFX_I2C_STACK_ERROR If setting slave address fails. + */ +host_lib_status_t ifx_i2c_pl_write_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t storage_type); +/** + * @} + **/ + +#ifdef __cplusplus +} +#endif +#endif /* _IFX_I2C_PHYSICAL_LAYER_H_ */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_transport_layer.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_transport_layer.h new file mode 100644 index 0000000..6b61011 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/ifx_i2c_transport_layer.h @@ -0,0 +1,84 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_transport_layer.h +* +* \brief This file defines the API prototype for transport layer of the Infineon I2C Protocol Stack library. +* +* \addtogroup grIFXI2C +* @{ +*/ + +#ifndef _IFX_I2C_TRANSPORT_LAYER_H_ +#define _IFX_I2C_TRANSPORT_LAYER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +#include "ifx_i2c_config.h" +#include "pal_os_timer.h" + +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ +/** + * @brief Function for initializing the module. + * + * Function initializes and enables the module and registers + * an event handler to receive events from this module. + * @attention This function must be called before using the module. + * + * @param[in,out] p_ctx Pointer to ifx i2c context. + * @param[in] handler Function pointer to the event handler of the upper layer. + * + * @retval IFX_I2C_STACK_SUCCESS If initialization was successful. + * @retval IFX_I2C_STACK_ERROR If the module is already initialized. + */ +host_lib_status_t ifx_i2c_tl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler); + +/** + * @brief Function to transmit and receive a packet. + * + * Asynchronous function to send and receive a packet. + * The function returns immediately. One of the following events is + * propagated to the event handler registered with @ref ifx_i2c_tl_init + * + * @param[in,out] p_ctx Pointer to ifx i2c context. + * @param[in] p_packet Buffer containing the packet header. + * @param[in] packet_len Packet header length. + * @param[in] p_recv_packet Buffer containing the packet payload. + * @param[in] recv_packet_len Packet payload length. + * + * @retval IFX_I2C_STACK_SUCCESS If function was successful. + * @retval IFX_I2C_STACK_ERROR If the module is busy. + */ +host_lib_status_t ifx_i2c_tl_transceive(ifx_i2c_context_t *p_ctx,uint8_t* p_packet, uint16_t packet_len, + uint8_t* p_recv_packet, uint16_t* recv_packet_len); + +/** + * @} + **/ +#ifdef __cplusplus +} +#endif +#endif /* IFX_I2C_TRANSPORT_LAYER_H__ */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/optiga_comms.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/optiga_comms.h new file mode 100644 index 0000000..d04cd95 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/optiga_comms.h @@ -0,0 +1,90 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements optiga comms abstraction layer for IFX I2C Protocol. +* +* \addtogroup grOptigaComms +* @{ +*/ + +#ifndef _OPTIGA_COMMS_H_ +#define _OPTIGA_COMMS_H_ +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "Datatypes.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + +/// Succesfull execution +#define OPTIGA_COMMS_SUCCESS 0x0000 +/// Error in execution +#define OPTIGA_COMMS_ERROR 0x0001 +/// Busy, doing operation +#define OPTIGA_COMMS_BUSY 0x0002 + +/********************************************************************************************************************** + * DATA STRUCTURES + *********************************************************************************************************************/ + +/** @brief optiga comms structure */ +typedef struct optiga_comms +{ + /// Comms structure pointer + void* comms_ctx; + /// Upper layer contect + void* upper_layer_ctx; + /// Upper layer handler + app_event_handler_t upper_layer_handler; + /// Optiga comms state + uint8_t state; +}optiga_comms_t; + +extern optiga_comms_t optiga_comms; + +/********************************************************************************************************************** + * API Prototypes + *********************************************************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Opens the communication channel with OPTIGA. + */ +LIBRARY_EXPORTS host_lib_status_t optiga_comms_open(optiga_comms_t *p_ctx); + +/** + * \brief Resets the OPTIGA. + */ +LIBRARY_EXPORTS host_lib_status_t optiga_comms_reset(optiga_comms_t *p_ctx,uint8_t reset_type); + +/** + * \brief Sends and receives the APDU. + */ +LIBRARY_EXPORTS host_lib_status_t optiga_comms_transceive(optiga_comms_t *p_ctx,const uint8_t* p_data, + const uint16_t* p_data_length, + uint8_t* p_buffer, uint16_t* p_buffer_len); + +/** + * \brief Closes the communication channel with OPTIGA. + */ +LIBRARY_EXPORTS host_lib_status_t optiga_comms_close(optiga_comms_t *p_ctx); + +/** +* @} +*/ + +#endif /*_OPTIGA_COMMS_H_*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal.h new file mode 100644 index 0000000..f66b41a --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal.h @@ -0,0 +1,60 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the prototype declarations of platform abstraction layer +* +* \addtogroup grPAL +* @{ +*/ + + +#ifndef _PAL_H_ +#define _PAL_H_ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include + +/********************************************************************************************************************** + * pal.h + *********************************************************************************************************************/ + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + +/// PAL API execution is successful +#define PAL_STATUS_SUCCESS (0x0000) +/// PAL API execution failed +#define PAL_STATUS_FAILURE (0x0001) +/// PAL I2C is busy +#define PAL_STATUS_I2C_BUSY (0x0002) + +/********************************************************************************************************************** + * ENUMS + *********************************************************************************************************************/ +/** + * \brief PAL return status. + */ +typedef uint16_t pal_status_t; + +/********************************************************************************************************************** + * API Prototypes + *********************************************************************************************************************/ + +#endif /* _PAL_H_ */ + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_gpio.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_gpio.h new file mode 100644 index 0000000..171811b --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_gpio.h @@ -0,0 +1,84 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the prototype declarations of pal gpio +* +* \addtogroup grPAL +* @{ +*/ + +#ifndef _PAL_GPIO_H_ +#define _PAL_GPIO_H_ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ + +#include "pal.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * ENUMS + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * DATA STRUCTURES + *********************************************************************************************************************/ + +/** + * \brief Structure defines the PAL GPIO configuration. + */ +typedef struct pal_gpio +{ + /// Pointer to gpio platform specific context/structure + void* p_gpio_hw; + +} pal_gpio_t; + +/********************************************************************************************************************** + * API Prototypes + *********************************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initializes the GPIO PAL. + */ +void pal_gpio_init(void); + +/** + * \brief Sets the gpio pin to high state. + */ +void pal_gpio_set_high(const pal_gpio_t* p_gpio_context); + +/** + * \brief Sets the gpio pin to Low state. + */ +void pal_gpio_set_low(const pal_gpio_t* p_gpio_context); + +#ifdef __cplusplus +} +#endif + +#endif /* _PAL_GPIO_H_ */ + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_i2c.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_i2c.h new file mode 100644 index 0000000..fd470d3 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_i2c.h @@ -0,0 +1,92 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the prototype declarations of pal i2c +* +* \addtogroup grPAL +* @{ +*/ + +#ifndef _PAL_I2C_H_ +#define _PAL_I2C_H_ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ + +#include "pal.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ +/// Event returned when I2C master completes execution +#define PAL_I2C_EVENT_SUCCESS (0x0000) +/// Event returned when I2C master operation fails +#define PAL_I2C_EVENT_ERROR (0x0001) +/// Event returned when lower level I2C bus is busy +#define PAL_I2C_EVENT_BUSY (0x0002) + +/********************************************************************************************************************** + * ENUMS + *********************************************************************************************************************/ + +/********************************************************************************************************************** + * DATA STRUCTURES + *********************************************************************************************************************/ +/** @brief PAL I2C context structure */ +typedef struct pal_i2c +{ + /// Pointer to I2C master platform specific context + void* p_i2c_hw_config; + /// I2C slave address + uint8_t slave_address; + /// Pointer to store the callers context information + void* upper_layer_ctx; + /// Pointer to store the callers handler + void* upper_layer_event_handler; + +} pal_i2c_t; + +/********************************************************************************************************************** + * API Prototypes + *********************************************************************************************************************/ +/** + * @brief Initializes the I2C master. + */ +pal_status_t pal_i2c_init(const pal_i2c_t* p_i2c_context); + +/** + * @brief Sets the I2C Master bitrate + */ +pal_status_t pal_i2c_set_bitrate(const pal_i2c_t* p_i2c_context, uint16_t bitrate); + +/** + * @brief Writes to I2C bus. + */ +pal_status_t pal_i2c_write(pal_i2c_t* p_i2c_context, uint8_t* p_data , uint16_t length); + +/** + * @brief Reads from I2C bus. + */ +pal_status_t pal_i2c_read(pal_i2c_t* p_i2c_context, uint8_t* p_data , uint16_t length); + +/** + * @brief De-initializes the I2C master. + */ +pal_status_t pal_i2c_deinit(const pal_i2c_t* p_i2c_context); + +#endif /* _PAL_I2C_H_ */ + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_ifx_i2c_config.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_ifx_i2c_config.h new file mode 100644 index 0000000..0df491a --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_ifx_i2c_config.h @@ -0,0 +1,49 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the platform abstraction layer extern declarations for ifx i2c. +* +* \addtogroup grPAL +* @{ +*/ + +#ifndef _PAL_IFX_I2C_CONFIG_H_ +#define _PAL_IFX_I2C_CONFIG_H_ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "pal.h" +#include "pal_i2c.h" +#include "pal_gpio.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * ENUMS + *********************************************************************************************************************/ + +/********************************************************************************************************************** + * PAL extern definitions for IFX I2C + *********************************************************************************************************************/ +extern pal_i2c_t optiga_pal_i2c_context_0; +extern pal_gpio_t optiga_vdd_0; +extern pal_gpio_t optiga_reset_0; + +#endif /* _PAL_IFX_I2C_CONFIG_H_ */ + +/** +* @} +*/ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_event.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_event.h new file mode 100644 index 0000000..e4a1315 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_event.h @@ -0,0 +1,61 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the prototype declarations of pal os event +* +* \addtogroup grPAL +* @{ +*/ + + +#ifndef _PAL_OS_EVENT_H_ +#define _PAL_OS_EVENT_H_ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ + +#include "Datatypes.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * ENUMS + *********************************************************************************************************************/ + +/********************************************************************************************************************** + * PAL extern definitions + *********************************************************************************************************************/ + +/** + * @brief typedef for Callback function when timer elapses. + */ +typedef void (*register_callback)(void*); + +/** + * \brief Initializes the OS event PAL. + */ +void pal_os_event_init(void); + +/** + * @brief Callback registration function to trigger once when timer expires. + */ +void pal_os_event_register_callback_oneshot(register_callback callback, void* callback_args, uint32_t time_us); + +#endif //_PAL_OS_EVENT_H_ + +/** +* @} +*/ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_timer.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_timer.h new file mode 100644 index 0000000..796e39e --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_os_timer.h @@ -0,0 +1,76 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the prototype declarations of pal os timer functionalities. +* +* \addtogroup grPAL +* @{ +*/ +#ifndef _PAL_OS_TIMER_H_ +#define _PAL_OS_TIMER_H_ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ + +#include "pal.h" + +/********************************************************************************************************************* + * pal_os_timer.h +*********************************************************************************************************************/ + + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * ENUMS + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * DATA STRUCTURES + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * API Prototypes + *********************************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Gets tick count value in milliseconds + */ +uint32_t pal_os_timer_get_time_in_milliseconds(void); + +/** + * @brief Waits or delay until the supplied milliseconds + */ +void pal_os_timer_delay_in_milliseconds(uint16_t milliseconds); + + +#ifdef __cplusplus +} +#endif + +#endif /* _PAL_OS_TIMER_H_ */ + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_socket.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_socket.h new file mode 100644 index 0000000..5456bca --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/include/pal_socket.h @@ -0,0 +1,182 @@ +/** +* \copyright +* Copyright© 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA™ Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the prototype declarations of pal socket functionalities +* \ingroup grPAL +* @{ +*/ + + +#ifndef _PAL_SOCKET_H_ +#define _PAL_SOCKET_H_ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ + +#ifndef WIN32 + #include "Datatypes.h" + #include "DAVE.h" + #include "udp.h" + #include "inet.h" +#else + #include + #include "Datatypes.h" +#endif + +#include "ErrorCodes.h" +#include "UDPErrorCodes.h" + +/// @cond hidden +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ +#ifndef WIN32 + #define IPAddressParse(pzIpAddress, psIPAddress) (inet_aton(pzIpAddress, psIPAddress)) +#else + #define IPAddressParse(pzIpAddress, psIPAddress) (1) +#endif +/// @endcond +/********************************************************************************************************************** + * ENUMS + *********************************************************************************************************************/ + + +/********************************************************************************************************************** + * DATA STRUCTURES + *********************************************************************************************************************/ + +#ifndef WIN32 +/** + * \brief Pointer type definition of pal socket receive event callback + */ +typedef void (*pal_socket_event_listener)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port); +#endif + + + +/** + * \brief This structure contains socket communication data + */ +typedef enum eRecvMode_d +{ + eBlock = 0x10, + + eNonBlock = 0x20 +}eRecvMode_d; + +/** + * \brief This structure contains socket communication data + */ +#ifndef WIN32 + +typedef struct pal_socket +{ + + ///UDP structure Tx + struct udp_pcb *pcbTx; + + ///UDP structure Rx + struct udp_pcb *pcbRx; + + //Received IP address + ip_addr_t sIPAddress; + + ///Function pointer to hold receive callback + pal_socket_event_listener pfListen; + + ///Port for UDP communication + uint16_t wPort; + + ///Transport Layer Timeout + uint16_t wTimeout; + + ///Enumeration to indicate Blocking or Non blocking + uint8_t bMode; + +} pal_socket_t; + +#else + +typedef struct pal_socket +{ + ///Received IP address + char* sIPAddress; + + ///Port for UDP communication + uint16_t wPort; + + ///Pointer to the socket for Receiving + SOCKET SocketHdl; + + ///IPv4 Socket address for Receiving + SOCKADDR_IN sSocketAddrIn; + + ///Transport Layer Timeout + uint16_t wTimeout; + + ///Enumeration to indicate Blocking or Non blocking + uint8_t bMode; + +} pal_socket_t; +#endif + +/********************************************************************************************************************** + * API Prototypes + *********************************************************************************************************************/ + +/** + * \brief Assign IP address + */ +#ifndef WIN32 +int32_t pal_socket_assign_ip_address(const char* p_ip_address,void *p_input_ip_address); +#else +int32_t pal_socket_assign_ip_address(const char_t* p_ip_address,char** p_input_ip_address); +#endif + +/** + * \brief Initializes the socket communication structure + */ +int32_t pal_socket_init(pal_socket_t* p_socket); + +/** + * \brief Creates server port and bind + */ +int32_t pal_socket_open(pal_socket_t* p_socket, + uint16_t port); +/** + * \brief Creates a client port and connect + */ +int32_t pal_socket_connect(pal_socket_t* p_socket, + uint16_t port); +/** + * \brief Receive data from the client + */ +int32_t pal_socket_listen(pal_socket_t* p_socket, uint8_t *p_data, + uint32_t *p_length); +/** + * \brief Sends the data to the the client + */ +int32_t pal_socket_send(const pal_socket_t* p_socket, uint8_t *p_data, + uint32_t length); +/** + * \brief Closes the socket communication and release the udp port + */ +void pal_socket_close(pal_socket_t* p_socket); + +#endif //_PAL_SOCKET_H_ + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c.c new file mode 100644 index 0000000..9c15cfd --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c.c @@ -0,0 +1,419 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c.c +* +* \brief This file implements the wrapper API Layer for IFX I2C protocol v1.65. +* +* \addtogroup grIFXI2C +* @{ +*/ + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +#include "ifx_i2c.h" +#include "ifx_i2c_transport_layer.h" +#include "pal_os_event.h" + +/// @cond hidden +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ + +// IFX I2C states +#define IFX_I2C_STATE_UNINIT (0x01) +#define IFX_I2C_STATE_IDLE (0x02) +#define IFX_I2C_STATUS_BUSY (0x03) +#define IFX_I2C_STATUS_NOT_BUSY (0x04) + +/// IFX I2C Reset states +#define IFX_I2C_STATE_RESET_PIN_LOW (0xB1) +#define IFX_I2C_STATE_RESET_PIN_HIGH (0xB2) +#define IFX_I2C_STATE_RESET_INIT (0xB3) + +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ + +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +* GLOBAL +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +* LOCAL ROUTINES +***********************************************************************************************************************/ +/// Transport Layer event handler +void ifx_i2c_tl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len); + +/// Performs initialization +static host_lib_status_t ifx_i2c_init(ifx_i2c_context_t* ifx_i2c_context); + +//lint --e{526} suppress "This API is defined in ifx_i2c_physical_layer. Since it is a low level API, +//to avoid exposing, header file is not included " +extern host_lib_status_t ifx_i2c_pl_write_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t storage_type); +/// @endcond +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ +/** + * Initializes the IFX I2C protocol stack for the given context. + *
+ *
+ * \image html ifx_i2c_open.png "ifx_i2c_open()" width=20cm + * + *Pre Conditions: + * - None
+ * + *API Details: + * - Performs a reset sequence.
+ * - Initializes the I2C slave device.
+ * - Initializes the ifx i2c protocol stack and registers the event callbacks. + * - Negotiates the frame size and bit rate with the I2C slave.
+ *
+ * + *User Input:
+ * - The input #ifx_i2c_context_t p_ctx must not be NULL. + * - The following parameters in #ifx_i2c_context_t must be initialized with appropriate values
+ * - slave address : Address of I2C slave + * - frame_size : Frame size in bytes.Minimum supported value is 16 bytes.
+ * - It is recommended not to use a value greater than the slave's frame size. + * - The user specified frame size is written to I2C slave's frame size register. + * The frame size register is read back from I2C slave. + * This frame value is used by the ifx-i2c protocol even if it is not equal to the user specified value. + * + * - frequency : Frequency/speed of I2C master in KHz. + * - This must be lowest of the maximum frequency supported by the devices (master/slave) connected on the bus. + * - Initial negotiation starts with a frequency of 100KHz. + * - If the user specified frequency is more than 400 KHz, the I2C slave is configured to operate in "Fm+" mode, + * otherwise the I2C slave is configured for "SM & Fm" mode.
+ * - If the user specified frequency frequency negotiation fails, the I2C master frequency remains at 100KHz
+ * + * - upper_layer_event_handler : Upper layer event handler.This is invoked when #ifx_i2c_open() is asynchronously completed. + * - upper_layer_ctx : Context of upper layer. + * - p_slave_vdd_pin : GPIO pin for VDD. If not set, cold reset is not done. + * - p_slave_reset_pin : GPIO pin for Reset. If not set, warm reset is not done. + * + *Notes: + * - The values of registers MAX_SCL_FREQU and DATA_REG_LEN, read from slave are not validated. + * - At present, only single instance of #ifx_i2c_context_t is supported. + * + *
+ * + * \param[in,out] p_ctx Pointer to #ifx_i2c_context_t + * + * \retval #IFX_I2C_STACK_SUCCESS + * \retval #IFX_I2C_STACK_ERROR + */ +host_lib_status_t ifx_i2c_open(ifx_i2c_context_t *p_ctx) +{ + host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR; + + //If api status is not busy, proceed + if ((IFX_I2C_STATUS_BUSY != p_ctx->status)) + { + p_ctx->p_pal_i2c_ctx->upper_layer_ctx = p_ctx; + p_ctx->reset_type = (uint8_t)IFX_I2C_COLD_RESET; + p_ctx->reset_state = IFX_I2C_STATE_RESET_PIN_LOW; + p_ctx->do_pal_init = TRUE; + p_ctx->state = IFX_I2C_STATE_UNINIT; + + // Init GPIO and OS event PAL + pal_gpio_init(); + pal_os_event_init(); + + api_status = ifx_i2c_init(p_ctx); + if(IFX_I2C_STACK_SUCCESS == api_status) + { + p_ctx->status = IFX_I2C_STATUS_BUSY; + } + } + + return api_status; +} + +/** + * Resets the I2C slave and initializes the IFX I2C protocol stack for the given context. + *
+ *
+ * \image html ifx_i2c_reset.png "ifx_i2c_reset()" width=20cm + * + *Pre Conditions: + * - IFX I2C protocol stack must be initialized.
+ * + *API Details: + * - Resets the I2C slave.
+ * - Initializes the ifx i2c protocol stack.
+ * - Re-Initializes and negotiates the frame size and bit rate with the I2C slave. + * The values remain same as that in previous #ifx_i2c_open().
+ *
+ * + *User Input:
+ * - The input #ifx_i2c_context_t p_ctx must not be NULL. + * + *Notes: + * For COLD and WARM reset type: If the gpio(vdd and/or reset) pins are not configured, + * the API continues without any failure return status
+ * + * \param[in,out] p_ctx Pointer to #ifx_i2c_context_t + * \param[in,out] reset_type type of reset + * + * \retval #IFX_I2C_STACK_SUCCESS + * \retval #IFX_I2C_STACK_ERROR + */ +host_lib_status_t ifx_i2c_reset(ifx_i2c_context_t *p_ctx, ifx_i2c_reset_type_t reset_type) +{ + host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR; + + // Proceed, if not busy and in idle state + if ((IFX_I2C_STATE_IDLE == p_ctx->state) && (IFX_I2C_STATUS_BUSY != p_ctx->status)) + { + p_ctx->reset_type = (uint8_t)reset_type; + p_ctx->reset_state = IFX_I2C_STATE_RESET_PIN_LOW; + p_ctx->do_pal_init = FALSE; + + api_status = ifx_i2c_init(p_ctx); + if(IFX_I2C_STACK_SUCCESS == api_status) + { + p_ctx->status = IFX_I2C_STATUS_BUSY; + } + } + return api_status; +} + +/** + + * Sends a command and receives a response for the command.
+ *
+ * \image html ifx_i2c_transceive.png "ifx_i2c_transceive()" width=20cm + * + * + *Pre Conditions: + * - IFX I2C protocol stack must be initialized.
+ * + *API Details: + * - Transmit data(Command) to I2C slave.
+ * - Receive data(Response) from I2C slave.
+ *
+ * + *User Input:
+ * - The input #ifx_i2c_context_t p_ctx must not be NULL. + * - The following parameters in #ifx_i2c_context_t must be initialized with appropriate values
+ * - upper_layer_event_handler : Upper layer event handler, if it is different from that in #ifx_i2c_open(). + * This is invoked when #ifx_i2c_transceive is asynchronously completed. + * - upper_layer_ctx : Context of upper layer, if it is different from that in #ifx_i2c_open. + * + *Notes: + * - The actual number of bytes received is stored in p_rx_buffer_len. In case of error,p_rx_buffer_len is set to 0.
+ * - If the size of p_rx_buffer is zero or insufficient to copy the response bytes then + * #IFX_I2C_STACK_MEM_ERROR error is returned. + * + * \param[in,out] p_ctx Pointer to #ifx_i2c_context_t + * \param[in] p_data Pointer to the write data buffer + * \param[in] p_data_length Pointer to the length of the write data buffer + * \param[in,out] p_rx_buffer Pointer to the receive data buffer + * \param[in,out] p_rx_buffer_len Pointer to the length of the receive data buffer + * + * \retval #IFX_I2C_STACK_SUCCESS + * \retval #IFX_I2C_STACK_ERROR + * \retval #IFX_I2C_STACK_MEM_ERROR + */ +host_lib_status_t ifx_i2c_transceive(ifx_i2c_context_t *p_ctx,const uint8_t* p_data, const uint16_t* p_data_length, + uint8_t* p_rx_buffer, uint16_t* p_rx_buffer_len) +{ + host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR; + // Proceed, if not busy and in idle state + if ((IFX_I2C_STATE_IDLE == p_ctx->state) && (IFX_I2C_STATUS_BUSY != p_ctx->status)) + { + p_ctx->p_upper_layer_rx_buffer = p_rx_buffer; + p_ctx->p_upper_layer_rx_buffer_len = p_rx_buffer_len; + api_status = ifx_i2c_tl_transceive(p_ctx,(uint8_t*)p_data, (*p_data_length), + (uint8_t*)p_rx_buffer , p_rx_buffer_len); + if (IFX_I2C_STACK_SUCCESS == api_status) + { + p_ctx->status = IFX_I2C_STATUS_BUSY; + } + } + return api_status; +} + + +/** + * Closes the IFX I2C protocol stack for a given context. + *
+ *
+ * \image html ifx_i2c_close.png "ifx_i2c_close()" width=20cm + * + *Pre Conditions: + * - None
+ * + *API Details: + * - De-Initializes the I2C slave device.
+ * - Power downs the I2C slave.
+ *
+ * + *User Input:
+ * - The input #ifx_i2c_context_t p_ctx must not be NULL. + * + *Notes: + * + * \param[in,out] p_ctx Pointer to #ifx_i2c_context_t + * + * \retval #IFX_I2C_STACK_SUCCESS + */ +host_lib_status_t ifx_i2c_close(ifx_i2c_context_t *p_ctx) +{ + host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR; + // Proceed, if not busy and in idle state + if (IFX_I2C_STATUS_BUSY != p_ctx->status) + { + api_status = IFX_I2C_STACK_SUCCESS; + //lint --e{534} suppress "Return value is not required to be checked" + // Close I2C master + pal_i2c_deinit(p_ctx->p_pal_i2c_ctx); + // Also power off the device + pal_gpio_set_low(p_ctx->p_slave_vdd_pin); + pal_gpio_set_low(p_ctx->p_slave_reset_pin); + + ifx_i2c_tl_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS,NULL,0); + p_ctx->state = IFX_I2C_STATE_UNINIT; + p_ctx->status = IFX_I2C_STATUS_NOT_BUSY; + } + return api_status; +} + +/** +* Writes new I2C slave Address to the target device.
+* +*Pre Conditions: +* - IFX I2C protocol stack must be initialized.
+* +*API Details: +* - This API is implemented in synchronous mode. +* - If the write fails due to the following reasons, this API repeats the write for #PL_POLLING_MAX_CNT times +* with a fixed interval of #PL_POLLING_INVERVAL_US microseconds and exits with respective return status. +* - I2C bus is in busy state, returns #IFX_I2C_STACK_BUSY +* - No-acknowledge(NACK) received from slave, returns #IFX_I2C_STACK_ERROR +* - I2C errors, returns #IFX_I2C_STACK_ERROR +* - Only bits [6:0] from parameter "slave_address" are considered as slave address. Hence the bit 7 is ignored. +* - Slave address validation is not done in the implementation. Provide a valid slave address as input. +* +*Notes: +* - If persistent mode is selected, the ifx i2c context slave address will be over-written with the new slave address. +* Even after ifx i2c open/reset, all future executions will use the new slave address.
+* - If volatile mode is selected, the pal_i2c_context slave address will be over-written with the new slave address. +* This persists only till the next ifx_i2c open/reset is called. +* +* \param[in,out] p_ctx Pointer to #ifx_i2c_context_t +* \param[in] slave_address Holds new slave address[7 Bit] to be set. +* \param[in] persistent 0 - To set the Slave address until next reset.
+* Non-zero - To set the slave address to persistent memory. +* +* \retval #IFX_I2C_STACK_SUCCESS +* \retval #IFX_I2C_STACK_ERROR +*/ +host_lib_status_t ifx_i2c_set_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t persistent) +{ + host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR; + + if ((IFX_I2C_STATE_IDLE == p_ctx->state)) + { + p_ctx->p_pal_i2c_ctx->upper_layer_ctx = p_ctx; + + api_status = ifx_i2c_pl_write_slave_address(p_ctx, slave_address, persistent); + } + + return api_status; +} + +/// @cond hidden +//lint --e{715} suppress "This is ignored as ifx_i2c_event_handler_t handler function prototype requires this argument" +void ifx_i2c_tl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len) +{ + // If there is no upper layer handler, don't do anything and return + if (NULL != p_ctx->upper_layer_event_handler) + { + p_ctx->upper_layer_event_handler(p_ctx->p_upper_layer_ctx,event); + } + p_ctx->status = IFX_I2C_STATUS_NOT_BUSY; + switch(p_ctx->state) + { + case IFX_I2C_STATE_UNINIT: + if (IFX_I2C_STACK_SUCCESS == event) + { + p_ctx->state = IFX_I2C_STATE_IDLE; + } + break; + default: + break; + } +} + + +static host_lib_status_t ifx_i2c_init(ifx_i2c_context_t* p_ifx_i2c_context) +{ + host_lib_status_t api_status = IFX_I2C_STACK_ERROR; + + if ((p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_WARM_RESET)|| + (p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_COLD_RESET)) + { + switch(p_ifx_i2c_context->reset_state) + { + case IFX_I2C_STATE_RESET_PIN_LOW: + // Setting the Vdd & Reset pin to low + if (p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_COLD_RESET) + { + pal_gpio_set_low(p_ifx_i2c_context->p_slave_vdd_pin); + } + pal_gpio_set_low(p_ifx_i2c_context->p_slave_reset_pin); + p_ifx_i2c_context->reset_state = IFX_I2C_STATE_RESET_PIN_HIGH; + pal_os_event_register_callback_oneshot((register_callback)ifx_i2c_init, + (void *)p_ifx_i2c_context, RESET_LOW_TIME_MSEC); + api_status = IFX_I2C_STACK_SUCCESS; + break; + + case IFX_I2C_STATE_RESET_PIN_HIGH: + // Setting the Vdd & Reset pin to high + if (p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_COLD_RESET) + { + pal_gpio_set_high(p_ifx_i2c_context->p_slave_vdd_pin); + } + pal_gpio_set_high(p_ifx_i2c_context->p_slave_reset_pin); + p_ifx_i2c_context->reset_state = IFX_I2C_STATE_RESET_INIT; + pal_os_event_register_callback_oneshot((register_callback)ifx_i2c_init, + (void *)p_ifx_i2c_context, STARTUP_TIME_MSEC); + api_status = IFX_I2C_STACK_SUCCESS; + break; + + case IFX_I2C_STATE_RESET_INIT: + //Frequency and frame size negotiation + api_status = ifx_i2c_tl_init(p_ifx_i2c_context,ifx_i2c_tl_event_handler); + break; + default: + break; + } + } + //soft reset + else + { + p_ifx_i2c_context->pl.request_soft_reset = (uint8_t)TRUE; //Soft reset + api_status = ifx_i2c_tl_init(p_ifx_i2c_context,ifx_i2c_tl_event_handler); + } + + return api_status; +} +/// @endcond +/** +* @} +*/ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_config.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_config.c new file mode 100644 index 0000000..92cafb2 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_config.c @@ -0,0 +1,68 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_config.c +* +* \brief This file provides the ifx i2c platform specific context configurations. +* +* \addtogroup grIFXI2C +* @{ +*/ + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +// Protocol Stack Includes +#include "pal_ifx_i2c_config.h" +#include "ifx_i2c_config.h" + +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ + + +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ + +/** @brief This is IFX I2C context. Only one context is supported per slave.*/ +//lint --e{785} suppress "Only required fields are initialized, the rest are handled by consumer of this structure" +ifx_i2c_context_t ifx_i2c_context_0 = +{ + /// Slave address + 0x30, + /// i2c-master frequency + 400, + /// IFX-I2C frame size + 0x3B, + /// Vdd pin + &optiga_vdd_0, + /// Reset pin + &optiga_reset_0, + /// optiga pal i2c context + &optiga_pal_i2c_context_0 +}; + +/*********************************************************************************************************************** +* GLOBAL +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* LOCAL ROUTINES +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ + +/** + * @} + **/ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_data_link_layer.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_data_link_layer.c new file mode 100644 index 0000000..aea960c --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_data_link_layer.c @@ -0,0 +1,568 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_data_link_layer.c +* +* \brief This file implements the IFX I2C Datalink Layer. +* +* \addtogroup grIFXI2C +* @{ +*/ + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +#include "ifx_i2c_data_link_layer.h" +#include "ifx_i2c_physical_layer.h" // include lower layer header + +/// @cond hidden +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ +// Data Link layer internal states +#define DL_STATE_UNINIT (0x00) +#define DL_STATE_IDLE (0x01) +#define DL_STATE_TX (0x02) +#define DL_STATE_RX (0x03) +#define DL_STATE_ACK (0x04) +#define DL_STATE_RESEND (0x05) +#define DL_STATE_NACK (0x06) +#define DL_STATE_ERROR (0x08) +#define DL_STATE_DISCARD (0x09) +#define DL_STATE_RX_DF (0x0A) +#define DL_STATE_RX_CF (0x0B) + +// Data Link Layer Frame Control Constants +#define DL_FCTR_FTYPE_MASK (0x80) +#define DL_FCTR_FTYPE_OFFSET (7) +#define DL_FCTR_VALUE_CONTROL_FRAME (0x01) + +#define DL_FCTR_SEQCTR_MASK (0x60) +#define DL_FCTR_SEQCTR_OFFSET (5) +#define DL_FCTR_SEQCTR_VALUE_ACK (0x00) +#define DL_FCTR_SEQCTR_VALUE_NACK (0x01) +#define DL_FCTR_SEQCTR_VALUE_RESYNC (0x02) +#define DL_FCTR_SEQCTR_VALUE_RFU (0x03) + +#define DL_FCTR_FRNR_MASK (0x0C) +#define DL_FCTR_FRNR_OFFSET (2) + +#define DL_FCTR_ACKNR_MASK (0x03) +#define DL_FCTR_ACKNR_OFFSET (0) + +// Data Link Layer frame counter max value +#define DL_MAX_FRAME_NUM (0x03) + +// Data link layer length +#define DL_CONTROL_FRAME_LENGTH (5) + +// Setup debug log statements +#if IFX_I2C_LOG_DL == 1 +#define LOG_DL IFX_I2C_LOG +#else +#define LOG_DL(...) //printf(__VA_ARGS__) +#endif + + +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* GLOBAL +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* LOCAL ROUTINES +***********************************************************************************************************************/ +/// Helper function to calculate CRC of a byte +_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc_byte(uint16_t wSeed, uint8_t bByte); +/// Helper function to calculate CRC of a frame +_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc(const uint8_t* p_data, uint16_t data_len); +/// Internal function to send frame +_STATIC_H host_lib_status_t ifx_i2c_dl_send_frame_internal(ifx_i2c_context_t *p_ctx,uint16_t frame_len,uint8_t seqctr_value, uint8_t resend); +/// Helper function to send resync +_STATIC_H host_lib_status_t ifx_i2c_dl_resync(ifx_i2c_context_t* p_ctx); +/// Helper function to resend frame +_STATIC_H void ifx_i2c_dl_resend_frame(ifx_i2c_context_t* p_ctx,uint8_t seqctr_value); +/// Data Link Layer state machine +_STATIC_H void ifx_i2c_pl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len); + +/// @endcond +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ +host_lib_status_t ifx_i2c_dl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler) +{ + LOG_DL("[IFX-DL]: Init\n"); + + p_ctx->dl.state = DL_STATE_UNINIT; + // Initialize Physical Layer (and register event handler) + if (ifx_i2c_pl_init(p_ctx, ifx_i2c_pl_event_handler) != IFX_I2C_STACK_SUCCESS) + { + return IFX_I2C_STACK_ERROR; + } + + // Initialize internal variables + p_ctx->dl.upper_layer_event_handler = handler; + p_ctx->dl.state = DL_STATE_IDLE; + p_ctx->dl.tx_seq_nr = DL_MAX_FRAME_NUM; + p_ctx->dl.rx_seq_nr = DL_MAX_FRAME_NUM; + p_ctx->dl.resynced = 0; + p_ctx->dl.error = 0; + p_ctx->dl.p_tx_frame_buffer = p_ctx->tx_frame_buffer; + p_ctx->dl.p_rx_frame_buffer = p_ctx->rx_frame_buffer; + + return IFX_I2C_STACK_SUCCESS; +} + +host_lib_status_t ifx_i2c_dl_send_frame(ifx_i2c_context_t *p_ctx,uint16_t frame_len) +{ + LOG_DL("[IFX-DL]: Start TX Frame\n"); + // State must be idle and payload available + if (p_ctx->dl.state != DL_STATE_IDLE || !frame_len) + { + return IFX_I2C_STACK_ERROR; + } + + p_ctx->dl.state = DL_STATE_TX; + p_ctx->dl.retransmit_counter = 0; + p_ctx->dl.action_rx_only = 0; + p_ctx->dl.tx_buffer_size = frame_len; + p_ctx->dl.data_poll_timeout = PL_TRANS_TIMEOUT_MS; + + return ifx_i2c_dl_send_frame_internal(p_ctx,frame_len, DL_FCTR_SEQCTR_VALUE_ACK, 0); +} + +host_lib_status_t ifx_i2c_dl_receive_frame(ifx_i2c_context_t *p_ctx) +{ + LOG_DL("[IFX-DL]: Start RX Frame\n"); + + if (p_ctx->dl.state != DL_STATE_IDLE) + { + return IFX_I2C_STACK_ERROR; + } + + // Set internal state + p_ctx->dl.state = DL_STATE_RX; + p_ctx->dl.retransmit_counter = 0; + p_ctx->dl.action_rx_only = 1; + p_ctx->dl.frame_start_time = pal_os_timer_get_time_in_milliseconds(); + p_ctx->dl.data_poll_timeout = TL_MAX_EXIT_TIMEOUT*1000; + + return ifx_i2c_pl_receive_frame(p_ctx); +} + +_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc_byte(uint16_t wSeed, uint8_t bByte) +{ + uint16_t wh1; + uint16_t wh2; + uint16_t wh3; + uint16_t wh4; + + wh1 = (wSeed ^ bByte) & 0xFF; + wh2 = wh1 & 0x0F; + wh3 = ((uint16_t)(wh2 << 4)) ^ wh1; + wh4 = wh3 >> 4; + + return ((uint16_t)((((uint16_t)((((uint16_t)(wh3 << 1)) ^ wh4) << 4)) ^ wh2) << 3)) ^ wh4 + ^ (wSeed >> 8); +} + +_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc(const uint8_t* p_data, uint16_t data_len) +{ + uint16_t i; + uint16_t crc = 0; + + for (i = 0; i < data_len; i++) + { + crc = ifx_i2c_dl_calc_crc_byte(crc, p_data[i]); + } + + return crc; +} + +_STATIC_H host_lib_status_t ifx_i2c_dl_send_frame_internal(ifx_i2c_context_t *p_ctx,uint16_t frame_len, + uint8_t seqctr_value, uint8_t resend) +{ + uint16_t crc; + uint16_t ack_nr = p_ctx->dl.rx_seq_nr; + uint8_t* p_buffer; + + LOG_DL("[IFX-DL]: TX Frame len %d\n", frame_len); + // In case of sending a NACK the next frame is referenced + if (seqctr_value == DL_FCTR_SEQCTR_VALUE_NACK) + { + ack_nr = (p_ctx->dl.rx_seq_nr + 1) & DL_MAX_FRAME_NUM; + } + if(seqctr_value == DL_FCTR_SEQCTR_VALUE_RESYNC) + { + ack_nr = 0; + // Use rx buffer to send resync + p_buffer = p_ctx->dl.p_rx_frame_buffer; + } + else + { + p_buffer = p_ctx->dl.p_tx_frame_buffer; + } + // Set sequence control value (ACK or NACK) and referenced frame number + p_buffer[0] = (uint8_t)(ack_nr << DL_FCTR_ACKNR_OFFSET); + p_buffer[0] |= (uint8_t)(seqctr_value << DL_FCTR_SEQCTR_OFFSET); + + if (frame_len) // Data frame + { + // Increment and set frame transmit sequence number + if ((!resend)||(p_ctx->dl.resynced)) + { + p_ctx->dl.tx_seq_nr = (p_ctx->dl.tx_seq_nr + 1) & DL_MAX_FRAME_NUM; + } + p_buffer[0] |= (uint8_t)(p_ctx->dl.tx_seq_nr << DL_FCTR_FRNR_OFFSET); + // Reset resync received + p_ctx->dl.resynced = 0; + } + else // Control frame + { + p_buffer[0] |= DL_FCTR_FTYPE_MASK; + } + + // Set frame length + p_buffer[1] = (uint8_t)(frame_len >> 8); + p_buffer[2] = (uint8_t)frame_len; + + // Calculate frame CRC + crc = ifx_i2c_dl_calc_crc(p_buffer, 3 + frame_len); + p_buffer[3 + frame_len] = (uint8_t) (crc >> 8); + p_buffer[4 + frame_len] = (uint8_t)crc; + + // Transmit frame + return ifx_i2c_pl_send_frame(p_ctx,p_buffer, DL_HEADER_SIZE + frame_len); +} + +_STATIC_H host_lib_status_t ifx_i2c_dl_resync(ifx_i2c_context_t* p_ctx) +{ + host_lib_status_t api_status = IFX_I2C_STACK_SUCCESS; + // Reset tx and rx counters + p_ctx->dl.tx_seq_nr = DL_MAX_FRAME_NUM; + p_ctx->dl.rx_seq_nr = DL_MAX_FRAME_NUM; + p_ctx->dl.resynced = 1; + LOG_DL("[IFX-DL]: Send Re-Sync Frame\n"); + p_ctx->dl.state = DL_STATE_RESEND; + api_status = ifx_i2c_dl_send_frame_internal(p_ctx,0,DL_FCTR_SEQCTR_VALUE_RESYNC,0); + return api_status; +} + +_STATIC_H void ifx_i2c_dl_resend_frame(ifx_i2c_context_t* p_ctx,uint8_t seqctr_value) +{ + host_lib_status_t status; + // If exit timeout not violated + uint32_t current_time_stamp = pal_os_timer_get_time_in_milliseconds(); + if ((current_time_stamp - p_ctx->tl.api_start_time) < (TL_MAX_EXIT_TIMEOUT * 1000)) + { + if(p_ctx->dl.retransmit_counter == DL_TRANS_REPEAT) + { + LOG_DL("[IFX-DL]: Re-Sync counters\n"); + p_ctx->dl.retransmit_counter = 0; + status = ifx_i2c_dl_resync(p_ctx); + } + else + { + LOG_DL("[IFX-DL]: Re-TX Frame\n"); + p_ctx->dl.retransmit_counter++; + p_ctx->dl.state = DL_STATE_TX; + status = ifx_i2c_dl_send_frame_internal(p_ctx,p_ctx->dl.tx_buffer_size,seqctr_value, 1); + } + // Handle error in above case by sending NACK + if (IFX_I2C_STACK_SUCCESS != status) + { + p_ctx->dl.state = DL_STATE_NACK; + } + } + else + { + p_ctx->dl.state = DL_STATE_ERROR; + } +} + +_STATIC_H void ifx_i2c_pl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len) +{ + uint8_t fctr = 0; + uint8_t fr_nr = 0; + uint8_t ack_nr = 0; + uint8_t seqctr = 0; + uint8_t current_event; + uint8_t ftype; + uint8_t continue_state_machine = TRUE; + uint16_t packet_len = 0; + uint16_t crc_received = 0; + uint16_t crc_calculated = 0; + LOG_DL("[IFX-DL]: #Enter DL Handler\n"); + do + { + if((event == IFX_I2C_FATAL_ERROR) && (DL_STATE_IDLE != p_ctx->dl.state)) + { // Exit in case of fatal error + LOG_DL("[IFX-DL]: Fatal error received\n"); + p_ctx->dl.state = DL_STATE_ERROR; + } + switch(p_ctx->dl.state) + { + case DL_STATE_IDLE: + { + current_event = (event != IFX_I2C_STACK_SUCCESS)?IFX_I2C_DL_EVENT_ERROR:IFX_I2C_DL_EVENT_TX_SUCCESS; + continue_state_machine = FALSE; + p_ctx->dl.upper_layer_event_handler(p_ctx,current_event, 0, 0); + } + break; + case DL_STATE_TX: + { + // If writing a frame failed retry sending + if (event == IFX_I2C_STACK_ERROR) + { + p_ctx->dl.state = DL_STATE_RESEND; + break; + } + LOG_DL("[IFX-DL]: Frame Sent\n"); + // Transmission successful, start receiving frame + p_ctx->dl.frame_start_time = pal_os_timer_get_time_in_milliseconds(); + p_ctx->dl.state = DL_STATE_RX; + if (ifx_i2c_pl_receive_frame(p_ctx)) + { + p_ctx->dl.state = DL_STATE_NACK; + } + else + { + continue_state_machine = FALSE; + } + } + break; + case DL_STATE_RX: + { + if (event == IFX_I2C_STACK_ERROR) + { // If no frame was received retry sending + p_ctx->dl.state = DL_STATE_RESEND; + break; + } + // Received frame from device, start analyzing + LOG_DL("[IFX-DL]: Received Frame of length %d\n",data_len); + + if (data_len < DL_HEADER_SIZE) + { // Received length is less than minimum size + LOG_DL("[IFX-DL]: received data_len < DL_HEADER_SIZE\n"); + p_ctx->dl.state = DL_STATE_NACK; + break; + } + // Check transmit frame sequence number + fctr = p_data[0]; + ftype = (fctr & DL_FCTR_FTYPE_MASK) >> DL_FCTR_FTYPE_OFFSET; + seqctr = (fctr & DL_FCTR_SEQCTR_MASK) >> DL_FCTR_SEQCTR_OFFSET; + ack_nr = (fctr & DL_FCTR_ACKNR_MASK) >> DL_FCTR_ACKNR_OFFSET; + fr_nr = (fctr & DL_FCTR_FRNR_MASK) >> DL_FCTR_FRNR_OFFSET; + packet_len = (p_data[1] << 8) | p_data[2]; + + // Check frame CRC value + crc_received = (p_data[data_len - 2] << 8) | p_data[data_len - 1]; + crc_calculated = ifx_i2c_dl_calc_crc(p_data, data_len - 2); + p_ctx->dl.state = (ftype == DL_FCTR_VALUE_CONTROL_FRAME)?DL_STATE_RX_CF:DL_STATE_RX_DF; + } + break; + case DL_STATE_RX_DF: + { + LOG_DL("[IFX-DL]: Data Frame Received\n"); + if ((crc_received != crc_calculated)||(packet_len == 0)||(data_len != DL_HEADER_SIZE + packet_len)|| + (seqctr == DL_FCTR_SEQCTR_VALUE_RFU) || (seqctr == DL_FCTR_SEQCTR_VALUE_RESYNC)) + { + // CRC,Length of data frame is 0/ SEQCTR has RFU/Re-sync in Data frame + LOG_DL("[IFX-DL]: NACK for CRC error,Data frame length is not correct,RFU in SEQCTR\n"); + p_ctx->dl.state = DL_STATE_NACK; + break; + } + if (fr_nr != ((p_ctx->dl.rx_seq_nr + 1) & DL_MAX_FRAME_NUM)) + { + LOG_DL("[IFX-DL]: Data frame number not expected\n"); + p_ctx->dl.state = DL_STATE_DISCARD; + continue_state_machine = FALSE; + //lint --e{534} suppress "Return value is not required to be checked" + ifx_i2c_dl_send_frame_internal(p_ctx,0, DL_FCTR_SEQCTR_VALUE_ACK, 0); + break; + } + if (ack_nr != p_ctx->dl.tx_seq_nr) + { + // ack number error + LOG_DL("[IFX-DL]: Error in ack number\n"); + //lint --e{534} suppress "Return value is not required to be checked" + p_ctx->dl.state = DL_STATE_DISCARD; + break; + } + if (seqctr == DL_FCTR_SEQCTR_VALUE_NACK) + { + // NACK for transmitted frame + LOG_DL("[IFX-DL]: NACK received in data frame\n"); + p_ctx->dl.state = DL_STATE_RESEND; + break; + } + p_ctx->dl.rx_seq_nr = (p_ctx->dl.rx_seq_nr + 1) & DL_MAX_FRAME_NUM; + memcpy(p_ctx->dl.p_rx_frame_buffer, p_data, data_len); + p_ctx->dl.rx_buffer_size = data_len; + + // Send control frame to acknowledge reception of this data frame + LOG_DL("[IFX-DL]: Read Data Frame -> Send ACK\n"); + p_ctx->dl.retransmit_counter = 0; + p_ctx->dl.state = DL_STATE_ACK; + continue_state_machine = FALSE; + //lint --e{534} suppress "Return value is not required to be checked" + ifx_i2c_dl_send_frame_internal(p_ctx,0, DL_FCTR_SEQCTR_VALUE_ACK, 0); + } + break; + case DL_STATE_RX_CF: + { + LOG_DL("[IFX-DL]: Control Frame Received\n"); + // Discard Control frame when in receiver mode except for Re-Sync + //lint --e{514} suppress "The check is intended to be done this way" + if((p_ctx->dl.action_rx_only) ^ (seqctr == DL_FCTR_SEQCTR_VALUE_RESYNC)) + { + //If control frame already received for data frame, ignore any received control frame + LOG_DL("[IFX-DL]: CF in receiver mode,Discard\n"); + p_ctx->dl.state = DL_STATE_DISCARD; + break; + } + if (crc_received != crc_calculated) + { + // Re-Transmit frame in case of CF CRC error + LOG_DL("[IFX-DL]: Retransmit frame for CF CRC error\n"); + p_ctx->dl.state = DL_STATE_RESEND; + break; + } + if((data_len > DL_CONTROL_FRAME_LENGTH)||(packet_len != 0)) + { + // Control frame is more than 5/Control frame with non-zero FRNR/packet len is not 0 + LOG_DL("[IFX-DL]: Errors in control frame\n"); + p_ctx->dl.state = DL_STATE_DISCARD; + break; + } + if(seqctr == DL_FCTR_SEQCTR_VALUE_RESYNC) + { // Re-sync received + LOG_DL("[IFX-DL]: Re-Sync received\n"); + p_ctx->dl.state = DL_STATE_DISCARD; + p_ctx->dl.resynced = 1; + p_ctx->dl.tx_seq_nr = DL_MAX_FRAME_NUM; + p_ctx->dl.rx_seq_nr = DL_MAX_FRAME_NUM; + break; + } + if((fr_nr!=0)||(seqctr == DL_FCTR_SEQCTR_VALUE_RFU)||(ack_nr != p_ctx->dl.tx_seq_nr)) + { + // Control frame with non-zero FRNR/ ACK not received/ ack number != tx number + LOG_DL("[IFX-DL]: Errors in control frame\n"); + p_ctx->dl.state = DL_STATE_DISCARD; + break; + } + if (seqctr == DL_FCTR_SEQCTR_VALUE_NACK) + { + // NACK for transmitted frame + LOG_DL("[IFX-DL]: NACK received\n"); + p_ctx->dl.state = DL_STATE_RESEND; + break; + } + + LOG_DL("[IFX-DL]: ACK received\n"); + // Report frame reception to upper layer and go in idle state + p_ctx->dl.state = DL_STATE_IDLE; + continue_state_machine = FALSE; + p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_TX_SUCCESS, 0, 0); + } + break; + case DL_STATE_DISCARD: + { + LOG_DL("[IFX-DL]: Discard frame\n"); + p_ctx->dl.state = DL_STATE_RX; + continue_state_machine = FALSE; + //lint --e{534} suppress "Return value is not required to be checked" + ifx_i2c_pl_receive_frame(p_ctx); + } + break; + case DL_STATE_ACK: + { + LOG_DL("[IFX-DL]: ACK sent\n"); + if (event == IFX_I2C_STACK_ERROR) + { + // If writing the ACK frame failed, Re-Send + LOG_DL("[IFX-DL]: Physical Layer error -> Resend ACK\n"); + p_ctx->dl.state = DL_STATE_RESEND; + break; + } + // Control frame successful transmitted + p_ctx->dl.state = DL_STATE_IDLE; + continue_state_machine = FALSE; + if (p_ctx->dl.action_rx_only) + { + p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_RX_SUCCESS, p_ctx->dl.p_rx_frame_buffer + 3, + p_ctx->dl.rx_buffer_size - DL_HEADER_SIZE); + } + else + { + p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_TX_SUCCESS | IFX_I2C_DL_EVENT_RX_SUCCESS, + p_ctx->dl.p_rx_frame_buffer + 3, p_ctx->dl.rx_buffer_size - DL_HEADER_SIZE); + } + } + break; + case DL_STATE_NACK: + { + // Sending NACK + LOG_DL("[IFX-DL]: Sending NACK\n"); + p_ctx->dl.state = DL_STATE_TX; + continue_state_machine = FALSE; + //lint --e{534} suppress "Return value is not required to be checked" + ifx_i2c_dl_send_frame_internal(p_ctx,0, DL_FCTR_SEQCTR_VALUE_NACK, 0); + } + break; + case DL_STATE_RESEND: + { + //Resend frame + ifx_i2c_dl_resend_frame(p_ctx,DL_FCTR_SEQCTR_VALUE_ACK); + if(p_ctx->dl.state != DL_STATE_ERROR) + { + continue_state_machine = FALSE; + } + } + break; + case DL_STATE_ERROR: + { + if(!p_ctx->dl.resynced) + { + p_ctx->dl.error = 1; + } + if(0 == p_ctx->dl.error) + { + LOG_DL("[IFX-DL]: Exit error after fatal error\n"); + //After sending resync, inform upper layer + p_ctx->dl.state = DL_STATE_IDLE; + p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_ERROR, 0, 0); + } + else + { + LOG_DL("[IFX-DL]: Sending re-sync after fatal error\n"); + // Send re-sync to slave on error + //lint --e{534} suppress "As this is last step, no effect of checking return code" + ifx_i2c_dl_resync(p_ctx); + p_ctx->dl.state = DL_STATE_ERROR; + p_ctx->dl.error = 0; + } + continue_state_machine = FALSE; + } + break; + default: + LOG_DL("[IFX-DL]: Default condition occurred. Exiting with error\n"); + p_ctx->dl.state = DL_STATE_IDLE; + p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_ERROR, 0, 0); + continue_state_machine = FALSE; + break; + } + }while(continue_state_machine == TRUE); + LOG_DL("[IFX-DL]: #Exiting DL Handler\n"); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_physical_layer.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_physical_layer.c new file mode 100644 index 0000000..8067685 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_physical_layer.c @@ -0,0 +1,742 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_physical_layer.c +* +* \brief This file implements the IFX I2C Physical Layer. +* +* \addtogroup grIFXI2C +* @{ +*/ + +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +#include "ifx_i2c_physical_layer.h" +#include "pal_os_event.h" + +/// @cond hidden +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ +// Physical Layer Register addresses +#define PL_REG_DATA (0x80) +#define PL_REG_DATA_REG_LEN (0x81) +#define PL_REG_I2C_STATE (0x82) +#define PL_REG_BASE_ADDR (0x83) +#define PL_REG_MAX_SCL_FREQU (0x84) +#define PL_REG_SOFT_RESET (0x88) +#define PL_REG_I2C_MODE (0x89) + +// Physical Layer Register lengths +#define PL_REG_LEN_I2C_STATE (4) +#define PL_REG_LEN_MAX_SCL_FREQU (4) +#define PL_REG_LEN_I2C_MODE (2) +#define PL_REG_LEN_DATA_REG_LEN (2) +#define PL_REG_LEN_SOFT_RESET (2) +#define PL_REG_LEN_BASE_ADDR (2) + +// Physical Layer State Register masks +#define PL_REG_I2C_STATE_RESPONSE_READY (0x40) +#define PL_REG_I2C_STATE_SOFT_RESET (0x08) + +// Physical Layer low level interface constants +#define PL_ACTION_READ_REGISTER (0x01) +#define PL_ACTION_WRITE_REGISTER (0x02) +#define PL_I2C_CMD_WRITE (0x01) +#define PL_I2C_CMD_READ (0x02) + +// Physical Layer high level interface constants +#define PL_ACTION_WRITE_FRAME (0x01) +#define PL_ACTION_READ_FRAME (0x02) +#define PL_STATE_UNINIT (0x00) +#define PL_STATE_INIT (0x01) +#define PL_STATE_READY (0x02) +#define PL_STATE_DATA_AVAILABLE (0x03) +#define PL_STATE_RXTX (0x04) +#define PL_STATE_SOFT_RESET (0x05) + +//Physical Layer negotiation constants +#define PL_INIT_SET_DATA_REG_LEN (0x11) +#define PL_INIT_GET_DATA_REG_LEN (0x22) +#define PL_INIT_GET_FREQ_REG (0x33) +#define PL_INIT_SET_FREQ_REG (0x44) +#define PL_INIT_READ_FREQ (0x55) +#define PL_INIT_VERIFY_FREQ (0x66) +#define PL_INIT_AGREE_FREQ (0x77) +#define PL_INIT_VERIFY_DATA_REG (0x88) +#define PL_INIT_GET_STATUS_REG (0x99) +#define PL_INIT_DONE (0xAA) +#define PL_INIT_SET_FREQ_DEFAULT (0xBB) + +//Physical layer soft reset states +#define PL_RESET_INIT (0xA1) +#define PL_RESET_WRITE (0xA2) +#define PL_RESET_STARTUP (0xA3) + +#define PL_REG_I2C_MODE_PERSISTANT (0x80) +#define PL_REG_I2C_MODE_SM_FM (0x03) +#define PL_REG_I2C_MODE_FM_PLUS (0x04) +#define PL_SM_FM_MAX_FREQUENCY (0x190) +#define PL_DEFAULT_FREQUENCY (0x64) +#define PL_REG_BASE_ADDR_PERSISTANT (0x80) +#define PL_REG_BASE_ADDR_VOLATILE (0x00) + +// Physical Layer Base Address Register mask +#define PL_REG_I2C_BASE_ADDRESS_MASK (0x7F) + +// Setup debug log statements +#if IFX_I2C_LOG_PL == 1 +#define LOG_PL IFX_I2C_LOG +#else +#define LOG_PL(...) //printf(__VA_ARGS__) +#endif +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* GLOBAL +***********************************************************************************************************************/ + +static host_lib_status_t pal_event_status; + +/*********************************************************************************************************************** +* LOCAL ROUTINES +***********************************************************************************************************************/ +/// Physical Layer low level interface function +static void ifx_i2c_pl_read_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len); +/// Physical Layer low level interface function +static void ifx_i2c_pl_write_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len, const uint8_t* p_content); +/// Physical Layer high level interface timer callback (Status register polling) +static void ifx_i2c_pl_status_poll_callback(void *p_ctx); +/// Physical Layer intermediate state machine (Negotiation with slave) +static void ifx_i2c_pl_negotiation_event_handler(void *p_input_ctx); +/// Physical Layer intermediate state machine(Set bit rate) +static host_lib_status_t ifx_i2c_pl_set_bit_rate(ifx_i2c_context_t *p_ctx, uint16_t bitrate); +/// Physical Layer intermediate state machine (soft reset) +static void ifx_i2c_pl_soft_reset(ifx_i2c_context_t *p_ctx); +/// Physical Layer high level interface state machine (read/write frames) +static void ifx_i2c_pl_frame_event_handler(ifx_i2c_context_t *p_ctx,host_lib_status_t event); +/// Physical Layer low level interface timer callback (I2C Nack/Busy polling) +static void ifx_i2c_pal_poll_callback(void *p_ctx); +/// Physical Layer low level guard time callback +static void ifx_i2c_pl_guard_time_callback(void *p_ctx); +/// Physical Layer low level interface state machine (read/write registers) +static void ifx_i2c_pl_pal_event_handler(void *p_ctx, host_lib_status_t event); +/// Physical layer low level event handler for set slave address +static void ifx_i2c_pl_pal_slave_addr_event_handler(void *p_input_ctx, host_lib_status_t event); + +/// @endcond +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ +/// Physical Layer high level interface function +host_lib_status_t ifx_i2c_pl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler) +{ + LOG_PL("[IFX-PL]: Init\n"); + + p_ctx->pl.upper_layer_event_handler = handler; + p_ctx->pl.frame_state = PL_STATE_UNINIT; + p_ctx->pl.negotiate_state = PL_INIT_SET_FREQ_DEFAULT; + p_ctx->p_pal_i2c_ctx->slave_address = p_ctx->slave_address; + p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = (void *) ifx_i2c_pl_pal_event_handler; + p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT; + if(TRUE == p_ctx->do_pal_init) + { + // Initialize I2C driver + if (PAL_STATUS_SUCCESS != pal_i2c_init(p_ctx->p_pal_i2c_ctx)) + { + return IFX_I2C_STACK_ERROR; + } + } + // Set Physical Layer internal state + if(p_ctx->pl.request_soft_reset == (uint8_t)TRUE) + { + //Set the soft reset request to initial state to read register + p_ctx->pl.request_soft_reset = PL_INIT_GET_STATUS_REG; + p_ctx->pl.frame_state = PL_STATE_SOFT_RESET; + } + else + { + p_ctx->pl.frame_state = PL_STATE_INIT; + } + + ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS); + + return IFX_I2C_STACK_SUCCESS; +} + +/// Physical Layer high level interface function +host_lib_status_t ifx_i2c_pl_send_frame(ifx_i2c_context_t *p_ctx,uint8_t* p_frame, uint16_t frame_len) +{ + // Physical Layer must be idle, set requested action + if (p_ctx->pl.frame_state != PL_STATE_INIT && p_ctx->pl.frame_state != PL_STATE_READY) + { + return IFX_I2C_STACK_ERROR; + } + p_ctx->pl.frame_action = PL_ACTION_WRITE_FRAME; + + // Store reference to frame for sending it later + p_ctx->pl.p_tx_frame = p_frame; + p_ctx->pl.tx_frame_len = frame_len; + + ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS); + return IFX_I2C_STACK_SUCCESS; +} + +/// Physical Layer high level interface function +host_lib_status_t ifx_i2c_pl_receive_frame(ifx_i2c_context_t *p_ctx) +{ + // Physical Layer must be idle, set requested action + if (p_ctx->pl.frame_state != PL_STATE_INIT && p_ctx->pl.frame_state != PL_STATE_READY) + { + return IFX_I2C_STACK_ERROR; + } + p_ctx->pl.frame_action = PL_ACTION_READ_FRAME; + + ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS); + return IFX_I2C_STACK_SUCCESS; +} + +host_lib_status_t ifx_i2c_pl_write_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t persistent) +{ + host_lib_status_t status = IFX_I2C_STACK_ERROR; + app_event_handler_t * temp_upper_layer_event_handler; + + /// @cond hidden + #define PAL_WRITE_INIT_STATUS (0x00FF) + #define ADDRESS_OFFSET (0x02) + #define BASE_ADDRESS_REG_OFFSET (0x00) + #define MODE_OFFSET (0x01) + #define POLLING_INTERVAL (0x01) + #define DELAY_FOR_COMPLETION (0x0A) + /// @endcond + + //lint --e{611} suppress "void* function pointer is type casted to app_event_handler_t type" + //ifx i2c wrapper api for setting slave address in synchronous. hence the event handler is backed up. + temp_upper_layer_event_handler = (app_event_handler_t *)(p_ctx->p_pal_i2c_ctx->upper_layer_event_handler); + //since the lower level APIs are asynchronous, a temporary event handler for set slave address is assigned + p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = (void *) ifx_i2c_pl_pal_slave_addr_event_handler; + + p_ctx->pl.buffer[BASE_ADDRESS_REG_OFFSET] = PL_REG_BASE_ADDR; + p_ctx->pl.buffer[MODE_OFFSET] = PL_REG_BASE_ADDR_VOLATILE; + //supported base addresses are 0x00 - 0x7F. Hence 8th bit is ignored + p_ctx->pl.buffer[ADDRESS_OFFSET] = slave_address & PL_REG_I2C_BASE_ADDRESS_MASK; + p_ctx->pl.buffer_tx_len = 1 + PL_REG_LEN_BASE_ADDR; + + if(PL_REG_BASE_ADDR_VOLATILE != persistent) + { + p_ctx->pl.buffer[MODE_OFFSET] = PL_REG_BASE_ADDR_PERSISTANT; + } + + p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT; + + while(p_ctx->pl.retry_counter) + { + pal_event_status = PAL_WRITE_INIT_STATUS; + + //lint --e{534} suppress "Return value is not required to be checked" + pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len); + while(PAL_WRITE_INIT_STATUS == pal_event_status){}; + if(PAL_I2C_EVENT_SUCCESS == pal_event_status) + { + break; + } + p_ctx->pl.retry_counter--; + pal_os_timer_delay_in_milliseconds(POLLING_INTERVAL); + } + + if(PAL_I2C_EVENT_SUCCESS == pal_event_status) + { + p_ctx->p_pal_i2c_ctx->slave_address = p_ctx->pl.buffer[ADDRESS_OFFSET]; + if(PL_REG_BASE_ADDR_VOLATILE != persistent) + { + p_ctx->slave_address = p_ctx->pl.buffer[ADDRESS_OFFSET]; + } + pal_os_timer_delay_in_milliseconds(DELAY_FOR_COMPLETION); + status = IFX_I2C_STACK_SUCCESS; + } + //restoring the backed up event handler + p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = temp_upper_layer_event_handler; + + /// @cond hidden + #undef PAL_WRITE_INIT_STATUS + #undef ADDRESS_OFFSET + #undef BASE_ADDRESS_REG_OFFSET + #undef MODE_OFFSET + #undef POLLING_INTERVAL + #undef DELAY_FOR_COMPLETION + /// @endcond + + return status; +} + +static void ifx_i2c_pl_read_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len) +{ + LOG_PL("[IFX-PL]: Read register %x len %d\n", reg_addr, reg_len); + + // Prepare transmit buffer to write register address + p_ctx->pl.buffer[0] = reg_addr; + p_ctx->pl.buffer_tx_len = 1; + + // Set low level interface variables and start transmission + p_ctx->pl.buffer_rx_len = reg_len; + p_ctx->pl.register_action = PL_ACTION_READ_REGISTER; + p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT; + p_ctx->pl.i2c_cmd = PL_I2C_CMD_WRITE; + + //lint --e{534} suppress "Return value is not required to be checked" + pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len); +} + + +static void ifx_i2c_pl_write_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len, const uint8_t* p_content) +{ + LOG_PL("[IFX-PL]: Write register %x len %d\n", reg_addr, reg_len); + + // Prepare transmit buffer to write register address and content + p_ctx->pl.buffer[0] = reg_addr; + memcpy(p_ctx->pl.buffer + 1, p_content, reg_len); + p_ctx->pl.buffer_tx_len = 1 + reg_len; + + // Set Physical Layer low level interface variables and start transmission + p_ctx->pl.register_action = PL_ACTION_WRITE_REGISTER; + p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT; + p_ctx->pl.i2c_cmd = PL_I2C_CMD_WRITE; + //lint --e{534} suppress "Return value is not required to be checked" + pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len); +} + + +static void ifx_i2c_pl_status_poll_callback(void *p_ctx) +{ + LOG_PL("[IFX-PL]: Status poll Timer elapsed -> Read STATUS register\n"); + ifx_i2c_pl_read_register((ifx_i2c_context_t*)p_ctx,PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE); +} + +static host_lib_status_t ifx_i2c_pl_set_bit_rate(ifx_i2c_context_t *p_ctx, uint16_t bitrate) +{ + host_lib_status_t status; + void* pal_ctx_upper_layer_handler; + // Save upper layer context in pal + pal_ctx_upper_layer_handler = p_ctx->p_pal_i2c_ctx->upper_layer_event_handler; + // Pass context as NULL to avoid callback invocation + p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = NULL; + status = pal_i2c_set_bitrate(p_ctx->p_pal_i2c_ctx , bitrate); + // Restore callback + p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = pal_ctx_upper_layer_handler; + if(PAL_I2C_EVENT_SUCCESS != status) + { + if (p_ctx->pl.retry_counter--) + { + LOG_PL("[IFX-PL]: Set bit rate failed, Retry setting.\n"); + pal_os_event_register_callback_oneshot(ifx_i2c_pl_negotiation_event_handler,((void*)p_ctx),PL_POLLING_INVERVAL_US); + status = IFX_I2C_STACK_BUSY; + } + else + { + status = IFX_I2C_STACK_ERROR; + } + } + else + { + status = IFX_I2C_STACK_SUCCESS; + } + + return status; + +} +static void ifx_i2c_pl_negotiation_event_handler(void *p_input_ctx) +{ + host_lib_status_t event = (uint8_t)IFX_I2C_STACK_ERROR; + uint8_t continue_negotiation; + ifx_i2c_context_t* p_ctx = (ifx_i2c_context_t*)p_input_ctx; + uint8_t i2c_mode_value[2]; + uint8_t max_frame_size[2] = { (uint8_t)(p_ctx->frame_size >> 8), (uint8_t)(p_ctx->frame_size) }; + uint16_t buffer_len = 0; + uint16_t slave_frequency; + uint16_t slave_frame_len; + uint8_t* p_buffer = NULL; + + do + { + continue_negotiation = FALSE; + LOG_PL("[IFX-PL]: Negotiation started\n"); + switch(p_ctx->pl.negotiate_state) + { + // Set initial frequency to PL_DEFAULT_FREQUENCY to be able to negotiate with slave + case PL_INIT_SET_FREQ_DEFAULT: + { + // Default frequency set to master + event = ifx_i2c_pl_set_bit_rate(p_input_ctx,PL_DEFAULT_FREQUENCY); + if(IFX_I2C_STACK_SUCCESS == event) + { + p_ctx->pl.negotiate_state = PL_INIT_GET_FREQ_REG; + continue_negotiation = TRUE; + } + else if (IFX_I2C_STACK_ERROR == event) + { + p_ctx->pl.negotiate_state = PL_INIT_DONE; + p_buffer = NULL; + buffer_len = 0; + } + } + break; + // Read the current Max frequency supported by slave + case PL_INIT_GET_FREQ_REG: + { + p_ctx->pl.negotiate_state = PL_INIT_SET_FREQ_REG; + ifx_i2c_pl_read_register(p_ctx,PL_REG_MAX_SCL_FREQU, PL_REG_LEN_MAX_SCL_FREQU); + } + break; + // Set the I2C mode register + case PL_INIT_SET_FREQ_REG: + { + slave_frequency = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3]; + + i2c_mode_value[0] = PL_REG_I2C_MODE_PERSISTANT; + if((p_ctx->frequency > PL_SM_FM_MAX_FREQUENCY)&&(slave_frequency<=PL_SM_FM_MAX_FREQUENCY)) + { + //Change to FM+ mode if slave's current supported frequency is below user's requested frequency + i2c_mode_value[1] = PL_REG_I2C_MODE_FM_PLUS; + p_ctx->pl.negotiate_state = PL_INIT_READ_FREQ; + ifx_i2c_pl_write_register(p_ctx,PL_REG_I2C_MODE, PL_REG_LEN_I2C_MODE, i2c_mode_value); + } + else if((p_ctx->frequency <= PL_SM_FM_MAX_FREQUENCY)&&(slave_frequency>PL_SM_FM_MAX_FREQUENCY)) + { + //Change to SM&FM mode if slave's current supported frequency is above user's requested frequency + i2c_mode_value[1] = PL_REG_I2C_MODE_SM_FM; + p_ctx->pl.negotiate_state = PL_INIT_READ_FREQ; + ifx_i2c_pl_write_register(p_ctx,PL_REG_I2C_MODE, PL_REG_LEN_I2C_MODE, i2c_mode_value); + } + else + { + p_ctx->pl.negotiate_state = PL_INIT_VERIFY_FREQ; + continue_negotiation = TRUE; + } + } + break; + // After setting I2C mode register, read the slave's supported frequency + case PL_INIT_READ_FREQ: + { + p_ctx->pl.negotiate_state = PL_INIT_VERIFY_FREQ; + ifx_i2c_pl_read_register(p_ctx,PL_REG_MAX_SCL_FREQU, PL_REG_LEN_MAX_SCL_FREQU); + } + break; + // Verify the requested frequency and slave's supported frequency + case PL_INIT_VERIFY_FREQ: + { + slave_frequency = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3]; + if(p_ctx->frequency > slave_frequency) + { + LOG_PL("[IFX-PL]: Unexpected frequency in MAX_SCL_FREQU\n"); + p_buffer = NULL; + buffer_len = 0; + p_ctx->pl.negotiate_state = PL_INIT_DONE; + } + else + { + p_ctx->pl.negotiate_state = PL_INIT_AGREE_FREQ; + } + continue_negotiation = TRUE; + } + break; + // Frequency negotiated, Set frequency at master + case PL_INIT_AGREE_FREQ: + { + // Frequency negotiation between master and slave is complete + event = ifx_i2c_pl_set_bit_rate(p_input_ctx, p_ctx->frequency); + if(IFX_I2C_STACK_SUCCESS == event) + { + p_ctx->pl.negotiate_state = PL_INIT_SET_DATA_REG_LEN; + continue_negotiation = TRUE; + } + else if (IFX_I2C_STACK_ERROR == event) + { + p_ctx->pl.negotiate_state = PL_INIT_DONE; + p_buffer = NULL; + buffer_len = 0; + } + } + break; + // Start frame length negotiation by writing the requested frame length + case PL_INIT_SET_DATA_REG_LEN: + { + p_ctx->pl.negotiate_state = PL_INIT_GET_DATA_REG_LEN; + ifx_i2c_pl_write_register(p_ctx,PL_REG_DATA_REG_LEN, sizeof(max_frame_size), max_frame_size); + } + break; + // Read the frame length to verify + case PL_INIT_GET_DATA_REG_LEN: + { + p_ctx->pl.negotiate_state = PL_INIT_VERIFY_DATA_REG; + ifx_i2c_pl_read_register(p_ctx,PL_REG_DATA_REG_LEN,PL_REG_LEN_DATA_REG_LEN); + } + break; + // Check is slave accepted the new frame length + case PL_INIT_VERIFY_DATA_REG: + { + p_ctx->pl.negotiate_state = PL_INIT_DONE; + slave_frame_len = (p_ctx->pl.buffer[0] << 8) | p_ctx->pl.buffer[1]; + // Error if slave's frame length is more than requested frame length + if(p_ctx->frame_size >= slave_frame_len) + { + p_ctx->frame_size = slave_frame_len; + event = IFX_I2C_STACK_SUCCESS; + } + p_buffer = NULL; + buffer_len = 0; + continue_negotiation = TRUE; + } + break; + case PL_INIT_DONE: + { + if(IFX_I2C_STACK_SUCCESS == event) + { + p_ctx->pl.frame_state = PL_STATE_READY; + } + else + { + p_ctx->pl.frame_state = PL_STATE_UNINIT; + } + // Negotiation between master and slave is complete + p_ctx->pl.upper_layer_event_handler(p_ctx,event, p_buffer, buffer_len); + } + break; + default: + break; + } + }while(continue_negotiation); +} + + +static void ifx_i2c_pl_frame_event_handler(ifx_i2c_context_t *p_ctx,host_lib_status_t event) +{ + uint16_t frame_size; + if (event != IFX_I2C_STACK_SUCCESS) + { + p_ctx->pl.frame_state = PL_STATE_READY; + // I2C read or write failed, report to upper layer + p_ctx->pl.upper_layer_event_handler(p_ctx,event, 0, 0); + } + else + { + switch(p_ctx->pl.frame_state) + { + // Perform soft reset + case PL_STATE_SOFT_RESET: + { + ifx_i2c_pl_soft_reset(p_ctx); + } + break; + // Negotiate frame and frequency with slave + case PL_STATE_INIT: + { + ifx_i2c_pl_negotiation_event_handler(p_ctx); + } + break; + // Check status of slave data + case PL_STATE_READY: + { + // Start polling status register + p_ctx->pl.frame_state = PL_STATE_DATA_AVAILABLE; + ifx_i2c_pl_read_register(p_ctx,PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE); + } + break; + // Do read/write frame + case PL_STATE_DATA_AVAILABLE: + { + // Read frame, if response is ready. Ignore busy flag + if ((p_ctx->pl.frame_action == PL_ACTION_READ_FRAME) + && (p_ctx->pl.buffer[0] & PL_REG_I2C_STATE_RESPONSE_READY)) + { + frame_size = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3]; + if ((frame_size > 0) && (frame_size <= p_ctx->frame_size)) + { + p_ctx->pl.frame_state = PL_STATE_RXTX; + ifx_i2c_pl_read_register(p_ctx,PL_REG_DATA, frame_size); + } + else + { + // Continue polling STATUS register if retry limit is not reached + if ((pal_os_timer_get_time_in_milliseconds() - p_ctx->dl.frame_start_time) < p_ctx->dl.data_poll_timeout) + { + pal_os_event_register_callback_oneshot(ifx_i2c_pl_status_poll_callback, (void *)p_ctx, PL_DATA_POLLING_INVERVAL_US); + } + else + { + p_ctx->pl.frame_state = PL_STATE_READY; + p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_ERROR, 0, 0); + } + } + } + // Write frame is slave is not busy + else if (p_ctx->pl.frame_action == PL_ACTION_WRITE_FRAME) + { + // Write frame if device is not busy, otherwise wait and poll STATUS again later + p_ctx->pl.frame_state = PL_STATE_RXTX; + ifx_i2c_pl_write_register(p_ctx,PL_REG_DATA, p_ctx->pl.tx_frame_len, (uint8_t*)p_ctx->pl.p_tx_frame); + } + // Continue checking the slave status register + else + { + // Continue polling STATUS register if retry limit is not reached + if ((pal_os_timer_get_time_in_milliseconds() - p_ctx->dl.frame_start_time) < p_ctx->dl.data_poll_timeout) + { + pal_os_event_register_callback_oneshot(ifx_i2c_pl_status_poll_callback, (void *)p_ctx, PL_DATA_POLLING_INVERVAL_US); + } + else + { + p_ctx->pl.frame_state = PL_STATE_READY; + p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_ERROR, 0, 0); + } + } + } + break; + // Frame reading is complete + case PL_STATE_RXTX: + { + // Writing/reading of frame to/from DATA register complete + p_ctx->pl.frame_state = PL_STATE_READY; + p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS, p_ctx->pl.buffer, p_ctx->pl.buffer_rx_len); + } + break; + default: + break; + } + } +} + +static void ifx_i2c_pal_poll_callback(void *p_ctx) +{ + ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t *)p_ctx; + if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_WRITE) + { + LOG_PL("[IFX-PL]: Poll Timer elapsed -> Restart TX\n"); + //lint --e{534} suppress "Return value is not required to be checked" + pal_i2c_write(p_local_ctx->p_pal_i2c_ctx, p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_tx_len); + } + else if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_READ) + { + LOG_PL("[IFX-PL]: Poll Timer elapsed -> Restart Read Register -> Start TX\n"); + //lint --e{534} suppress "Return value is not required to be checked" + pal_i2c_read(p_local_ctx->p_pal_i2c_ctx,p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_rx_len); + } +} + + +static void ifx_i2c_pl_guard_time_callback(void *p_ctx) +{ + ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t*)p_ctx; + if (p_local_ctx->pl.register_action == PL_ACTION_READ_REGISTER) + { + if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_WRITE) + { + LOG_PL("[IFX-PL]: GT done-> Start RX\n"); + p_local_ctx->pl.i2c_cmd = PL_I2C_CMD_READ; + //lint --e{534} suppress "Return value is not required to be checked" + pal_i2c_read(p_local_ctx->p_pal_i2c_ctx,p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_rx_len); + } + else if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_READ) + { + LOG_PL("[IFX-PL]: GT done -> REG is read\n"); + ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_STACK_SUCCESS); + } + } + else if (p_local_ctx->pl.register_action == PL_ACTION_WRITE_REGISTER) + { + LOG_PL("[IFX-PL]: GT done -> REG written\n"); + ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_STACK_SUCCESS); + } +} + +static void ifx_i2c_pl_pal_event_handler(void *p_ctx, host_lib_status_t event) +{ + ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t*)p_ctx; + switch (event) + { + case PAL_I2C_EVENT_ERROR: + case PAL_I2C_EVENT_BUSY: + // Error event usually occurs when the device is in sleep mode and needs time to wake up + if (p_local_ctx->pl.retry_counter--) + { + LOG_PL("[IFX-PL]: PAL Error -> Continue polling\n"); + pal_os_event_register_callback_oneshot(ifx_i2c_pal_poll_callback,p_local_ctx,PL_POLLING_INVERVAL_US); + } + else + { + LOG_PL("[IFX-PL]: PAL Error -> Stop\n"); + ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_FATAL_ERROR); + } + break; + + case PAL_I2C_EVENT_SUCCESS: + LOG_PL("[IFX-PL]: PAL Success -> Wait Guard Time\n"); + pal_os_event_register_callback_oneshot(ifx_i2c_pl_guard_time_callback,p_local_ctx,PL_GUARD_TIME_INTERVAL_US); + break; + default: + break; + } +} + + +static void ifx_i2c_pl_soft_reset(ifx_i2c_context_t *p_ctx) +{ + uint8_t i2c_mode_value[2] = {0}; + switch(p_ctx->pl.request_soft_reset) + { + case PL_INIT_GET_STATUS_REG: + p_ctx->pl.request_soft_reset = PL_RESET_WRITE; + //Read the status register to check if soft reset is supported + ifx_i2c_pl_read_register(p_ctx, PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE); + break; + + case PL_RESET_WRITE: + //Mask for soft reset bit(5th bit) from the 1st byte of status register + p_ctx->pl.buffer[0] &= PL_REG_I2C_STATE_SOFT_RESET; + if(p_ctx->pl.buffer[0] == PL_REG_I2C_STATE_SOFT_RESET) + { + p_ctx->pl.request_soft_reset = PL_RESET_STARTUP; + //Write 88 register with 0 value + ifx_i2c_pl_write_register(p_ctx, PL_REG_SOFT_RESET, PL_REG_LEN_SOFT_RESET, i2c_mode_value); + } + else + { + //Soft reset is not supported by the slave + p_ctx->pl.frame_state = PL_STATE_UNINIT; + ifx_i2c_pl_frame_event_handler(p_ctx, IFX_I2C_STACK_ERROR); + } + break; + + case PL_RESET_STARTUP: + p_ctx->pl.request_soft_reset= PL_RESET_INIT; + pal_os_event_register_callback_oneshot((register_callback)ifx_i2c_pl_soft_reset, (void *)p_ctx, STARTUP_TIME_MSEC); + break; + + case PL_RESET_INIT: + p_ctx->pl.frame_state = PL_STATE_INIT; + ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS); + break; + + default: + break; + } +} + +//lint --e{715} suppress "This is used for synchromous implementation, hence p_ctx not used" +//lint --e{818} suppress "This is ignored as upper layer handler function prototype requires this argument" +static void ifx_i2c_pl_pal_slave_addr_event_handler(void *p_ctx, host_lib_status_t event) +{ + pal_event_status = event; +} + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_transport_layer.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_transport_layer.c new file mode 100644 index 0000000..f3191e6 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/ifx_i2c/ifx_i2c_transport_layer.c @@ -0,0 +1,502 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file ifx_i2c_transport_layer.c +* +* \brief This file implements the IFX I2C Transport Layer. +* +* \addtogroup grIFXI2C +* @{ +*/ +/*********************************************************************************************************************** +* HEADER FILES +**********************************************************************************************************************/ +#include "ifx_i2c_transport_layer.h" +#include "ifx_i2c_data_link_layer.h" // include lower layer header + +/// @cond hidden +/*********************************************************************************************************************** +* MACROS +**********************************************************************************************************************/ +// Transport Layer states +#define TL_STATE_UNINIT (0x00) +#define TL_STATE_IDLE (0x01) +#define TL_STATE_TX (0x02) +#define TL_STATE_RX (0x04) +#define TL_STATE_CHAINING (0x05) +#define TL_STATE_ERROR (0x06) +#define TL_STATE_CHAINING_ERROR (0x07) +#define TL_STATE_RESEND (0x08) +// Transport Layer header size +#define TL_HEADER_SIZE 1 + +// Transport Layer chaining values +#define TL_CHAINING_NO (0x00) +#define TL_CHAINING_FIRST (0x01) +#define TL_CHAINING_INTERMEDIATE (0x02) +#define TL_CHAINING_LAST (0x04) +#define TL_CHAINING_ERROR (0x07) + +#define TL_PCTR_CHANNEL_MASK (0xF8) +#define TL_PCTR_CHAIN_MASK (0x07) +// Setup debug log statements +#if IFX_I2C_LOG_TL == 1 +#define LOG_TL IFX_I2C_LOG +#else +#define LOG_TL(...) //printf(__VA_ARGS__); +#endif +/*********************************************************************************************************************** +* ENUMS +**********************************************************************************************************************/ +/*********************************************************************************************************************** +* DATA STRUCTURES +***********************************************************************************************************************/ +static uint8_t pctr_states_table[5][2]={ + {TL_CHAINING_NO,TL_CHAINING_LAST}, + {TL_CHAINING_NO,TL_CHAINING_LAST}, + {TL_CHAINING_FIRST,TL_CHAINING_INTERMEDIATE}, + {0xFF,0xFF}, + {TL_CHAINING_FIRST,TL_CHAINING_INTERMEDIATE}, + }; +/*********************************************************************************************************************** +* GLOBAL +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +* LOCAL ROUTINES +***********************************************************************************************************************/ +/// Sends available fragment +_STATIC_H host_lib_status_t ifx_i2c_tl_send_next_fragment(ifx_i2c_context_t *p_ctx); +/// Datalink Layer event handler +_STATIC_H void ifx_i2c_dl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len); +/// Resends all the packets +_STATIC_H host_lib_status_t ifx_i2c_tl_resend_packets(ifx_i2c_context_t *p_ctx); +/// Sends chaining error to I2C slave +_STATIC_H host_lib_status_t ifx_i2c_tl_send_chaining_error(ifx_i2c_context_t *p_ctx); +/// Calculates the pctr value +_STATIC_H uint8_t ifx_i2c_tl_calculate_pctr(const ifx_i2c_context_t *p_ctx); +/// Checks if chaining error occured based on current and previous pctr +_STATIC_H host_lib_status_t ifx_i2c_tl_check_chaining_error(uint8_t current_chaning, uint8_t previous_chaining); +/// @endcond +/*********************************************************************************************************************** +* API PROTOTYPES +**********************************************************************************************************************/ +/// Transport Layer initialization function +host_lib_status_t ifx_i2c_tl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler) +{ + LOG_TL("[IFX-TL]: Init\n"); + + p_ctx->tl.state = TL_STATE_UNINIT; + + // Initialize Data Link layer (and register event handler) + if (ifx_i2c_dl_init(p_ctx,ifx_i2c_dl_event_handler) != IFX_I2C_STACK_SUCCESS) + { + return IFX_I2C_STACK_ERROR; + } + + p_ctx->tl.upper_layer_event_handler = handler; + p_ctx->tl.state = TL_STATE_IDLE; + p_ctx->tl.max_packet_length = p_ctx->frame_size - (DL_HEADER_SIZE + TL_HEADER_SIZE); + + return IFX_I2C_STACK_SUCCESS; +} + + +host_lib_status_t ifx_i2c_tl_transceive(ifx_i2c_context_t *p_ctx,uint8_t* p_packet, uint16_t packet_len, + uint8_t* p_recv_packet, uint16_t* recv_packet_len) +{ + host_lib_status_t status = IFX_I2C_STACK_ERROR; + LOG_TL("[IFX-TL]: Transceive txlen %d\n", packet_len); + + do + { + // Check function arguments + if (p_packet == NULL || packet_len == 0 ) + { + break; + } + // Transport Layer must be idle + if (p_ctx->tl.state != TL_STATE_IDLE) + { + break; + } + p_ctx->tl.state = TL_STATE_TX; + p_ctx->tl.api_start_time = pal_os_timer_get_time_in_milliseconds(); + p_ctx->tl.p_actual_packet = p_packet; + p_ctx->tl.actual_packet_length = packet_len; + p_ctx->tl.packet_offset = 0; + p_ctx->tl.p_recv_packet_buffer = p_recv_packet; + p_ctx->tl.p_recv_packet_buffer_length = recv_packet_len; + p_ctx->tl.total_recv_length = 0; + p_ctx->tl.chaining_error_count = 0; + p_ctx->tl.master_chaining_error_count = 0; + p_ctx->tl.transmission_completed = 0; + p_ctx->tl.error_event = IFX_I2C_STACK_ERROR; + status = ifx_i2c_tl_send_next_fragment(p_ctx); + }while(FALSE); + return status; +} + + +_STATIC_H host_lib_status_t ifx_i2c_tl_resend_packets(ifx_i2c_context_t *p_ctx) +{ + // Transport Layer must be idle + if (p_ctx->tl.state != TL_STATE_IDLE) + { + return IFX_I2C_STACK_ERROR; + } + + p_ctx->tl.packet_offset = 0; + p_ctx->tl.total_recv_length = 0; + p_ctx->tl.state = TL_STATE_TX; + return ifx_i2c_tl_send_next_fragment(p_ctx); +} + +_STATIC_H uint8_t ifx_i2c_tl_calculate_pctr(const ifx_i2c_context_t *p_ctx) +{ + uint8_t pctr; + uint16_t fragment_size = p_ctx->tl.max_packet_length; + uint16_t remaining_data = p_ctx->tl.actual_packet_length - p_ctx->tl.packet_offset; + // No chain + if((p_ctx->tl.packet_offset==0)&&(remaining_data<=fragment_size)) + { + pctr = TL_CHAINING_NO; + } + // First chain + else if((p_ctx->tl.packet_offset==0)&&(remaining_data>fragment_size)) + { + pctr = TL_CHAINING_FIRST; + } + // Intermediate chain + else if((p_ctx->tl.packet_offset!=0)&&(remaining_data>fragment_size)) + { + pctr = TL_CHAINING_INTERMEDIATE; + } + // Last chain + else + { + pctr = TL_CHAINING_LAST; + } + + return pctr; +} +_STATIC_H host_lib_status_t ifx_i2c_tl_send_next_fragment(ifx_i2c_context_t *p_ctx) +{ + uint8_t pctr = 0; + // Calculate size of fragment (last one might be shorter) + uint16_t tl_fragment_size = p_ctx->tl.max_packet_length; + pctr = ifx_i2c_tl_calculate_pctr(p_ctx); + if ((p_ctx->tl.actual_packet_length - p_ctx->tl.packet_offset) < tl_fragment_size) + { + tl_fragment_size = p_ctx->tl.actual_packet_length - p_ctx->tl.packet_offset; + } + + // Assign the pctr + p_ctx->tx_frame_buffer[IFX_I2C_TL_HEADER_OFFSET] = pctr; + //copy the data + memcpy(p_ctx->tx_frame_buffer+IFX_I2C_TL_HEADER_OFFSET+1,p_ctx->tl.p_actual_packet + p_ctx->tl.packet_offset,tl_fragment_size); + p_ctx->tl.packet_offset += tl_fragment_size; + //send the fragment to dl layer + return ifx_i2c_dl_send_frame(p_ctx,tl_fragment_size+1); +} + +_STATIC_H host_lib_status_t ifx_i2c_tl_send_chaining_error(ifx_i2c_context_t *p_ctx) +{ + uint16_t tl_fragment_size = 1; + p_ctx->tx_frame_buffer[IFX_I2C_TL_HEADER_OFFSET] = 0x07; + p_ctx->tl.total_recv_length = 0; + //send the fragment to dl layer + return ifx_i2c_dl_send_frame(p_ctx,tl_fragment_size); +} + +_STATIC_H host_lib_status_t ifx_i2c_tl_check_chaining_error(uint8_t current_chaning, uint8_t previous_chaining) +{ + host_lib_status_t status = IFX_I2C_STACK_ERROR; + if(((current_chaning == TL_CHAINING_ERROR) || (current_chaning == TL_CHAINING_NO) || (current_chaning == TL_CHAINING_LAST) + || (current_chaning == TL_CHAINING_INTERMEDIATE) || (current_chaning == TL_CHAINING_FIRST))) + { + if((pctr_states_table[current_chaning][0] == previous_chaining) || (pctr_states_table[current_chaning][1] == previous_chaining)) + { + status = IFX_I2C_STACK_SUCCESS; + } + } + + return status; +} + +_STATIC_H void ifx_i2c_dl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len) +{ + uint8_t pctr = 0; + uint8_t chaining = 0; + uint8_t exit_machine = TRUE; + do + { + if(NULL != p_data) + { + pctr = p_data[0]; + chaining = pctr & TL_PCTR_CHAIN_MASK; + } + // Propagate errors to upper layer + if ((event & IFX_I2C_DL_EVENT_ERROR)||(pctr & TL_PCTR_CHANNEL_MASK)) + { + p_ctx->tl.state = TL_STATE_ERROR; + p_ctx->tl.error_event = IFX_I2C_STACK_ERROR; + } + switch(p_ctx->tl.state) + { + case TL_STATE_IDLE: + { + exit_machine = FALSE; + p_ctx->tl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS, 0, 0); + } + break; + case TL_STATE_TX: + { + // Frame transmission in Data Link layer complete, start receiving frames + if (event & IFX_I2C_DL_EVENT_TX_SUCCESS) + { + if (p_ctx->tl.packet_offset < p_ctx->tl.actual_packet_length) + { + // Transmission of one fragment complete, send next fragment + LOG_TL("[IFX-TL]: Tx:Fragment sent,now send next\n"); + // Chaining error from slave + if(TL_CHAINING_ERROR == chaining) + { + LOG_TL("[IFX-TL]: Tx:Chaining error received while Tx\n"); + p_ctx->tl.state = TL_STATE_RESEND; + break; + } + // Any fragment received before complete transmission is error + if(data_len) + { + LOG_TL("[IFX-TL]: Tx:Data received while Tx\n"); + p_ctx->tl.state = TL_STATE_ERROR; + break; + } + exit_machine = FALSE; + //lint --e{534} suppress "Return value is not required to be checked" + ifx_i2c_tl_send_next_fragment(p_ctx); + } + else + { + // Transmission of all fragments complete, start receiving fragments + LOG_TL("[IFX-TL]: Tx:All fragment sent\n"); + p_ctx->tl.state = TL_STATE_RX; + p_ctx->tl.total_recv_length = 0; + p_ctx->tl.previous_chaining = TL_CHAINING_NO; + p_ctx->tl.transmission_completed = 1; + // if data is received after sending last frame + if (!(event & IFX_I2C_DL_EVENT_RX_SUCCESS)) + { + LOG_TL("[IFX-TL]: Tx:Data already received after Tx\n"); + // Received CTRL frame, trigger reception in Data Link layer + if (ifx_i2c_dl_receive_frame(p_ctx)) + { + LOG_TL("[IFX-TL]: Tx:RX Received CTRL frame fail -> Inform UL\n"); + p_ctx->tl.state = TL_STATE_ERROR; + } + exit_machine = FALSE; + } + } + } + else + { + LOG_TL("[IFX-TL]: Tx:IFX_I2C_DL_EVENT_TX_SUCCESS is not satisfied Tx\n"); + p_ctx->tl.state = TL_STATE_ERROR; + break; + } + } + break; + case TL_STATE_RX: + { + // Reception of frame from Data Link layer + if (event & IFX_I2C_DL_EVENT_RX_SUCCESS) + { + // Message must contain at least the transport layer header + if (data_len < TL_HEADER_SIZE) + { + LOG_TL("[IFX-TL]: Rx : Data received is more than header len\n"); + p_ctx->tl.state = TL_STATE_ERROR; + break; + } + + if(p_ctx->tl.error_event == IFX_I2C_STACK_MEM_ERROR) + { + if ((chaining == TL_CHAINING_LAST) || (ifx_i2c_dl_receive_frame(p_ctx))) + { + p_ctx->tl.state = TL_STATE_ERROR; + break; + } + p_ctx->tl.state = TL_STATE_RX; + exit_machine = FALSE; + break; + } + + // If chaining error detected + if(IFX_I2C_STACK_SUCCESS != ifx_i2c_tl_check_chaining_error(chaining,p_ctx->tl.previous_chaining)) + { + LOG_TL("[IFX-TL]: Rx : Chaining state is not correct\n"); + p_ctx->tl.state = TL_STATE_RESEND; + break; + } + + p_ctx->tl.previous_chaining = chaining; + if(NULL == p_data) + { + p_ctx->tl.state = TL_STATE_ERROR; + break; + } + + // No chaining and Last + if ((chaining == TL_CHAINING_NO)||(chaining == TL_CHAINING_LAST)) + { + LOG_TL("[IFX-TL]: Rx : No chain/Last chain received, Inform UL\n"); + + exit_machine = FALSE; + // Copy frame payload to transport layer receive buffer + memcpy(p_ctx->tl.p_recv_packet_buffer + p_ctx->tl.total_recv_length, p_data + 1, data_len - 1); + p_ctx->tl.total_recv_length += (data_len - 1); + // Inform upper layer that a packet has arrived + p_ctx->tl.state = TL_STATE_IDLE; + *p_ctx->tl.p_recv_packet_buffer_length = p_ctx->tl.total_recv_length; + p_ctx->tl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS, p_ctx->tl.p_recv_packet_buffer, *p_ctx->tl.p_recv_packet_buffer_length); + } + else + { + p_ctx->tl.state = TL_STATE_CHAINING; + } + } + else + { + LOG_TL("[IFX-TL]: Tx:IFX_I2C_DL_EVENT_TX_SUCCESS is not satisfied Tx\n"); + p_ctx->tl.state = TL_STATE_ERROR; + break; + } + } + break; + + case TL_STATE_CHAINING: + { + LOG_TL("[IFX-TL]: Chain : Chaining mode entered\n"); + // When receiving a starting fragment, fragment length must be max frame size for intermediate and last frame + // the buffer should not be empty + if (data_len != (p_ctx->tl.max_packet_length+1)) + { + LOG_TL("[IFX-TL]: Chain : Data len not equal to max frame size\n"); + p_ctx->tl.state = TL_STATE_CHAINING_ERROR; + break; + } + // Check for possible receive buffer overflow + if ((p_ctx->tl.total_recv_length + data_len - 1) > (*p_ctx->tl.p_recv_packet_buffer_length)) + { + LOG_TL("[IFX-TL]: Chain : Buffer overflow\n"); + p_ctx->tl.error_event = IFX_I2C_STACK_MEM_ERROR; + p_ctx->tl.state = TL_STATE_RX; + break; + } + if(NULL == p_data) + { + p_ctx->tl.state = TL_STATE_ERROR; + break; + } + // Copy frame payload to transport layer receive buffer + memcpy(p_ctx->tl.p_recv_packet_buffer + p_ctx->tl.total_recv_length, p_data + 1, data_len - 1); + p_ctx->tl.total_recv_length += (data_len - 1); + + p_ctx->tl.previous_chaining = pctr; + LOG_TL("[IFX-TL]: Chain : Continue in receive mode\n"); + p_ctx->tl.state = TL_STATE_RX; + // Continue receiving frames until packet is complete + if (ifx_i2c_dl_receive_frame(p_ctx)) + { + p_ctx->tl.state = TL_STATE_ERROR; + } + exit_machine = FALSE; + } + break; + + case TL_STATE_RESEND: + { + LOG_TL("[IFX-TL]: Resend Enter\n"); + // In received mode , for wrong pctr with data + if((data_len > 1) && (p_ctx->tl.transmission_completed == 1)) + { + LOG_TL("[IFX-TL]: Resend : Send chaining error\n"); + p_ctx->tl.state = TL_STATE_CHAINING_ERROR; + break; + } + // Master Resend the packets,Resend only once, otherwise exit with error + if(0 == (p_ctx->tl.chaining_error_count++)) + { + LOG_TL("[IFX-TL]: Resend : Resending\n"); + p_ctx->tl.state = TL_STATE_IDLE; + if(ifx_i2c_tl_resend_packets(p_ctx)) + { + p_ctx->tl.state = TL_STATE_ERROR; + } + else + { + exit_machine = FALSE; + } + } + else + { + LOG_TL("[IFX-TL]: Resend : chaining_error_count exceeded\n"); + p_ctx->tl.state = TL_STATE_ERROR; + } + } + break; + + case TL_STATE_CHAINING_ERROR: + { + // Send chaining error to slave + p_ctx->tl.state = TL_STATE_TX; + if(0 == (p_ctx->tl.master_chaining_error_count++)) + { + LOG_TL("[IFX-TL]: Chain error : Sending chain error\n"); + // Send chaining error only once + if(ifx_i2c_tl_send_chaining_error(p_ctx)) + { + p_ctx->tl.state = TL_STATE_ERROR; + } + else + { + exit_machine = FALSE; + } + } + else + { + LOG_TL("[IFX-TL]: Chain error : master_chaining_error_count exceeded\n"); + p_ctx->tl.state = TL_STATE_ERROR; + } + } + break; + case TL_STATE_ERROR: + { + LOG_TL("[IFX-TL]: Error\n"); + exit_machine = FALSE; + if ((event & IFX_I2C_DL_EVENT_ERROR) || (data_len)) + { + p_ctx->tl.state = TL_STATE_IDLE; + } + p_ctx->tl.upper_layer_event_handler(p_ctx,p_ctx->tl.error_event, 0u, 0u); + } + break; + default: + LOG_TL("[IFX-TL]: Exit from default case\n"); + p_ctx->tl.state = TL_STATE_IDLE; + exit_machine = FALSE; + p_ctx->tl.upper_layer_event_handler(p_ctx,p_ctx->tl.error_event, 0u, 0u); + break; + } + }while(exit_machine); +} + + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/optiga_comms_ifx_i2c.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/optiga_comms_ifx_i2c.c new file mode 100644 index 0000000..92db5d2 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/optiga_comms/optiga_comms_ifx_i2c.c @@ -0,0 +1,250 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements optiga comms abstraction layer for IFX I2C Protocol. +* +* \addtogroup grOptigaComms +* @{ +*/ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "optiga_comms.h" +#include "ifx_i2c.h" +/// @cond hidden +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + /// Optiga comms is in use + #define OPTIGA_COMMS_INUSE (0x01) + /// Optiga comms is free + #define OPTIGA_COMMS_FREE (0x00) +/********************************************************************************************************************** + * LOCAL DATA + *********************************************************************************************************************/ +/********************************************************************************************************************** + * LOCAL ROUTINES + *********************************************************************************************************************/ +static host_lib_status_t check_optiga_comms_state(optiga_comms_t *p_ctx); +static void ifx_i2c_event_handler(void* upper_layer_ctx, host_lib_status_t event); + +/// @endcond +/********************************************************************************************************************** + * API IMPLEMENTATION + *********************************************************************************************************************/ + +/** + * Initializes the commmunication with OPTIGA.
+ * + *Pre Conditions: + * - None
+ * + *API Details: + * - Initializes OPTIGA and establishes the communication channel.
+ * - Initializes the ifx i2c protocol stack and registers the event callbacks.
+ * - Negotiates the frame size and bit rate with the OPTIGA.
+ *
+ * + *User Input:
+ * - The input #optiga_comms_t p_ctx must not be NULL.
+ * - The following parameters in #optiga_comms_t must be initialized with appropriate values.
+ * - The comms_ctx must be initialized with a valid #ifx_i2c_context.
+ * - The upper_layer_event_handler parameter must be properly initialized. + * This is invoked when #optiga_comms_open is asynchronously completed.
+ * - The upper_layer_ctx must be properly initialized.
+ * + *Notes: + * - None
+ * + *
+ * \param[in,out] p_ctx Pointer to optiga comms context + * + * \retval #OPTIGA_COMMS_SUCCESS + * \retval #OPTIGA_COMMS_ERROR + */ +host_lib_status_t optiga_comms_open(optiga_comms_t *p_ctx) +{ + host_lib_status_t status = OPTIGA_COMMS_ERROR; + if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx)) + { + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx; + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler; + status = ifx_i2c_open((ifx_i2c_context_t*)(p_ctx->comms_ctx)); + if (IFX_I2C_STACK_SUCCESS != status) + { + p_ctx->state = OPTIGA_COMMS_FREE; + } + } + return status; +} + +/** + * Resets the OPTIGA.
+ * + *Pre Conditions: + * - Communication channel must be established with OPTIGA.
+ * + *API Details: + * - Resets the OPTIGA device.
+ * - Initializes the ifx i2c protocol stack.
+ * - Re-Initializes and negotiates the frame size and bit rate with the OPTIGA. + * The values remain same as that in previous #optiga_comms_open().
+ *
+ * + *User Input:
+ * - The input #optiga_comms_t p_ctx must not be NULL. + * + *Notes: + * For COLD and WARM reset type: If the gpio(vdd and/or reset) pins are not configured, + * the API continues without returning error status
+ * + * + * \param[in,out] p_ctx Pointer to #optiga_comms_t + * \param[in,out] reset_type type of reset + * + * \retval #OPTIGA_COMMS_SUCCESS + * \retval #OPTIGA_COMMS_ERROR + */ +host_lib_status_t optiga_comms_reset(optiga_comms_t *p_ctx,uint8_t reset_type) +{ + host_lib_status_t status = OPTIGA_COMMS_ERROR; + if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx)) + { + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx; + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler; + status = ifx_i2c_reset((ifx_i2c_context_t*)(p_ctx->comms_ctx),(ifx_i2c_reset_type_t)reset_type); + if (IFX_I2C_STACK_SUCCESS != status) + { + p_ctx->state = OPTIGA_COMMS_FREE; + } + } + return status; +} + +/** + * Sends a command to OPTIGA and receives a response.
+ * + * + *Pre Conditions: + * - Communication channel must be established with OPTIGA.
+ * + *API Details: + * - Transmit data(Command) to OPTIGA.
+ * - Receive data(Response) from OPTIGA.
+ *
+ * + *User Input:
+ * - The input #optiga_comms_t p_ctx must not be NULL.
+ * - The following parameters in #optiga_comms_t must be initialized with appropriate values
+ * - The comms_ctx must be initialized with a valid #ifx_i2c_context
+ * - The upper_layer_event_handler parameter must be properly initialized, + * if it is different from that in #optiga_comms_open(). + * This is invoked when optiga_comms_transceive is asynchronously completed.
+ * - The upper_layer_ctx must be properly initialized, + * if it is different from that in #optiga_comms_open().
+ * + *Notes: + * - The actual number of bytes received is stored in p_buffer_len. In case of error, p_buffer_len is set to 0.
+ * - If the size of p_buffer is zero or insufficient to copy the response bytes then + * #IFX_I2C_STACK_MEM_ERROR error is returned. + * + * + * \param[in,out] p_ctx Pointer to #optiga_comms_t + * \param[in] p_data Pointer to the write data buffer + * \param[in] p_data_length Pointer to the length of the write data buffer + * \param[in,out] p_buffer Pointer to the receive data buffer + * \param[in,out] p_buffer_len Pointer to the length of the receive data buffer + * + * \retval #OPTIGA_COMMS_SUCCESS + * \retval #OPTIGA_COMMS_ERROR + * \retval #IFX_I2C_STACK_MEM_ERROR + */ +host_lib_status_t optiga_comms_transceive(optiga_comms_t *p_ctx,const uint8_t* p_data, + const uint16_t* p_data_length, + uint8_t* p_buffer, uint16_t* p_buffer_len) +{ + host_lib_status_t status = OPTIGA_COMMS_ERROR; + if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx)) + { + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx; + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler; + status = (ifx_i2c_transceive((ifx_i2c_context_t*)(p_ctx->comms_ctx),p_data,p_data_length,p_buffer,p_buffer_len)); + if (IFX_I2C_STACK_SUCCESS != status) + { + p_ctx->state = OPTIGA_COMMS_FREE; + } + } + return status; +} + +/** + * Closes the communication with OPTIGA.
+ * + *Pre Conditions: + * - None
+ * + *API Details: + * - De-Initializes the OPTIGA and closes the communication channel.
+ * - Power downs the OPTIGA.
+ *
+ * + *User Input:
+ * - The input #optiga_comms_t p_ctx must not be NULL.
+ * - The #optiga_comms_t comms_ctx must be initialized with a valid #ifx_i2c_context
+ * + * \param[in,out] p_ctx Pointer to #optiga_comms_t + * + * \retval #OPTIGA_COMMS_SUCCESS + * \retval #OPTIGA_COMMS_ERROR + */ +host_lib_status_t optiga_comms_close(optiga_comms_t *p_ctx) +{ + host_lib_status_t status = OPTIGA_COMMS_ERROR; + if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx)) + { + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx; + ((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler; + status = ifx_i2c_close((ifx_i2c_context_t*)(p_ctx->comms_ctx)); + if (IFX_I2C_STACK_SUCCESS != status) + { + p_ctx->state = OPTIGA_COMMS_FREE; + } + } + return status; +} + +/// @cond hidden +static host_lib_status_t check_optiga_comms_state(optiga_comms_t *p_ctx) +{ + host_lib_status_t status = OPTIGA_COMMS_ERROR; + if ((NULL != p_ctx) && (p_ctx->state != OPTIGA_COMMS_INUSE)) + { + p_ctx->state = OPTIGA_COMMS_INUSE; + status = OPTIGA_COMMS_SUCCESS; + } + return status; +} + +//lint --e{818} suppress "This is ignored as upper layer handler function prototype requires this argument" +static void ifx_i2c_event_handler(void* upper_layer_ctx, host_lib_status_t event) +{ + void* ctx = ((optiga_comms_t*)upper_layer_ctx)->upper_layer_ctx; + ((optiga_comms_t*)upper_layer_ctx)->upper_layer_handler(ctx,event); + ((optiga_comms_t*)upper_layer_ctx)->state = OPTIGA_COMMS_FREE; +} + +/// @endcond +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_gpio.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_gpio.c new file mode 100644 index 0000000..d4243d8 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_gpio.c @@ -0,0 +1,97 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the platform abstraction layer APIs for gpio. +* +* \addtogroup grPAL +* @{ +*/ + + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "pal_gpio.h" +#include "nrf_gpio.h" +#include "pal_ifx_i2c_config.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + +/********************************************************************************************************************** + * LOCAL DATA + *********************************************************************************************************************/ + +/********************************************************************************************************************** + * LOCAL ROUTINES + *********************************************************************************************************************/ + +/********************************************************************************************************************** + * API IMPLEMENTATION + *********************************************************************************************************************/ + +void pal_gpio_init() +{ + // Init power pins + nrf_gpio_cfg_output(19); + nrf_gpio_cfg_output(20); + + // Set power pins to enable power + nrf_gpio_pin_clear(19); // Enable power for the *on-board* Trust X device + nrf_gpio_pin_set(20); // Disable power for *external* Trust X device inside the 2GO slot + + // Init reset pin + nrf_gpio_cfg_output((uint32_t)(optiga_reset_0.p_gpio_hw)); +} + +/** +* Sets the GPIO pin to high state +* +* API Details: +* The API sets the pin high, only if the pin is assigned to a valid gpio context.
+* Otherwise the API returns without any failure status.
+* +*\param[in] p_gpio_context Pointer to pal layer gpio context +* +* +*/ +void pal_gpio_set_high(const pal_gpio_t* p_gpio_context) +{ + if (p_gpio_context != NULL && p_gpio_context->p_gpio_hw != NULL) + { + nrf_gpio_pin_set((uint32_t)(p_gpio_context->p_gpio_hw)); + } +} + +/** +* Sets the gpio pin to low state +* +* API Details: +* The API set the pin low, only if the pin is assigned to a valid gpio context.
+* Otherwise the API returns without any failure status.
+* +*\param[in] p_gpio_context Pointer to pal layer gpio context +* +*/ +void pal_gpio_set_low(const pal_gpio_t* p_gpio_context) +{ + if (p_gpio_context != NULL && p_gpio_context->p_gpio_hw != NULL) + { + nrf_gpio_pin_clear((uint32_t)(p_gpio_context->p_gpio_hw)); + } +} + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_i2c.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_i2c.c new file mode 100644 index 0000000..24897ba --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_i2c.c @@ -0,0 +1,314 @@ +/** +* \copyright +* Copyright(c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the platform abstraction layer(pal) APIs for I2C. +* +* \addtogroup grPAL +* @{ +*/ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "pal_i2c.h" +#include "ifx_i2c.h" +#include "nrf_twi_mngr.h" + +/// @cond hidden + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ +#define PAL_I2C_MASTER_MAX_BITRATE (400) + +/** @brief PIN for I2C SCL to Infineon OPTIGA Trust X device */ +#define OPTIGA_PIN_I2C_SCL (27) +/** @brief PIN for I2C SDA to Infineon OPTIGA Trust X device */ +#define OPTIGA_PIN_I2C_SDA (26) + +/** @brief I2C driver instance */ +#define TWI_INSTANCE_ID 0 + +/** @brief Maximal number of pending I2C transactions */ +#define MAX_PENDING_TRANSACTIONS 5 + +/********************************************************************************************************************* + * LOCAL DATA + *********************************************************************************************************************/ + +/* Pointer to the current pal i2c context */ +static pal_i2c_t * gp_pal_i2c_current_ctx; + +/** @brief Definition of TWI manager instance */ +NRF_TWI_MNGR_DEF(m_app_twi, MAX_PENDING_TRANSACTIONS, TWI_INSTANCE_ID); + +/** @brief Definition of TWI manager transfer instance */ +static nrf_twi_mngr_transfer_t m_transfer; + +/** @brief Definition of TWI manager transaction instance */ +static nrf_twi_mngr_transaction_t m_transaction; + +/********************************************************************************************************************** + * LOCAL ROUTINES + *********************************************************************************************************************/ + +/** + * Pal I2C event handler function to invoke the registered upper layer callback
+ * + *API Details: + * - This function implements the platform specific i2c event handling mechanism
+ * - It calls the registered upper layer function after completion of the I2C read/write operations
+ * - The respective event status are explained below. + * - #PAL_I2C_EVENT_ERROR when I2C fails due to low level failures(NACK/I2C protocol errors) + * - #PAL_I2C_EVENT_SUCCESS when operation is successfully completed + * + * \param[in] p_pal_i2c_ctx Pointer to the pal i2c context #pal_i2c_t + * \param[in] event Status of the event reported after read/write completion or due to I2C errors + * + */ +static void app_twi_callback(ret_code_t result, void * p_user_data) +{ + app_event_handler_t upper_layer_handler; + //lint --e{611} suppress "void* function pointer is type casted to app_event_handler_t type" + upper_layer_handler = (app_event_handler_t)gp_pal_i2c_current_ctx->upper_layer_event_handler; + + if (result == NRF_SUCCESS) + { + upper_layer_handler(gp_pal_i2c_current_ctx->upper_layer_ctx, PAL_I2C_EVENT_SUCCESS); + } + else + { + upper_layer_handler(gp_pal_i2c_current_ctx->upper_layer_ctx, PAL_I2C_EVENT_ERROR); + } +} + +/// @endcond + +/********************************************************************************************************************** + * API IMPLEMENTATION + *********************************************************************************************************************/ + +/** + * API to initialize the i2c master with the given context. + *
+ * + *API Details: + * - The platform specific initialization of I2C master has to be implemented as part of this API, if required.
+ * - If the target platform does not demand explicit initialization of i2c master + * (Example: If the platform driver takes care of init after the reset), it would not be required to implement.
+ * - The implementation must take care the following scenarios depending upon the target platform selected. + * - The implementation must handle the acquiring and releasing of the I2C bus before initializing the I2C master to + * avoid interrupting the ongoing slave I2C transactions using the same I2C master. + * - If the I2C bus is in busy state, the API must not initialize and return #PAL_STATUS_I2C_BUSY status. + * - Repeated initialization must be taken care with respect to the platform requirements. (Example: Multiple users/applications + * sharing the same I2C master resource) + * + *User Input:
+ * - The input #pal_i2c_t p_i2c_context must not be NULL.
+ * + * \param[in] p_i2c_context Pal i2c context to be initialized + * + * \retval #PAL_STATUS_SUCCESS Returns when the I2C master init it successfull + * \retval #PAL_STATUS_FAILURE Returns when the I2C init fails. + */ +pal_status_t pal_i2c_init(const pal_i2c_t* p_i2c_context) +{ + nrf_drv_twi_config_t const config = { + .scl = OPTIGA_PIN_I2C_SCL, + .sda = OPTIGA_PIN_I2C_SDA, + .frequency = (nrf_drv_twi_frequency_t) NRF_TWI_FREQ_400K, + .interrupt_priority = APP_IRQ_PRIORITY_LOWEST, + .clear_bus_init = false + }; + + // Initialize I2C driver + if (nrf_twi_mngr_init(&m_app_twi, &config) != NRF_SUCCESS) + { + return PAL_STATUS_FAILURE; + } + return PAL_STATUS_SUCCESS; +} + +/** + * API to de-initialize the I2C master with the specified context. + *
+ * + *API Details: + * - The platform specific de-initialization of I2C master has to be implemented as part of this API, if required.
+ * - If the target platform does not demand explicit de-initialization of i2c master + * (Example: If the platform driver takes care of init after the reset), it would not be required to implement.
+ * - The implementation must take care the following scenarios depending upon the target platform selected. + * - The implementation must handle the acquiring and releasing of the I2C bus before de-initializing the I2C master to + * avoid interrupting the ongoing slave I2C transactions using the same I2C master. + * - If the I2C bus is in busy state, the API must not de-initialize and return #PAL_STATUS_I2C_BUSY status. + * - This API must ensure that multiple users/applications sharing the same I2C master resource is not impacted. + * + *User Input:
+ * - The input #pal_i2c_t p_i2c_context must not be NULL.
+ * + * \param[in] p_i2c_context I2C context to be de-initialized + * + * \retval #PAL_STATUS_SUCCESS Returns when the I2C master de-init it successfull + * \retval #PAL_STATUS_FAILURE Returns when the I2C de-init fails. + */ +pal_status_t pal_i2c_deinit(const pal_i2c_t* p_i2c_context) +{ + nrf_twi_mngr_uninit(&m_app_twi); + return PAL_STATUS_SUCCESS; +} + +/** + * Platform abstraction layer API to write the data to I2C slave. + *
+ *
+ * \image html pal_i2c_write.png "pal_i2c_write()" width=20cm + * + * + *API Details: + * - The API attempts to write if the I2C bus is free, else it returns busy status #PAL_STATUS_I2C_BUSY
+ * - The bus is released only after the completion of transmission or after completion of error handling.
+ * - The API invokes the upper layer handler with the respective event status as explained below. + * - #PAL_I2C_EVENT_BUSY when I2C bus in busy state + * - #PAL_I2C_EVENT_ERROR when API fails + * - #PAL_I2C_EVENT_SUCCESS when operation is successfully completed asynchronously + *
+ * + *User Input:
+ * - The input #pal_i2c_t p_i2c_context must not be NULL.
+ * - The upper_layer_event_handler must be initialized in the p_i2c_context before invoking the API.
+ * + *Notes:
+ * - Otherwise the below implementation has to be updated to handle different bitrates based on the input context.
+ * - The caller of this API must take care of the guard time based on the slave's requirement.
+ * + * \param[in] p_i2c_context Pointer to the pal I2C context #pal_i2c_t + * \param[in] p_data Pointer to the data to be written + * \param[in] length Length of the data to be written + * + * \retval #PAL_STATUS_SUCCESS Returns when the I2C write is invoked successfully + * \retval #PAL_STATUS_FAILURE Returns when the I2C write fails. + * \retval #PAL_STATUS_I2C_BUSY Returns when the I2C bus is busy. + */ +pal_status_t pal_i2c_write(pal_i2c_t* p_i2c_context,uint8_t* p_data , uint16_t length) +{ + gp_pal_i2c_current_ctx = p_i2c_context; + + m_transfer.p_data = p_data; + m_transfer.length = length; + m_transfer.operation = NRF_TWI_MNGR_WRITE_OP(IFX_I2C_BASE_ADDR); + m_transfer.flags = 0; + + m_transaction.callback = app_twi_callback; + m_transaction.number_of_transfers = 1; + m_transaction.p_required_twi_cfg = NULL; + m_transaction.p_transfers = &m_transfer; + m_transaction.p_user_data = (void*) PAL_STATUS_SUCCESS; + + if (nrf_twi_mngr_schedule(&m_app_twi, &m_transaction) != NRF_SUCCESS) + { + app_twi_callback(NRF_ERROR_BUSY, 0); + } + + return PAL_STATUS_SUCCESS; +} + +/** + * Platform abstraction layer API to read the data from I2C slave. + *
+ *
+ * \image html pal_i2c_read.png "pal_i2c_read()" width=20cm + * + *API Details: + * - The API attempts to read if the I2C bus is free, else it returns busy status #PAL_STATUS_I2C_BUSY
+ * - The bus is released only after the completion of reception or after completion of error handling.
+ * - The API invokes the upper layer handler with the respective event status as explained below. + * - #PAL_I2C_EVENT_BUSY when I2C bus in busy state + * - #PAL_I2C_EVENT_ERROR when API fails + * - #PAL_I2C_EVENT_SUCCESS when operation is successfully completed asynchronously + *
+ * + *User Input:
+ * - The input #pal_i2c_t p_i2c_context must not be NULL.
+ * - The upper_layer_event_handler must be initialized in the p_i2c_context before invoking the API.
+ * + *Notes:
+ * - Otherwise the below implementation has to be updated to handle different bitrates based on the input context.
+ * - The caller of this API must take care of the guard time based on the slave's requirement.
+ * + * \param[in] p_i2c_context pointer to the PAL i2c context #pal_i2c_t + * \param[in] p_data Pointer to the data buffer to store the read data + * \param[in] length Length of the data to be read + * + * \retval #PAL_STATUS_SUCCESS Returns when the I2C read is invoked successfully + * \retval #PAL_STATUS_FAILURE Returns when the I2C read fails. + * \retval #PAL_STATUS_I2C_BUSY Returns when the I2C bus is busy. + */ +pal_status_t pal_i2c_read(pal_i2c_t* p_i2c_context , uint8_t* p_data , uint16_t length) +{ + gp_pal_i2c_current_ctx = p_i2c_context; + + m_transfer.p_data = p_data; + m_transfer.length = length; + m_transfer.operation = NRF_TWI_MNGR_READ_OP(IFX_I2C_BASE_ADDR); + m_transfer.flags = 0; + + m_transaction.callback = app_twi_callback; + m_transaction.number_of_transfers = 1; + m_transaction.p_required_twi_cfg = 0; + m_transaction.p_transfers = &m_transfer; + m_transaction.p_user_data = (void*) PAL_STATUS_SUCCESS; + + if (nrf_twi_mngr_schedule(&m_app_twi, &m_transaction) != NRF_SUCCESS) + { + app_twi_callback(NRF_ERROR_BUSY, 0); + } + + return PAL_STATUS_SUCCESS; +} + +/** + * Platform abstraction layer API to set the bitrate/speed(KHz) of I2C master. + *
+ * + *API Details: + * - Sets the bitrate of I2C master if the I2C bus is free, else it returns busy status #PAL_STATUS_I2C_BUSY
+ * - The bus is released after the setting the bitrate.
+ * - This API must take care of setting the bitrate to I2C master's maximum supported value. + * - Eg. In XMC4500, the maximum supported bitrate is 400 KHz. If the supplied bitrate is greater than 400KHz, the API will + * set the I2C master's bitrate to 400KHz. + * - Use the #PAL_I2C_MASTER_MAX_BITRATE macro to specify the maximum supported bitrate value for the target platform. + * - If upper_layer_event_handler is initialized, the upper layer handler is invoked with the respective event + * status listed below. + * - #PAL_I2C_EVENT_BUSY when I2C bus in busy state + * - #PAL_I2C_EVENT_ERROR when API fails to set the bit rate + * - #PAL_I2C_EVENT_SUCCESS when operation is successful + *
+ * + *User Input:
+ * - The input #pal_i2c_t p_i2c_context must not be NULL.
+ * + * \param[in] p_i2c_context Pointer to the pal i2c context + * \param[in] bitrate Bitrate to be used by i2c master in KHz + * + * \retval #PAL_STATUS_SUCCESS Returns when the setting of bitrate is successfully completed + * \retval #PAL_STATUS_FAILURE Returns when the setting of bitrate fails. + * \retval #PAL_STATUS_I2C_BUSY Returns when the I2C bus is busy. + */ +pal_status_t pal_i2c_set_bitrate(const pal_i2c_t* p_i2c_context , uint16_t bitrate) +{ + // Bitrate is fixed to the maximum frequency on this platform (400K) + return PAL_STATUS_SUCCESS; +} + +/** +* @} +*/ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_ifx_i2c_config.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_ifx_i2c_config.c new file mode 100644 index 0000000..bb4b51f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_ifx_i2c_config.c @@ -0,0 +1,71 @@ +/** +* \copyright +* Copyright(c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(RM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements platform abstraction layer configurations for ifx i2c protocol. +* +* \addtogroup grPAL +* @{ +*/ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "stdlib.h" +#include "stdio.h" +#include "pal_gpio.h" +#include "pal_i2c.h" +#include "ifx_i2c_config.h" + +/********************************************************************************************************************* + * pal ifx i2c instance + *********************************************************************************************************************/ +/** + * \brief PAL I2C configuration for OPTIGA. + */ +pal_i2c_t optiga_pal_i2c_context_0 = +{ + /// Pointer to I2C master platform specific context + NULL, + /// Slave address + IFX_I2C_BASE_ADDR, + /// Upper layer context + NULL, + /// Callback event handler + NULL +}; + +/********************************************************************************************************************* + * PAL GPIO configurations defined for XMC4500 + *********************************************************************************************************************/ +/** +* \brief PAL vdd pin configuration for OPTIGA. + */ +pal_gpio_t optiga_vdd_0 = +{ + // Platform specific GPIO context for the pin used to toggle Vdd. + (void*)NULL +}; + +/** + * \brief PAL reset pin configuration for OPTIGA. + */ +pal_gpio_t optiga_reset_0 = +{ + // Platform specific GPIO context for the pin used to toggle Reset. + (void*)18 +}; + + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_event.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_event.c new file mode 100644 index 0000000..809c2bd --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_event.c @@ -0,0 +1,127 @@ +/** +* \copyright +* Copyright(c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the platform abstraction layer APIs for os event/scheduler. +* +* \addtogroup grPAL +* @{ +*/ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "stdlib.h" +#include "stdio.h" +#include "pal_os_event.h" +#include "nrf_rtc.h" +#include "nrf_drv_rtc.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + +/********************************************************************************************************************* + * LOCAL DATA + *********************************************************************************************************************/ +/// @cond hidden +/// Callback function when timer elapses +static volatile register_callback callback_registered = NULL; +/// Pointer to store upper layer callback context (For example: Ifx i2c context) +static void * callback_ctx; + +const nrf_drv_rtc_t rtc2 = NRF_DRV_RTC_INSTANCE(2); +static nrf_drv_rtc_config_t m_rtc2_config = NRF_DRV_RTC_DEFAULT_CONFIG; + +// Tick count for pal_os_timer +volatile uint32_t g_tick_count = 0; + +/** +* Timer callback handler. +* +* This get called from the TIMER elapse event.
+* Once the timer expires, the registered callback funtion gets called from the timer event handler, if +* the call back is not NULL.
+* +*\param[in] args Callback argument +* +*/ +static void ifx_rtc_handler(nrf_drv_rtc_int_type_t int_type) +{ + volatile register_callback callback; + + if (int_type == NRF_DRV_RTC_INT_TICK) + { + g_tick_count++; + } + + if (int_type == NRF_DRV_RTC_INT_COMPARE0) + { + nrf_drv_rtc_cc_disable(&rtc2, 0); + + if (callback_registered != NULL) + { + callback = callback_registered; + callback_registered = NULL; + callback(callback_ctx); + } + } +} + +/// @endcond + +void pal_os_event_init() +{ + // Initialize the RTC2 driver instance + APP_ERROR_CHECK(nrf_drv_rtc_init(&rtc2, &m_rtc2_config, ifx_rtc_handler)); + + // Set the prescaler to approximately get 1 ms intervals + m_rtc2_config.prescaler = 31; + + // Enable tick event and interrupt + nrf_drv_rtc_tick_enable(&rtc2, true); + + // Power on RTC instance + nrf_drv_rtc_enable(&rtc2); +} + +/** +* Platform specific event call back registration function to trigger once when timer expires. +*
+* +* API Details: +* This function registers the callback function supplied by the caller.
+* It triggers a timer with the supplied time interval in microseconds.
+* Once the timer expires, the registered callback function gets called.
+* +* \param[in] callback Callback function pointer +* \param[in] callback_args Callback arguments +* \param[in] time_us time in micro seconds to trigger the call back +* +*/ +void pal_os_event_register_callback_oneshot(register_callback callback, + void* callback_args, + uint32_t time_us) +{ + callback_registered = callback; + callback_ctx = callback_args; + + // Clear the counter + nrf_drv_rtc_counter_clear(&rtc2); + + // Set the compare register to trigger approximately at time_us + APP_ERROR_CHECK(nrf_drv_rtc_cc_set(&rtc2, 0, (time_us / 1024) + 1 , true)); +} + +/** +* @} +*/ + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_timer.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_timer.c new file mode 100644 index 0000000..da2deba --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/infineon/pal/nrf5x/pal_os_timer.c @@ -0,0 +1,71 @@ +/** +* \copyright +* Copyright (c) 2018, Infineon Technologies AG +* All rights reserved. +* +* This software is provided with terms and conditions as specified in OPTIGA(TM) Trust X Evaluation Kit License Agreement. +* \endcopyright +* +* \author Infineon AG +* +* \file +* +* \brief This file implements the platform abstraction layer APIs for timer. +* +* \addtogroup grPAL +* @{ +*/ + +/********************************************************************************************************************** + * HEADER FILES + *********************************************************************************************************************/ +#include "pal_os_timer.h" +#include "nrf_delay.h" +#include "nrf_rtc.h" +#include "nrf_drv_rtc.h" + +/********************************************************************************************************************** + * MACROS + *********************************************************************************************************************/ + +/// @cond hidden +/********************************************************************************************************************* + * LOCAL DATA + *********************************************************************************************************************/ +// Defined in pal_os_event.c +extern volatile uint32_t g_tick_count; + +/********************************************************************************************************************** + * LOCAL ROUTINES + *********************************************************************************************************************/ +/// @endcond + +/********************************************************************************************************************** + * API IMPLEMENTATION + *********************************************************************************************************************/ +/** +* Get the current time in milliseconds
+* +* +* \retval uint32_t time in milliseconds +*/ +uint32_t pal_os_timer_get_time_in_milliseconds(void) +{ + return (g_tick_count); +} + +/** +* Function to wait or delay until the given milliseconds time +* +* \param[in] milliseconds Delay value in milliseconds +* +*/ +void pal_os_timer_delay_in_milliseconds(uint16_t milliseconds) +{ + nrf_delay_ms(milliseconds); +} + +/** +* @} +*/ + -- cgit v1.2.3