/* * Common IO - basic V1.0.0 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * http://aws.amazon.com/freertos * http://www.FreeRTOS.org */ /** * @file iot_i2c.h * @brief File for the APIs of I2C called by application layer. */ #ifndef _IOT_I2C_H_ #define _IOT_I2C_H_ /* Standard includes. */ #include #include /** * @defgroup iot_i2c I2C Abstraction APIs. * @{ */ /** * The speeds supported by I2C bus. */ #define IOT_I2C_STANDARD_MODE_BPS ( 100000 ) /*!< Standard mode bits per second. */ #define IOT_I2C_FAST_MODE_BPS ( 400000 ) /*!< Fast mode bits per second. */ #define IOT_I2C_FAST_MODE_PLUS_BPS ( 1000000 ) /*!< Fast plus mode bits per second. */ #define IOT_I2C_HIGH_SPEED_BPS ( 3400000 ) /*!< High speed mode bits per second. */ /** * The return codes for the functions in I2C. */ #define IOT_I2C_SUCCESS ( 0 ) /*!< I2C operation completed successfully. */ #define IOT_I2C_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ #define IOT_I2C_BUSY ( 2 ) /*!< I2C bus is busy at current time. */ #define IOT_I2C_WRITE_FAILED ( 3 ) /*!< I2C driver returns error when performing write operation. */ #define IOT_I2C_READ_FAILED ( 4 ) /*!< I2C driver returns error when performing read operation. */ #define IOT_I2C_NACK ( 5 ) /*!< Unexpected NACK is caught. */ #define IOT_I2C_BUS_TIMEOUT ( 6 ) /*!< I2C operation not completed within specified timeout. */ #define IOT_I2C_NOTHING_TO_CANCEL ( 7 ) /*!< No ongoing transaction when cancel operation is performed. */ #define IOT_I2C_FUNCTION_NOT_SUPPORTED ( 8 ) /*!< I2C operation is not supported. */ #define IOT_I2C_SLAVE_ADDRESS_NOT_SET ( 9 ) /*!< Slave address is not set before calling I2C read or write operation. */ /** * @brief I2C Bus status */ typedef enum { eI2CBusIdle = 0, /*!< I2C bus is idle. */ eI2cBusBusy = IOT_I2C_BUSY, /*!< I2C bus is busy. */ } IotI2CBusStatus_t; /** * @brief I2C operation status. */ typedef enum { eI2CCompleted = IOT_I2C_SUCCESS, /*!< I2C operation completed successfully. */ eI2CDriverFailed, /*!< I2C driver returns error during last operation. */ eI2CNackFromSlave = IOT_I2C_NACK, /*!< Unexpected NACK is caught. */ eI2CMasterTimeout = IOT_I2C_BUS_TIMEOUT, /*!< I2C operation not completed within specified timeout. */ } IotI2COperationStatus_t; /** * @brief I2C bus configuration */ typedef struct IotI2CConfig { uint32_t ulMasterTimeout; /**Example * @code{c} * // Declare an I2C handle. * IotI2CHandle_t xI2CHandle; * * // Return value of I2C functions. * int32_t lRetVal = IOT_I2C_SUCCESS; * * // Register address on I2C slave device. * uint8_t xDeviceRegisterAddress = 0x73; * * // Number of read/write bytes. * uint16_t usReadBytes = 0; * uint16_t usWriteBytes = 0; * * uint8_t ucReadBuffer[2] = {0}; * * // Configurations of I2C master device. * IotI2CConfig_t xI2CConfig = * { * .ulBusFreq = IOT_I2C_FAST_MODE_BPS, * .ulMasterTimeout = 500 * }; * * // Open one of the I2C instance and get a handle. * xI2CHandle = iot_i2c_open( 1 ); * * if ( xI2CHandle != NULL ) * { * // Set I2C configuration. * lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); * // assert(lRetVal == IOT_I2C_SUCCESS); * * // Set slave address. * lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); * // assert(lRetVal == IOT_I2C_SUCCESS); * * // Write the register address as single byte, in a transaction. * lRetVal = iot_i2c_write_sync( xI2CHandle, &xDeviceRegisterAddress, sizeof( xDeviceRegisterAddress ) ); * * if ( lRetVal == IOT_I2C_SUCCESS ) * { * // Get the number of written bytes in last transaction. * lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &usWriteBytes ); * // assert(lRetVal == IOT_I2C_SUCCESS); * // assert(usWriteBytes == 1); * * // Read two bytes of data to allocated buffer, in a transaction. * lRetVal = iot_i2c_read_sync( xI2CHandle, &ucReadBuffer, sizeof( ucReadBuffer ) ); * * if ( lRetVal == IOT_I2C_SUCCESS ) * { * // Get the number of read bytes in last transaction. * lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetRxNoOfbytes, &usReadBytes ); * // assert(lRetVal == IOT_I2C_SUCCESS); * // assert(usReadBytes == 2); * } * } * * lRetVal = iot_i2c_close( xI2CHandle ); * // assert(lRetVal == IOT_I2C_SUCCESS); * } * @endcode */ int32_t iot_i2c_read_sync( IotI2CHandle_t const pxI2CPeripheral, uint8_t * const pucBuffer, size_t xBytes ); /** * @brief Starts the I2C master write operation in synchronous mode. * * This function attempts to write certain number of bytes from a pre-allocated buffer to a slave device, in synchronous way. * Partial write might happen, e.g. slave device unable to receive more data. * And the number of bytes that have been actually written can be obtained by calling iot_i2c_ioctl. * * @note Usually, the first byte is treated as the register address and the following bytes are treated as data to be written. * @note If eI2CSendNoStopFlag is set and this function returns, whether the actual transaction has been started is undefined. This is board-specific behavior. * * @warning Prior to this function, slave address must be already configured. * @warning None of other read or write functions shall be called during this function. * * @param[in] pxI2CPeripheral The I2C handle returned in open() call. * @param[in] pucBuffer The transmit buffer containing the data to be written. It must stay allocated before this function returns. * @param[in] xBytes The number of bytes to write. * * @return * - IOT_I2C_SUCCESS, on success (all the requested bytes have been written) * - IOT_I2C_INVALID_VALUE, if * - pxI2CPeripheral is NULL * - pxI2CPeripheral is not opened yet * - pucBuffer is NULL * - xBytes is 0 * - IOT_I2C_SLAVE_ADDRESS_NOT_SET, if slave address is not set yet * - IOT_I2C_NACK or IOT_I2C_WRITE_FAILED, if * - no device correspond to the slave address * - the slave is unable to receive or transmit * - the slave gets data or commands that it does not understand * - there is some unknown driver error * - IOT_I2C_BUS_TIMEOUT, if timeout is supported and slave device does not respond within configured timeout. * - IOT_I2C_BUSY, if the bus is busy which means there is an ongoing transaction. */ int32_t iot_i2c_write_sync( IotI2CHandle_t const pxI2CPeripheral, uint8_t * const pucBuffer, size_t xBytes ); /** * @brief Starts the I2C master read operation in asynchronous mode. * * This function attempts to read certain number of bytes from a pre-allocated buffer, in asynchronous way. * It returns immediately when the operation is started and the status can be check by calling iot_i2c_ioctl. * Once the operation completes, successful or not, the user callback will be invoked. * * Partial read might happen, e.g. slave device unable to receive more data. * And the number of bytes that have been actually read can be obtained by calling iot_i2c_ioctl. * * @note Usually, the address of register needs to be written before calling this function. * @note If eI2CSendNoStopFlag is set and this function returns, whether the actual transaction has been started is undefined. This is board-specific behavior. * @note In order to get notification when the asynchronous call is completed, iot_i2c_set_callback must be called prior to this. * * @warning Prior to this function, slave address must be already configured. * @warning pucBuffer must be valid before callback is invoked. * @warning None of other read or write functions shall be called during this function or before user callback. * * @param[in] pxI2CPeripheral The I2C handle returned in open() call. * @param[out] pucBuffer The receive buffer to read the data into * @param[in] xBytes The number of bytes to read. * * @return * - IOT_I2C_SUCCESS, on success * - IOT_I2C_INVALID_VALUE, if * - pxI2CPeripheral is NULL * - pxI2CPeripheral is not opened yet * - pucBuffer is NULL * - xBytes is 0 * - IOT_I2C_SLAVE_ADDRESS_NOT_SET, if slave address is not set yet * - IOT_I2C_NACK or IOT_I2C_READ_FAILED, if * - no device correspond to the slave address * - the slave is unable to receive or transmit * - the slave gets data or commands that it does not understand * - there is some unknown driver error */ int32_t iot_i2c_read_async( IotI2CHandle_t const pxI2CPeripheral, uint8_t * const pucBuffer, size_t xBytes ); /** * @brief Starts the I2C master write operation in asynchronous mode. * * This function attempts to write certain number of bytes from a pre-allocated buffer to a slave device, in asynchronous way. * It returns immediately when the operation is started and the status can be check by calling iot_i2c_ioctl. * Once the operation completes, successful or not, the user callback will be invoked. * * Partial write might happen, e.g. slave device unable to receive more data. * And the number of bytes that have been actually written can be obtained by calling iot_i2c_ioctl. * * @note Usually, the first byte is treated as the register address and the following bytes are treated as data to be written. * @note If eI2CSendNoStopFlag is set and this function returns, whether the actual transaction has been started is undefined. This is board-specific behavior. * @note In order to get notification when the asynchronous call is completed, iot_i2c_set_callback must be called prior to this. * * @warning Prior to this function, slave address must be already configured. * @warning None of other read or write functions shall be called during this function. * * @param[in] pxI2CPeripheral The I2C handle returned in open() call. * @param[in] pucBuffer The transmit buffer containing the data to be written. It must stay allocated before this function returns. * @param[in] xBytes The number of bytes to write. * * @return * - IOT_I2C_SUCCESS, on success * - IOT_I2C_INVALID_VALUE, if * - pxI2CPeripheral is NULL * - pxI2CPeripheral is not opened yet * - pucBuffer is NULL * - xBytes is 0 * - IOT_I2C_SLAVE_ADDRESS_NOT_SET, if slave address is not set yet * - IOT_I2C_NACK or IOT_I2C_WRITE_FAILED, if * - no device correspond to the slave address * - the slave is unable to receive or transmit * - the slave gets data or commands that it does not understand * - there is some unknown driver error * - IOT_I2C_BUS_TIMEOUT, if timeout is supported and slave device does not respond within configured timeout. * - IOT_I2C_BUSY, if the bus is busy which means there is an ongoing transaction. */ int32_t iot_i2c_write_async( IotI2CHandle_t const pxI2CPeripheral, uint8_t * const pucBuffer, size_t xBytes ); /** * @brief Configures the I2C master with user configuration. * * @param[in] pxI2CPeripheral The I2C handle returned in open() call. * @param[in] xI2CRequest Should be one of I2C_Ioctl_Request_t. * @param[in,out] pvBuffer The configuration values for the IOCTL request. * * @note SetMasterConfig is expected only called once at beginning. * This request expects the buffer with size of IotI2CConfig_t. * * @note eI2CGetMasterConfig gets the current configuration for I2C master. * This request expects the buffer with size of IotI2CConfig_t. * * @note eI2CGetBusState gets the current bus state. * This request expects buffer with size of IotI2CBusStatus_t. * * @note eI2CSendNoStopFlag is called at every operation you want to not send stop condition. * * @note eI2CSetSlaveAddr sets either 7-bit address or 10-bit address, according to hardware's capability. * This request expects 2 bytes buffer (uint16_t) * * @note eI2CGetTxNoOfbytes returns the number of written bytes in last transaction. * This is supposed to be called in the caller task or application callback, right after last transaction completes. * This request expects 2 bytes buffer (uint16_t). * * - If the last transaction only did write, this returns the actual number of written bytes which might be smaller than the requested number (partial write). * - If the last transaction only did read, this returns 0. * - If the last transaction did both write and read, this returns the number of written bytes. * * @note eI2CGetRxNoOfbytes returns the number of read bytes in last transaction. * This is supposed to be called in the caller task or application callback, right after last transaction completes. * This request expects 2 bytes buffer (uint16_t). * * - If the last transaction only did read, this returns the actual number of read bytes which might be smaller than the requested number (partial read). * - If the last transaction only did write, this returns 0. * - If the last transaction did both write and read, this returns the number of read bytes. * * * @return * - IOT_I2C_SUCCESS, on success * - IOT_I2C_INVALID_VALUE, if * - pxI2CPeripheral is NULL * - pxI2CPeripheral is not opened yet * - pucBuffer is NULL with requests which needs buffer * - IOT_I2C_FUNCTION_NOT_SUPPORTED, if this board doesn't support this feature. * - eI2CSetSlaveAddr: 10-bit address is not supported * - eI2CSendNoStopFlag: explicitly not sending stop condition is not supported * - eI2CBusReset: reset bus is not supported */ int32_t iot_i2c_ioctl( IotI2CHandle_t const pxI2CPeripheral, IotI2CIoctlRequest_t xI2CRequest, void * const pvBuffer ); /** * @brief Stops the ongoing operation and de-initializes the I2C peripheral. * * @param[in] pxI2CPeripheral The I2C handle returned in open() call. * * @return * - IOT_I2C_SUCCESS, on success * - IOT_I2C_INVALID_VALUE, if * - pxI2CPeripheral is NULL * - pxI2CPeripheral is not opened yet */ int32_t iot_i2c_close( IotI2CHandle_t const pxI2CPeripheral ); /** * @brief This function is used to cancel the current operation in progress, if possible. * * @param[in] pxI2CPeripheral The I2C handle returned in open() call. * * @return * - IOT_I2C_SUCCESS, on success * - IOT_I2C_INVALID_VALUE, if * - pxI2CPeripheral is NULL * - pxI2CPeripheral is not opened yet * - IOT_I2C_NOTHING_TO_CANCEL, if there is no on-going transaction. * - IOT_I2C_FUNCTION_NOT_SUPPORTED, if this board doesn't support this operation. */ int32_t iot_i2c_cancel( IotI2CHandle_t const pxI2CPeripheral ); /** * @} */ /* end of group iot_i2c */ #endif /* ifndef _IOT_I2C_H_ */