From 3367c263fd6a89b61405bc2766bbef9bde1865c6 Mon Sep 17 00:00:00 2001 From: qiutongs Date: Wed, 27 Nov 2019 12:59:54 -0800 Subject: [PATCH] Initial merge of Common IO libraries and tests (#1551) --- .../abstractions/common_io/CMakeLists.txt | 43 + .../abstractions/common_io/include/iot_adc.h | 358 ++++ .../common_io/include/iot_battery.h | 420 +++++ .../common_io/include/iot_efuse.h | 160 ++ .../common_io/include/iot_flash.h | 436 +++++ .../abstractions/common_io/include/iot_gpio.h | 243 +++ .../abstractions/common_io/include/iot_hw.h | 63 + .../abstractions/common_io/include/iot_i2c.h | 479 ++++++ .../abstractions/common_io/include/iot_i2s.h | 311 ++++ .../common_io/include/iot_perfcounter.h | 88 + .../common_io/include/iot_power.h | 285 ++++ .../abstractions/common_io/include/iot_pwm.h | 161 ++ .../common_io/include/iot_reset.h | 110 ++ .../abstractions/common_io/include/iot_rtc.h | 231 +++ .../abstractions/common_io/include/iot_spi.h | 439 +++++ .../common_io/include/iot_timer.h | 240 +++ .../common_io/include/iot_tsensor.h | 223 +++ .../abstractions/common_io/include/iot_uart.h | 410 +++++ .../common_io/include/iot_usb_device.h | 568 +++++++ .../common_io/include/iot_watchdog.h | 257 +++ .../common_io/test/iot_test_common_io.c | 66 + .../common_io/test/test_iot_i2c.c | 1241 ++++++++++++++ .../common_io/test/test_iot_internal.h | 162 ++ .../common_io/test/test_iot_spi.c | 1503 +++++++++++++++++ .../common_io/test/test_iot_uart.c | 787 +++++++++ 25 files changed, 9284 insertions(+) create mode 100644 libraries/abstractions/common_io/CMakeLists.txt create mode 100644 libraries/abstractions/common_io/include/iot_adc.h create mode 100644 libraries/abstractions/common_io/include/iot_battery.h create mode 100644 libraries/abstractions/common_io/include/iot_efuse.h create mode 100644 libraries/abstractions/common_io/include/iot_flash.h create mode 100644 libraries/abstractions/common_io/include/iot_gpio.h create mode 100644 libraries/abstractions/common_io/include/iot_hw.h create mode 100644 libraries/abstractions/common_io/include/iot_i2c.h create mode 100644 libraries/abstractions/common_io/include/iot_i2s.h create mode 100644 libraries/abstractions/common_io/include/iot_perfcounter.h create mode 100644 libraries/abstractions/common_io/include/iot_power.h create mode 100644 libraries/abstractions/common_io/include/iot_pwm.h create mode 100644 libraries/abstractions/common_io/include/iot_reset.h create mode 100644 libraries/abstractions/common_io/include/iot_rtc.h create mode 100644 libraries/abstractions/common_io/include/iot_spi.h create mode 100644 libraries/abstractions/common_io/include/iot_timer.h create mode 100644 libraries/abstractions/common_io/include/iot_tsensor.h create mode 100644 libraries/abstractions/common_io/include/iot_uart.h create mode 100644 libraries/abstractions/common_io/include/iot_usb_device.h create mode 100644 libraries/abstractions/common_io/include/iot_watchdog.h create mode 100644 libraries/abstractions/common_io/test/iot_test_common_io.c create mode 100644 libraries/abstractions/common_io/test/test_iot_i2c.c create mode 100644 libraries/abstractions/common_io/test/test_iot_internal.h create mode 100644 libraries/abstractions/common_io/test/test_iot_spi.c create mode 100644 libraries/abstractions/common_io/test/test_iot_uart.c diff --git a/libraries/abstractions/common_io/CMakeLists.txt b/libraries/abstractions/common_io/CMakeLists.txt new file mode 100644 index 00000000000..4b3b088e5e0 --- /dev/null +++ b/libraries/abstractions/common_io/CMakeLists.txt @@ -0,0 +1,43 @@ +afr_module(INTERFACE) + +set(inc_dir "${CMAKE_CURRENT_LIST_DIR}/include") +set(test_dir "${CMAKE_CURRENT_LIST_DIR}/test") + +afr_module_sources( + ${AFR_CURRENT_MODULE} + INTERFACE + "${inc_dir}/iot_i2c.h" + "${inc_dir}/iot_uart.h" + "${inc_dir}/iot_spi.h" +) + +afr_module_include_dirs( + ${AFR_CURRENT_MODULE} + INTERFACE "${inc_dir}" +) + +afr_module_dependencies( + ${AFR_CURRENT_MODULE} + INTERFACE AFR::common_io::mcu_port +) + +# Common I/O tests +afr_test_module() +afr_module_sources( + ${AFR_CURRENT_MODULE} + INTERFACE + "${test_dir}/iot_test_common_io.c" + "${test_dir}/test_iot_i2c.c" + "${test_dir}/test_iot_uart.c" + "${test_dir}/test_iot_spi.c" +) + +afr_module_include_dirs( + ${AFR_CURRENT_MODULE} + INTERFACE "${test_dir}" +) + +afr_module_dependencies( + ${AFR_CURRENT_MODULE} + INTERFACE AFR::common_io +) diff --git a/libraries/abstractions/common_io/include/iot_adc.h b/libraries/abstractions/common_io/include/iot_adc.h new file mode 100644 index 00000000000..34808da905c --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_adc.h @@ -0,0 +1,358 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_adc.h + * @brief File for the HAL APIs of ADC called by application layer. + */ +#ifndef _IOT_ADC_H_ +#define _IOT_ADC_H_ + +/** + * @brief Error code returned by ADC driver + */ +#define IOT_ADC_SUCCESS ( 0 ) /*!< ADC operation completed successfully. */ +#define IOT_ADC_FAILED ( 1 ) /*!< ADC operation failed. */ +#define IOT_ADC_INVALID_VALUE ( 2 ) /*!< At least one parameter is invalid. */ +#define IOT_ADC_NOT_OPEN ( 3 ) /*!< ADC operation not possible unless ADC instance is opened. */ +#define IOT_ADC_FUNCTION_NOT_SUPPORTED ( 4 ) /*!< ADC operation not supported. */ +#define IOT_ADC_CH_BUSY ( 5 ) /*!< ADC channel is busy at current time. */ + +/** + * @brief The handle for a ADC peripheral, defined in the source file. + * This is an anonymous struct that is vendor/driver specific. + */ +struct IotAdcDescriptor; + +/** + * @brief IotAdcHandle_t is the handle type returned by calling iot_adc_open(). + * This is initialized in open and returned to caller. The caller must pass + * this pointer to the rest of the ADC APIs. + */ +typedef struct IotAdcDescriptor * IotAdcHandle_t; + +/** + * @brief adc notification callback type + * + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used or modified by the driver. The context is + * provided by the caller when setting the callback, and is + * passed back to the caller in the callback. + * @param[out] pusConvertedData pointer to converted ADC sample data. + */ +typedef void ( * IotAdcCallback_t )( uint16_t * pusConvertedData, + void * pvUserContext ); + +/** + * @brief Initializes ADC controller with default configuration. + * init ADC controller, enable ADC clock, reset HW FIFO, set default + * configuration parameters, etc. Also allocate all required resources + * for ADC operation such as software data buffer etc. + * + * @warning Must be called prior to any other ADC api's so that a valid handle is obtained. + * @warning Once opened, the same ADC instance must be closed before calling open again. + * + * @param[in] lAdc The instance of ADC controller to initialize. + * + * @return + * - handle to the ADC controller on success + * - NULL, if + * - invalid instance number + * - open same instance more than once before closing it. + */ +IotAdcHandle_t iot_adc_open( int32_t lAdc ); + +/** + * @brief Close ADC controller. + * All pending operation will be cancelled, put ADC module in reset state or low + * power state if possible. Release all resources claimed during open call + * + * @param[in] pxAdc handle to ADC controller returned from iot_adc_open() call. + * + * @return + * - IOT_ADC_SUCCESS, on success; + * - IOT_I2C_INVALID_VALUE, if pxAdc is NULL + * - IOT_ADC_NOT_OPEN, if is not in open state (already closed). + */ +int32_t iot_adc_close( IotAdcHandle_t const pxAdc ); + +/** + * @brief Sets channel callback on availability of channel scan data. + * On availability of ADC scan data, the application is notified with a + * function callback. The callback function and user context for callback + * are set using iot_adc_set_callback. + * + * @note This callback is per AdcChannel for each handle. + * @note If input handle or AdcChannel is invalid, or if callback function is NULL, + * this function silently takes no action. + * + * @param[in] pxAdc The Adc handle returned in the open() call. + * @param[in] ucAdcChannel The Adc channel for which the callback is set + * @param[in] xAdcCallback The callback function to be called on availability of ADC channel data. + * @param[in] pvUserContext The user context to be passed when callback is called. + * + * Example Callback Function + * For asychronous ADC calls, a callback function is used to signal when the async + * task is complete. This example uses a Semaphore to signal the completion. + * @code{c} + * static void prvAdcChCallback( uint16_t * pusConvertedData, + * void * pvUserContext ) + * { + * BaseType_t xHigherPriorityTaskWoken; + * xSemaphoreGiveFromISR( xIotAdcSemaphore, &xHigherPriorityTaskWoken ); + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * } + * @endcode + */ +void iot_adc_set_callback( IotAdcHandle_t const pxAdc, + uint8_t ucAdcChannel, + IotAdcCallback_t xAdcCallback, + void * pvUserContext ); + +/** + * @brief Start data acquisition for ADC channel until iot_adc_stop API is called. + * data will be passed back to client using callback function. + * by default each callback will pass back one data sample, however if client has + * used ioctl to pass in data buffer, only when buffer is full will callback + * be triggered + * + * @warning iot_adc_set_callback() must be called prior to this in order to get notification + * when adc scan is complete and data is available + * + * @note iot_adc_set_callback() must be called prior to iot_adc_start(). + * + * @param[in] pxAdc. The ADC handle returned in the open() call + * @param[in] ucAdcChannel. The ADC channel to start data acquisition + * + * @return + * - IOT_ADC_SUCCESS on success + * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid AdcChannel + * - IOT_ADC_NOT_OPEN if ADC has not been opened yet. + * - IOT_ADC_CH_BUSY if ADC operation has started but is not complete + * - IOT_ADC_FAILED if not callback function has been set. + * Example Asynchronous read + * @code{c} + * // ADC Instance to open + * int32_t lAdcInstance = 0; + * + * // Return value of ADC functions + * int32_t lRetVal; + * + * // ADC Channel to read + * int32_t lAdcChannel = 0; + * + * // User/Driver context; if necessary + * void xUserContext = NULL; + * + * // Open the ADC instance and get a handle. + * xAdcHandle = iot_adc_open( lAdcInstance ); + * // assert(lRetVal == IOT_ADC_SUCCESS); + * + * // set the callback function + * iot_adc_set_callback( xAdcHandle, lAdcChannel, prvAdcChCallback, &xUserCntx ); + * + * // start channel data scan on channel + * lRetVal = iot_adc_start( xAdcHandle, lAdcChannel ); + * // assert( IOT_ADC_SUCCESS == lRetVal ); + * + * // wait for the Adc operation to complete + * lRetVal = xSemaphoreTake( xIotAdcSemaphore, lIotAdcChWaitTime ); + * // assert ( pdTRUE == lRetVal ); + * + * // stop channel data scan + * lRetVal = iot_adc_stop( xAdcHandle, lAdcChannel ); + * assert( IOT_ADC_SUCCESS == lRetVal ); + * + * // close ADC module + * lRetVal = iot_adc_close( xAdcHandle ); + * // assert( IOT_ADC_SUCCESS == lRetVal ); + * @endcode + */ +int32_t iot_adc_start( IotAdcHandle_t const pxAdc, + uint8_t ucAdcChannel ); + +/** + * @brief Stop data acquisition for ADC channel + * + * @param[in] pxAdc. The ADC handle returned in the open() call + * @param[in] ucAdcChannel. The ADC channel to stop data acquisition + * + * @return + * - IOT_ADC_SCUCCESS on success + * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid AdcChannel + * - IOT_ADC_NOT_OPEN if Adc has been closed without re-opening. + */ +int32_t iot_adc_stop( IotAdcHandle_t const pxAdc, + uint8_t ucAdcChannel ); + +/** + * @brief read one ADC data sample. This API will return one ADC sample. + * + * @param[in] pxAdc. The ADC handle returned in the open() call + * @param[in] ucAdcChannel. The ADC channel to read data from + * @param[out] pusAdcSample. ADC channel read sample value + * + * @return + * - IOT_ADC_SCUCCESS on success + * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid AdcChannel + * - IOT_ADC_CH_BUSY if ADC operation not complete. + * - IOT_ADC_NOT_OPEN if Adc has been closed without re-opening. + * Example Synchronous read + * @code{c} + * // ADC Instance to open + * int32_t lAdcInstance = 0; + * + * // ADC Channel to read + * int32_t lAdcChannel = 0; + * + * // Declare and ADC handle + * IotAdcHandle_t xAdcHandle; + * + * // Return value of ADC functions + * int32_t lRetVal; + * + * // ADC value read + * uint16_t usSample; + * + * // Open the ADC instance and get a handle. + * xAdcHandle = iot_adc_open( lAdcInstance ); + * // assert(lRetVal == IOT_ADC_SUCCESS); + * + * // Read sample from ADC channel + * lRetVal = iot_adc_read_sample( xAdcHandle, lAdcChannel, &usSample); + * // assert(lRetVal == IOT_ADC_SUCCESS); + * + * // Close the ADC instance and get a handle. + * lRetVal = iot_adc_close( xAdcHandle ); + * // assert(lRetVal == IOT_ADC_SUCCESS); + * @endcode + * + */ +int32_t iot_adc_read_sample( IotAdcHandle_t const pxAdc, + uint8_t ucAdcChannel, + uint16_t * pusAdcSample ); + +/** + * @brief data structures for ioctl request + */ + +/** + * @brief data structure for ioctl SetAdcConfig and GetAdcConfig + */ +typedef struct IotAdcConfig_s +{ + uint32_t ulAdcSampleTime; /*!< Sample time in ADC clock cycles, apply to all channels. + *!< Shortest sample time maximize conversion speed for lower impedance input + *!< Extending sample time improve sample accuracy for higher impedance input */ + uint8_t ucAdcResolution; /*!< ADC channel resolution, value = resolution bits; 12 = 12bit, 13 = 13bit, etc */ +} IotAdcConfig_t; + +typedef enum +{ + eChStateIdle, /*!< ADC channel is idle. */ + eChStateBusy, /*!< ADC channel is busy. */ +} IotAdcChState_t; + +/** + * @brief data structure for ioctl GetChStatus + */ +typedef struct IotAdcChStatus_s +{ + uint8_t ucAdcChannel; /*!< ADC Channel number */ + IotAdcChState_t xAdcChState; /*!< ADC Channel State */ +} IotAdcChStatus_t; + +/** + * @brief data structure for ioctl SetChBuffer + * setting channel data buffer is optional using this ioctl + * if client doesn't pass in data buffer for driver to use, callback is triggered + * for every ADC sample to pass data back to client as driver doesn't have buffer + * to accumulate data. As soon as callback returns, xConverted_Data becomes invalid. + * On the other hand however if client does pass a buffer for driver to use, + * callback is triggered only after driver has filled buffer with xBufLen samples, + * client buffer is passed back in callback as XConverted_Data whose life span is + * controlled by the client even after callback returns. + */ +typedef struct IotAdcChBuffer_s +{ + uint8_t ucAdcChannel; /*!< Adc Channel number */ + void * pvBuffer; /*!< Buffer to store adc results in */ + uint8_t ucBufLen; /*!< Max buffer length to write into pvBuffer */ +} IotAdcChBuffer_t; + +/** + * @brief Some ADC host controller supports grouping multiple ADC channels into a chain. + * When the chain is triggered to sample ADC data, all ADC channels in the group + * are sampled in sequence so that client doesn't need to trigger each channel + * individually. Coverted ADC samples from such chain group can be passed back + * to the client with a single callback. + * This data structure is used for ioctl to define ADC chain setting. + */ +typedef struct IoTAdcChain_s +{ + uint8_t ucAdcChannel; /*!< logical ADC channel number as input to ioctl. It is recommended + *!< that client uses the first ADC channel number in the group as its + *!< logical number which client can use later to trigger group sampling */ + void * pvBuffer; /*!< data buffer used by driver to save converted sample data. + *!< the buffer is allocated by client and passed to driver to use */ + uint8_t ucBufLen; /*!< data buffer length, shall be large enough to hold group sample data */ + uint16_t usChainMask; /*!< define which ADC channels are in the chain group. + *!< e.g. 'x' bit set to 1 means ADC channel x is inclued in the group. + *!< Client shall manage potential ADC channel use conflict. */ +} IotAdcChain_t; + +/** + * @brief adc ioctl request types. + */ +typedef enum IotAdcIoctlRequest_s +{ + eSetAdcConfig, /*!< Set the ADC Configuration. Takes IotAdcConfig_t parameter. */ + eGetAdcConfig, /*!< Get the ADC Configuration. Returns results in IotAdcConfig_t parameter. */ + eGetChStatus, /*!< Get the Channel Status. Returns results in IotAdcChStatus_t parameter. */ + eSetChBuffer, /*!< Set the buffer for ADC values to be stored in. Takes IotAdcChBuffer_t parameter. */ + eSetAdcChain, /*!< ADC Chain for multiple ADC channels. Takes IotAdcChain_t parameter. */ +} IotAdcIoctlRequest_t; + +/** + * @brief Used for various ADC control functions. + * + * @param[in] pxAdc The Adc handle returned in the open() call. + * @param[in] xRequest ioctl request defined by IotAdcIoctlRequest_s enums + * @param[in/out] pvBuffer data buffer for ioctl request + * @param[in] pvBuffer size + * + * @return + * - IOT_ADC_SCUCCESS on success + * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid request or NULL or invalid buffer pointer + * - IOT_ADC_CH_BUSY if ADC operation not complete. + * - IOT_ADC_NOT_OPEN if Adc has been closed without re-opening. + * - IOT_ADC_FAILED if invalid ADC chain is requested. + * - IOT_ADC_FUNCTION_NOT_SUPPORTED only valid for eSetAdcChain, if feature not supported + */ +int32_t iot_adc_ioctl( IotAdcHandle_t const pxAdc, + IotAdcIoctlRequest_t xRequest, + void * const pvBuffer ); + +#endif /* _IOT_ADC_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_battery.h b/libraries/abstractions/common_io/include/iot_battery.h new file mode 100644 index 00000000000..5f6d52255ff --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_battery.h @@ -0,0 +1,420 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_battery.h + * + * @brief HAL APIs for Battery + ******************************************************************************* + */ + +/** + * @file iot_battery.h + * @brief This file contains all the Battery HAL API definitions. The APIs defined in this file + * helps with battery information and charging related functions. + */ + +#ifndef _IOT_BATTERY_H_ +#define _IOT_BATTERY_H_ + +/** + * @defgroup iot_battery BATTERY HAL APIs + * @{ + */ + +/** + * @brief Return values used by BATTERY driver + */ +#define IOT_BATTERY_SUCCESS ( 0 ) /*!< Battery operation completed successfully. */ +#define IOT_BATTERY_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_BATTERY_NOT_EXIST ( 2 ) /*!< No battery exists in this hardware. */ +#define IOT_BATTERY_READ_FAILED ( 3 ) /*!< Battery read operation failed. */ +#define IOT_BATTERY_FUNCTION_NOT_SUPPORTED ( 4 ) /*!< Battery operation not supported. */ + +/** + * @brief Battery Type + */ +typedef enum +{ + eBatteryChargeable, /*!< Re-chargeable batteries with charging enabled */ + eBatteryNotChargeable /*!< Not chargeable batteries */ +} IotBatteryType_t; + +/** + * @brief Charger type + */ +typedef enum +{ + eBatteryChargeNone, /*!< No Charge source, or non-chargeable battery */ + eBatteryChargeUSB, /*!< USB battery source */ + eBatteryChargePowerSupply, /*!< AC power supply source */ + erBatteryChargeWireless, /*!< Wireless charging source */ +} IotBatteryChargeSource_t; + +/** + * @brief Battery status + */ +typedef enum +{ + eBatteryCharging, /*!< Battery is Charging. Applicable only if the battery is chargeable */ + eBatteryDischarging, /*!< Battery is Discharging. This is the normal status of battery is no charger + * is connected */ + eBatteryNotCharging, /*!< Battery is not charging. This is set when charger is connected, but battery is not + * charging - usually an error condition */ + eBatteryChargeFull, /*!< Battery is fully charged. This status will be set only when the charger is connected + * and battery is fully charged */ + eBatteryChargeLow, /*!< Battery is low on charging and no charger connected. This status is set when battery + * is discharging and reaches a low cahrge value. Low charge value is defined by implementation */ + eBatteryOverVoltage, /*!< Battery maximum voltage limit reached. */ + eBatteryUnderVoltage, /*!< Battery low voltage limit reached. */ + eBatteryOverTemp, /*!< Battery maximum temperature limit reached. */ + eBatteryUnderTemp, /*!< Battery minimum temperature limit reached. */ + eBatteryOverChargingTemp, /*!< Battery maximum charging temperature limit reached. */ + eBatteryUnderhargingTemp, /*!< Battery minimum charging temperature limit reached. */ + eBatteryChargeTimeExpired, /*!< Battery charge timer expired. Charge timer can be set if the underlying hardware supports it using + * eSetBatteryChargeTimer IOCTL, and once the chargeTimer expires registered callback is called with this status set */ + eBatteryUnknown /*!< Unknown status. Default status if no battery is present */ +} IotBatteryStatus_t; + +/** + * @brief Battery information. + */ +typedef struct IotBatteryInfo +{ + IotBatteryType_t xBatteryType; /*!< Battery type. chargeable or non-chargeable */ + uint16_t usMinVoltage; /*!< minimum designed voltage battery can be used at */ + uint16_t usMaxVoltage; /*!< maximum designed voltage battery can be used at */ + int16_t sMinTemperature; /*!< lowest temperature the battery can be used at by design */ + int16_t sMaxTemperature; /*!< max temperature the battery can be used at by design */ + uint8_t usMaxCapacity; /*!< max capacity of battery by design */ + uint8_t ucAsyncSupported; /*!< Is asynchronous notifications supported by the driver. This will be + * set, if the battery/charging has an IC/battery and charging hw module that + * can atonomously monitor battery characterstics and generate interrupts */ +} IotBatteryInfo_t; + +/** + * @brief Ioctl request types. + */ +typedef enum IotBatteryIoctlRequest +{ + eSetBatteryMinVoltageThreshold, /*!< Set the battery minimum voltage threshold. When the voltage goes below this threshold + * value, the registered callback will be called with the status set to "eBatteryUnderVoltage". + * If battery management HW does not have a way to monitor voltage, this IOCTL will not be supported. + * Parameter is uint16_t value in milliVolt units. */ + eSetBatteryMaxVoltageThreshold, /*!< Set the battery mimimum voltage threshold. When the voltage goes below this threshold + * value, the registered callback will be called with the status set to "eBatteryOverVoltage". + * If battery management HW does not have a way to monitor voltage, this IOCTL will not be supported. + * Parameter is uint16_t value in milliVolt units. */ + eSetBatteryMinBatteryTempThreshold, /*!< Set the minimum battery temperature threshold. When the battery temperature goes below this value, + * the registered callback will be called with the status value "eBatteryUnderTemp". + * This IOCTL takes int16_t value as input in milliCelcius units. */ + eSetBatteryMaxBatteryTempThreshold, /*!< Set the maximum battery temperature threshold. When the battery temperature goes above this value, + * the registered callback will be called with the status value "eBatteryUnderTemp". + * This IOCTL takes int16_t value as input in milliCelcius units. */ + eSetBatteryMinChargeTempThreshold, /*!< Set the minimum charge temperature threshold. When the charging temperature goes below this value, + * the registered callback will be called with the status value "eBatteryUnderChargingTemp". + * This IOCTL takes int16_t value as input in milliCelcius units.*/ + eSetBatteryMaxChargeTempThreshold, /*!< Set the maximum charge temperature threshold. When the charging temperature goes above this value, + * the registered callback will be called with the status value "eBatteryOverChargingTemp". + * This IOCTL takes int16_t value as input in milliCelcius units. */ + eSetBatteryMaxOutputCurrent, /*!< Set the maximum output current limit from the battery. + * This IOCTL takes uint16_t value as input in milliAmp units. */ + eSetBatteryMaxInputChargeCurrent, /*!< Set the maximum input charging current limit to the battery. + * This IOCTL takes uint16_t value as input in milliAmp units. */ + eSetBatteryChargeTimer, /*!< Set the battery charging timer limit. AFter the timer expires charging will stop. + * This IOCTL takes uint16_t value as input in milliSec units. */ + eGetBatteryMinVoltageThreshold, /*!< Get the battery minimum thresold. + * This IOCTL returns uint16_t value in milliVolt units. */ + eGetBatteryMaxVoltageThreshold, /*!< Get the battery maximum thresold. + * This IOCTL returns uint16_t value in milliVolt units. */ + eGetBatteryOCV, /*!< Get the battery OCV (open circuit voltage) + * This IOCTL returns uint16_t value in milliVolt units. */ + eGetBatteryBootVoltage, /*!< Get the battery boot-up voltage + * This IOCTL returns uint16_t value in milliVolt units. */ + eGetBatteryMinBatteryTempThreshold, /*!< Get the minimum battery temperature thresholde + * This IOCTL returns int16_t value in milliCelcius units. */ + eGetBatteryMaxBatteryTempThreshold, /*!< Get the maximum battery temperature threshold. + * This IOCTL returns int16_t value in milliCelcius units. */ + eGetBatteryMinChargeTempThreshold, /*!< Get the minimum charging temperature threshold. + * This IOCTL returns int16_t value in milliCelcius units. */ + eGetBatteryMaxChargeTempThreshold, /*!< Get the maximum charging temperature threshold. + * This IOCTL returns int16_t value in milliCelcius units. */ + eGetBatteryMaxOutputCurrent, /*!< Get the battery output current limit. + * This IOCTL returns uint16_t value in milliAmp units. */ + eGetBatteryMaxInputChargeCurrent, /*!< Get the battery input charge current limit. + * This IOCTL returns uint16_t value in milliAmp units. */ + eGetBatteryChargeTimer, /*!< Get the current battery charge time limit. + * This IOCTL returns uint16_t value in milliSec units. */ + eGetBatteryChargeSource, /*!< Get the current battery charge source. + * This IOCTL returns a IotBatteryChargeSource_t as it's parameter. */ + eGetBatteryStatus /*!< Get the battery status. Returns one of the IotBatteryStatus_t values as it's parameter. */ +} IotBatteryIoctlRequest_t; + +/** + * @brief Battery descriptor type defined in the source file. + */ +struct IotBatteryDescriptor_t; + +/** + * @brief IotBatteryHandle_t type is the Battery handle returned by calling iot_battery_open() + * this is initialized in open and returned to caller. Caller must pass this pointer + * to the rest of the APIs. + */ +typedef struct IotBatteryDescriptor_t * IotBatteryHandle_t; + +/** + * @brief Battery notification callback type. This callback is passed + * to the driver by using iot_battery_set_callback API. The callback is + * used to get the notifications about battery status changes for ex: when charging starts, or + * when critical threshold is reached or when battery is full etc... + * The callback is only used if the driver supports the asynchronous notifications. The caller + * must get the batteryInfo to find if the asynchronous notifications are supported. + * On simiple underlying batteries, the caller/application must manage the battery conditions by + * periodically probing the battery using read APIs, and for sophisticated battery management service + * modules, these can be managed in the HW hence asyncrhonous notifications can be sent (using registered callback) + * + * @param[in] xStatus battery status from IotBatteryStatus_t + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used by the driver, but just passed back to the user + * in the callback. + */ +typedef void ( * IotBatteryCallback_t)( IotBatteryStatus_t xStatus, + void * pvUserContext ); + +/** + * @brief iot_battery_open is used to initialize the Battery and Charging driver. + * + * @param[in] lBatteryInstance The instance of the battery interface to initialize. + * Usually, there is only one battery interface. + * + * @return + * - handle to the Battery controller on success + * - NULL, if + * - invalid instance + * - open same instance more than once before closing it. + * - on failure. + */ +IotBatteryHandle_t iot_battery_open( int32_t lBatteryInstance ); + +/*! + * @brief iot_battery_set_callback is used to set the callback to be called when a notification + * needs to be sent to the caller. THe callback is only called if the battery supports async + * notifications. Caller must check isAsyncNotificationSupported value before registering + * for callbacks, if async is not supported, registering for callback has no affect, and the callback + * will never be called. + * + * @note Single callback is used for all features that support callback + * - eBatteryChargeTimeExpired, + * - eSetBatteryMinVoltageThreshold, eSetBatteryMaxVoltageThreshold, + * - eSetBatteryMinBatteryTempThreshold, eSetBatteryMaxBatteryTempThreshold, + * - eSetBatteryMinChargeTempThreshold, eSetBatteryMaxChargeTempThreshold, + * @note Newly set callback overrides the one previously set + * @note This callback is per handle. Each instance has its own callback. + * + * @warning If input handle or if callback function is NULL, this function silently takes no action. + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[in] xCallback callback function to be called. + * @param[in] pvUserContext user context to be passed when callback is called. + * + */ +void iot_battery_set_callback( IotBatteryHandle_t const pxBatteryHandle, + IotBatteryCallback_t xCallback, + void * pvUserContext ); + +/*! + * @brief iot_battery_getInfo is used to get the battery info + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * + * @return + * - returns a pointer to the IotBatteryInfo structure on success + * - NULL on error + */ +IotBatteryInfo_t * iot_battery_getInfo( IotBatteryHandle_t const pxBatteryHandle ); + +/*! + * @brief iot_battery_current is used to get the battery current in mA. + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[out] pusCurrent battery current value. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if pxBatteryHandle == NULL or pusCurrent == NULL + * - IOT_BATTERY_NOT_EXIST if no battery present. + * - IOT_BATTERY_READ_FAILED on error obtaining valid reading + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED if its not supported by the hardware. + */ +int32_t iot_battery_current( IotBatteryHandle_t const pxBatteryHandle, + uint16_t * pusCurrent ); + +/*! + * @brief iot_battery_voltage is used to get the battery voltage in milli-volts. + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[out] pusVoltage battery voltage value. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if pxBatteryHandle == NULL or pusVoltage == NULL + * - IOT_BATTERY_NOT_EXIST if no battery in this hardware + * - IOT_BATTERY_READ_FAILED on error + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED if its not supported by the hardware. + */ +int32_t iot_battery_voltage( IotBatteryHandle_t const pxBatteryHandle, + uint16_t * pusVoltage ); + +/*! + * @brief iot_battery_chargeLevel is used to get the battery charging level in percentage (from 1 to 100). + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[out] pucChargeLevel battery charging value. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if pxBatteryHandle == NULL or pusChargeLevel == NULL + * - IOT_BATTERY_NOT_EXIST if no battery in this hardware + * - IOT_BATTERY_READ_FAILED on error + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED if its not supported by the hardware. + */ +int32_t iot_battery_chargeLevel( IotBatteryHandle_t const pxBatteryHandle, + uint8_t * pucChargeLevel ); + + +/*! + * @brief iot_battery_capacity is used to get the current battery capacity value in mAh + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[out] pusCapacity battery capacity value. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if pxBatteryHandle == NULL or pusCapacity == NULL + * - IOT_BATTERY_NOT_EXIST if no battery in this hardware + * - IOT_BATTERY_READ_FAILED on error + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED if its not supported by the hardware. + */ +int32_t iot_battery_capacity( IotBatteryHandle_t const pxBatteryHandle, + uint16_t * pusCapacity ); + +/*! + * @brief iot_battery_temp is used to get the battery temperature in milliCelcius + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[out] psTemp battery temperature in milliCelcius + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if pxBatteryHandle == NULL or psTemp == NULL + * - IOT_BATTERY_NOT_EXIST if no battery in this hardware + * - IOT_BATTERY_READ_FAILED on error + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED if its not supported by the hardware. + */ +int32_t iot_battery_temp( IotBatteryHandle_t const pxBatteryHandle, + int16_t * psTemp ); + +/*! + * @brief iot_battery_enable_charging is used to enable battery charging if charging is supported. + * if battery is already at full charge, enable will not charge battery until the charging level + * drops below 100, and even if battery is at critical level, and charging is not enabled, battery will + * not be charging. Charging is always enabled by default unless disabled by using this API. + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[in] pucEnable Enable or Disable the charging of battery. set to 1 to enable, or 0 to disable. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if NULL handle or NULL voltage pointer + * - IOT_BATTERY_NOT_EXIST if no battery in this hardware + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED if its not supported by the hardware. + */ +int32_t iot_battery_enable_charging( IotBatteryHandle_t const pxBatteryHandle, + uint8_t * pucEnable ); + +/*! + * @brief iot_battery_is_charging is used to query if the battery is currently charging. + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[out] pucCharging If charging this will contain value of 1 otherwise 0. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if pxBatteryHandle == NULL or pusCharging == NULL + * - IOT_BATTERY_NOT_EXIST if no battery in this hardware + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED if its not supported by the hardware. + */ +int32_t iot_battery_is_charging( IotBatteryHandle_t const pxBatteryHandle, + uint8_t * pucCharging ); + +/** + * @brief iot_battery_ioctl is used to set Battery configuration and + * Battery properties like battery threshold, temperature threshold, charging max, chargin min etc.. + * + * @param[in] pxBatteryHandle handle to Battery driver returned in + * iot_battery_open() + * @param[in] xRequest configuration request of type IotBatteryIoctlRequest_t + * @param[in,out] pvBuffer buffer holding Battery set and get values. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if + * - pxBatteryHandle == NULL + * - invalid xRequest + * - pvBuffer == NULL when required + * - IOT_BATTERY_NOT_EXIST if no battery in this hardware + * - IOT_BATTERY_FUNCTION_NOT_SUPPORTED valid for any ioctl if its not supported by the hardware. + */ +int32_t iot_battery_ioctl( IotBatteryHandle_t const pxBatteryHandle, + IotBatteryIoctlRequest_t xRequest, + void * const pvBuffer ); + +/** + * @brief iot_battery_close is used to de-Initialize Battery driver. + * + * @param[in] pxBatteryHandle handle to Battery interface. + * + * @return + * - IOT_BATTERY_SUCCESS on success + * - IOT_BATTERY_INVALID_VALUE if + * - pxBatteryHandle == NULL + * - if is not in open state (already closed). + */ +int32_t iot_battery_close( IotBatteryHandle_t const pxBatteryHandle ); + +/** + * @} + */ + +#endif /* ifndef _IOT_BATTERY_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_efuse.h b/libraries/abstractions/common_io/include/iot_efuse.h new file mode 100644 index 00000000000..9f34600fd6b --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_efuse.h @@ -0,0 +1,160 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_efuse.h + * @brief File for the APIs of efuse called by application layer. + */ +#ifndef _IOT_EFUSE_H_ +#define _IOT_EFUSE_H_ + +/** + * @defgroup iot_efuse EFUSE Abstraction APIs. + * @{ + */ + +/** + * The return codes for the functions in EFUSE. + */ +#define IOT_EFUSE_SUCCESS ( 0 ) /*!< Efuse operation completed successfully. */ +#define IOT_EFUSE_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_EFUSE_READ_FAIL ( 2 ) /*!< Error reading Efuse value. */ +#define IOT_EFUSE_WRITE_FAIL ( 3 ) /*!< Error writing Efuse value. */ +#define IOT_EFUSE_CLOSE_FAIL ( 4 ) /*!< Error closing Efuse instance. */ +#define IOT_EFUSE_FUNCTION_NOT_SUPPORTED ( 5 ) /*!< Efuse operation not supported. */ +#define IOT_EFUSE_ERROR ( 6 ) /*!< Error performing Efuse operation. */ + +/** + * @brief The Efuse descriptor type defined in the source file. + */ +struct IotEfuseDescriptor; + +/** + * @brief IotEfuseHandle_t is the handle type returned by calling iot_efuse_open(). + * This is initialized in open and returned to caller. The caller must pass + * this pointer to the rest of APIs. + */ +typedef struct IotEfuseDescriptor * IotEfuseHandle_t; + +/** + * @brief iot_efuse_open is used to Initialize things needed to access efuse. + * + * @return + * - Handle to IotEfuseHandle_t on success + * - NULL if the handle is already opened. handle must be closed before calling open again + */ +IotEfuseHandle_t iot_efuse_open( void ); + +/** + * @brief iot_efuse_close is used to de Initialize things needed to disable efuse access. + * + * @param[in] pxEfuseHandle handle to efuse interface returned in iot_efuse_open() + * + * @return + * - IOT_EFUSE_SUCCESS if succeeded, + * - IOT_EFUSE_INVALID_VALUE on NULL pxEfuseHandle + * - IOT_EFUSE_INVALID_VALUE if instance not previously opened. + * - IOT_EFUSE_CLOSE_FAIL if the underneath HW deinit api returns fail. + */ +int32_t iot_efuse_close( IotEfuseHandle_t const pxEfuseHandle ); + +/** + * @brief Read 32-bit efuse word from specified index. + * + * @param[in] pxEfuseHandle handle to efuse interface returned in iot_efuse_open() + * @param[in] ulIndex index of efuse word to read. Caller must know the underlying + * efuse mechanism and make sure index is a valid one. + * @param[out] ulValue The receive buffer to read the data into + * + * @return + * - IOT_EFUSE_SUCCESS if read succeeded, + * - IOT_EFUSE_READ_FAIL if read failed, + * - IOT_EFUSE_INVALID_VALUE if pxEfuseHandle is NULL, index is invalid, or ulValue is NULL. + * - IOT_EFUSE_FUNCTION_NOT_SUPPORTED if 32-bit efuse word is not supported + */ +int32_t iot_efuse_read_32bit_word( IotEfuseHandle_t const pxEfuseHandle, + uint32_t ulIndex, + uint32_t * ulValue ); + +/** + * @brief Write 32-bit value to the 32-bit efuse word at specified index. + * + * @param[in] pxEfuseHandle handle to efuse interface returned in iot_efuse_open() + * @param[in] ulIndex index of efuse word to write to. Caller must know the underlying + * efuse mechanism and make sure index is a valid one. + * @param[in] ulValue The 32-bit value to write. + * + * @return + * - IOT_EFUSE_SUCCESS if write succeeded, + * - IOT_EFUSE_WRITE_FAIL if write failed + * - IOT_EFUSE_INVALID_VALUE if pxEfuseHandle is NULL, or index is invalid. + * - IOT_EFUSE_FUNCTION_NOT_SUPPORTED if 32-bit efuse word is not supported + */ +int32_t iot_efuse_write_32bit_word( IotEfuseHandle_t const pxEfuseHandle, + uint32_t ulIndex, + uint32_t ulValue ); + +/** + * @brief Read 16-bit efuse word from specified index. + * + * @param[in] pxEfuseHandle handle to efuse interface returned in iot_efuse_open() + * @param[in] ulIndex index of efuse word to read. Caller must know the underlying + * efuse mechanism and make sure index is a valid one. + * @param[out] ulValue The receive buffer to read the data into + * + * @return + * - IOT_EFUSE_SUCCESS if read succeeded, + * - IOT_EFUSE_READ_FAIL if read failed + * - IOT_EFUSE_INVALID_VALUE if pxEfuseHandle or ulValue is NULL, or index is invalid + * - IOT_EFUSE_FUNCTION_NOT_SUPPORTED if 16-bit efuse word is not supported + */ +int32_t iot_efuse_read_16bit_word( IotEfuseHandle_t const pxEfuseHandle, + uint32_t ulIndex, + uint16_t * ulValue ); + +/** + * @brief Write 16-bit value to the 16-bit efuse word at specified index. + * + * @param[in] pxEfuseHandle handle to efuse interface returned in iot_efuse_open() + * @param[in] ulIndex index of efuse word to write to. Caller must know the underlying + * efuse mechanism and make sure index is a valid one. + * @param[in] ulValue The 16-bit value to write. + * + * @return + * - IOT_EFUSE_SUCCESS if write succeeded, + * - IOT_EFUSE_WRITE_FAIL if write failed + * - IOT_EFUSE_INVALID_VALUE if index is invalid, or pxEfuseHandle is NULL. + * - IOT_EFUSE_FUNCTION_NOT_SUPPORTED if 16-bit efuse word is not supported + */ +int32_t iot_efuse_write_16bit_word( IotEfuseHandle_t const pxEfuseHandle, + uint32_t ulIndex, + uint16_t value ); + +/** + * @} + */ +/* end of group iot_efuse */ + +#endif /* ifndef _IOT_EFUSE_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_flash.h b/libraries/abstractions/common_io/include/iot_flash.h new file mode 100644 index 00000000000..1bdf732f54f --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_flash.h @@ -0,0 +1,436 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_flash.h + * @brief This file contains all the Flash HAL API definitions + */ + +#ifndef _IOT_FLASH_H_ +#define _IOT_FLASH_H_ + +/** + * @defgroup iot_flash Flash HAL APIs + * @{ + */ + +/** + * @brief Return values used by this driver + */ +#define IOT_FLASH_SUCCESS ( 0 ) /*!< Flash operation completed succesfully. */ +#define IOT_FLASH_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_FLASH_WRITE_FAILED ( 2 ) /*!< Flash write operation failed. */ +#define IOT_FLASH_READ_FAILED ( 3 ) /*!< Flash read operation failed. */ +#define IOT_FLASH_ERASE_FAILED ( 4 ) /*!< Flash erase operation failed. */ +#define IOT_FLASH_DEVICE_BUSY ( 5 ) /*!< Previous flash operation not complete yet. */ +#define IOT_FLASH_CTRL_OP_FAILED ( 6 ) /*!< Flash control operation failed. */ +#define IOT_FLASH_FUNCTION_NOT_SUPPORTED ( 7 ) /*!< Flash operation not supported. */ + +/** + * @brief Flash current status + */ +typedef enum +{ + eFlashIdle, /*!< Flash is idle. */ + eFlashCmdInProgress, /*!< Flash command in progress. */ + eFlashEraseFailed, /*!< Flash erase failed. */ + eFlashProgramSuspended, /*!< Flash program operation suspended. */ + eFlashEraseSuspended /*Example + * @code{c} + * IotFlashHandle_t xFlashHandle; + * IotFlashInfo_t* pxFlashInfo; + * int32_t lRetVal; + * uint32_t ulChunkOffset; + * + * // Open flash to initialize hardware. + * xFlashHandle = iot_flash_open(0); + * // assert(xFlashHandle == NULL ); + * + * // Get the flash information. + * pxFlashInfo = iot_flash_getinfo(xFlashHandle); + * // assert(pxFlashInfo == NULL); + * + * // If Erase asyc is supported, register a callback + * if ( pxFlashInfo->ucAsyncSupported ) + * { + * iot_flash_set_callback(xFlashHandle, + * prvIotFlashEraseCallback, + * NULL); + * } + * + * // Erase 2 sectors + * lRetVal = iot_flash_erase_sectors(xFlashHandle, + * ultestIotFlashStartOffset, + * pxFlashInfo->ulSectorSize * 2); + * //assert(IOT_FLASH_SUCCESS != lRetVal); + * + * if ( pxFlashInfo->ucAsyncSupported ) + * { + * // Wait for the Erase to be completed and callback is called. + * lRetVal = xSemaphoreTake(xtestIotFlashSemaphore, portMAX_DELAY); + * //assert(pdTRUE != lRetVal); + * } + * + * // Close the flash handle. + * lRetVal = iot_flash_close(xFlashHandle); + * //assert(IOT_FLASH_SUCCESS != lRetVal); + * + * @endcode + */ +int32_t iot_flash_erase_sectors( IotFlashHandle_t const pxFlashHandle, + uint32_t ulStartAddress, + size_t xSize ); + +/*! + * @brief iot_erase_chip is used to erase the entire flash chip. + * If there is another flash operation is in progress, the erase_chip API will return an error. + * + * @param[in] pxFlashHandle handle to flash driver returned in + * iot_flash_open() + * + * @return + * - IOT_FLASH_SUCCESS on success. + * - IOT_FLASH_INVALID_VALUE if any parameter is invalid. + * - IOT_FLASH_DEVICE_BUSY if another asynchronous operation is currently being executed. + * - IOT_FLASH_ERASE_FAILED on error. + */ +int32_t iot_flash_erase_chip( IotFlashHandle_t const pxFlashHandle ); + +/*! + * @brief iot_flash_write_sync is used to write data to flash starting at the address provided. + * The sector(s) being written to, must be erased first before any write can take place. + * This is a blocking operation and waits until the number of bytes are written before returning. + * If there is another flash operation is in progress, write will return an error. + * + * @warning writing to a sector that was not erased first, may result in incorrect data being written while + * the API returns IOT_FLASH_SUCCESS. + * + * @param[in] pxFlashHandle handle to flash driver returned in + * iot_flash_open() + * @param[in] ulAddress starting address(offset) in flash to write. + * @param[in] xBytes number of bytes to write. + * @param[in] pvBuffer data buffer to write to flash + * + * @return + * - IOT_FLASH_SUCCESS on success. + * - IOT_FLASH_INVALID_VALUE if any parameter is invalid. + * - IOT_FLASH_DEVICE_BUSY if another asynchronous operation is currently being executed. + * - IOT_FLASH_WRITE_FAILED on error. + */ +int32_t iot_flash_write_sync( IotFlashHandle_t const pxFlashHandle, + uint32_t ulAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/*! + * @brief iot_flash_read_sync is used to read data from flash. This is a blocking operation + * and waits until the number of bytes are read before returning. + * If there is another flash operation is in progress, this will return an error. + * + * @param[in] pxFlashHandle handle to flash driver returned in + * iot_flash_open() + * @param[in] ulAddress starting address(offset) in flash to read. + * @param[in] xBytes number of bytes to be read. + * @param[out] pvBuffer data buffer to hold the data read from flash + * + * @return + * - IOT_FLASH_SUCCESS on success. + * - IOT_FLASH_INVALID_VALUE if any parameter is invalid. + * - IOT_FLASH_DEVICE_BUSY if another asynchronous operation is currently being executed. + * - IOT_FLASH_READ_FAILED on error. + */ +int32_t iot_flash_read_sync( IotFlashHandle_t const pxFlashHandle, + uint32_t ulAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/*! + * @brief iot_flash_write_async is used to write data to flash starting at the address provided. + * The sector(s) being written to, must be erased first before any write can take place. + * This is an asynchronous (non-blocking) operation and returns as soon as the write + * operation is started. When the write is completed, user callback is called to + * notify that the write is complete. The caller can check the status of the operation + * by using eGetStatus IOCTL. User must register for a callback when using the non-blocking + * operations to know when they are complete. + * If there is another flash operation is in progress, write will return an error. + * + * @param[in] pxFlashHandle handle to flash driver returned in + * iot_flash_open() + * @param[in] ulAddress starting address(offset) in flash to write. + * @param[in] xBytes number of bytes to write. + * @param[in] pvBuffer data buffer to write to flash + * + * @return + * - IOT_FLASH_SUCCESS on success. + * - IOT_FLASH_INVALID_VALUE if any parameter is invalid. + * - IOT_FLASH_DEVICE_BUSY if another asynchronous operation is currently being executed. + * - IOT_FLASH_WRITE_FAILED on error. + * - IOT_FLASH_FUNCTION_NOT_SUPPORTED if asynchronous operation is not supported + * (i,e ucAsyncSupported is set to false) + */ +int32_t iot_flash_write_async( IotFlashHandle_t const pxFlashHandle, + uint32_t ulAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/*! + * @brief iot_flash_read_async is used to read data from flash. + * This is an asynchronous (non-blocking) operation and returns as soon as the read + * operation is started. When the read is completed, user callback is called to + * notify that the read is complete. The caller can check the status of the operation + * by using eGetStatus IOCTL and use the buffer. User must register for a callback when + * using the non-blocking operations to know when they are complete. + * If there is another flash operation is in progress, this will return an error. + * + * @param[in] pxFlashHandle handle to flash driver returned in + * iot_flash_open() + * @param[in] ulAddress starting address(offset) in flash to read. + * @param[in] xBytes number of bytes to be read. + * @param[out] pvBuffer data buffer to hold the data read from flash + * + * @return + * - IOT_FLASH_SUCCESS on success. + * - IOT_FLASH_INVALID_VALUE if any parameter is invalid. + * - IOT_FLASH_DEVICE_BUSY if another asynchronous operation is currently being executed. + * - IOT_FLASH_READ_FAILED on error. + * - IOT_FLASH_FUNCTION_NOT_SUPPORTED if asynchronous operation is not supported + * (i,e ucAsyncSupported is set to false) + */ +int32_t iot_flash_read_async( IotFlashHandle_t const pxFlashHandle, + uint32_t ulAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/*! + * @brief iot_flash_close is used to close the flash device. + * If any operations are in progress when close is called, + * flash driver aborts those if possible. + * + * @param[in] pxFlashHandle handle to flash driver returned in + * iot_flash_open() + * + * @return + * - IOT_FLASH_SUCCESS on success close + * - IOT_FLASH_INVALID_VALUE on invalid pxFlashHandle. + */ +int32_t iot_flash_close( IotFlashHandle_t const pxFlashHandle ); + +/** + * @} + */ + +#endif /* ifndef _IOT_FLASH_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_gpio.h b/libraries/abstractions/common_io/include/iot_gpio.h new file mode 100644 index 00000000000..ad14079c424 --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_gpio.h @@ -0,0 +1,243 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_gpio.h + * @brief This file contains all the GPIO HAL API definitions. + * This GPIO interface APIs only provides pin-level functions. To modify a GPIO pin, a handle must be obtained + * by calling the iot_gpio_open() function. This handle must be passed to other functions in this interface. + * Handling multiple GPIOs simultaneously in the same bank or different banks is outside of the scope of this file. + * User can modify multiple pins sequentially using this interface by iterating over multiple GPIOs in a loop. + */ + +#ifndef _IOT_GPIO_H_ +#define _IOT_GPIO_H_ + +/** + * @defgroup iot_gpio GPIO HAL APIs + * @{ + */ + +/** + * @brief Error codes + */ +#define IOT_GPIO_SUCCESS ( 0 ) /*!< GPIO operation completed succesfully. */ +#define IOT_GPIO_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_GPIO_READ_FAILED ( 2 ) /*!< GPIO read operation failed. */ +#define IOT_GPIO_WRITE_FAILED ( 3 ) /*!< GPIO write operation failed. */ +#define IOT_GPIO_FUNCTION_NOT_SUPPORTED ( 4 ) /*!< GPIO operation not supported. */ + +/** + * @brief enum for configuring GPIO input/output direction. + */ +typedef enum +{ + eGpioDirectionInput, /*!< Configure GPIO pin direction for input. */ + eGpioDirectionOutput /*!< Configure GPIO pin direction for output. */ +} IotGpioDirection_t; + +/** + * @brief enum for configuring GPIO output type. + */ +typedef enum +{ + eGpioOpenDrain, /*!< Configure GPIO pin mode as open drain. */ + eGpioPushPull /*!< Configure GPIO pin mode as push pull. */ +} IotGpioOutputMode_t; + +/** + * @brief GPIO pin internal pull state. Sets the default state for output pins. + */ +typedef enum +{ + eGpioPullNone, /*!< Configure GPIO pin with no pull direction. */ + eGpioPullUp, /*!< Configure GPIO pin as pull up. */ + eGpioPullDown /*!< Configure GPIO pin as pull down. */ +} IotGpioPull_t; + +/** + * @brief GPIO pin interrupt config types. + */ +typedef enum +{ + eGpioInterruptNone, /*!< Configure GPIO pin to not generate an interrupt. */ + eGpioInterruptRising, /*!< Configure GPIO pin to generate an interrupt when signal rises. */ + eGpioInterruptFalling, /*!< Configure GPIO pin to generate an interrupt when signal falls. */ + eGpioInterruptEdge, /*!< Configure GPIO pin to generate an interrupt when either rising or falling. */ + eGpioInterruptLow, /*!< Configure GPIO pin to generate an interrupt when signal is low. */ + eGpioInterruptHigh, /*!< Configure GPIO pin to generate an interrupt when signal is high. */ +} IotGpioInterrupt_t; + +/** + * @brief Ioctl request types. + */ +typedef enum +{ + eSetGpioFunction, /*!< Set GPIO function. Takes int32_t as input to set the alternate function. + * The value of the alternate function depends on the HW */ + eSetGpioDirection, /*!< Set GPIO Direction. Takes input type IotGpioDirection_t */ + eSetGpioPull, /*!< Set GPIO Pull mode. Takes input type IotGpioPull_t */ + eSetGpioOutputMode, /*!< Set GPIO output type. Takes input type IotGpioOutputType_t */ + eSetGpioInterrupt, /*!< Set GPIO Interrupt type. This configures the GPIO to generate an interrupt based on the configuration. + * Takes input type IotGpioInterrupt_t */ + eSetGpioSpeed, /*!< Set GPIO Speed. Takes a int32_t value based on the underlying HW support */ + eSetGpioDriveStrength, /*!< Set GPIO Drive Strength. Takes an int32_t value based on the underlying HW support */ + eGetGpioFunction, /*!< Get GPIO function setting. Returns an int32_t */ + eGetGpioDirection, /*!< Get GPIO Direction setting. Returns IotGpioDirection_t */ + eGetGpioPull, /*!< Get GPIO Pull mode setting. Returns IotGpioPull_t */ + eGetGpioOutputType, /*!< Get GPIO output type. Returns IotGpioOutputType_t */ + eGetGpioInterrupt, /*!< Get GPIO Interrupt config. Returns IotGpioInterrupt_t type */ + eGetGpioSpeed, /*!< Get GPIO Speed setting. Returns an int32_t type */ + eGetGpioDriveStrength /*!< Get GPIO Drive Strength. Returns int32_t type */ +} IotGpioIoctlRequest_t; + +/** + * @brief GPIO descriptor type defined in the source file. + */ +struct IotGpioDescriptor; + +/** + * @brief IotGpioHandle_t type is the GPIO handle returned by calling iot_gpio_open() + * this is initialized in open and returned to caller. Caller must pass this pointer + * to the rest of the APIs. + */ +typedef struct IotGpioDescriptor * IotGpioHandle_t; + +/** + * @brief GPIO interrupt callback type. This callback is passed + * to the driver by using iot_gpio_set_callback API. + * @param[out] ucPinState The variable which has state of the GPIO pin. + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used by the driver, but just passed back to the user + * in the callback. + */ +typedef void ( * IotGpioCallback_t )( uint8_t ucPinState, + void * pvUserContext ); + +/** + * @brief iot_gpio_open is used to open the GPIO handle. + * The application must call this function to open desired GPIO and use other functions. + * + * @param[in] lGpioNumber The logical GPIO number to open. It depends on the + * implementation to map logical GPIO number to physical GPIO port + * and pin. + * + * @return + * - handle to the GPIO peripheral if everything succeeds + * - NULL, if + * - invalid instance number + * - open same instance more than once before closing it. + */ +IotGpioHandle_t iot_gpio_open( int32_t lGpioNumber ); + +/** + * @brief iot_gpio_set_callback is used to set the callback to be called when an + * interrupt is tirggered. + * + * @note Single callback is used for both read_async and write_async. Newly set callback overrides the one previously set + * @note This callback will not be invoked when synchronous operation completes. + * @note This callback is per handle. Each instance has its own callback. + * + * @warning If input handle or if callback function is NULL, this function silently takes no action. + * + * @param[in] pxGpio The GPIO handle returned in the open() call. + * @param[in] xGpioCallback The callback function to be called on interrupt. + * @param[in] pvUserContext The user context to be passed back when callback is called. + */ +void iot_gpio_set_callback( IotGpioHandle_t const pxGpio, + IotGpioCallback_t xGpioCallback, + void * pvUserContext ); + +/** + * @brief iot_gpio_read_sync is used to read data from GPIO pin in blocking mode. + * + * @param[in] pxGpio The GPIO handle returned in the open() call. + * @param[out] pucPinState The variable which reads state of the GPIO pin. + * + * @return + * - IOT_GPIO_SUCCESS on success + * - IOT_GPIO_INVALID_VALUE if pxGpio or pucPinState are NULL + * - IOT_GPIO_READ_FAILED on failure. + * + */ +int32_t iot_gpio_read_sync( IotGpioHandle_t const pxGpio, + uint8_t * pucPinState ); + +/** + * @brief iot_gpio_write_sync is used to write data into the GPIO pin in blocking mode. + * + * @param[in] pxGpio The GPIO handle returned in the open() call. + * @param[in] ucState The value to write into the GPIO pin. + * + * @return + * - IOT_GPIO_SUCCESS on success + * - IOT_GPIO_INVALID_VALUE if pxGpio or pucPinState are NULL + * - IOT_GPIO_WRITE_FAILED on failure. + */ +int32_t iot_gpio_write_sync( IotGpioHandle_t const pxGpio, + uint8_t ucPinState ); + +/** + * @brief iot_gpio_close is used to deinitializes the GPIO pin to default value and close the handle. + * The application should call this function to reset and deinitialize the GPIO pin. + * + * @param[in] pxGpio The GPIO handle returned in the open() call. + * + * @return + * - IOT_GPIO_SUCCESS on success + * - IOT_GPIO_INVALID_VALUE if + * - pxGpio handle is NULL + * - if is not in open state (already closed). + */ +int32_t iot_gpio_close( IotGpioHandle_t const pxGpio ); + +/** + * @brief iot_gpio_ioctl is used to configure GPIO pin options. + * The application should call this function to configure various GPIO + * pin options: pin function, I/O direction, pin internal pull mode, + * drive strength, slew rate etc + * + * @param[in] pxGpio The GPIO handle returned in the open() call. + * @param[in] xRequest One of IotGpioIoctlRequest_t enum + * @param[in/out] pvBuffer Buffer holding GPIO set or get values. + * + * @return + * - IOT_GPIO_SUCCESS on success + * - IOT_GPIO_INVALID_VALUE on NULL handle, invalid request, or NULL buffer when required. + * - IOT_GPIO_FUNCTION_NOT_SUPPORTED is only valid for + * - eSetGpioFunction / eGetGpioFunction + * - eSetGpioSpeed / eGetGpioSpeed + * - eSetGpioDriveStrength / eGetGpioDriveStrength + * - eSetGpioInterrupt / eGetGpioInterrupt + */ +int32_t iot_gpio_ioctl( IotGpioHandle_t const pxGpio, + IotGpioIoctlRequest_t xRequest, + void * const pvBuffer ); + +/** + * @} + */ + +#endif /* _IOT_GPIO_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_hw.h b/libraries/abstractions/common_io/include/iot_hw.h new file mode 100644 index 00000000000..ae02248916d --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_hw.h @@ -0,0 +1,63 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_hw.h + * @brief Define common APIs to get hardware ID and hardware revision. + */ +#ifndef _IOT_HW_H_ +#define _IOT_HW_H_ + +/** + * @brief Error code returned by platform + * + * We assume that neither hardware ID nor hardware revision number will ever be greater than 255 + * it means that API is not implemented or supported if API returns 0xFF + */ +#define IOT_HW_UNSUPPORTED ( 0xFFFF ) + +/** + * @brief API to read hardware ID. + * + * @note: the format and contents of this field are specific + * to each vendor. With the expectation that they will + * be unique for each board. + * + * @return hardware ID number as unsigned byte + */ +uint16_t iot_hw_get_id( void ); + +/** + * @brief API to read hardware revision. + * + * @note: the format and contents of this field are specific + * to each vendor. With the expectation that they will + * be unique for each revision. + * + * @return hardware revision number as unsigned byte + */ +uint16_t iot_hw_get_rev( void ); + +#endif /* _IOT_HW_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_i2c.h b/libraries/abstractions/common_io/include/iot_i2c.h new file mode 100644 index 00000000000..dbe5eee9a3c --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_i2c.h @@ -0,0 +1,479 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_ */ diff --git a/libraries/abstractions/common_io/include/iot_i2s.h b/libraries/abstractions/common_io/include/iot_i2s.h new file mode 100644 index 00000000000..a904d1bb34e --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_i2s.h @@ -0,0 +1,311 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_hal_i2s.h + * @brief File for the APIs of I2S called by application layer. + ******************************************************************************* + */ + +#ifndef _IOT_I2S_H_ +#define _IOT_I2S_H_ + +/** + * The return codes for the functions in I2S. + */ +#define IOT_I2S_SUCCESS ( 0 ) /*!< I2S operation completed successfully. */ +#define IOT_I2S_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_I2S_NOT_INITIALIZED ( 2 ) /*!< I2S interface not initialized. */ +#define IOT_I2S_BUSY ( 3 ) /*!< I2S operation can't be completed because another operation is happening. */ +#define IOT_I2S_WRITE_FAILED ( 4 ) /*!< I2S write operation failed. */ +#define IOT_I2S_READ_FAILED ( 5 ) /*!< I2S read operation failed. */ +#define IOT_I2S_NOTHING_TO_CANCEL ( 7 ) /*!< No active I2S operations to cancel. */ +#define IOT_I2S_FUNCTION_NOT_SUPPORTED ( 8 ) /*!< I2S operation not supported. */ + +/** + * @brief I2S Bus status + */ +typedef enum +{ + eI2SBusIdle = 0, /*!< I2S Bus status is idle. */ + eI2SBusBusy = IOT_I2S_BUSY, /*!< I2S Bus status is busy. */ +} IotI2SBusStatus_t; + +/** + * @brief I2S operation status. + */ +typedef enum +{ + eI2SCompleted = IOT_I2S_SUCCESS, /*!< I2S operation completed successfully. */ + eI2SLastWriteFailed = IOT_I2S_WRITE_FAILED, /*!< I2S write operation failed. */ + eI2SLastReadFailed = IOT_I2S_READ_FAILED, /*!< I2S read operation failed. */ +} IotI2SOperationStatus_t; + +/** + * @brief Ioctl request types. + */ +typedef enum +{ + eI2SSetConfig, /*!< Set I2S configuration taking the struct IotI2SIoctlConfig_t */ + eI2SGetConfig, /*!< Get I2S configuration returning the struct IotI2SIoctlConfig_t */ + eI2SGetBusState, /*!< Get the State of the I2S Bus returning the struct IotI2SBusStatus_t */ + eI2SGetTxNoOfbytes, /*!< Get the number of bytes sent in write operation. Returns uint32_t type. */ + eI2SGetRxNoOfbytes, /*!< Get the number of bytes received in read operation. Returns uint32_t type. */ +} IotI2SIoctlRequest_t; + +/** + * @brief I2S mode types. + */ +typedef enum +{ + eI2SNormalMode, /*!< HW uses normal mode for signal detection. */ + eI2SLeftJustifiedMode, /*!< HW uses left justified mode for signal detection. */ + eI2SRightJustifiedMode, /*!< HW uses right justified mode for signal detection. */ + eI2SPcmMode, /*!< HW uses PCM mode for signal detection. */ + eI2SDspMode, /*!< HW uses DSP mode for signal detection. */ +} IotI2SMode_t; + +/** + * @brief I2S channel types. + */ +typedef enum +{ + eI2SChannelStereo, /*!< Channel is in stereo. */ + eI2SChannelMono, /*!< Channel is in mono. */ +} IotI2SChannel_t; + +/** + * @brief I2S clock polarity for SCK and WS + */ +typedef enum +{ + eI2SFallingEdge, /*!< Clock polarity detected on falling edge of signal. */ + eI2SRisingEdge, /*!< Clock polarity detected on rising edge of signal. */ +} IotI2SClkPolarity_t; + +/** + * @brief I2S configuration + */ +typedef struct +{ + IotI2SMode_t xI2SMode; /*!< Set I2S mode using IotI2SMode_t */ + IotI2SChannel_t xI2SChannel; /*!< Set I2S channel using IotI2SChannel_t */ + IotI2SClkPolarity_t xI2SSckPolarity; /*!< Set I2S SCK polarity using IotI2SClkPolarity_t */ + IotI2SClkPolarity_t xI2SWsPolarity; /*!< Set I2S WS polarity using IotI2SClkPolarity_t */ + uint32_t ulI2SFrequency; /*!< Frequency to transfer/receive data*/ + uint32_t ulI2SDataLength; /*!< Number of data bits per sample */ + uint32_t ulI2SFrameLength; /*!< Number of data bits in the frames */ +} IotI2sIoctlConfig_t; + +/** + * @brief Opaque descriptor of I2C + */ +struct IotI2SDescriptor; + +/** + * @brief The handle for a I2S peripheral. + */ +typedef struct IotI2SDescriptor * IotI2SHandle_t; + +/** + * @brief The callback function for completion of I2C operation. + * + * @param[out] xOpStatus I2S asynchronous operation status. + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used or modified by the driver. The context + * is provided by the caller when setting the callback, and is + * passed back to the caller in the callback. + */ +typedef void ( * IotI2SCallback_t )( IotI2SOperationStatus_t xOpStatus, + void * pvUserContext ); + +/** + * @brief Initiates the I2S bus as. + * + * @param[in] lI2SInstance The index of I2S to initialize. + * + * @return + * - The handle to the I2S port if SUCCESS + * - NULL if + * - invalid lI2SInstance + * - lI2SInstance already open + */ +IotI2SHandle_t iot_i2s_open( int32_t lI2SInstance ); + +/** + * @brief Sets the application callback to be called on completion of an operation. + * + * @note Single callback is used per instance for iot_i2s_read_async() and iot_i2s_write_async() calls only. + * @note Newly set callback overrides the one previously set + * + * @warning If input handle or if callback function is NULL, this function silently takes no action. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * @param[in] xCallback The callback function to be called on completion of transaction. + * @param[in] pvUserContext The user context to be passed back when callback is called. + */ +void iot_i2s_set_callback( IotI2SHandle_t const pxI2SPeripheral, + IotI2SCallback_t xCallback, + void * pvUserContext ); + +/** + * @brief Starts the I2S read operation in non-blocking mode. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * @param[in] pvBuffer The receive buffer to read the data into. + * @param[in] xBytes The number of bytes to read. + * + * @return + * - IOT_I2S_SUCCESS on success + * - IOT_I2S_INVALID_VALUE if + * - pxI2SPeriperal or pvBuffer are NULL + * - xBytes == 0 + * - IOT_I2S_READ_FAIL if there was an error doing the read + * - IOT_I2S_NOT_INITIALIZED if I2S not first initialized with ioctl call eI2SSetConfig. + * - IOT_I2S_BUSY if another read (sync or async) is in process + */ +int32_t iot_i2s_read_async( IotI2SHandle_t const pxI2SPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the I2S write operation in non-blocking mode. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * @param[in] pvBuffer The transmit buffer to write the data into. + * @param[in] xBytes The number of bytes to write. + * + * @return + * - IOT_I2S_SUCCESS on success + * - IOT_I2S_INVALID_VALUE if + * - pxI2SPeriperal or pvBuffer are NULL + * - xBytes == 0 + * - IOT_I2S_WRITE_FAIL if there was an error doing the write + * - IOT_I2S_NOT_INITIALIZED if I2S not first initialized with ioctl call eI2SSetConfig. + * - IOT_I2S_BUSY if another write (sync or async) is in process + */ +int32_t iot_i2s_write_async( IotI2SHandle_t const pxI2SPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the I2S read operation in blocking mode. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * @param[in] pvBuffer The receive buffer to read the data into. + * @param[in] xBytes The number of bytes to read. + * + * @return + * - IOT_I2S_SUCCESS on success + * - IOT_I2S_INVALID_VALUE if + * - pxI2SPeriperal or pvBuffer are NULL + * - xBytes == 0 + * - IOT_I2S_READ_FAIL if there was an error doing the read + * - IOT_I2S_NOT_INITIALIZED if I2S not first initialized with ioctl call eI2SSetConfig. + * - IOT_I2S_BUSY if another read (sync or async) is in process + */ +int32_t iot_i2s_read_sync( IotI2SHandle_t const pxI2SPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the I2S write operation in blocking mode. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * @param[in] pvBuffer The transmit buffer to write the data into. + * @param[in] xBytes The number of bytes to write. + * + * @return + * - IOT_I2S_SUCCESS on success + * - IOT_I2S_INVALID_VALUE if + * - pxI2SPeriperal or pvBuffer are NULL + * - xBytes == 0 + * - IOT_I2S_WRITE_FAIL if there was an error doing the write + * - IOT_I2S_NOT_INITIALIZED if I2S not first initialized with ioctl call eI2SSetConfig. + * - IOT_I2S_BUSY if another write (sync or async) is in process + */ +int32_t iot_i2s_write_sync( IotI2SHandle_t const pxI2SPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Stops the ongoing operation and deinitializes the I2S peripheral. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * + * @return + * - IOT_I2S_SUCCESS on success + * - IOT_I2S_INVALID_VALUE if + * - pxI2SPeriperal is NULL + * - instance not open (previously closed) + */ +int32_t iot_i2s_close( IotI2SHandle_t const pxI2SPeripheral ); + +/** + * @brief Configures the I2S with user configuration. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * @param[in] lRequest Should be one of I2S_Ioctl_Request_t. + * @param[in] pvBuffer The configuration values for the IOCTL request. + * + * @note eI2SGetTxNoOfbytes returns the number of written bytes in last operation. + * This is supposed to be called in the caller task or application callback, right after last operation completes. + * This request expects 4 bytes buffer (uint32_t). + * + * - If the last operation only did read, this returns 0. + * + * @note eI2SGetRxNoOfbytes returns the number of read bytes in last operation. + * This is supposed to be called in the caller task or application callback, right after last operation completes. + * This request expects 4 bytes buffer (uint32_t). + * + * - If the last operation was a read, this returns the actual number of read bytes which might be smaller than the requested number (partial read). + * - If the last operation was a write, this returns 0. + * + * @return + * - IOT_I2S_SUCCESS on success + * - IOT_I2S_INVALID_VALUE if + * - pxI2SPeriperal is NULL + * - xI2SRequest is invalid + * - pvBuffer is NULL + * - IOT_I2S_FUNCTION_NOT_SUPPORTED if designated IotI2SMode_t in eI2SSetConfig is not supported. + */ +int32_t iot_i2s_ioctl( IotI2SHandle_t const pxI2SPeripheral, + IotI2SIoctlRequest_t xI2SRequest, + void * const pvBuffer ); + +/** + * @brief This function is used to cancel the current operation in progress if possible. + * + * @param[in] pxI2SPeripheral The I2S handle returned in open() call. + * + * @return + * - IOT_I2S_SUCCESS on success + * - IOT_I2S_INVALID_VALUE if pxI2SPeriperal is NULL + * - IOT_I2S_NOTHING_TO_CANCEL if nothing to cancel. + * - IOT_I2S_FUNCTION_NOT_SUPPORTED if cancel operation not supported. + */ +int32_t iot_i2s_cancel( IotI2SHandle_t const pxI2SPeripheral ); + +#endif /* ifndef _IOT_HAL_I2S_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_perfcounter.h b/libraries/abstractions/common_io/include/iot_perfcounter.h new file mode 100644 index 00000000000..502ad0b7685 --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_perfcounter.h @@ -0,0 +1,88 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_perfcounter.h + * + * @breif HAL APIs for Performance Counter + * + ******************************************************************************* + */ + +/** + * @file iot_perfcounter.h + * @brief This file contains all the Performance counters HAL API definitions + */ + +#ifndef _IOT_PERFCOUNTER_H +#define _IOT_PERFCOUNTER_H + +/** + * @defgroup iot_perfcounter PerfCounter HAL APIs + * @{ + * @brief The perf counter is generally used to measure the cycles (usually processor clock cycles ) + * taken between 2 places in code. perfcounters can be implemented using cycle counters if + * the processor supports, or any generic timer that is granular enough to measure the time + * between 2 points in code. + */ + +/** + * @brief iot_perfcounter_open is used to Initialize the performance counter. + * + */ +void iot_perfcounter_open( void ); + +/** + * @brief iot_perfcounter_get_value is used to get the current performance counter + * value. + * + * @return returns performance counter value as uint64 value. + */ +uint64_t iot_perfcounter_get_value( void ); + +/** + * @brief iot_perfcounter_get_frequency is used to get the current frequency + * performance counters are running at. This can be used to determine the + * time delta between two perfcounter values returned by valling iot_perfcounter_get_value() + * + * @return returns the frequency of the performance counter as a uint32 value. + * This can be used to deterime the period between perfcounter + * increments. + */ +uint32_t iot_perfcounter_get_frequency( void ); + + +/** + * @brief iot_perfcounter_close is used to de-initialize the perfcounter. + * It may reset the counter value in perfcounter. + * + */ +void iot_perfcounter_close( void ); + +/** + * @} + */ + +#endif /* ifndef _IOT_PERFCOUNTER_H */ diff --git a/libraries/abstractions/common_io/include/iot_power.h b/libraries/abstractions/common_io/include/iot_power.h new file mode 100644 index 00000000000..c50200a609e --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_power.h @@ -0,0 +1,285 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_power.h + * @brief This file contains all the Power HAL API definitions + */ + +#ifndef _IOT_HAL_POWER_H_ +#define _IOT_HAL_POWER_H_ + +#include +#include + +/** + * @defgroup iot_power Power HAL APIs + * @{ + */ + +/** + * @brief Return values used by the driver. + */ +#define IOT_POWER_SUCCESS ( 0 ) /*!< Power operation completed successfully. */ +#define IOT_POWER_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_POWER_NOT_INITIALIZED ( 2 ) /*!< Power operation completed successfully. */ +#define IOT_POWER_GET_FAILED ( 3 ) /*!< Power get operation failed. */ +#define IOT_POWER_SET_FAILED ( 4 ) /*!< Power set operation failed. */ +#define IOT_POWER_FUNCTION_NOT_SUPPORTED ( 5 ) /*!< Power operation not supported. */ + +/** + * @brief power descriptor type defined in the source file. + */ +struct IotPowerDescriptor; + +/** + * @brief IotPowerHandle_t type is the power handle returned by calling iot_power_open() + * this is initialized in open and returned to caller. Caller must pass this pointer + * to the rest of the APIs. + */ +typedef struct IotPowerDescriptor * IotPowerHandle_t; + +/** + * @brief Power modes supported by the driver. + * These power modes may perform different actions on + * different platforms based on the underlying HW support. + */ +typedef enum +{ + eHighPowerPerfMode, /*!< Set the high performance mode at the SoC level */ + eNormalPowerPerfMode, /*!< Set the Normal mode. power_open sets the system to this mode by default*/ + eLowPowerPerfMode, /*!< Set the lower performance mode at the Soc level */ + eUnknownPowerMode = 0xFFFF /*!< This mode cannot be set, and when a reset_mode is called currentMode will be set to eUnknown */ +} IotPowerMode_t; + +/** + * @brief Different Idle mode mappings to the threshold values set using the IOCTLs. + */ +typedef enum +{ + eIdleNoneMode, /*!< No Idle mode entered. */ + eIdlePCMode, /*!< Normal Idle mode with core collapsed or clock gated. Actual + * mode implementation may differ based on the underlying SoC support. */ + eIdleClkSrcOffModeMode, /*!< Source clock off in addition to core collapse. Actual + * mode implementation may differ based on the underlying SoC support. */ + eIdleVddOffMode /*!< Vddcore off in addition to clock source and core collapse. Actual + * mode implementation may differ based on the underlying SoC support. */ +} IotPowerIdleMode_t; + +/** + * @brief Wakeup source information. + */ +typedef struct IotPowerWakeupSources +{ + uint8_t * pucWakeupSources; /*!< Wakeup sources byte stream, where each bit in the bytes + * may indicate a different wakeup source and is platform dependent */ + uint16_t usLength; /*!< Length of the Wakeup sources in number of bytes.*/ +} IotPowerWakeupSources_t; + +/** + * @brief Ioctl request types. + */ +typedef enum IotPowerIoctlRequest +{ + eSetPCWakeThreshold, /*!< IdlePCMode is entered when expected idle time provided by RTOS + * is greater or equal to the PCWakeThreshold. For example - when + * IdleTask runs, all the other tasks are delayed by a time at least + * PCWakeThreshold and less than ClkSrcOffWakeThreshold then the + * device would enter PCMode. Threshold values are uint32_t in millisecond units.*/ + eGetPCWakeThreshold, /*!< Get Wakeup threshold time. Threshold values are uint32_t in millisecond units.*/ + eSetClkSrcOffWakeThreshold, /*!< ClkSrcOffModeMode is entered when expected idle time provided + * by RTOS is greater or equal to the ClkSrcOffWakeThreshold. For + * example - when IdleTask runs, SOC clock sources will be gated for + * the time you set to ClkSrcOffWakeThreshold then the device would + * enter ClkSrcOffModeMode. Threshold values are uint32_t in millisecond units.*/ + eGetClkSrcOffWakeThreshold, /*!< Get Clock off threshold time. Threshold values are uint32_t in millisecond units.*/ + eSetVddOfffWakeThreshold, /*!< VddOffMode is entered when expected idle time provided by RTOS + * is greater or equal to the VddOfffWakeThreshold. If all idleTask meet + * this condition, core will shut off to enter VddOffMode. + * Threshold values are uint32_t in millisecond units. */ + eGetVddOfffWakeThreshold, /*!< Get power off (vdd rails off - or lower input voltage etc..) threshold time. + * Threshold values are uint32_t in millisecond units. */ + eSetWakeupSources, /*!< Set wakeup sources that can wake-up the target from idle modes. Wakeup sources + * may only be needed for specific idle modes based on the thresholds set above + * and may are platform/SoC dependent. Takes input of type IotPowerWakeupSources_t */ + eGetWakeupSources, /*!< Get the current wakeup sources set to wakeup the target from idle mode. Returns the + * wake-up sources as IotPowerWakeupSources_t type */ + eGetLastIdleMode /*!< Get the last Idle mode entered when the target was idle. Returns one of the modes + * defined in IotPowerIdleMode_t */ +} IotPowerIoctlRequest_t; + +/** + * @brief This callback type is used to set a callback for idle enter and exit notification callback type. + * This callback is used for notifying the registered caller(s) before + * entering and after coming out of target low power state (i,e:idle/sleep). + * bIdleState is used to let the caller know if the callback is called when entering or exiting the low + * power mode. "true" indicates that target is entering idle and "false" indicates that its exiting. + * The callback is not used for any other mode transitions which are synchronous and blocking. + * For example when the caller calls a set_mode to eHighPerfMode, the mode is set in the same context and the call is blocking. + * + * @param[in] bIdleState IdleState set to "true" when entering idle and "false" when exiting. + * @param[in] pvUserContext User Context passed when setting the callback. + */ +typedef void ( * IotPowerCallback_t )( bool bIdleState, + void * pvUserContext ); + +/** + * @brief iot_power_open is used to Initialize the CPU power management driver. + * power_open sets up the default mode to eNomralMode, so when the power_open is called, + * the caller must set the mode using set_mode to a specific mode of interest. + * + * @return + * - handle to power interface on success + * - NULL if already open + */ +IotPowerHandle_t iot_power_open( void ); + +/** + * @brief iot_power_set_mode is used to set or change the power mode to a specific mode. The actual changes made as part + * of switching to a specific power mode are platform specific. When set_mode is called to switch + * from high mode to low mode, the target may go through several steps to enter low performance mode. + * The aggregation of switching to a particular mode must be made prior to calling this, as a call + * to this API may change the CPU frequency and voltage which may affect the software execution. + * This API is blocking and the mode switched in the same context as the caller and is a blocking call. + * + * @param[in] pxPowerHandle handle to power driver returned in + * iot_power_open + * @param[in] xMode power mode to be switched to. + * + * @return + * - IOT_POWER_SUCCESS on success + * - IOT_POWER_INVALID_VALUE if any parameter is invalid + * - IOT_POWER_SET_FAILED if unable to set to the desired mode + * - IOT_POWER_FUNCTION_NOT_SUPPORTED if specified mode is not supported. + */ +int32_t iot_power_set_mode( IotPowerHandle_t const pxPowerHandle, + IotPowerMode_t xMode ); + +/** + * @brief iot_power_reset_mode is used to reset the mode (i,e remove the vote to set mode). When reset mode is called, + * its implicitly notifying the OS to enter deepest low power mode possible in idle state based on + * existing timers. If a set_mode is called with any of the performance modes with out calling reset_mode, + * then when target enters idle state, it will not be able to enter deep power states since there is an + * existing vote for a performance mode from the caller. The target will still do clock gating of the core + * by doing a WFI and WFE. + * Additionally, if a reset_mode is called, followed by a get_mode, eUnKnownMode will be returned to the caller. + * But if reset_mode is called, and then target enters idle state, when coming out of the idle_state it will resume + * to a known previous state. + * For example, if we take the following flow: + * 1. set_mode(eHighPerformanceMode) + *  2. reset_modqe() -> At this point the current mode is set to eUnKnownMode + *  3. Idle checks to see if it can enter a deep power state based on existing timers. + *  4. If a callback is registered, the callback is called with bIdle set to "true" + * 4a. The callback can request a mode change causing idle to abort. + *  5. Target enters Idle state and goes to 'some' deep power state + *  6. Target wakes up due to external interrupt or scheduled timer interrupt. + *  7. If a callback is registered, the callback is called with bIdle set to "false" + *  8. At this point the caller can set the desired performance state. + *  9. Target is set to eHighPerformanceMode as this was the known mode before entering idle. (optional if mode was not set at #6) + * + * @param[in] pxPowerHandle handle to power driver returned in + * iot_power_open + * + * @return + * - IOT_POWER_SUCCESS on success + * - IOT_POWER_INVALID_VALUE on pxPowerHandle == NULL + * - IOT_POWER_FUNCTION_NOT_SUPPORTED if power reset not supported. + */ +int32_t iot_power_reset_mode( IotPowerHandle_t const pxPowerHandle ); + +/** + * @brief iot_power_set_callback is used to set the callback to be called when the target is entering low power mode, + * and when target is coming out of low power mode. Callback must not use any HW resources + * when this callback is called with out first requesting for a performance mode. + * + * @note Single callback is used for both entering and exiting low power mode. + * @note Newly set callback overrides the one previously set + * + * @warning If input handle or if callback function is NULL, this function silently takes no action. + * + * @param[in] pxPowerHandle handle to power driver returned in + * iot_power_open + * @param[in] xCallback The callback function to be called. + * @param[in] pvUserContext The user context to be passed when callback is called. + */ +void iot_power_set_callback( IotPowerHandle_t const pxPowerHandle, + IotPowerCallback_t xCallback, + void * pvUserContext ); + +/** + * @brief iot_power_ioctl is used to set power configuration and + * power properties like Wakeup time thresholds. + * Supported IOCTL requests are defined in iot_PowerIoctlRequest_t + * + * @param[in] pxPowerHandle handle to power driver returned in + * iot_power_open() + * @param[in] xRequest configuration request of type IotPowerIoctlRequest_t + * @param[in,out] pvBuffer buffer holding Power set and get values. + * + * @return + * - IOT_POWER_SUCCESS on success + * - IOT_POWER_INVALID_VALUE on any invalid parameter + * - IOT_POWER_FUNCTION_NOT_SUPPORTED for any IotPowerIoctlRequest_t not supported. + * + * @note: For any Set ioctl that is supported, the corresponding Get ioctl must also be supported. + */ +int32_t iot_power_ioctl( IotPowerHandle_t const pxPowerHandle, + IotPowerIoctlRequest_t xRequest, + void * const pvBuffer ); + +/** + * @brief iot_power_get_mode is used to get the current power mode the target is in. + * + * @param[in] pxPowerHandle handle to power driver returned in + * iot_power_open + * @param[out] xMode current power mode. + * + * @return + * - IOT_POWER_SUCCESS on success + * - IOT_POWER_INVALID_VALUE on pxPowerHandle or xMode being NULL + * - IOT_POWER_GET_FAILED on error. + */ +int32_t iot_power_get_mode( IotPowerHandle_t const pxPowerHandle, + IotPowerMode_t * xMode ); + +/** + * @brief iot_power_close is used to de-initialize power driver. + * + * @param[in] pxPowerHandle handle to power driver returned in + * iot_power_open + * + * @return + * - IOT_POWER_SUCCESS on success + * - IOT_POWER_INVALID_VALUE if + * - pxPowerHandle == NULL + * - not in open state (already closed). + */ +int32_t iot_power_close( IotPowerHandle_t const pxPowerHandle ); + +/** + * @} + */ + +#endif /* ifndef _IOT_HAL_POWER_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_pwm.h b/libraries/abstractions/common_io/include/iot_pwm.h new file mode 100644 index 00000000000..f64ae68ae5b --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_pwm.h @@ -0,0 +1,161 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_pwm.h + * @brief This file contains all the PWM HAL API definitions + */ + +#ifndef _IOT_PWM_H_ +#define _IOT_PWM_H_ + +/** + * @defgroup iot_pwm PWM HAL APIs + * @{ + */ + +/** + * @brief Return values used by PWM driver. + */ +#define IOT_PWM_SUCCESS ( 0 ) /*!< PWM operation completed successfully. */ +#define IOT_PWM_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_PWM_NOT_CONFIGURED ( 2 ) /*!< PWM must be configured prior to start. */ +#define IOT_PWM_FUNCTION_NOT_SUPPORTED ( 3 ) /*!< PWM operation not supported. */ + + +/** + * @brief PWM configuration type. + */ +typedef struct IotPwmConfig +{ + uint32_t ulPwmFrequency; /*!< PWM frequency */ + uint8_t ucPwmDutyCycle; /*!< PWM duty cycle */ + uint8_t ucPwmChannel; /*!< PWM output channel. Depending on individual HW implementations, + * each pwm controller may have one or more channels, where the + * output signal can be directed. */ +} IotPwmConfig_t; + +/** + * @brief PWM descriptor type defined in the source file. + */ +struct IotPwmDescriptor; + +/** + * @brief IotPwmHandle_t type is the PWM handle returned by calling iot_pwm_open() + * this is initialized in open and returned to caller. Caller must pass this pointer + * to the rest of the APIs. + */ +typedef struct IotPwmDescriptor * IotPwmHandle_t; + +/** + * @brief iot_pwm_open is used to initialize the PWM driver instance. + * this API will configure PWM and may reset the PWM hardware. + * + * @param[in] lPwmInstance The instance of the PWM to initialize. + * PWM is output only. + * + * @return + * - Handle to PWM interface on success + * - NULL if + * - invalid instance + * - instance already open + */ +IotPwmHandle_t iot_pwm_open( int32_t lPwmInstance ); + +/** + * @brief iot_pwm_set_config sets up the PWM frequency and duty cycle + * to generate the PWM pulses required. + * + * @param[in] pxPwmHandle Handle to PWM driver returned in + * iot_pwm_open + * @param[in] xConfig PWM configuration to be setup. + * + * @return + * - IOT_PWM_SUCCESS on success + * - IOT_PWM_INVALID_VALUE if pxPwmHandle == NULL or invalid config setting + */ +int32_t iot_pwm_set_config( IotPwmHandle_t const pxPwmHandle, + const IotPwmConfig_t xConfig ); + +/** + * @brief iot_pwm_get_config returns the current PWM configuration + * + * @param[in] pxPwmHandle Handle to PWM driver returned in + * iot_pwm_open + * + * @return + * - pointer to current PWM configuration on success + * - NULL if pxPwmHandle == NULL + */ +IotPwmConfig_t * iot_pwm_get_config( IotPwmHandle_t const pxPwmHandle ); + +/*! + * @brief Start the PWM hardware. PWM configuration must be + * set before PWM is started. PWM signal availability + * on the configured output based on the PWMChannel configured + * in iot_pwm_set_config(). + * + * @param[in] pxPwmHandle Handle to PWM driver returned in + * iot_pwm_open + * + * @return + * - IOT_PWM_SUCCESS on success + * - IOT_PWM_INVALID_VALUE if pxPwmHandle == NULL + * - IOT_PWM_NOT_CONFIGURED if iot_pwm_set_config hasn't been called. + */ +int32_t iot_pwm_start( IotPwmHandle_t const pxPwmHandle ); + +/*! + * @brief Stop the PWM hardware. + * + * @param[in] pxPwmHandle Handle to PWM driver returned in + * iot_pwm_open + * + * @return + * - IOT_PWM_SUCCESS on success + * - IOT_PWM_INVALID_VALUE if pxPwmHandle == NULL + */ +int32_t iot_pwm_stop( IotPwmHandle_t const pxPwmHandle ); + +/** + * @brief iot_pwm_close de-initializes the PWM. + * + * @param[in] pxPwmHandle Handle to PWM driver returned in + * iot_pwm_open + * + * @return + * - IOT_PWM_SUCCESS on success + * - IOT_PWM_INVALID_VALUE if + * - pxPwmHandle == NULL + * - not in open state (already closed). + * + */ +int32_t iot_pwm_close( IotPwmHandle_t const pxPwmHandle ); + +/** + * @} + */ + +#endif /* ifndef _IOT_PWM_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_reset.h b/libraries/abstractions/common_io/include/iot_reset.h new file mode 100644 index 00000000000..50f60028be9 --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_reset.h @@ -0,0 +1,110 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_reset.h + * @brief This file contains all the Reset HAL API definitions + */ + +#ifndef _IOT_RESET_H_ +#define _IOT_RESET_H_ + +#include + +/** + * @defgroup iot_reset Reset HAL APIs + * @{ + */ + +/** + * Return values used by reset driver + */ +#define IOT_RESET_SUCCESS ( 0 ) /**< Reset operation completed successfully. */ +#define IOT_RESET_FUNCTION_NOT_SUPPORTED ( 1 ) /**< Reset function not supported. */ +#define IOT_RESET_INVALID_VALUE ( 2 ) /**< At least one parameter is invalid. */ + +typedef enum +{ + eResetPowerOnBoot, /**< Normal power on Boot, when the power is applied to the device. */ + eResetWarmBoot, /**< Last reset triggered due to warm Reset. for ex: iot_reset_reboot(0) was called to reset the device */ + eResetColdBoot, /**< Last reset triggered due to cold Reset. for ex: iot_reset_reboot(1) */ + eResetWatchdog, /**< Last reset triggered due to watchdog expiration */ + eResetBusTimeout, /**< Last reset triggered due to internal bus timeout on the SoC */ + eResetPmic, /**< Last reset caused by power management IC */ + eResetBrownOut, /**< Last reset caused by power brown out */ + eResetOther, /**< Last reset caused by other reasons specific to the underlying hardware */ +} IotResetReason_t; + +typedef enum +{ + eResetWarmBootFlag, /**< Perform warm-reset */ + eResetColdBootFlag, /**< Perform cold-reset */ +} IotResetBootFlag_t; + +/** + * @brief iot_reset_reboot is used to reboot the device. + * + * @param[in] xResetBootFlag flag to determine either to do cold-reset or warm-reset. + * cold-reset means the device is restarted and does not keep + * any blocks of the SOC powered on i.e. device is shutdown and rebooted), + * and warm-reset means the device is restarted while keeping some of the SoC blocks + * powered on through the reboot process. + * For example warm-boot may keep the RAM contents valid after reset by keeping the power + * on for RAM banks, while cold-boot will wipe off the contents. + * One of the IotResetBootFlag_t value. + */ +void iot_reset_reboot( IotResetBootFlag_t xResetBootFlag ); + +/** + * @brief iot_reset_shutdown is used to shutdown the device. + * If the target does not support shutdown of the device, IOT_RESET_FUNCTION_NOT_SUPPORTED + * is returned to the user. + * + * @return + * - does not return and device shutdown on success + * - IOT_RESET_FUNCTION_NOT_SUPPORTED if shutdown not supported. + */ +int32_t iot_reset_shutdown(); + +/** + * @brief iot_get_reset_reason is used to get the last reset reason. + * If the underlying HW does not support the feature of persisting the + * reset reason, then this API will return IOT_RESET_FUNCTION_NOT_SUPPORTED + * error with the value in out as don't care. + * + * @param[out] xResetReason One of the reset reasons specified in IotResetReason_t types + * + * @return + * - IOT_RESET_SUCCESS on success. + * - IOT_RESET_FUNCTION_NOT_SUPPORTED if not supported. + * - IOT_RESET_INVALID_VALUE if xREsetReason == NULL + */ +int32_t iot_get_reset_reason( IotResetReason_t * xResetReason ); + +/** + * @} + */ + +#endif /* ifndef _IOT_RESET_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_rtc.h b/libraries/abstractions/common_io/include/iot_rtc.h new file mode 100644 index 00000000000..b40c0ad59ea --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_rtc.h @@ -0,0 +1,231 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_rtc.h + * + * @brief HAL APIs for RTC + ******************************************************************************* + */ + +/** + * @file iot_rtc.h + * @brief This file contains all the RTC HAL API definitions + */ + +#ifndef _IOT_RTC_H_ +#define _IOT_RTC_H_ + +/** + * @defgroup iot_rtc RTC HAL APIs + * @{ + */ + +/** + * @brief Return values used by RTC driver + */ +#define IOT_RTC_SUCCESS ( 0 ) /*!< RTC operation completed successfully. */ +#define IOT_RTC_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_RTC_NOT_STARTED ( 2 ) /*!< RTC not started. */ +#define IOT_RTC_GET_FAILED ( 3 ) /*!< RTC get operation failed. */ +#define IOT_RTC_SET_FAILED ( 4 ) /*!< RTC set operation failed. */ +#define IOT_RTC_FUNCTION_NOT_SUPPORTED ( 5 ) /*!< RTC operation not supported. */ + +/** + * @brief RTC driver status values + */ +typedef enum +{ + eRtcTimerStopped, /*!< RTC Timer status: stopped. */ + eRtcTimerRunning, /*!< RTC Timer status: running. */ + eRtcTimerAlarmTriggered, /*!< RTC Timer status: alarm triggered. */ + eRtcTimerWakeupTriggered, /*!< RTC Timer status: wakeup triggered. */ +} IotRtcStatus_t; + +/** + * @brief RTC date and time format info. + */ +typedef struct IotRtcDatetime +{ + uint8_t ucSecond; /*!< Seconds - range from 0 to 59.*/ + uint8_t ucMinute; /*!< minutes - range from 0 to 59.*/ + uint8_t ucHour; /*!< hours - range from 0 to 23.*/ + uint8_t ucDay; /*!< date of month - range from 1 to 31 (depending on month).*/ + uint8_t ucMonth; /*!< months since January - range from 0 to 11.*/ + uint16_t usYear; /*!< years since 1900 */ + uint8_t ucWday; /*!< Week day from Sunday - range from 0 to 6 */ +} IotRtcDatetime_t; + +/** + * @brief Ioctl request types. + * + * @note: WakeupTime is a timer, in milliseconds in the future. AlarmTime is an exact time in the future. + */ +typedef enum IotRtcIoctlRequest +{ + eSetRtcAlarm, /*!< Set Alarm, date&time when Alarm need to occur. Takes input type IotRtcDatetime_t + * @warning time must be in the future.*/ + eGetRtcAlarm, /*!< Get Alarm, gives the date&time when Alarm will occur. Returns IotRtcDatetime_t */ + eCancelRtcAlarm, /*!< Cancel any scheduled Alarm */ + eSetRtcWakeupTime, /*!< Set Wakeup time in miliseconds. Maximum number of miliseconds depend on the platform. Value is uint32_t */ + eGetRtcWakeupTime, /*!< Get Wakeup time in milli-seconds */ + eCancelRtcWakeup, /*!< Cancel any scheduled wake-up */ + eGetRtcStatus /*!< Get the RTC timer status value. Returns IotRtcStatus_t type*/ +} IotRtcIoctlRequest_t; + +/** + * @brief RTC descriptor type defined in the source file. + */ +struct IotRtcDescriptor_t; + +/** + * @brief IotRtcHandle_t type is the RTC handle returned by calling iot_rtc_open() + * this is initialized in open and returned to caller. Caller must pass this pointer + * to the rest of the APIs. + */ +typedef struct IotRtcDescriptor_t * IotRtcHandle_t; + +/** + * @brief RTC notification callback type. This callback is passed + * to the driver by using iot_rtc_set_callback API. The callback is + * used to get the notifications for Alarm and Wakeup timers. + * + * @param[out] xStatus RTC timer status. + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used by the driver, but just passed back to the user + * in the callback. + */ +typedef void ( * IotRtcCallback_t)( IotRtcStatus_t xStatus, + void * pvUserContext ); + +/** + * @brief iot_rtc_open is used to initialize the RTC timer. + * It usually resets the RTC timer, sets up the clock for RTC etc... + * + * @param[in] lRtcInstance The instance of the RTC timer to initialize. + * + * @return + * - the handle IotRtcHandle_t on success + * - NULL if + * - if instance is already open + * - invalid instance + */ +IotRtcHandle_t iot_rtc_open( int32_t lRtcInstance ); + +/*! + * @brief iot_rtc_set_callback is used to set the callback to be called when alarmTime triggers. + * The caller must set the Alarm time using IOCTL to get the callback. + * + * @note Single callback is used for both rtc_alarm, and rtc_wakeup features. + * @note Newly set callback overrides the one previously set + * @note This callback is per handle. Each instance has its own callback. + * + * @param[in] pxRtcHandle handle to RTC driver returned in + * iot_rtc_open() + * @param[in] xCallback callback function to be called. + * @param[in] pvUserContext user context to be passed when callback is called. + * + */ +void iot_rtc_set_callback( IotRtcHandle_t const pxRtcHandle, + IotRtcCallback_t xCallback, + void * pvUserContext ); + +/** + * @brief iot_rtc_ioctl is used to set RTC configuration and + * RTC properties like Wakeup time, alarms etc. + * Supported IOCTL requests are defined in iot_RtcIoctlRequest_t + * + * @param[in] pxRtcHandle handle to RTC driver returned in + * iot_rtc_open() + * @param[in] xRequest configuration request of type IotRtcIoctlRequest_t + * @param[in,out] pvBuffer buffer holding RTC set and get values. + * + * @return + * - IOT_RTC_SUCCESS on success + * - IOT_RTC_INVALID_VALUE if + * - pxRtcHandle == NULL + * - xRequest is invalid + * - pvBuffer == NULL (excluding eCancelRtcAlarm, eCancelRtcWakeup) + * - if date/time is set in the past for eSetRtcAlarm + * - IOT_RTC_NOT_STARTED on error + * - IOT_RTC_FUNCTION_NOT_SUPPORTED if feature not supported + * - Only valid for eCancelRtcAlarm, eCancelRtcWakeup + */ +int32_t iot_rtc_ioctl( IotRtcHandle_t const pxRtcHandle, + IotRtcIoctlRequest_t xRequest, + void * const pvBuffer ); + +/** + * @brief iot_rtc_set_date_time is used to set the current time as a reference in RTC timer counter. + * + * @param[in] pxRtcHandle handle to RTC driver returned in + * iot_rtc_open() + * @param[in] pxDatetime pointer to IotRtcDatetime_t structure to set the date&time + * to be set in RTC counter. + * + * @return + * - IOT_RTC_SUCCESS on success + * - IOT_RTC_INVALID_VALUE if pxRtcHandle == NULL or pxDatetime == NULL + * - IOT_RTC_SET_FAILED on error. + */ +int32_t iot_rtc_set_datetime( IotRtcHandle_t const pxRtcHandle, + const IotRtcDatetime_t * pxDatetime ); + +/** + * @brief iot_rtc_get_datetime is used to get the current time from the RTC counter. + * The time must be set first as a reference to get the time. + * + * @param[in] pxRtcHandle handle to RTC driver returned in + * iot_rtc_open() + * @param[in] pxDatetime pointer to IotRtcDatetime_t structure to get the date&time + * from RTC counter. + * + * @return + * - IOT_RTC_SUCCESS on success + * - IOT_RTC_INVALID_VALUE if pxRtcHandle == NULL or pxDatetime == NULL + * - IOT_RTC_NOT_STARTED on error + */ +int32_t iot_rtc_get_datetime( IotRtcHandle_t const pxRtcHandle, + IotRtcDatetime_t * pxDatetime ); + +/** + * @brief iot_rtc_close is used to de-Initialize RTC Timer. + * it resets the RTC timer and may stop the timer. + * + * @param[in] pxRtcHandle handle to RTC interface. + * + * @return + * - IOT_RTC_SUCCESS on success + * - IOT_RTC_INVALID_VALUE if + * - pxRtcHandle == NULL + * - not in open state (already closed). + */ +int32_t iot_rtc_close( IotRtcHandle_t const pxRtcHandle ); + +/** + * @} + */ + +#endif /* ifndef _IOT_RTC_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_spi.h b/libraries/abstractions/common_io/include/iot_spi.h new file mode 100644 index 00000000000..e33237856bc --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_spi.h @@ -0,0 +1,439 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_spi.h + * @brief File for the APIs of SPI called by application layer. + */ +#ifndef _IOT_SPI_H_ +#define _IOT_SPI_H_ + +/* Standard includes. */ +#include + +/** + * @defgroup iot_spi SPI Abstraction APIs. + * @{ + */ + +/** + * @brief The return codes for the methods in SPI. + */ +#define IOT_SPI_SUCCESS ( 0 ) /*!< SPI operation completed successfully. */ +#define IOT_SPI_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_SPI_WRITE_FAILED ( 2 ) /*!< SPI driver returns error when performing write operation. */ +#define IOT_SPI_READ_FAILED ( 3 ) /*!< SPI driver returns error when performing read operation. */ +#define IOT_SPI_TRANSFER_ERROR ( 4 ) /*!< SPI driver returns error when performing transfer. */ +#define IOT_SPI_BUS_BUSY ( 5 ) /*!< SPI bus is busy at current time. */ +#define IOT_SPI_NOTHING_TO_CANCEL ( 6 ) /*!< No ongoing operation when cancel operation is performed. */ +#define IOT_SPI_FUNCTION_NOT_SUPPORTED ( 7 ) /*!< SPI operation is not supported. */ + + +/** + * @brief The SPI return status from Async operations. + */ +typedef enum +{ + eSPISuccess = IOT_SPI_SUCCESS, /*!< SPI operation completed successfully. */ + eSPIWriteError = IOT_SPI_WRITE_FAILED, /*!< SPI driver returns error when performing write operation. */ + eSPIReadError = IOT_SPI_READ_FAILED, /*!< SPI driver returns error when performing read operation. */ + eSPITransferError = IOT_SPI_TRANSFER_ERROR, /*!< SPI driver returns error when performing transfer. */ +} IotSPITransactionStatus_t; + +/** + * @brief The SPI Modes denoting the clock polarity + * and clock phase. + */ +typedef enum +{ + eSPIMode0, /*!< CPOL = 0 and CPHA = 0 */ + eSPIMode1, /*!< CPOL = 0 and CPHA = 1 */ + eSPIMode2, /*!< CPOL = 1 and CPHA = 0 */ + eSPIMode3, /*!Example timer delay execution + * The callback function is called to signal when the timer reaches the count (delay) + * set by the caller. + * @code{c} + * + * IotTimerHandle_t xTimerHandle; + * + * xTimerHandle = iot_timer_open( ltestIotTimerInstance); + * // assert( xTimerHandle == NULL ); + * + * // Set the callback to call prvTimerCallbackFunction() when delay reached. + * iot_timer_set_callback(xTimerHandle, prvTimerCallbackFunction, NULL); + * + * // Set the timer delay to be TIMER_DEFAULT_DELAY_US + * lRetVal = iot_timer_delay(xTimerHandle, TIMER_DEFAULT_DELAY_US ); + * // assert( lRetVal != IOT_TIMER_SUCCESS ); + * + * //Start the timer + * lRetVal = iot_timer_start(xTimerHandle); + * // assert ( lRetVal != IOT_TIMER_SUCCESS); + * + * // Wait for the Delay callback to be called. Inside of prvTimerCallbackFunction() + * // the function will use xSemaphoreGive() to signal completion. + * lRetVal = xSemaphoreTake(IotTimerSemaphore, portMAX_DELAY); + * // assert( lRetVal != TRUE ); + * + * lRetVal = iot_timer_close(xTimerHandle); + * //assert ( lRetVal != IOT_TIMER_SUCCESS); + * @endcode + * + * @return + * - IOT_TIMER_SUCCESS on success + * - IOT_TIMER_INVALID_VALUE if pxTimerHandle or ulMicroSeconds pointers are NULL + * - IOT_TIMER_NOT_RUNNING if timer hasn't been started. + * - IOT_TIMER_SET_FAILED on error. + */ +int32_t iot_timer_delay( IotTimerHandle_t const pxTimerHandle, + uint32_t ulDelayMicroSeconds ); + +/** + * @brief iot_timer_cancel is used to cancel any existing delay call. + * If a call to iot_timer_delay() was made earlier, calling iot_timer_cancel + * will cancel that delay call, so no call-back will be called. + * + * @param[in] pxTimerHandle handle to Timer interface returned in + * iot_timer_open() + * + * @return + * - IOT_TIMER_SUCCESS on success + * - IOT_TIMER_INVALID_VALUE if pxTimerHandle is NULL + * - IOT_TIMER_FUNCTION_NOT_SUPPORTED if timer can't be cancelled. + * - IOT_TIMER_NOTHING_TO_CANCEL if there is no timer running to cancel. + */ +int32_t iot_timer_cancel( IotTimerHandle_t const pxTimerHandle ); + +/** + * @brief iot_timer_close is used to de-initializes the timer, stops the timer + * if it was started and cancels the delay calls, and resets the timer value. + * + * @param[in] pxTimerHandle handle to Timer interface returned in + * iot_timer_open() + * + * @return + * - IOT_TIMER_SUCCESS on success + * - IOT_TIMER_INVALID_VALUE if + * - pxTimerHandle is NULL. + * - pxTimerHandle not open (previously closed). + */ +int32_t iot_timer_close( IotTimerHandle_t const pxTimerHandle ); + +/** + * @} + */ + +#endif /* ifndef _IOT_TIMER_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_tsensor.h b/libraries/abstractions/common_io/include/iot_tsensor.h new file mode 100644 index 00000000000..01ecbe96e6c --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_tsensor.h @@ -0,0 +1,223 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_tsensor.h + * @brief File for the APIs of TempSensor called by application layer. + */ + +#ifndef _IOT_TSENSOR_H_ +#define _IOT_TSENSOR_H_ + +/** + * @defgroup iot_tsensor TempSensor Abstraction APIs. + * @{ + */ + +#include + +/** + * @brief Return values used by tsensor driver + */ +#define IOT_TSENSOR_SUCCESS ( 0 ) /*!< TempSensor operation completed successfully.*/ +#define IOT_TSENSOR_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid.*/ +#define IOT_TSENSOR_DISABLED ( 2 ) /*!< TempSensor is disabled.*/ +#define IOT_TSENSOR_CLOSED ( 3 ) /*!< TempSensor instance is not open.*/ +#define IOT_TSENSOR_GET_TEMP_FAILED ( 4 ) /*!< TempSensor failed to get the temperature.*/ +#define IOT_TSENSOR_SET_FAILED ( 5 ) /*!< TempSensor set threshold operation failed.*/ +#define IOT_TSENSOR_NOT_SUPPORTED ( 6 ) /*!< TempSensor operation not supported.*/ + +/** + * @brief tsensor threshold reached status + */ +typedef enum +{ + eTsensorMinThresholdReached, /*!< min temperature threshold reached status */ + eTsensorMaxThresholdReached /*!< max temperature threshold reached status */ +} IotTsensorStatus_t; + +/** + * @brief Ioctl request types. + */ +typedef enum +{ + eTsensorSetMinThreshold, /*!< Set min temperature threshold using IotI2CIoctlConfig_t. Takes int32_t value in degrees celcius.*/ + eTsensorSetMaxThreshold, /*!< Set max temperature threshold using IotI2CIoctlConfig_t . Takes int32_t value in degrees celcius.*/ + eTsensorGetMinThreshold, /*!< Get min temperature threshold using IotI2CIoctlConfig_t. Returns int32_t value in degrees celcius.*/ + eTsensorGetMaxThreshold, /*!< Get max temperature threshold using IotI2CIoctlConfig_t. Returns int32_t value in degrees celcius.*/ + eTsensorPerformCalibration /*!< Perform calibration of the sensor */ +} IotTsensorIoctlRequest_t; + +/** + * @brief tsensor descriptor type defined in the source file. + */ +struct IotTsensorDescriptor_t; + +/** + * @brief IotTsensorHandle_t type is the tsensor handle returned by calling iot_tsensor_open() + * this is initialized in open and returned to caller. Caller must pass this pointer + * to the rest of the APIs. + */ +typedef struct IotTsensorDescriptor_t * IotTsensorHandle_t; + +/** + * @brief The callback function for completion of Tsensor operation. + * + * @param[in] xStatus tsensor threshold reached status + * @param[in] pvUserContext user provid context + */ +typedef void ( * IotTsensorCallback_t)( IotTsensorStatus_t xStatus, + void * pvUserContext ); + +/** + * @brief iot_tsensor_open is used to initialize the temperature sensor. + * It sets up the clocks and power etc, if the sensor is internal + * and sets up the communication channel if the sensor is external. + * + * @param[in] lTsensorInstance The instance of the tsensor to initialize. The instance + * number is platform specific. i,e if you have more than one temperature + * ensors, then 2 instances point to 2 different sensors. + * + * @return + * - Handle to tsensor interface on success. + * - NULL if + * - lTesnsorInstance is invalid. + * - instance is already open. + */ +IotTsensorHandle_t iot_tsensor_open( int32_t lTsensorInstance ); + +/** + * @brief Set the callback to be called when a threshold is reached on the sensor. + * The caller must set the threshold level using IOCTL before the callback can be called. + * + * @note Single callback is used per instance for both min and max threshold points being reached. + * @note Newly set callback overrides the one previously set + * + * @warning If input handle or if callback function is NULL, this function silently takes no action. + * + * @warning If threshold detection is not supported by the hardware, then the callback function will not work. + * + * @param[in] xTsensorHandle Handle to tsensor driver returned in open() call + * @param[in] xCallback The callback function to be called on completion of transaction. + * @param[in] pvUserContext user provid context + */ +void iot_tsensor_set_callback( IotTsensorHandle_t const xTsensorHandle, + IotTsensorCallback_t xCallback, + void * pvUserContext ); + +/** + * @brief iot_tsensor_enable is used to enable the temperature sensor + * to start reading the temperature and trigger thresholds (if any were set and supported) + * + * @param[in] xTsensorHandle Handle to tsensor driver returned in + * iot_tsensor_open + * + * @return + * - IOT_TSENSOR_SUCCESS on success + * - IOT_TSENSOR_INVALID_VALUE if xTsensorHandle is NULL. + */ +int32_t iot_tsensor_enable( IotTsensorHandle_t const xTsensorHandle ); + +/** + * @brief iot_tsensor_disable is used to disable the temperature sensor + * which stops monitoring the temperature. + * + * @param[in] xTsensorHandle Handle to tsensor driver returned in + * iot_tsensor_open + * + * @return + * - IOT_TSENSOR_SUCCESS on success + * - IOT_TSENSOR_INVALID_VALUE if xTsensorHandle is NULL. + */ +int32_t iot_tsensor_disable( IotTsensorHandle_t const xTsensorHandle ); + +/** + * @brief iot_tsensor_get_temp is used to get the current temperature + * read from the sensor. + * + * @param[in] xTsensorHandle handle to tsensor driver returned in + * iot_tsensor_open + * @param[out] plTemp temperature read from the sensor. + * + * @return + * - IOT_TSENSOR_SUCCESS on success + * - IOT_TSENSOR_INVALID_VALUE if + * - xTsensorHandle is NULL + * - lTemp is NULL + * - IOT_TSENSOR_DISABLED if tsensor instance has been disabled with call to iot_tsensor_disable(). + * - IOT_TSENSOR_GET_TEMP_FAILED if error occured reading the temperature. + */ +int32_t iot_tsensor_get_temp( IotTsensorHandle_t const xTsensorHandle, + int32_t * plTemp ); + +/** + * @brief iot_tsensor_ioctl is used to set tsensor configuration + * and tsensor properties like minimum threshold, maximum threshold value, etc. + * Supported IOCTL requests are defined in aws_hal_Tsensor_Ioctl_Request_t + * + * @param[in] xTsensorHandle handle to tsensor driver returned in + * iot_tsensor_open + * @param[in] xRequest configuration request. + * @param[in,out] pvBuffer buffer holding tsensor set and get values. + * + * @return + * - IOT_TSENSOR_SUCCESS on success + * - IOT_TSENSOR_INVALID_VALUE + * - xTsensorHandle is NULL + * - xRequest is invalid + * - pvBuffer is NULL (excluding eTsensorPerformCalibration) + * - IOT_TSENSOR_CLOSED if instance not in open state. + * - IOT_TSENSOR_DISABLED if tsensor instance has been disabled with call to iot_tsensor_disable(). + * - IOT_TSENSOR_GET_TEMP_FAILED if error occured reading the temperature. + * - IOT_TSENSOR_SET_FAILED if set threshold operation failed. + * - IOT_TSENSOR_NOT_SUPPORTED valid if xRequest feature not supported. + * @note: If eTsensorSetMinThreshold or eTsensorSetMaxThreshold ioctl is supported, then the + * corresponding eTsensorGetMinThreshold and eTsensorGetMaxThreshold must also be supported. + */ +int32_t iot_tsensor_ioctl( IotTsensorHandle_t const xTsensorHandle, + IotTsensorIoctlRequest_t xRequest, + void * const pvBuffer ); + +/** + * @brief iot_tsensor_close is used to de-initialize Tsensor. + * + * @param[in] xTsensorHandle handle to tsensor driver returned in + * iot_tsensor_open + * + * @return + * - IOT_TSENSOR_SUCCESS on success + * - IOT_TSENSOR_INVALID_VALUE if + * - xTensorHandle is NULL + * - not in open state (already closed) + */ +int32_t iot_tsensor_close( IotTsensorHandle_t const xTsensorHandle ); + + +/** + * @} + */ +/* end of group iot_tsensor */ + +#endif /* ifndef _IOT_TSENSOR_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_uart.h b/libraries/abstractions/common_io/include/iot_uart.h new file mode 100644 index 00000000000..64a71de5a5e --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_uart.h @@ -0,0 +1,410 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_uart.h + * @brief File for the HAL APIs of UART called by application layer. + */ +#ifndef _IOT_UART_H_ +#define _IOT_UART_H_ + +/* Standard includes. */ +#include +#include + +/** + * @defgroup IOT_UART UART Abstraction APIs. + * @{ + */ + +/** + * @brief The default baud rate for a given UART port. + */ +#define IOT_UART_BAUD_RATE_DEFAULT ( 115200 ) + +/** + * @brief Error codes returned by every function module in UART HAL. + */ +#define IOT_UART_SUCCESS ( 0 ) /*!< UART operation completed successfully. */ +#define IOT_UART_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid. */ +#define IOT_UART_WRITE_FAILED ( 2 ) /*!< UART driver returns error when performing write operation. */ +#define IOT_UART_READ_FAILED ( 3 ) /*!< UART driver returns error when performing read operation. */ +#define IOT_UART_BUSY ( 4 ) /*!< UART bus is busy at current time. */ +#define IOT_UART_NOTHING_TO_CANCEL ( 5 ) /*!< No ongoing operation when cancel is performed. */ +#define IOT_UART_FUNCTION_NOT_SUPPORTED ( 6 ) /*!< UART operation is not supported. */ + +/** + * @brief UART read/write operation status values + */ +typedef enum +{ + eUartCompleted = IOT_UART_SUCCESS, /*!< UART operation completed successfully. */ + eUartLastWriteFailed = IOT_UART_WRITE_FAILED, /*!< UART driver returns error when performing write operation. */ + eUartLastReadFailed = IOT_UART_READ_FAILED, /*!< UART driver returns error when performing read operation. */ +} IotUARTOperationStatus_t; + +/** + * @brief UART parity mode + */ +typedef enum +{ + eUartParityNone, /*!< UART parity as none. */ + eUartParityOdd, /*!< UART parity as odd. */ + eUartParityEven, /*!< UART parity as even. */ +} IotUARTParity_t; + +/** + * @brief UART stop bits + */ +typedef enum +{ + eUartStopBitsOne, /*!< UART stop bits is 1. */ + eUartStopBitsTwo, /*!< UART stop bits is 2. */ +} IotUARTStopBits_t; + +/** + * @brief The callback function for completion of UART operation. + * + * @param[out] xStatus UART asynchronous operation status. + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used or modified by the driver. The context + * is provided by the caller when setting the callback, and is + * passed back to the caller in the callback. + */ +typedef void ( * IotUARTCallback_t )( IotUARTOperationStatus_t xStatus, + void * pvUserContext ); + + +/** + * @brief The UART descriptor type defined in the source file. + */ +struct IotUARTDescriptor_t; + +/** + * @brief IotUARTHandle_t is the handle type returned by calling iot_uart_open(). + * This is initialized in open and returned to caller. The caller must pass + * this pointer to the rest of APIs. + */ +typedef struct IotUARTDescriptor_t * IotUARTHandle_t; + +/** + * @brief Ioctl requests for UART HAL. + */ +typedef enum +{ + eUartSetConfig, /** Sets the UART configuration according to @IotUARTConfig_t. */ + eUartGetConfig, /** Gets the UART configuration according to @IotUARTConfig_t. */ + eGetTxNoOfbytes, /** Get the number of bytes sent in write operation. */ + eGetRxNoOfbytes /** Get the number of bytes received in read operation. */ +} IotUARTIoctlRequest_t; + +/** + * @brief Configuration parameters for the UART. + * + * The application will send the user configuration in the form of the + * following structure in ioctl. + */ +typedef struct +{ + uint32_t ulBaudrate; /**< The baud rate to be set for the UART port. */ + IotUARTParity_t xParity; /**< The parity to be set for the UART port, defined in IotUARTParity_t. */ + IotUARTStopBits_t xStopbits; /**< The stop bits to be set for the UART port, defined in IotUARTStopBits_t. */ + uint8_t ucWordlength; /**< The word length to be set for the UART port. */ + uint8_t ucFlowControl; /**< The flow control to be set for the UART port: 0 is disabled and 1 is enabled. */ +} IotUARTConfig_t; + +/** + * @brief Initializes the UART peripheral of the board. + * + * The application should call this function to initialize the desired UART port. + * + * @warning Once opened, the same UART instance must be closed before calling open again. + * + * @param[in] lUartInstance The instance of the UART port to initialize. + * + * @return + * - 'the handle to the UART port (not NULL)', on success. + * - 'NULL', if + * - invalid instance number + * - open same instance more than once before closing it + * + * Example + * @code{c} + * // These two buffers can contain 32 bytes for reading and writing. + * uint8_t cpBuffer[ 32 ] = { 0 }; + * uint8_t cpBufferRead[ 32 ] = { 0 }; + * + * IotUARTHandle_t xOpen; + * int32_t lRead, lWrite, lClose; + * BaseType_t xCallbackReturn; + * uint8_t ucPort = 1; /* Each UART peripheral will be assigned an integer. + * + * xOpen = iot_uart_open( ucPort ); + * if( xOpen != NULL ) + * { + * iot_uart_set_callback( xOpen, prvReadWriteCallback, NULL ); + * + * lWrite = iot_uart_write_async( xOpen, cpBuffer, testIotUART_READ_BUFFER_LENGTH ); + * // assert(IOT_UART_SUCCESS, lWrite) + * // Wait for asynchronous write to complete + * xCallbackReturn = xSemaphoreTake( ( SemaphoreHandle_t ) &xUartSemaphore, IotUART_DEFAULT_SEMPAHORE_DELAY ); + * // assert(xCallbackReturn, pdTrue) + * + * lRead = iot_uart_read_async( xOpen, cpBufferRead, testIotUART_READ_BUFFER_LENGTH ); + * // assert(IOT_UART_SUCCESS, lRead) + * + * // Wait for asynchronous read to complete + * xCallbackReturn = xSemaphoreTake( ( SemaphoreHandle_t ) &xUartSemaphore, IotUART_DEFAULT_SEMPAHORE_DELAY ); + * // assert(xCallbackReturn, pdTrue) + * } + * + * lClose = iot_uart_close( xOpen ); + * // assert(IOT_UART_SUCCESS, lClose) + * @endcode + */ +IotUARTHandle_t iot_uart_open( int32_t lUartInstance ); + +/** + * @brief Sets the application callback to be called on completion of an operation. + * + * The callback is guaranteed to be invoked when the current asynchronous operation completes, either successful or failed. + * This simply provides a notification mechanism to user's application. It has no impact if the callback is not set. + * + * @note This callback will not be invoked when synchronous operation completes. + * @note This callback is per handle. Each instance has its own callback. + * @note Single callback is used for both read_async and write_async. Newly set callback overrides the one previously set. + * @warning If the input handle is invalid, this function silently takes no action. + * + * @param[in] pxUartPeripheral The peripheral handle returned in the open() call. + * @param[in] xCallback The callback function to be called on completion of transaction (This can be NULL). + * @param[in] pvUserContext The user context to be passed back when callback is called (This can be NULL). + */ +void iot_uart_set_callback( IotUARTHandle_t const pxUartPeripheral, + IotUARTCallback_t xCallback, + void * pvUserContext ); + +/** + * @brief Starts receiving the data from UART synchronously. + * + * This function attempts to read certain number of bytes from transmitter device to a pre-allocated buffer, in synchronous way. + * Partial read might happen, e.g. no more data is available. + * And the number of bytes that have been actually read can be obtained by calling iot_uart_ioctl. + * + * @note If the number of bytes is not known, it is recommended that the application reads one byte at a time. + * + * @warning None of other read or write functions shall be called during this function. + * + * @param[in] pxUartPeripheral The peripheral handle returned in the open() call. + * @param[out] pvBuffer The buffer to store the received data. + * @param[in] xBytes The number of bytes to read. + * + * @return IOT_UART_SUCCESS on successful completion of synchronous read, + * else one of the IOT_UART_INVALID_VALUE, IOT_UART_BUSY, IOT_UART_READ_FAILED on error. + * @return + * - IOT_UART_SUCCESS, on success (all the requested bytes have been read) + * - IOT_UART_INVALID_VALUE, if + * - pxUartPeripheral is NULL + * - pxUartPeripheral is not opened yet + * - pucBuffer is NULL + * - xBytes is 0 + * - IOT_UART_READ_FAILED, if there is unknown driver error + * - IOT_UART_BUSY, if the bus is busy which means there is an ongoing operation. + */ +int32_t iot_uart_read_sync( IotUARTHandle_t const pxUartPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the transmission of data from UART synchronously. + * + * This function attempts to write certain number of bytes from a pre-allocated buffer to a receiver device, in synchronous way. + * Partial write might happen, e.g. receiver device unable to receive more data. + * And the number of bytes that have been actually written can be obtained by calling iot_uart_ioctl. + * + * @warning None of other read or write functions shall be called during this function. + * + * @param[in] pxUartPeripheral The peripheral handle returned in the open() call. + * @param[in] pvBuffer The buffer with data to transmit. + * @param[in] xBytes The number of bytes to send. + * + * @return + * - IOT_UART_SUCCESS, on success (all the requested bytes have been write) + * - IOT_UART_INVALID_VALUE, if + * - pxUartPeripheral is NULL + * - pxUartPeripheral is not opened yet + * - pucBuffer is NULL + * - xBytes is 0 + * - IOT_UART_WRITE_FAILED, if there is unknown driver error + * - IOT_UART_BUSY, if the bus is busy which means there is an ongoing operation. + */ +int32_t iot_uart_write_sync( IotUARTHandle_t const pxUartPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts receiving the data from UART asynchronously. + * + * 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_uart_ioctl. + * Once the operation completes, successful or not, the user callback will be invoked. + * + * Partial read might happen. + * And the number of bytes that have been actually read can be obtained by calling iot_uart_ioctl. + * + * @note In order to get notification when the asynchronous call is completed, iot_uart_set_callback must be called prior to this. + * @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] pxUartPeripheral The peripheral handle returned in the open() call. + * @param[out] pvBuffer The buffer to store the received data. + * @param[in] xBytes The number of bytes to read. + * + * @return + * - IOT_UART_SUCCESS, on success + * - IOT_UART_INVALID_VALUE, if + * - pxUartPeripheral is NULL + * - pxUartPeripheral is not opened yet + * - pucBuffer is NULL + * - xBytes is 0 + * - IOT_UART_READ_FAILED, if there is unknown driver error + */ +int32_t iot_uart_read_async( IotUARTHandle_t const pxUartPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the transmission of data from UART asynchronously. + * + * This function attempts to write certain number of bytes from a pre-allocated buffer to a receiver device, in asynchronous way. + * It returns immediately when the operation is started and the status can be check by calling iot_uart_ioctl. + * Once the operation completes, successful or not, the user callback will be invoked. + * + * Partial write might happen. + * And the number of bytes that have been actually written can be obtained by calling iot_uart_ioctl. + * + * @note In order to get notification when the asynchronous call is completed, iot_uart_set_callback must be called prior to this. + * + * @warning None of other read or write functions shall be called during this function. + * + * @param[in] pxUartPeripheral The peripheral handle returned in the open() call. + * @param[in] pvBuffer The buffer with data to transmit. + * @param[in] xBytes The number of bytes to send. + * + * @return + * - IOT_UART_SUCCESS, on success + * - IOT_UART_INVALID_VALUE, if + * - pxUartPeripheral is NULL + * - pxUartPeripheral is not opened yet + * - pucBuffer is NULL + * - xBytes is 0 + * - IOT_UART_WRITE_FAILED, if there is unknown driver error + */ +int32_t iot_uart_write_async( IotUARTHandle_t const pxUartPeripheral, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Configures the UART port with user configuration. + * + * + * @note eUartSetConfig sets the UART configuration. + * This request expects the buffer with size of IotUARTConfig_t. + * + * @note eUartGetConfig gets the current UART configuration. + * This request expects the buffer with size of IotUARTConfig_t. + * + * @note eGetTxNoOfbytes returns the number of written bytes in last operation. + * This is supposed to be called in the caller task or application callback, right after last operation completes. + * This request expects 2 bytes buffer (uint16_t). + * + * - If the last operation was write, this returns the actual number of written bytes which might be smaller than the requested number (partial write). + * - If the last operation was read, this returns 0. + * + * @note eGetRxNoOfbytes returns the number of read bytes in last operation. + * This is supposed to be called in the caller task or application callback, right after last operation completes. + * This request expects 2 bytes buffer (uint16_t). + * + * - If the last operation was read, this returns the actual number of read bytes which might be smaller than the requested number (partial read). + * - If the last operation was write, this returns 0. + * + * @param[in] pxUartPeripheral The peripheral handle returned in the open() call. + * @param[in] xUartRequest The configuration request. Should be one of the values + * from IotUARTIoctlRequest_t. + * @param[in,out] pvBuffer The configuration values for the UART port. + * + * @return IOT_UART_SUCCESS on successful configuartion of UART port, + * else one of the IOT_UART_INVALID_VALUE, IOT_UART_BUSY, + * IOT_UART_FUNCTION_NOT_SUPPORTED on error. + * @return + * - IOT_UART_SUCCESS, on success + * - IOT_UART_INVALID_VALUE, if + * - pxUartPeripheral is NULL + * - pxUartPeripheral is not opened yet + * - pucBuffer is NULL with requests which needs buffer + * - IOT_UART_FUNCTION_NOT_SUPPORTED, if this board doesn't support this feature. + * - eUartSetConfig: specific configuration is not supported + */ +int32_t iot_uart_ioctl( IotUARTHandle_t const pxUartPeripheral, + IotUARTIoctlRequest_t xUartRequest, + void * const pvBuffer ); + +/** + * @brief Aborts the operation on the UART port if any underlying driver allows + * cancellation of the operation. + * + * The application should call this function to stop the ongoing operation. + * + * @param[in] pxUartPeripheral The peripheral handle returned in the open() call. + * + * @return + * - IOT_UART_SUCCESS, on success + * - IOT_UART_INVALID_VALUE, if + * - pxUartPeripheral is NULL + * - pxUartPeripheral is not opened yet + * - IOT_UART_NOTHING_TO_CANCEL, if there is no on-going transaction. + * - IOT_UART_FUNCTION_NOT_SUPPORTED, if this board doesn't support this operation. + */ +int32_t iot_uart_cancel( IotUARTHandle_t const pxUartPeripheral ); + +/** + * @brief Stops the operation and de-initializes the UART peripheral. + * + * + * @param[in] pxUartPeripheral The peripheral handle returned in the open() call. + * + * @return + * - IOT_UART_SUCCESS, on success + * - IOT_UART_INVALID_VALUE, if + * - pxUartPeripheral is NULL + * - pxUartPeripheral is not opened yet + */ +int32_t iot_uart_close( IotUARTHandle_t const pxUartPeripheral ); + + +/** + * @} + */ +/* end of group IOT_UART */ +#endif /* _IOT_UART_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_usb_device.h b/libraries/abstractions/common_io/include/iot_usb_device.h new file mode 100644 index 00000000000..6ffba254c41 --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_usb_device.h @@ -0,0 +1,568 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_usb_device.h + * @brief File for the APIs of USB device called by application or class layer. + */ +#ifndef _IOT_USB_DEVICE_H_ +#define _IOT_USB_DEVICE_H_ + +/** + * @brief Return values used by this driver + */ +#define IOT_USB_DEVICE_SUCCESS ( 0 ) /*!< USB operation completed successfully. */ +#define IOT_USB_DEVICE_ERROR ( 1 ) /*!< USB device error. */ +#define IOT_USB_DEVICE_BUSY ( 2 ) /*!< USB device busy. */ +#define IOT_USB_DEVICE_INVALID_VALUE ( 3 ) /*!< At least one parameter is invalid. */ +#define IOT_USB_DEVICE_WRITE_FAILED ( 4 ) /*!< USB device write operation failed. */ +#define IOT_USB_DEVICE_READ_FAILED ( 5 ) /*!< USB device read operation failed. */ +#define IOT_USB_DEVICE_FUNCTION_NOT_SUPPORTED ( 6 ) /*!< USB device function not supported. */ +#define IOT_USB_DEVICE_NOTHING_TO_CANCEL ( 7 ) /*!< No operation in progress to cancel. */ + +/** + * @brief Control endpoint index. + */ +#define IOT_USB_CONTROL_ENDPOINT ( 0U ) + +/** + * @brief The setup packet size of USB control transfer. + */ +#define IOT_USB_SETUP_PACKET_SIZE ( 8U ) + +/** + * @brief USB endpoint mask. + */ +#define IOT_USB_ENDPOINT_NUMBER_MASK ( 0x0FU ) + +/** + * @brief Default invalid value or the endpoint callback length of cancelled transfer. + */ +#define IOT_USB_UNINITIALIZED_VAL_32 ( 0xFFFFFFFFU ) + +/** + * @defgroup iot_usb_device usb device Abstraction APIs. + * @{ + */ + +/** + * @brief common notify event types in device callback. + */ +typedef enum +{ + eUSBDeviceBusResetEvent, /*!< USB bus reset signal detected. Signal is initiated from USB Host. */ + eUSBDeviceLPMState1Event, /*!< USB LPM (link power management) state 1 event: for usb 2.0, correspond to L1 sleep, host initialize + * LPM extended transaction; for usb 3.0, correspond to U1 standby, both device and host can initialize. */ + eUSBDeviceLPMState2Event, /*!< USB LPM state 2 event: for usb 2.0, correspond to L2 suspend, host nees to support to trigger it after + * 3ms of inactivity; for usb 3.0, correspond to U2 standby, both device and host can initialize. */ + eUSBDeviceLPMState3Event, /*!< USB LPM state 3 event: for usb 2.0, correspond to L3 off, disconnect or power off will trigger it; + * for usb 3.0, correspond to U3 suspend, it can only be initialized by host. */ + eUSBDeviceLPMState1ResumeEvent, /*!< USB resume event from LPM state 1: for usb 2.0 and 3.0, both device and host can initialize + * resume signaling. */ + eUSBDeviceLPMState2ResumeEvent, /*!< USB resume event from LPM state 2: for usb 2.0 and 3.0, both device and host can initialize + * resume signaling. */ + eUSBDeviceLPMState3ResumeEvent, /*!< USB resume event from LPM state 3: for usb 2.0, L3 is off state, port needs reset or power on; for usb 3.0, + * both device and host can initialize resume signaling.*/ + eUSBDeviceErrorEvent, /*!< An error is happened in the bus. */ + eUSBDeviceDetachEvent, /*!< USB device is disconnected from a host. */ + eUSBDeviceAttachEvent, /*!< USB device is connected to a host. */ +} IotUsbDeviceEvent_t; + +/** + * @brief Ioctl request types. + */ +typedef enum +{ + eUSBDeviceGetSpeed, /*!< Get device speed. Return uint8_t integer. */ + eUSBDeviceGetAddress, /*!< Get device address. Return an uint8_t integer range from 1~127. */ + eUSBDeviceSetAddress, /*!< Set device address. Take an uint8_t integer to set it as address. */ + eUSBDeviceGetEndpointStatus, /*!< Get endpoint status. Return IotUsbDeviceEndpointStatus_t type. */ + eUSBDeviceGetState, /*!< Get device state. Return IotUsbDeviceState_t. */ + eUSBDeviceGetStatus, /*!< Get device status. Return uint16_t. */ + eUSBDeviceGetSyncFrame, /*!< Get Sync frame. Returns the frame number of synchronization frame as uint16_t. */ + eUSBDeviceSetTestMode, /*!< Set device in test mode. For compliance testing defined in usb protocol. + * @warning Device needs to power cycle to exit test mode.*/ + eUSBDeviceSetState, /*!< Set device state. Take IotUsbDeviceState_t and set it*/ + eUSBDeviceLPMState1Suspend, /*!< Suspend usb to LPM state 1: for usb 2.0, it is L1 state; for usb 3.0, it is U1 state. */ + eUSBDeviceLPMState1Resume, /*!< Resume usb from LPM state 1: for usb 2.0, it is exit L1 state; for usb 3.0, it is exit U1 state. */ + eUSBDeviceLPMState2Suspend, /*!< Suspend usb to LPM state 2: for usb 2.0, it is L2 state; for usb 3.0, it is U2 state. */ + eUSBDeviceLPMState2Resume, /*!< Resume usb from LPM state 2: for usb 2.0, it is exit L2 state; for usb 3.0, it is exit U2 state. */ + eUSBDeviceLPMState3Suspend, /*!< Suspend usb to LPM state 3: for usb 2.0, it is L3 state; for usb 3.0, it is U3 state. */ + eUSBDeviceLPMState3Resume, /*!< Resume usb from LPM state 3: for usb 2.0, it is exit L3 state; for usb 3.0, it is exit U3 state. */ + eUSBDeviceRemoteWakeup, /*!< Remote wakeup host. */ +} IotUsbDeviceIoctlRequest_t; + +/** + * @brief USB device state. + */ +typedef enum +{ + eUsbDeviceStateConfigured, /*!< Device state, usb device is configured and ready for use by host*/ + eUsbDeviceStateAddress, /*!< Device state, usb device Address assigned*/ + eUsbDeviceStateDefault, /*!< Device state, usb device is reset, but address not assigned yet*/ + eUsbDeviceStateAddressing, /*!< Device state, usb device is undergoing assigning address*/ + eUsbDeviceStateTestMode, /*!< Device state, usb device is in test mode*/ +} IotUsbDeviceState_t; + +/** + * @brief Defines endpoint state. + */ +typedef enum +{ + eUsbDeviceEndpointStateIdle, /*!< Endpoint state, idle*/ + eUsbDeviceEndpointStateStalled, /*!< Endpoint state, stalled*/ + eUsbDeviceEndpointStateBusy, /*!< Endpoint state, busy*/ + eUsbDeviceEndpointStateClosed, /*!< Endpoint state, Closed, not configured*/ +} IotUsbDeviceEndpointStatus_t; + +/** + * @brief Define device controller ID. + */ +typedef enum +{ + eUsbDeviceControllerOHCI, /*!< Open Device Controller Interface */ + eUsbDeviceControllerUHCI, /*!< Universal Device Controller Interface */ + eUsbDeviceControllerEHCI, /*!< Enhanced Device Controller Interface */ + eUsbDeviceControllerXHCI, /*!< Extensible Device Controller Interface */ +} IotUsbHostController_t; + +/** + * @brief USB device driver operation status. + */ +typedef enum +{ + eUsbDeviceCompleted = IOT_USB_DEVICE_SUCCESS, /*!< Device operation completed successfully. */ + eUsbDeviceReadFailed = IOT_USB_DEVICE_READ_FAILED, /*!< Device read operation failed. */ + eUsbDeviceWriteFailed = IOT_USB_DEVICE_WRITE_FAILED, /*!< Device write operation failed. */ +} IotUsbDeviceOperationStatus_t; + +/** + * @brief The USB device type defined in the source file. + */ +struct IotUsbDevice; + +/** + * @brief IotUsbDeviceHandle_t is the handle type returned by calling iot_usb_device_open(). + * This is initialized in open and returned to caller. The caller must pass + * this pointer to the rest of APIs. + */ +typedef struct IotUsbDevice * IotUsbDeviceHandle_t; + +/** + * @brief The callback function for USB device event operation. This callback is passed to + * driver by using iot_usb_device_set_callback API. It's called when one of the events + * (IotUsbDeviceEvent_t) happen. This callback is used by upper layer to set up upper layer + * callback by calling iot_usb_device_set_device_callback. It is used when the bus state changes + * and an event is generated, e.g. an bus reset event happened, usb class layer needs to know such + * event and react accordingly. + * + * @param[in] pxUsbDevice The usb device peripheral handle returned in the open() call. + * @param[in] ulDeviceEvent USB device asynchronous event. + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used or modified by the driver. The context + * is provided by the caller when setting the callback, and is + * passed back to the caller in the callback. + * + */ +typedef int32_t (* IotUsbDeviceCallback_t) ( IotUsbDeviceHandle_t const pxUsbDevice, + uint32_t ulDeviceEvent, + void * pvUserContext ); + +/** + * @brief The callback typedef for USB device endpoint. For each endpoint, it's passed when user + * set endpoint callback by iot_usb_device_set_endpoint_callback API. + * This callback is used to notify the upper layer about the endpoint tranafer result. + * + * @param[out] xStatus Usb device asynchronous operation status. + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used or modified by the driver. The context + * is provided by the caller when setting the callback, and is + * passed back to the caller in the callback. + * + */ +typedef int32_t (* IotUsbDeviceEndpointCallbackFn_t) ( IotUsbDeviceOperationStatus_t xStatus, + void * pvUserContext ); + +/** + * @brief Endpoint configuration structure. + */ +typedef struct +{ + uint16_t usMaxPacketSize; /*!< Endpoint maximum packet size. Depends on the USB controller + * Control Transfer: + * Full Speed: 8, 16, 32, 64 + * High Speed: 64 + * Low Speed: 8 + * Isochronous Transfer: + * Full Speed: 1023 + * High Speed: 1024 + * Not supported for low speed device + * Interrupt Transfer: + * Full Speed: 64 + * High Speed: 1024 + * Low Speed: 8 + * Bulk Transfer: + * Full Speed: 8, 16, 32, 64 + * High Speed: 512 + * Not supported for low speed device */ + uint8_t ucEndpointAddress; /*!< Endpoint address*/ + uint8_t ucTransferType; /*!< Endpoint transfer type defined as: control EP is 0; + * Isochronous EP is 1; Bulk EP is 2; Interrupt EP is 3. */ + uint8_t ucZlt; /*!< ZLT flag*/ + uint8_t ucInterval; /*!< Endpoint polling interval of transfer*/ +} IotUsbDeviceEndpointConfig_t; + +/** + * @brief Endpoint status structure. + */ +typedef struct +{ + uint8_t ucEndpointAddress; /*!< Endpoint address */ + uint16_t usEndpointStatus; /*!< Endpoint status: IotUsbDeviceEndpointStatus_t*/ +} IotUsbDeviceEndpointInfo_t; + +/** + * @brief Initiates the usb device controller interface. + * + * @lUsbDeviceControllerInstance The instance of USB device controller to initialize. + * + * @return + * - The handle to the USB device if SUCCESS + * - NULL if + * - invalid lUsbDeviceControllerInstance + * - already open + */ +IotUsbDeviceHandle_t iot_usb_device_open( int32_t lUsbDeviceControllerInstance ); + +/** + * @brief Connect the USB device. + * + * The function enables the device functionality, so that the device can be recognized + * by the host when the device detects that it has been connected to a host. + * + * @warning this function must be called in order for USB to be recognized + * but not necessarily enumerated which requires the class to exchange control packets. + * + * @param[in] pxUsbDevice The usb device peripheral handle returned in the open() call. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if pxUsbDevice is NULL. + */ +int32_t iot_usb_device_connect( IotUsbDeviceHandle_t const pxUsbDevice ); + +/** + * @brief Disconnect the USB device. + * + * The function disables the device functionality, after this function called, even the + * device is attached to the host, and the device can't work. + * + * @param[in] pxUsbDevice The usb device peripheral handle returned in the open() call. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if pxUsbDevice is NULL. + */ +int32_t iot_usb_device_disconnect( IotUsbDeviceHandle_t const pxUsbDevice ); + +/** + * @brief Sets the application callback to be called on device event. + * + * @note Single callback is used, per instance. + * @note Newly set callback overrides the one previously set + * + * @warning If input handle or if callback function is NULL, this function silently takes no action. + * + * @param[in] pxUsbDevice The usb device peripheral handle returned in the open() call. + * @param[in] xCallback The callback function to be called on device event. + * @param[in] pvUserContext The user context to be passed back when callback is called. + */ +void iot_usb_device_set_device_callback( IotUsbDeviceHandle_t const pxUsbDevice, + IotUsbDeviceCallback_t xCallback, + void * pvUserContext ); + +/** + * @brief Initiates the usb device specific endpoint. + * + * @warning: Its the class codes responsibility to make sure the endpoint address is only opened once. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] pxEpConfig Endpoint configuration. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - pxEpConfig is NULL. + * - endpoint address is already open + * - endpoint config parameter is not supported + * - endpoint address is invalid + * - IOT_USB_DEVICE_ERROR if an error occurred with the device + */ +int32_t iot_usb_device_endpoint_open( IotUsbDeviceHandle_t const pxUsbDevice, + IotUsbDeviceEndpointConfig_t * pxEpConfig ); + +/** + * @brief Sets the endpoint callback to be called on endpoint transfer. + * + * @note Single callback is used, per instance. + * @note Newly set callback overrides the one previously set + * + * @warning If input handle or if callback function is NULL, or invalid EndpointAddress issued, + * this function silently takes no action. + * + * @param[in] pxUsbDevice The usb device peripheral handle returned in the open() call. + * @param[in] ucEndpointAddress Endpoint Address. + * @param[in] xCallback The callback function to be called on endpoint transfer. + * @param[in] pvUserContext The user context to be passed back when callback is called. + */ +void iot_usb_device_set_endpoint_callback( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress, + IotUsbDeviceEndpointCallbackFn_t xCallback, + void * pvUserContext ); + +/** + * @brief De-initializes the usb device specific endpoint. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint Address. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + */ +int32_t iot_usb_device_endpoint_close( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress ); + +/** + * @brief Stall the usb device specific endpoint. + * This function is to set stall conditions for the specific endpoint. + * The STALL packet indicates that the endpoint has halted, or a control pipe + * does not support a certain request. + * A function uses the STALL handshake packet to indicate that it is unable to + * transmit or receive data. Besides the default control pipe, all of a function's + * endpoints are in an undefined state after the device issues a STALL handshake + * packet. The host must never issue a STALL handshake packet. + * Typically, the STALL handshake indicates a functional stall. A functional + * stall occurs when the halt feature of an endpoint is set. In this circumstance, + * host intervention is required via the default control pipe to clear the halt + * feature of the halted endpoint. Less often, the function returns a STALL + * handshake during a SETUP or DATA stage of a control transfer. This is called a + * protocol stall and is resolved when the host issues the next SETUP transaction + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint Address. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + */ +int32_t iot_usb_device_endpoint_stall( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress ); + +/** + * @brief Unstall the usb device specific endpoint. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint Address. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + */ +int32_t iot_usb_device_endpoint_unstall( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress ); + +/** + * @brief Starts the USB device read operation in blocking mode. + * + * @note This function will block until all xBytes have been read. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint index + * @param[out] pvBuffer The receive buffer to read the data into + * @param[in] xBytes The number of bytes to read. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + * - pvBuffer is NULL + * - xBytes == 0 + * - IOT_USB_DEVICE_BUSY if another operation is in progress on the same endpoint. + * - IOT_USB_DEVICE_READ_FAILED if unable to complete the read operation + */ +int32_t iot_usb_device_read_sync( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the USB device write operation in blocking mode. + * + * note: this function will block until all xBytes have been written. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint index + * @param[out] pvBuffer The receive buffer to read the data into + * @param[in] xBytes The number of bytes to read. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + * - pvBuffer is NULL + * - xBytes == 0 + * - IOT_USB_DEVICE_BUSY if another operation is in progress on the same endpoint. + * - IOT_USB_DEVICE_WRITE_FAILED if unable to complete the write operation + */ +int32_t iot_usb_device_write_sync( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the USB device read operation in non-blocking mode. + * + * @note iot_usb_device_set_device_callback() must be called first in + * order for the callback function to be called to signal when the + * read is complete. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint index + * @param[out] pvBuffer The receive buffer to read the data into + * @param[in] xBytes The number of bytes to read. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + * - pvBuffer is NULL + * - xBytes == 0 + * - IOT_USB_DEVICE_BUSY if another operation is in progress on the same endpoint. + * - IOT_USB_DEVICE_READ_FAILED if unable to complete the read operation + */ +int32_t iot_usb_device_read_async( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Starts the USB device write operation in non-blocking mode. + * + * @note iot_usb_device_set_device_callback() must be called first in + * order for the callback function to be called to signal when the + * write is complete. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint index + * @param[out] pvBuffer The receive buffer to read the data into + * @param[in] xBytes The number of bytes to read. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + * - pvBuffer is NULL + * - xBytes == 0 + * - IOT_USB_DEVICE_BUSY if another operation is in progress on the same endpoint. + * - IOT_USB_DEVICE_WRITE_FAILED if unable to complete the write operation + */ +int32_t iot_usb_device_write_async( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress, + uint8_t * const pvBuffer, + size_t xBytes ); + +/** + * @brief Used for various USB device control function. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] xUsbDeviceRequest Should be one of IotUsbDeviceIoctlRequest_t. + * @param[in,out] pvBuffer The configuration values for the IOCTL request. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid xUsbDeviceRequest + * - IOT_USB_DEVICE_FUNCTION_NOT_SUPPORTED if ioctl request not suported. + * - Only valid for + * - eUSBDeviceSleepBus + * - eUSBDeviceSuspendBus + * - eUSBDeviceResumeBus + * - eUSBDeviceRemoteWakeup + * - eUSBDeviceGetSyncFrame + * - or other USB Error. + */ +int32_t iot_usb_device_ioctl( IotUsbDeviceHandle_t const pxUsbDevice, + IotUsbDeviceIoctlRequest_t xUsbDeviceRequest, + void * const pvBuffer ); + +/** + * @brief This function is used to cancel the pending transfer for given endpoint. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * @param[in] ucEndpointAddress Endpoint Address. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - invalid ucEndpointAddress + * - IOT_USB_DEVICE_FUNCTION_NOT_SUPPORTED if cancel transfer opertion not supported + * - IOT_USB_DEVICE_NOTHING_TO_CANCEL if nothing to cancel + */ +int32_t iot_usb_device_endpoint_cancel_transfer( IotUsbDeviceHandle_t const pxUsbDevice, + uint8_t ucEndpointAddress ); + +/** + * @brief Close the USB device peripheral. + * + * @param[in] pxUsbDevice The USB device handle returned in open() call. + * + * @return + * - IOT_USB_DEVICE_SUCCESS on success + * - IOT_USB_DEVICE_INVALID_VALUE if + * - pxUsbDevice is NULL. + * - pxUsbDevice not open (already closed). + */ +int32_t iot_usb_device_close( IotUsbDeviceHandle_t const pxUsbDevice ); + +/** + * @} + */ +/* end of group iot_usb_device */ + +#endif /* ifndef _IOT_USB_DEVICE_H_ */ diff --git a/libraries/abstractions/common_io/include/iot_watchdog.h b/libraries/abstractions/common_io/include/iot_watchdog.h new file mode 100644 index 00000000000..b52b7d1f627 --- /dev/null +++ b/libraries/abstractions/common_io/include/iot_watchdog.h @@ -0,0 +1,257 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_watchdog.h + * + * @brief HAL APIs for WatchDog driver + ******************************************************************************* + */ + +/** + * @file iot_watchdog.h + * @brief This file contains all the WatchDog HAL API definitions + */ + +#ifndef _IOT_WATCHDOG_H_ +#define _IOT_WATCHDOG_H_ + +/** + * @defgroup iot_watchdog WatchDog HAL APIs + * @{ + */ + +/** + * @brief Return values used by WatchDog driver + */ +#define IOT_WATCHDOG_SUCCESS ( 0 ) /*!< Watchdog operation completed successfully.*/ +#define IOT_WATCHDOG_INVALID_VALUE ( 1 ) /*!< At least one parameter is invalid.*/ +#define IOT_WATCHDOG_TIME_NOT_SET ( 2 ) /*!< Watchdog timeout value not set.*/ +#define IOT_WATCHDOG_FUNCTION_NOT_SUPPORTED ( 3 ) /*!< Watchdog operation not supported.*/ + +/** + * @brief WatchDog timer status values + */ +typedef enum +{ + eWatchdogTimerStopped, /*!< WatchDog is stopped */ + eWatchdogTimerRunning, /*!< WatchDog is running */ + eWatchdogTimerBarkExpired, /*!< WatchDog bark timer expired */ + eWatchdogTimerBiteExpired /*!< WatchDog bite timer expired */ +} IotWatchdogStatus_t; + +/** + * @brief WatchDog timer bite behavior setting + */ +typedef enum +{ + eWatchdogBiteTimerReset, /*!< Reset the device when WatchDog bite timer expires */ + eWatchdogBiteTimerInterrupt /*!< Generate Interrupt when WatchDog bite timer expires */ +} IotWatchdogBiteConfig_t; + +/** + * @brief WatchDog descriptor type defined in the source file. + */ +struct IotWatchdogDescriptor; + +/** + * @brief IotWatchdogHandle_t type is the WatchDog handle returned by calling iot_watchdog_open() + * this is initialized in open and returned to caller. Caller must pass this pointer + * to the rest of the APIs. + */ +typedef struct IotWatchdogDescriptor * IotWatchdogHandle_t; + +/** + * @brief Ioctl request types. + * + * @note BarkTime is the number of msec before a warning signaled in the form of an interrupt call to the + * set callback function. + * @note BiteTime is the number of msec before a critical condition is signaled in the form of an interrupt + * (If supported and configured), and usually ends with the system being reset. + * + * @warning the BarkTime must be less than or equal to the BiteTime + */ +typedef enum +{ + eSetWatchdogBarkTime, /*!< Set the WatchDog warning time (bark value) as uint32_t in msec. + * @warning The maximum value is limited to by the number of bits used for + * WatchDog counter in the HW. ex: at 24-bit Watchdog counter would have + * a maximum of 16,777,215 msec.*/ + eGetWatchdogBarkTime, /*!< Get the WatchDog warning time (bark value) as uint32_t in msec */ + eSetWatchdogBiteTime, /*!< Set the WatchDog expire time (bite value) as uint32_t in msec. + * @warning The maximum value is limited to by the number of bits used for + * WatchDog counter in the HW. ex: at 24-bit Watchdog counter would have + * a maximum of 16,777,215 msec.*/ + eGetWatchdogBiteTime, /*!< Get the WatchDog expire time (bite value) as uint32_t in msec */ + eGetWatchdogStatus, /*!< Returns the WatchDog timer status of type IotWatchdogStatus_t */ + eSetWatchdogBiteBehaviour /*!< Set the WatchDog bite behavior. Takes IotWatchdogBiteConfig_t type */ + /*!< @warning Not all platforms may support interrupt generation. */ +} IotWatchdogIoctlRequest_t; + +/** + * @brief WatchDog notification callback type. This callback is passed + * to the driver by using iot_watchdog_set_callback API. This callback is used for + * warning notification when the bark timer or bite timer expires based on the configuration. + * Caller can check the status of the WatchDog timer by using eGetStatus IOCTL + * + * @warning The callback will only be called if WatchdogBark is supported, or if WatchdogBite behavior + * is set to interrupt and is supported. + * + * @param[in] pvUserContext User Context passed when setting the callback. + * This is not used by the driver, but just passed back to the user + * in the callback. + */ +typedef void (* IotWatchdogCallback_t)( void * pvUserContext ); + +/** + * @brief iot_watchdog_open is used to initialize the WatchDog, + * This function will stop the timer if it was started and resets the timer + * if any was configured earlier. + * + * @param[in] lWatchdogInstance The instance of the WatchDog to initialize. + * + * @return + * - Handle to IotWatchdogHandle_t on success + * - NULL if + * - invalid lWatchdogInstance + * - instance is already open + */ +IotWatchdogHandle_t iot_watchdog_open( int32_t lWatchdogInstance ); + +/** + * @brief iot_watchdog_start is used to start the WatchDog timer counter. + * WatchDog expiry (bite) time must be set before starting the WatchDog counter. + * Set the bite time using eSetBiteTime IOCTL. + * + * @param[in] pxWatchdogHandle handle to WatchDog interface returned in + * iot_watchdog_open. + * + * @return + * - IOT_WATCHDOG_SUCCESS on success + * - IOT_WATCHDOG_INVALID_VALUE if pxWatchdogHandle is NULL + * - IOT_WATCHDOG_TIME_NOT_SET if bite time has not been set. + */ +int32_t iot_watchdog_start( IotWatchdogHandle_t const pxWatchdogHandle ); + +/** + * @brief iot_watchdog_stop is used to stop and resets the WatchDog timer counter. + * After stopping the timer and before starting the timer again, + * expireTime must be set. + * + * @param[in] pxWatchdogHandle handle to WatchDog interface returned in + * iot_watchdog_open. + * + * @return + * - IOT_WATCHDOG_SUCCESS on success + * - IOT_WATCHDOG_INVALID_VALUE if pxWatchdogHandle is NULL + * - IOT_WATCHDOG_NOT_SUPPORTED if stop operation not supported. + */ +int32_t iot_watchdog_stop( IotWatchdogHandle_t const pxWatchdogHandle ); + +/** + * @brief iot_watchdog_restart is used to restart the WatchDog timer to the + * originally programmed values. This function is usually used + * once the WatchDog timer (either bark or bite) expired and generated + * a callback, so caller can restart the timer to original values to restart + * the WatchDog timer. The main difference b/w iot_watchdog_start and iot_watchdog_restart + * APIs are, the former requires the time values are set using the IOCTLs and the latter + * re-uses the already programmed values and re-programs them. If restart_timer is used + * without first setting the timers, it will return an error. + * + * @param[in] pxWatchdogHandle handle to WatchDog interface returned in + * iot_watchdog_open. + * + * @return + * - IOT_WATCHDOG_SUCCESS on success + * - IOT_WATCHDOG_INVALID_VALUE if pxWatchdogHandle is NULL + * - IOT_WATCHDOG_TIME_NOT_SET if watchdog bark or bite time have not been set. + */ +int32_t iot_watchdog_restart( IotWatchdogHandle_t const pxWatchdogHandle ); + +/*! + * @brief iot_wathcdog_set_callback is used to set the callback to be called when + * bark time reaches the WatchDog counter or if the bite time is configured to + * generate interrupt (if supported by HW). The caller must set the timers using + * IOCTL and start the timer for the callback to be called back. + * Caller must restart the timer when bark timer expires and bite time is configured + * to reset the device to avoid the target reset. + * + * @note Single callback is used, per instance, if eWatchdogBiteTimerInterrupt has been configured or + * if the bark time reaches the WatchDog counter. + * @note Newly set callback overrides the one previously set + * + * @warning If input handle or if callback function is NULL, this function silently takes no action. + * + * @param[in] pxWatchdogHandle handle to WatchDog interface returned in + * iot_watchdog_open. + * @param[in] xCallback The callback function to be called. + * @param[in] pvUserContext The user context to be passed when callback is called. + */ +void iot_watchdog_set_callback( IotWatchdogHandle_t const pxWatchdogHandle, + IotWatchdogCallback_t xCallback, + void * pvUserContext ); + +/** + * @brief iot_watchdog_ioctl is used to configure the WatchDog timer properties + * like the WatchDog timeout value, WatchDog clock, handler for + * WatchDog interrupt etc. + * + * @param[in] pxWatchdogHandle handle to WatchDog interface returned in + * iot_watchdog_open. + * @param[in] xRequest configuration request of type IotFlashIoctlRequest_t + * @param[in,out] pvBuffer the configuration buffer to hold the request or response of IOCTL. + * + * @return + * - returns IOT_WATCHDOG_SUCCESS on success + * - IOT_WATCHDOG_INVALID_VALUE if + * - pxWatchdogHandle is NULL + * - xRequest is invalid + * - pvBuffer is NULL + * - IOT_WATCHDOG_TIME_NOT_SET on error + * - IOT_WATCHDOG_FUNCTION_NOT_SUPPORTED + */ +int32_t iot_watchdog_ioctl( IotWatchdogHandle_t const pxWatchdogHandle, + IotWatchdogIoctlRequest_t xRequest, + void * const pvBuffer ); + +/** + * @brief iot_watchdog_close is used to de-initializes the WatchDog, stops the timer + * if it was started and resets the timer value. + * + * @param[in] pxWatchdogHandle handle to WatchDog interface returned in + * iot_watchdog_open. + * @return + * - IOT_WATCHDOG_SUCCESS on success + * - IOT_WATCHDOG_INVALID_VALUE if + * - pxWatchdogHandle == NULL + * - pxWatchdogHandle is not open (previously closed). + */ +int32_t iot_watchdog_close( IotWatchdogHandle_t const pxWatchdogHandle ); + +/** + * @} + */ + +#endif /* ifndef _IOT_WATCHDOG_H_ */ diff --git a/libraries/abstractions/common_io/test/iot_test_common_io.c b/libraries/abstractions/common_io/test/iot_test_common_io.c new file mode 100644 index 00000000000..1d59a535adf --- /dev/null +++ b/libraries/abstractions/common_io/test/iot_test_common_io.c @@ -0,0 +1,66 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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 + */ + +/* Test framework includes. */ +#include "unity_fixture.h" + +#include "test_iot_internal.h" + +/* Define Test Group. */ +TEST_GROUP( Common_IO ); + +/*-----------------------------------------------------------*/ + +/** + * @brief Setup function called before each test in this group is executed. + */ +TEST_SETUP( Common_IO ) +{ +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Tear down function called after each test in this group is executed. + */ +TEST_TEAR_DOWN( Common_IO ) +{ +} + +/** + * @brief Function to define which tests to execute as part of this group. + */ +TEST_GROUP_RUNNER( Common_IO ) +{ + #if ( IOT_TEST_COMMON_IO_UART_SUPPORTED == 1 ) + SET_TEST_IOT_UART_CONFIG( 0 ); + RUN_TEST_GROUP( TEST_IOT_UART ); + #endif + + #if ( IOT_TEST_COMMON_IO_I2C_SUPPORTED == 1 ) + SET_TEST_IOT_I2C_CONFIG( 0 ); + RUN_TEST_GROUP( TEST_IOT_I2C ); + #endif +} diff --git a/libraries/abstractions/common_io/test/test_iot_i2c.c b/libraries/abstractions/common_io/test/test_iot_i2c.c new file mode 100644 index 00000000000..829eff12ea8 --- /dev/null +++ b/libraries/abstractions/common_io/test/test_iot_i2c.c @@ -0,0 +1,1241 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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_test_i2c.c + * @brief Functional Unit Test - I2C + ******************************************************************************* + */ + +#include "unity.h" +#include "unity_fixture.h" + +/* Driver includes */ +#include "iot_i2c.h" + +#include "FreeRTOS.h" +#include "semphr.h" + +/* Common IO config includes. */ +#include "test_iot_config.h" + +/*-----------------------------------------------------------*/ +#define testIotI2C_BAUDRATE IOT_I2C_FAST_MODE_BPS +#define testIotI2C_BAUDRATE_LOW_SPEED IOT_I2C_STANDARD_MODE_BPS +#define testIotI2C_INSTANCE uctestIotI2CInstanceIdx +#define testIotI2C_INSTANCE_NUM uctestIotI2CInstanceNum +#define testIotI2C_DEFAULT_TIMEOUT 500 /**< 500 msec */ +#define testIotI2C_FAST_TIMEOUT 100 /**< 100 msec */ +#define testIotI2C_INVALID_IOCTL_INDEX UINT32_MAX +#define testIotI2C_HANDLE_NUM 4 +#define testIotI2C_MAX_TIMEOUT pdMS_TO_TICKS( 10000 ) +/*-----------------------------------------------------------*/ + +typedef struct CallbackParam +{ + IotI2CHandle_t xHandle; + uint8_t * pucBuffer; + size_t xBufferSize; + uint32_t ulRet; +} CallbackParam_t; + +/*-----------------------------------------------------------*/ + +/* Globals values which can be overwritten by the test + * framework invoking these tests */ +/*-----------------------------------------------------------*/ + +uint8_t uctestIotI2CSlaveAddr = 0; /**< The slave address to be set for the I2C port. */ +uint8_t uctestIotI2CInvalidSlaveAddr = 0xFF; /**< The slave address to be set for the I2C port. */ +uint8_t xtestIotI2CDeviceRegister = 0; /**< The device register to be set for the I2C port. */ +uint8_t uctestIotI2CWriteVal = 0; /**< The write value to write to device. */ +uint8_t uctestIotI2CInstanceIdx = 0; /**< The current I2C test instance index */ +uint8_t uctestIotI2CInstanceNum = 1; /**< The total I2C test instance number */ + +extern IotI2CHandle_t gIotI2cHandle[ testIotI2C_HANDLE_NUM ]; + +/*-----------------------------------------------------------*/ +/* Static Globals */ +/*-----------------------------------------------------------*/ +static SemaphoreHandle_t xtestIotI2CSemaphore = NULL; + +/*-----------------------------------------------------------*/ +/* Private Functions */ +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/* Define Test Group. */ +TEST_GROUP( TEST_IOT_I2C ); + +/*-----------------------------------------------------------*/ + +/** + * @brief Setup function called before each test in this group is executed. + */ +TEST_SETUP( TEST_IOT_I2C ) +{ + IotI2CHandle_t xGlobalI2CHandle = gIotI2cHandle[ testIotI2C_INSTANCE ]; + int32_t lRetVal; + + /* Close global handle it was opened. */ + if( xGlobalI2CHandle != NULL ) + { + lRetVal = iot_i2c_close( xGlobalI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + gIotI2cHandle[ testIotI2C_INSTANCE ] = NULL; + } +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Tear down function called after each test in this group is executed. + */ +TEST_TEAR_DOWN( TEST_IOT_I2C ) +{ +} + +/*-----------------------------------------------------------*/ + +/** + * @brief user callback function + */ +void prvI2CCallback( IotI2COperationStatus_t xOpStatus, + void * pvParam ) +{ + BaseType_t xHigherPriorityTaskWoken; + + if( xOpStatus == eI2CCompleted ) + { + xSemaphoreGiveFromISR( xtestIotI2CSemaphore, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} + +static void prvChainToReadCallback( IotI2COperationStatus_t xOpStatus, + void * pvParam ) +{ + static uint8_t ucOps = 0; + + BaseType_t xHigherPriorityTaskWoken; + + CallbackParam_t * pxCallbackParam = ( CallbackParam_t * ) pvParam; + + if( xOpStatus == eI2CCompleted ) + { + /* Write. */ + if( ucOps == 0 ) + { + pxCallbackParam->ulRet = iot_i2c_read_async( pxCallbackParam->xHandle, pxCallbackParam->pucBuffer, pxCallbackParam->xBufferSize ); + ucOps++; + } + else + { + xSemaphoreGiveFromISR( xtestIotI2CSemaphore, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } + } +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Function to define which tests to execute as part of this group. + */ +TEST_GROUP_RUNNER( TEST_IOT_I2C ) +{ + xtestIotI2CSemaphore = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_EQUAL( NULL, xtestIotI2CSemaphore ); + + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2COpenCloseSuccess ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2COpenCloseFail ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2COpenCloseFailUnsupportInst ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CSetGetConfigurationSuccess ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CSetGetConfigurationFail ); + + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteSyncSuccess ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteSyncFail ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CReadSyncFail ); + + /* If it supports not sending stop condition. */ + #if ( IOT_TEST_COMMON_IO_I2C_SUPPORTED_SEND_NO_STOP == 1 ) + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CGetBusStateSuccess ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteThenReadSyncSuccess ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CReadAsyncFailIoctl ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CReadAsyncFailReadTwice ); + #endif + + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteAsyncSuccess ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteAsyncFailIoctl ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteAsyncFailWriteTwice ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CReadAsyncFailSetAddr ); + + /* If it supports not sending stop condition. */ + #if ( IOT_TEST_COMMON_IO_I2C_SUPPORTED_SEND_NO_STOP == 1 ) + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteThenReadAsyncSuccess ); + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CWriteThenReadChainSuccess ); + #endif + + /* If it supports cancel the current operation. */ + #if ( IOT_TEST_COMMON_IO_I2C_SUPPORTED_CANCEL == 1 ) + #if ( IOT_TEST_COMMON_IO_I2C_SUPPORTED_SEND_NO_STOP == 1 ) + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CCancelReadSuccess ); + #endif + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CCancelFail ); + #endif + + /* Unsupported tests. */ + #if ( IOT_TEST_COMMON_IO_I2C_SUPPORTED_SEND_NO_STOP != 1 ) + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CSendNoStopUnsupported ); + #endif + + #if ( IOT_TEST_COMMON_IO_I2C_SUPPORTED_CANCEL != 1 ) + RUN_TEST_CASE( TEST_IOT_I2C, AFQP_IotI2CCancelUnsupported ); + #endif +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test iot_i2c_open and iot_i2c_close. + */ +TEST( TEST_IOT_I2C, AFQP_IotI2COpenCloseSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test iot_i2c_open and iot_i2c_close fail case. + */ +TEST( TEST_IOT_I2C, AFQP_IotI2COpenCloseFail ) +{ + IotI2CHandle_t xI2CHandle; + IotI2CHandle_t xI2CHandle_1; + int32_t lRetVal; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + /* Open i2c to initialize hardware again */ + xI2CHandle_1 = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_EQUAL( NULL, xI2CHandle_1 ); + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Close same i2c again which is NULL */ + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_INVALID_VALUE, lRetVal ); + + /* Close i2c with NULL pointer */ + lRetVal = iot_i2c_close( xI2CHandle_1 ); + TEST_ASSERT_EQUAL( IOT_I2C_INVALID_VALUE, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test iot_i2c_open and iot_i2c_close with unsupported instance + */ +TEST( TEST_IOT_I2C, AFQP_IotI2COpenCloseFailUnsupportInst ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE_NUM ); + TEST_ASSERT_EQUAL( NULL, xI2CHandle ); + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_INVALID_VALUE, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C set and get configuration success + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CSetGetConfigurationSuccess ) +{ + IotI2CHandle_t xI2CHandle; + IotI2CConfig_t xI2CConfig_write; + IotI2CConfig_t xI2CConfig_read; + int32_t lRetVal; + + xI2CConfig_write.ulBusFreq = testIotI2C_BAUDRATE; + xI2CConfig_write.ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set default i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig_write ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Get i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetMasterConfig, &xI2CConfig_read ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Make sure get the correct config from i2c */ + TEST_ASSERT_EQUAL( testIotI2C_BAUDRATE, xI2CConfig_read.ulBusFreq ); + TEST_ASSERT_EQUAL( testIotI2C_DEFAULT_TIMEOUT, xI2CConfig_read.ulMasterTimeout ); + + xI2CConfig_write.ulBusFreq = testIotI2C_BAUDRATE_LOW_SPEED; + xI2CConfig_write.ulMasterTimeout = testIotI2C_FAST_TIMEOUT; + + /* Set new i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig_write ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Get new i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetMasterConfig, &xI2CConfig_read ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Make sure get the correct config from i2c */ + TEST_ASSERT_EQUAL( testIotI2C_BAUDRATE_LOW_SPEED, xI2CConfig_read.ulBusFreq ); + TEST_ASSERT_EQUAL( testIotI2C_FAST_TIMEOUT, xI2CConfig_read.ulMasterTimeout ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C set and get configuration fail + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CSetGetConfigurationFail ) +{ + IotI2CHandle_t xI2CHandle; + IotI2CConfig_t xI2CConfig; + int32_t lRetVal; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set default i2c configuration with NULL pointer */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_INVALID_VALUE, lRetVal ); + + /* Get i2c configuration with NULL pointer */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetMasterConfig, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_INVALID_VALUE, lRetVal ); + + /* i2c ioctl with unsupported request */ + lRetVal = iot_i2c_ioctl( xI2CHandle, testIotI2C_INVALID_IOCTL_INDEX, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_INVALID_VALUE, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C async read success + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteThenReadAsyncSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint16_t readBytes; + uint16_t writeBytes; + + uint8_t singleByte; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address for writing the device register */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c not stop between transaction */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the device register address. */ + lRetVal = iot_i2c_write_sync( xI2CHandle, &xtestIotI2CDeviceRegister, sizeof( xtestIotI2CDeviceRegister ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address to read from the device register. */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Read from i2c device for single byte. */ + lRetVal = iot_i2c_read_async( xI2CHandle, &singleByte, sizeof( singleByte ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetRxNoOfbytes, &readBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being read is 1. */ + TEST_ASSERT_EQUAL( sizeof( singleByte ), readBytes ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &writeBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being written is 1. */ + TEST_ASSERT_EQUAL( sizeof( xtestIotI2CDeviceRegister ), writeBytes ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C async read success + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteThenReadChainSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint16_t readBytes; + uint16_t writeBytes; + + uint8_t singleByte; + + CallbackParam_t xCallbackParam; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + xCallbackParam.xHandle = xI2CHandle; + xCallbackParam.pucBuffer = &singleByte; + xCallbackParam.xBufferSize = 1; + xCallbackParam.ulRet = 0; + + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvChainToReadCallback, &xCallbackParam ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address for writing the device register */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c not stop between transaction */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the device register address. */ + lRetVal = iot_i2c_write_async( xI2CHandle, &xtestIotI2CDeviceRegister, sizeof( xtestIotI2CDeviceRegister ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetRxNoOfbytes, &readBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being read is 1. */ + TEST_ASSERT_EQUAL( sizeof( singleByte ), readBytes ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &writeBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being written is 1. */ + TEST_ASSERT_EQUAL( sizeof( xtestIotI2CDeviceRegister ), writeBytes ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C async read fail to do ioctl + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CReadAsyncFailIoctl ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t ucBuffer[ 10 ]; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the device register address. */ + lRetVal = iot_i2c_write_sync( xI2CHandle, &xtestIotI2CDeviceRegister, sizeof( xtestIotI2CDeviceRegister ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* read from i2c device register */ + lRetVal = iot_i2c_read_async( xI2CHandle, ucBuffer, sizeof( ucBuffer ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration during transaction */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_BUSY, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C async read twice fail + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CReadAsyncFailReadTwice ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t ucBuffer[ 10 ]; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c congifuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the device register address. */ + lRetVal = iot_i2c_write_sync( xI2CHandle, &xtestIotI2CDeviceRegister, sizeof( xtestIotI2CDeviceRegister ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* read from i2c device */ + lRetVal = iot_i2c_read_async( xI2CHandle, ucBuffer, sizeof( ucBuffer ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* read from i2c device again */ + lRetVal = iot_i2c_read_async( xI2CHandle, ucBuffer, sizeof( ucBuffer ) ); + TEST_ASSERT_EQUAL( IOT_I2C_BUSY, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C read async fail. slave address and register not set. + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CReadAsyncFailSetAddr ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t ucReadValue; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* read from i2c device */ + lRetVal = iot_i2c_read_async( xI2CHandle, &ucReadValue, sizeof( ucReadValue ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SLAVE_ADDRESS_NOT_SET, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C cancel + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CCancelReadSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t readBuffer[ 64 ]; + + uint16_t readBytes; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c configuration. */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the device register address. */ + lRetVal = iot_i2c_write_sync( xI2CHandle, &xtestIotI2CDeviceRegister, sizeof( xtestIotI2CDeviceRegister ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* read from i2c device */ + lRetVal = iot_i2c_read_async( xI2CHandle, readBuffer, sizeof( readBuffer ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Cancel the transaction while the reading operation is in flight. */ + lRetVal = iot_i2c_cancel( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Assert the completion callback is NOT invoked. */ + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdFALSE, lRetVal ); + + uint8_t writeVal1[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal }; + + /* Write after cancel should also succeed. */ + lRetVal = iot_i2c_write_sync( xI2CHandle, writeVal1, sizeof( writeVal1 ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetRxNoOfbytes, &readBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Assert the number of bytes being read is less than requested. */ + TEST_ASSERT_LESS_THAN( sizeof( readBuffer ), readBytes ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C cancel fail + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CCancelFail ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* cancel transaction with NULL */ + lRetVal = iot_i2c_cancel( NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_INVALID_VALUE, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +TEST( TEST_IOT_I2C, AFQP_IotI2CCancelUnsupported ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* cancel transaction with NULL */ + lRetVal = iot_i2c_cancel( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_FUNCTION_NOT_SUPPORTED, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C async write + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteAsyncSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t writeVal1[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal }; + uint8_t writeVal2[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal, uctestIotI2CWriteVal, uctestIotI2CWriteVal }; + + uint16_t writeBytes; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the value to the device */ + lRetVal = iot_i2c_write_async( xI2CHandle, writeVal1, sizeof( writeVal1 ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &writeBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being written is 2. */ + TEST_ASSERT_EQUAL( sizeof( writeVal1 ), writeBytes ); + + /* write the value to the device */ + lRetVal = iot_i2c_write_async( xI2CHandle, writeVal2, sizeof( writeVal2 ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &writeBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being written is 4. */ + TEST_ASSERT_EQUAL( sizeof( writeVal2 ), writeBytes ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C async write fail to do ioctl + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteAsyncFailIoctl ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t writeVal[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c congifuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* wirte the value to the device */ + lRetVal = iot_i2c_write_async( xI2CHandle, writeVal, sizeof( writeVal ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c congifuration during transaction */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_BUSY, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C async write twice fail + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteAsyncFailWriteTwice ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t writeVal[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c configuration. */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the value to the device */ + lRetVal = iot_i2c_write_async( xI2CHandle, writeVal, sizeof( writeVal ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the value to the device again */ + lRetVal = iot_i2c_write_async( xI2CHandle, writeVal, sizeof( writeVal ) ); + TEST_ASSERT_EQUAL( IOT_I2C_BUSY, lRetVal ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C sync write then read, in same transaction. + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteThenReadSyncSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t singleByte; + + uint16_t readBytes; + uint16_t writeBytes; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT, + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the device register address. */ + lRetVal = iot_i2c_write_sync( xI2CHandle, &xtestIotI2CDeviceRegister, sizeof( xtestIotI2CDeviceRegister ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* repeated start to read */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* read from i2c device for single byte */ + lRetVal = iot_i2c_read_sync( xI2CHandle, &singleByte, sizeof( singleByte ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &writeBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being written is 1. */ + TEST_ASSERT_EQUAL( sizeof( xtestIotI2CDeviceRegister ), writeBytes ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetRxNoOfbytes, &readBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being read is 1. */ + TEST_ASSERT_EQUAL( sizeof( singleByte ), readBytes ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C sync read Fail + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CReadSyncFail ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t ucReadValue; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT, + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* read from i2c device */ + lRetVal = iot_i2c_read_sync( xI2CHandle, &ucReadValue, sizeof( ucReadValue ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SLAVE_ADDRESS_NOT_SET, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C sync write + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteSyncSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t writeVal1[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal }; + uint8_t writeVal2[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal, uctestIotI2CWriteVal, uctestIotI2CWriteVal }; + + uint16_t writeBytes; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the value to the device */ + lRetVal = iot_i2c_write_sync( xI2CHandle, writeVal1, sizeof( writeVal1 ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &writeBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being written is 1. */ + TEST_ASSERT_EQUAL( sizeof( writeVal1 ), writeBytes ); + + /* write the value to the device */ + lRetVal = iot_i2c_write_sync( xI2CHandle, writeVal2, sizeof( writeVal2 ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetTxNoOfbytes, &writeBytes ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + /* Assert the number of bytes being written is 4. */ + TEST_ASSERT_EQUAL( sizeof( writeVal2 ), writeBytes ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C sync write + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CWriteSyncFail ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t writeVal[] = { xtestIotI2CDeviceRegister, uctestIotI2CWriteVal }; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT, + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write to i2c device */ + lRetVal = iot_i2c_write_sync( xI2CHandle, writeVal, sizeof( writeVal ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SLAVE_ADDRESS_NOT_SET, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function for I2C but getState + */ +TEST( TEST_IOT_I2C, AFQP_IotI2CGetBusStateSuccess ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + uint8_t readBuffer[ 64 ]; + + IotI2CBusStatus_t busStatus; + + IotI2CConfig_t xI2CConfig = + { + .ulBusFreq = testIotI2C_BAUDRATE, + .ulMasterTimeout = testIotI2C_DEFAULT_TIMEOUT + }; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + /* Set completion callback */ + iot_i2c_set_callback( xI2CHandle, prvI2CCallback, NULL ); + + /* Set i2c configuration. */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetMasterConfig, &xI2CConfig ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c slave address */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSetSlaveAddr, &uctestIotI2CSlaveAddr ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Set i2c configuration */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* write the device register address. */ + lRetVal = iot_i2c_write_sync( xI2CHandle, &xtestIotI2CDeviceRegister, sizeof( xtestIotI2CDeviceRegister ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Assert bus is idle before calling async read. */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetBusState, &busStatus ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( eI2CBusIdle, busStatus ); + + /* read from i2c device */ + lRetVal = iot_i2c_read_async( xI2CHandle, readBuffer, sizeof( readBuffer ) ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + + /* Assert bus is busy during async read. */ + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CGetBusState, &busStatus ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( eI2cBusBusy, busStatus ); + + lRetVal = xSemaphoreTake( xtestIotI2CSemaphore, testIotI2C_MAX_TIMEOUT ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} + +TEST( TEST_IOT_I2C, AFQP_IotI2CSendNoStopUnsupported ) +{ + IotI2CHandle_t xI2CHandle; + int32_t lRetVal; + + /* Open i2c to initialize hardware */ + xI2CHandle = iot_i2c_open( testIotI2C_INSTANCE ); + TEST_ASSERT_NOT_EQUAL( NULL, xI2CHandle ); + + if( TEST_PROTECT() ) + { + lRetVal = iot_i2c_ioctl( xI2CHandle, eI2CSendNoStopFlag, NULL ); + TEST_ASSERT_EQUAL( IOT_I2C_FUNCTION_NOT_SUPPORTED, lRetVal ); + } + + lRetVal = iot_i2c_close( xI2CHandle ); + TEST_ASSERT_EQUAL( IOT_I2C_SUCCESS, lRetVal ); +} diff --git a/libraries/abstractions/common_io/test/test_iot_internal.h b/libraries/abstractions/common_io/test/test_iot_internal.h new file mode 100644 index 00000000000..750cb955b1d --- /dev/null +++ b/libraries/abstractions/common_io/test/test_iot_internal.h @@ -0,0 +1,162 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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 + */ + +/******************************************************************************* + * IOT On-Target Unit Test + * @File: test_iot_internal.h + * @Brief: File for IOT HAL test board specific configuration setup + ******************************************************************************/ + +#include "test_iot_config.h" + +#pragma once + +/** + * Board specific UART config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_UART_CONFIG( int testSet ); + +/** + * Board specific Flash config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_FLASH_CONFIG( int testSet ); + +/** + * Board specific Watchdog config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_WATCHDOG_CONFIG( int testSet ); + +/** + * Board specific RTC config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_RTC_CONFIG( int testSet ); + +/** + * Board specific GPIO config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_GPIO_CONFIG( int testSet ); + +/** + * Board specific Timer config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_TIMER_CONFIG( int testSet ); + +/** + * Board specific ADC config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_ADC_CONFIG( int testSet ); + +/** + * Board specific Reset config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_RESET_CONFIG( int testSet ); + +/** + * Board specific Performance Counter config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_PERFCOUNTER_CONFIG( int testSet ); + +/** + * Board specific PWM config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_PWM_CONFIG( int testSet ); + +/** + * Board specific I2C config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_I2C_CONFIG( int testSet ); + +/** + * Board specific SPI config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_SPI_CONFIG( int testSet ); + +/** + * Board specific Power config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_POWER_CONFIG( int testSet ); + +/** + * Board specific SDIO config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_SDIO_CONFIG( int testSet ); + +/** + * Board specific Temp Sensor config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_TEMP_SENSOR_CONFIG( int testSet ); + +/** + * Board specific I2S config set + * + * @param: testSet: number of config set to be test + * @return None + */ +void SET_TEST_IOT_I2S_CONFIG( int testSet ); diff --git a/libraries/abstractions/common_io/test/test_iot_spi.c b/libraries/abstractions/common_io/test/test_iot_spi.c new file mode 100644 index 00000000000..2bb906910f8 --- /dev/null +++ b/libraries/abstractions/common_io/test/test_iot_spi.c @@ -0,0 +1,1503 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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 test_iot_spi.c + * @brief Functional Unit Test - SPI + ******************************************************************************* + */ + +/* Test includes */ +#include + +/* Test includes */ +#include "unity.h" +#include "unity_fixture.h" + +/* Driver includes */ +#include "iot_spi.h" +#include "test_iot_internal.h" + +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "semphr.h" + +#define SPI_BUFFER_SIZE ( 32 ) +#define testIotSPI_DEFAULT_SEMAPHORE_DELAY ( 3000U ) + +/*-----------------------------------------------------------*/ + +/* Globals values which can be overwritten by the test + * framework invoking these tests */ +/*-----------------------------------------------------------*/ +uint32_t ultestIotSpiInstance = 0; /* Test SPI Instance */ +uint32_t ultestIotSPIFrequency = 500000U; /* Test SPI Frequency */ +uint32_t ultestIotSPIDummyValue = 0; /* Test SPI Dummy Value */ +IotSPIMode_t xtestIotSPIDefaultConfigMode = eSPIMode0; /* Default SPI eSPIMode0 */ +IotSPIBitOrder_t xtestIotSPIDefaultconfigBitOrder = eSPIMSBFirst; /* Default SPI bit order eSPIMSBFirst */ +static SemaphoreHandle_t xtestIotSPISemaphore = NULL; +static StaticSemaphore_t xtestIotSPICompleted; +uint32_t ulAssistedTestIotSpiSlave = 0; +uint32_t ultestIotSpiSlave = 0; + + +/*-----------------------------------------------------------*/ + +/** + * @brief Application/POSIX defined callback for asynchronous operations + * This callback function releases a semaphore every time it is called. + */ +static void prvSpiAsyncCallback( IotSPITransactionStatus_t xStatus, + void * pvUserContext ) +{ + BaseType_t xHigherPriorityTaskWoken; + + xSemaphoreGiveFromISR( xtestIotSPISemaphore, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ +/* Define Test Group. */ +TEST_GROUP( TEST_IOT_SPI ); +/*-----------------------------------------------------------*/ + +/** + * @brief Setup function called before each test in this group is executed. + */ +TEST_SETUP( TEST_IOT_SPI ) +{ + xtestIotSPISemaphore = xSemaphoreCreateBinaryStatic( &xtestIotSPICompleted ); + TEST_ASSERT_NOT_EQUAL( NULL, xtestIotSPISemaphore ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Tear down function called after each test in this group is executed. + */ +TEST_TEAR_DOWN( TEST_IOT_SPI ) +{ +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/** + * @brief Function to define which tests to execute as part of this group. + */ +TEST_GROUP_RUNNER( TEST_IOT_SPI ) +{ + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_OpenClose ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_Init ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_CancelFail ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_CancelSuccess ); + + #if ( IOT_TEST_COMMON_IO_SPI_ASSISTED == 1 ) + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_ReadSync ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_ReadAsync ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_WriteSync ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_WriteAsync ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_TransferSync ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_TransferAsync ); + #endif + + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_OpenFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_CloseFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_IoctlFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_ReadSyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_ReadAsyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_WriteSyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_WriteAsyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_TransferSyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_TransferAsyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_SPI, AFQP_IotSPI_CancelFuzzing ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi open and close + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_OpenClose ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi init + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_Init ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMode_t xMode; + IotSPIMasterConfig_t xNewConfig, xOrigConfig, xConfirmConfig; + int32_t lRetVal; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + if( TEST_PROTECT() ) + { + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + memcpy( &xNewConfig, &xOrigConfig, sizeof( IotSPIMasterConfig_t ) ); + + for( xMode = eSPIMode0; xMode <= eSPIMode3; xMode++ ) + { + xNewConfig.eMode = xMode; + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xNewConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xConfirmConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xConfirmConfig.eMode, xNewConfig.eMode ); + } + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi read sync + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_ReadSync ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + int32_t lLoop = 0; + uint8_t ucRxBuf[ 4 ] = { 0xff, 0xff, 0xff, 0xff }; + size_t xBytesRx; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_read_sync( xSPIHandle, ucRxBuf, 4 ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetRxNoOfbytes, &xBytesRx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesRx, 4 ); + + /* Expect slave to send odd numbers on succesful master read */ + for( lLoop = 0; lLoop < 4; lLoop++ ) + { + TEST_ASSERT_EQUAL( ucRxBuf[ lLoop ], ( ( lLoop * 2 ) + 1 ) ); + } + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Assisted Test Function to test spi read sync + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_ReadSyncAssisted ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + int32_t lLoop = 0; + uint8_t ucRxBuf[ 16 ] = { 0 }; + char cMsg[ 50 ] = { 0 }; + size_t xBytesRx; + + /* If unit test and assisted test have different spi slave, make sure select slave function in + * ll hal is defined and select the slave for assisted slave. */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + #ifdef ASSISTED_TEST_COMMON_IO_SPI_SLAVE_SELECET_SUPPORTED + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + #else + TEST_ASSERT_MESSAGE( 0, "Assisted test has a different salve, but slave select is not supported." ); + #endif + } + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_read_sync( xSPIHandle, ucRxBuf, sizeof( ucRxBuf ) ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetRxNoOfbytes, &xBytesRx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesRx, 4 ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* restore slave select */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + /* Create a string with read bytes and print it to console. */ + for( int i = 0, j = 0, len = sizeof( ucRxBuf ); i < len; i++ ) + { + cMsg[ j++ ] = ','; + uint8_t upp = ucRxBuf[ i ] >> 4, low = ucRxBuf[ i ] & 0xF; + cMsg[ j++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ j++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + TEST_IGNORE_MESSAGE( cMsg ); +} + +/** + * @brief Test Function to test spi read async + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_ReadAsync ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucRxBuf[ 4 ] = { 0xff, 0xff, 0xff, 0xff }; + size_t xBytesRx; + int32_t lLoop = 0; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Set a callback for async call */ + iot_spi_set_callback( xSPIHandle, prvSpiAsyncCallback, NULL ); + + /* Make async call */ + lRetVal = iot_spi_read_async( xSPIHandle, ucRxBuf, 4 ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /*Wait for the callback. */ + lRetVal = xSemaphoreTake( xtestIotSPISemaphore, testIotSPI_DEFAULT_SEMAPHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetRxNoOfbytes, &xBytesRx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesRx, 4 ); + + /* Expect slave to send odd numbers on succesful master read */ + for( lLoop = 0; lLoop < 4; lLoop++ ) + { + TEST_ASSERT_EQUAL( ucRxBuf[ lLoop ], ( ( lLoop * 2 ) + 1 ) ); + } + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Assisted Test Function to test spi read async + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_ReadAsyncAssisted ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucRxBuf[ 16 ] = { 0 }; + char cMsg[ 50 ] = { 0 }; + size_t xBytesRx; + int32_t lLoop = 0; + + /* If unit test and assisted test have different spi slave, make sure select slave function in + * ll hal is defined and select the slave for assisted slave. */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + #ifdef ASSISTED_TEST_COMMON_IO_SPI_SLAVE_SELECET_SUPPORTED + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + #else + TEST_ASSERT_MESSAGE( 0, "Assisted test has a different salve, but slave select is not supported." ); + #endif + } + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Set a callback for async call */ + iot_spi_set_callback( xSPIHandle, prvSpiAsyncCallback, NULL ); + + /* Make async call */ + lRetVal = iot_spi_read_async( xSPIHandle, ucRxBuf, sizeof( ucRxBuf ) ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /*Wait for the callback. */ + lRetVal = xSemaphoreTake( xtestIotSPISemaphore, testIotSPI_DEFAULT_SEMAPHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetRxNoOfbytes, &xBytesRx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesRx, 4 ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* restore slave select */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + /* Create a string with read bytes and print it to console. */ + for( int i = 0, j = 0, len = sizeof( ucRxBuf ); i < len; i++ ) + { + cMsg[ j++ ] = ','; + uint8_t upp = ucRxBuf[ i ] >> 4, low = ucRxBuf[ i ] & 0xF; + cMsg[ j++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ j++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + TEST_IGNORE_MESSAGE( cMsg ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi write sync + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_WriteSync ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucTxBuf[ 4 ] = { 0, 2, 4, 6 }; + size_t xBytesTx; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_write_sync( xSPIHandle, ucTxBuf, 4 ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetTxNoOfbytes, &xBytesTx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesTx, 4 ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} + +/** + * @brief Assisted Test Function to test spi write sync + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_WriteSyncAssisted ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucTxBuf[ 16 ] = { 0 }; + char cMsg[ 50 ] = { 0 }; + size_t xBytesTx; + + srand( xTaskGetTickCount() ); + + /* Generate random tx bytes and load them to a string to print later. */ + for( int i = 0, j = 0, len = sizeof( ucTxBuf ); i < len; i++ ) + { + ucTxBuf[ i ] = ( uint8_t ) rand(); + cMsg[ j++ ] = ','; + uint8_t upp = ucTxBuf[ i ] >> 4, low = ucTxBuf[ i ] & 0xF; + cMsg[ j++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ j++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + /* If unit test and assisted test have different spi slave, make sure select slave function in + * ll hal is defined and select the slave for assisted slave. */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + #ifdef ASSISTED_TEST_COMMON_IO_SPI_SLAVE_SELECET_SUPPORTED + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + #else + TEST_ASSERT_MESSAGE( 0, "Assisted test has a different salve, but slave select is not supported." ); + #endif + } + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_write_sync( xSPIHandle, ucTxBuf, sizeof( ucTxBuf ) ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetTxNoOfbytes, &xBytesTx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesTx, 4 ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* restore slave select */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + TEST_IGNORE_MESSAGE( cMsg ); +} + +/** + * @brief Test Function to test spi write async + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_WriteAsync ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucTxBuf[ 4 ] = { 0, 2, 4, 6 }; + size_t xBytesTx; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Set a callback for async call */ + iot_spi_set_callback( xSPIHandle, prvSpiAsyncCallback, NULL ); + + /* Make async write call */ + lRetVal = iot_spi_write_async( xSPIHandle, ucTxBuf, 4 ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /*Wait for the callback. */ + lRetVal = xSemaphoreTake( xtestIotSPISemaphore, testIotSPI_DEFAULT_SEMAPHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetTxNoOfbytes, &xBytesTx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesTx, 4 ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} + +/** + * @brief Assisted Test Function to test spi write async + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_WriteAsyncAssisted ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucTxBuf[ 16 ] = { 0 }; + char cMsg[ 50 ] = { 0 }; + size_t xBytesTx; + + srand( xTaskGetTickCount() ); + + /* Generate random tx bytes and load them to a string to print later. */ + for( int i = 0, j = 0, len = sizeof( ucTxBuf ); i < len; i++ ) + { + ucTxBuf[ i ] = ( uint8_t ) rand(); + cMsg[ j++ ] = ','; + uint8_t upp = ucTxBuf[ i ] >> 4, low = ucTxBuf[ i ] & 0xF; + cMsg[ j++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ j++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + /* If unit test and assisted test have different spi slave, make sure select slave function in + * ll hal is defined and select the slave for assisted slave. */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + #ifdef ASSISTED_TEST_COMMON_IO_SPI_SLAVE_SELECET_SUPPORTED + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + #else + TEST_ASSERT_MESSAGE( 0, "Assisted test has a different salve, but slave select is not supported." ); + #endif + } + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Set a callback for async call */ + iot_spi_set_callback( xSPIHandle, prvSpiAsyncCallback, NULL ); + + /* Make async write call */ + lRetVal = iot_spi_write_async( xSPIHandle, ucTxBuf, sizeof( ucTxBuf ) ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /*Wait for the callback. */ + lRetVal = xSemaphoreTake( xtestIotSPISemaphore, testIotSPI_DEFAULT_SEMAPHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetTxNoOfbytes, &xBytesTx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xBytesTx, 4 ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* restore slave select */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + TEST_IGNORE_MESSAGE( cMsg ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi transfer sync + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_TransferSync ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucRxBuf[ 4 ] = { 0xff, 0xff, 0xff, 0xff }; + uint8_t ucTxBuf[ 4 ] = { 0x00, 0x02, 0x04, 0x06 }; + int32_t lLoop = 0; + size_t xBytesTx, xBytesRx; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* use some data to transfer. Send even, expect odd */ + lRetVal = iot_spi_transfer_sync( xSPIHandle, ucTxBuf, ucRxBuf, 4 ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetRxNoOfbytes, &xBytesRx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( 4, xBytesRx ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetTxNoOfbytes, &xBytesTx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( 4, xBytesTx ); + + /* Expect slave to send odd numbers on succesful master read */ + for( lLoop = 0; lLoop < 4; lLoop++ ) + { + TEST_ASSERT_EQUAL( ucRxBuf[ lLoop ], ( ( lLoop * 2 ) + 1 ) ); + } + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Assisted Test Function to test spi transfer sync + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_TransferSyncAssisted ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucRxBuf[ 8 ] = { 0 }; + uint8_t ucTxBuf[ 8 ] = { 0 }; + char cMsg[ 50 ] = { 0 }; + int32_t lLoop = 0; + size_t xBytesTx, xBytesRx; + + srand( xTaskGetTickCount() ); + + /* Generate random tx bytes and load them to a string to print later. */ + for( int i = 0, len = sizeof( ucTxBuf ); i < len; i++ ) + { + ucTxBuf[ i ] = ( uint8_t ) rand(); + cMsg[ lLoop++ ] = ','; + uint8_t upp = ucTxBuf[ i ] >> 4, low = ucTxBuf[ i ] & 0xF; + cMsg[ lLoop++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ lLoop++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + /* If unit test and assisted test have different spi slave, make sure select slave function in + * ll hal is defined and select the slave for assisted slave. */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + #ifdef ASSISTED_TEST_COMMON_IO_SPI_SLAVE_SELECET_SUPPORTED + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + #else + TEST_ASSERT_MESSAGE( 0, "Assisted test has a different salve, but slave select is not supported." ); + #endif + } + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* use some data to transfer. Send even, expect odd */ + lRetVal = iot_spi_transfer_sync( xSPIHandle, ucTxBuf, ucRxBuf, sizeof( ucRxBuf ) ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetRxNoOfbytes, &xBytesRx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( 4, xBytesRx ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetTxNoOfbytes, &xBytesTx ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( 4, xBytesTx ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* restore slave select */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + /* Append read bytes to string. */ + for( int i = 0, len = sizeof( ucRxBuf ); i < len; i++ ) + { + cMsg[ lLoop++ ] = ','; + uint8_t upp = ucRxBuf[ i ] >> 4, low = ucRxBuf[ i ] & 0xF; + cMsg[ lLoop++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ lLoop++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + TEST_IGNORE_MESSAGE( cMsg ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi transfer async + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_TransferAsync ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucRxBuf[ 4 ] = { 0xff, 0xff, 0xff, 0xff }; + uint8_t ucTxBuf[ 4 ] = { 0x00, 0x02, 0x04, 0x06 }; + int32_t lLoop = 0; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Set a callback for async call */ + iot_spi_set_callback( xSPIHandle, prvSpiAsyncCallback, NULL ); + + /* use some data to transfer. Send even, expect odd */ + lRetVal = iot_spi_transfer_async( xSPIHandle, ucTxBuf, ucRxBuf, 4 ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /*Wait for the callback. */ + lRetVal = xSemaphoreTake( xtestIotSPISemaphore, testIotSPI_DEFAULT_SEMAPHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + + /* Expect slave to send odd numbers on succesful master read */ + for( lLoop = 0; lLoop < 4; lLoop++ ) + { + TEST_ASSERT_EQUAL( ucRxBuf[ lLoop ], ( ( lLoop * 2 ) + 1 ) ); + } + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Assisted Test Function to test spi transfer async + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_TransferAsyncAssisted ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucRxBuf[ 8 ] = { 0 }; + uint8_t ucTxBuf[ 8 ] = { 0 }; + char cMsg[ 50 ] = { 0 }; + int32_t lLoop = 0; + + srand( xTaskGetTickCount() ); + + /* Generate random tx bytes and load them to a string to print later. */ + for( int i = 0, len = sizeof( ucTxBuf ); i < len; i++ ) + { + ucTxBuf[ i ] = ( uint8_t ) rand(); + cMsg[ lLoop++ ] = ','; + uint8_t upp = ucTxBuf[ i ] >> 4, low = ucTxBuf[ i ] & 0xF; + cMsg[ lLoop++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ lLoop++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + /* If unit test and assisted test have different spi slave, make sure select slave function in + * ll hal is defined and select the slave for assisted slave. */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + #ifdef ASSISTED_TEST_COMMON_IO_SPI_SLAVE_SELECET_SUPPORTED + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + #else + TEST_ASSERT_MESSAGE( 0, "Assisted test has a different salve, but slave select is not supported." ); + #endif + } + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Set a callback for async call */ + iot_spi_set_callback( xSPIHandle, prvSpiAsyncCallback, NULL ); + + /* use some data to transfer. Send even, expect odd */ + lRetVal = iot_spi_transfer_async( xSPIHandle, ucTxBuf, ucRxBuf, sizeof( ucRxBuf ) ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /*Wait for the callback. */ + lRetVal = xSemaphoreTake( xtestIotSPISemaphore, testIotSPI_DEFAULT_SEMAPHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, lRetVal ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* restore slave select */ + if( ulAssistedTestIotSpiSlave != ultestIotSpiSlave ) + { + lRetVal = iot_spi_select_slave( ultestIotSpiInstance, ulAssistedTestIotSpiSlave ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + /* Append read bytes to string. */ + for( int i = 0, len = sizeof( ucRxBuf ); i < len; i++ ) + { + cMsg[ lLoop++ ] = ','; + uint8_t upp = ucRxBuf[ i ] >> 4, low = ucRxBuf[ i ] & 0xF; + cMsg[ lLoop++ ] = upp + ( upp > 9 ? 'A' - 10 : '0' ); + cMsg[ lLoop++ ] = low + ( low > 9 ? 'A' - 10 : '0' ); + } + + TEST_IGNORE_MESSAGE( cMsg ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi cancel with nothing to cancel + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_CancelFail ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + if( TEST_PROTECT() ) + { + lRetVal = iot_spi_cancel( xSPIHandle ); + + if( lRetVal != IOT_SPI_FUNCTION_NOT_SUPPORTED ) + { + TEST_ASSERT_EQUAL( IOT_SPI_NOTHING_TO_CANCEL, lRetVal ); + } + } + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi cancel + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_CancelSuccess ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMasterConfig_t xOrigConfig, xTestConfig; + int32_t lRetVal; + uint8_t ucRxBuf[ 4 ] = { 0xff, 0xff, 0xff, 0xff }; + uint8_t ucTxBuf[ 4 ] = { 0x00, 0x02, 0x04, 0x06 }; + BaseType_t xCallbackReturn; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* save original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + if( TEST_PROTECT() ) + { + /* configure bus */ + xTestConfig.ulFreq = ultestIotSPIFrequency; + xTestConfig.eMode = xtestIotSPIDefaultConfigMode; + xTestConfig.eSetBitOrder = xtestIotSPIDefaultconfigBitOrder; + xTestConfig.ucDummyValue = ultestIotSPIDummyValue; + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xTestConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* use some data to transfer. Send even, expect odd */ + lRetVal = iot_spi_transfer_async( xSPIHandle, ucTxBuf, ucRxBuf, 4 ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_cancel( xSPIHandle ); + + if( lRetVal != IOT_SPI_FUNCTION_NOT_SUPPORTED ) + { + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + } + + /* Wait to make sure operation was really canceled. */ + xCallbackReturn = xSemaphoreTake( xtestIotSPISemaphore, testIotSPI_DEFAULT_SEMAPHORE_DELAY ); + TEST_ASSERT_EQUAL( pdFALSE, xCallbackReturn ); + } + + /* restore original configuration */ + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi open with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_OpenFuzzing ) +{ + IotSPIHandle_t xSPIHandle, xSPIHandle2; + int32_t lRetVal; + + /* Open invalid SPI handle */ + xSPIHandle = iot_spi_open( -1 ); + TEST_ASSERT_EQUAL( NULL, xSPIHandle ); + + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* Opening the same SPI is not allowed */ + xSPIHandle2 = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_EQUAL( NULL, xSPIHandle2 ); + + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi close with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_CloseFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + + /* Close with NULL handle */ + lRetVal = iot_spi_close( NULL ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + /* Close with valid handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Close with stale handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi ioctl with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_IoctlFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + IotSPIMode_t xMode; + IotSPIBitOrder_t xBitOrder; + IotSPIMasterConfig_t xNewConfig, xOrigConfig, xConfirmConfig; + IotSPIIoctlRequest_t xRequest; + int32_t lRetVal; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + memcpy( &xNewConfig, &xOrigConfig, sizeof( IotSPIMasterConfig_t ) ); + + for( xMode = eSPIMode0; xMode <= eSPIMode3; xMode++ ) + { + xNewConfig.eMode = xMode; + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xNewConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xConfirmConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xConfirmConfig.eMode, xNewConfig.eMode ); + } + + xNewConfig.eMode = xOrigConfig.eMode; + + for( xBitOrder = eSPIMSBFirst; xBitOrder <= eSPILSBFirst; xBitOrder++ ) + { + xNewConfig.eSetBitOrder = xBitOrder; + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xNewConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPIGetMasterConfig, &xConfirmConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + TEST_ASSERT_EQUAL( xConfirmConfig.eSetBitOrder, xNewConfig.eSetBitOrder ); + } + + lRetVal = iot_spi_ioctl( xSPIHandle, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); + + /* Try with invalid params. Expect failures. */ + lRetVal = iot_spi_ioctl( NULL, eSPISetMasterConfig, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_ioctl( xSPIHandle, -1, &xOrigConfig ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + for( xRequest = eSPISetMasterConfig; xRequest <= eSPIGetRxNoOfbytes; xRequest++ ) + { + lRetVal = iot_spi_ioctl( xSPIHandle, xRequest, NULL ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + } + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi readSync with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_ReadSyncFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + uint8_t ucBuffer[ SPI_BUFFER_SIZE ]; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_read_sync( NULL, ucBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_MASTER_NOT_INITIALIZED, lRetVal ); + + lRetVal = iot_spi_read_sync( xSPIHandle, NULL, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_read_sync( xSPIHandle, ucBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi readAsync with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_ReadAsyncFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + uint8_t ucBuffer[ SPI_BUFFER_SIZE ]; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_read_async( NULL, ucBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_MASTER_NOT_INITIALIZED, lRetVal ); + + lRetVal = iot_spi_read_async( xSPIHandle, NULL, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_read_async( xSPIHandle, ucBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi writeSync with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_WriteSyncFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + uint8_t ucBuffer[ SPI_BUFFER_SIZE ]; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_write_sync( NULL, ucBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_MASTER_NOT_INITIALIZED, lRetVal ); + + lRetVal = iot_spi_write_sync( xSPIHandle, NULL, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_write_sync( xSPIHandle, ucBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi writeAsync with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_WriteAsyncFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + uint8_t ucBuffer[ SPI_BUFFER_SIZE ]; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_write_async( NULL, ucBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_MASTER_NOT_INITIALIZED, lRetVal ); + + lRetVal = iot_spi_write_async( xSPIHandle, NULL, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_write_async( xSPIHandle, ucBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi transferSync with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_TransferSyncFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + uint8_t ucRxBuffer[ SPI_BUFFER_SIZE ]; + uint8_t ucTxBuffer[ SPI_BUFFER_SIZE ]; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_transfer_sync( NULL, ucRxBuffer, ucTxBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_MASTER_NOT_INITIALIZED, lRetVal ); + + lRetVal = iot_spi_transfer_sync( xSPIHandle, NULL, ucTxBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_transfer_sync( xSPIHandle, ucRxBuffer, NULL, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_transfer_sync( xSPIHandle, ucRxBuffer, ucTxBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi transferAsync with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_TransferAsyncFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + uint8_t ucRxBuffer[ SPI_BUFFER_SIZE ]; + uint8_t ucTxBuffer[ SPI_BUFFER_SIZE ]; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_transfer_async( NULL, ucRxBuffer, ucTxBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_MASTER_NOT_INITIALIZED, lRetVal ); + + lRetVal = iot_spi_transfer_async( xSPIHandle, NULL, ucTxBuffer, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_transfer_async( xSPIHandle, ucRxBuffer, NULL, SPI_BUFFER_SIZE ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + lRetVal = iot_spi_transfer_async( xSPIHandle, ucRxBuffer, ucTxBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test spi cancel with invalid params + * + */ +TEST( TEST_IOT_SPI, AFQP_IotSPI_CancelFuzzing ) +{ + IotSPIHandle_t xSPIHandle; + int32_t lRetVal; + + /* Open SPI handle */ + xSPIHandle = iot_spi_open( ultestIotSpiInstance ); + TEST_ASSERT_NOT_EQUAL( NULL, xSPIHandle ); + + lRetVal = iot_spi_cancel( NULL ); + + if( lRetVal != IOT_SPI_FUNCTION_NOT_SUPPORTED ) + { + TEST_ASSERT_EQUAL( IOT_SPI_INVALID_VALUE, lRetVal ); + } + + lRetVal = iot_spi_cancel( xSPIHandle ); + + if( ( lRetVal != IOT_SPI_FUNCTION_NOT_SUPPORTED ) && + ( lRetVal != IOT_SPI_MASTER_NOT_INITIALIZED ) ) + { + TEST_ASSERT_EQUAL( IOT_SPI_NOTHING_TO_CANCEL, lRetVal ); + } + + /* Close SPI handle */ + lRetVal = iot_spi_close( xSPIHandle ); + TEST_ASSERT_EQUAL( IOT_SPI_SUCCESS, lRetVal ); +} +/*-----------------------------------------------------------*/ diff --git a/libraries/abstractions/common_io/test/test_iot_uart.c b/libraries/abstractions/common_io/test/test_iot_uart.c new file mode 100644 index 00000000000..9a9416bb550 --- /dev/null +++ b/libraries/abstractions/common_io/test/test_iot_uart.c @@ -0,0 +1,787 @@ +/* + * Amazon FreeRTOS Common IO V1.0.0 + * Copyright (C) 2019 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 + */ + +/* Standard includes */ +#include + +/* Test includes. */ +#include "unity_fixture.h" +#include "unity.h" + +/* Driver model includes */ +#include "iot_uart.h" + +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "semphr.h" + +/*-----------------------------------------------------------*/ +/* Test Defines */ +#define testIotUART_DEFAULT_SEMPAHORE_DELAY ( 60 ) /** Amount of time a function waits for every callback to finish. */ +#define testIotUART_TEST_BAUD_RATE ( 38400 ) /** Alternative baud rate to test. */ +#define testIotUART_TEST_BAUD_RATE_DEFAULT ( IOT_UART_BAUD_RATE_DEFAULT ) /** Default baud rate. */ +#define testIotUART_BAUD_RATE_STRING ( "Baudrate: 38400\n" ) /** Signal external device to change to different baudrate. */ +#define testIotUART_BAUD_RATE_DEFAULT_STRING ( "Baudrate: 115200\n" ) /** Signal external device to revert back to default baudrate. */ +#define testIotUART_BAUD_RATE_BUFFER_TEST_LENGTH ( sizeof( testIotUART_BAUD_RATE_STRING ) - 1 ) +#define testIotUART_BAUD_RATE_BUFFER_DEFAULT_LENGTH ( sizeof( testIotUART_BAUD_RATE_DEFAULT_STRING ) - 1 ) +#define testIotUART_BUFFER_STRING ( "Test for UART read-write\n" ) +#define testIotUART_BUFFER_LENGTH ( sizeof( testIotUART_BUFFER_STRING ) - 1 ) + +#define testIotUART_BAUD_RATE_FAST ( 115200 ) +#define testIotUART_BAUD_RATE_SLOW ( 9600 ) +#define testIotUARTBUFFERSIZE ( 32 ) +#define testIotUART_BUFFER_LENGTH_LARGE ( 200 ) +#define testIotUART_DELAY ( 1000 ) +#define testIotUART_7BIT_WORD_LENGTH ( 0 ) +#define testIotUART_8BIT_WORD_LENGTH ( 1 ) +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/* Globals values which can be overwritten by the test + * framework invoking these tests */ +/*-----------------------------------------------------------*/ +uint8_t ustestIotUartPort = 0; /** Default UART port for testing */ +uint32_t ultestIotUartFlowControl = 0; +uint32_t ultestIotUartParity = 0; +uint32_t ultestIotUartWordLength = 0; +uint32_t ultestIotUartStopBits = 0; + +/*-----------------------------------------------------------*/ +/* Static Globals */ +/*-----------------------------------------------------------*/ +static SemaphoreHandle_t xtestIotUARTSemaphore = NULL; +static StaticSemaphore_t xtestIotUARTCompleted; + +/* note: config1 is different in each field from config2 */ +static IotUARTConfig_t xSampleConfig1 = +{ + .ulBaudrate = testIotUART_BAUD_RATE_FAST, + .ucFlowControl = 0, /* no flow control */ + .xParity = eUartParityNone, + .xStopbits = eUartStopBitsOne, + .ucWordlength = testIotUART_7BIT_WORD_LENGTH, +}; +static IotUARTConfig_t xSampleConfig2 = +{ + .ulBaudrate = testIotUART_BAUD_RATE_SLOW, + .ucFlowControl = 1, /* yes flow control */ + .xParity = eUartParityOdd, + .xStopbits = eUartStopBitsTwo, + .ucWordlength = testIotUART_8BIT_WORD_LENGTH, +}; + + +/** + * @brief Application/POSIX defined callback for asynchronous write operation on + * UART for testing the loopback function. + * This callback function releases a semaphore every time it is called. + */ +static void prvReadWriteCallback( IotUARTOperationStatus_t xOpStatus, + void * pvParams ) +{ + BaseType_t xHigherPriorityTaskWoken; + + TEST_ASSERT_EQUAL( ( xOpStatus ), eUartCompleted ); + TEST_ASSERT_EQUAL( pvParams, NULL ); + xSemaphoreGiveFromISR( xtestIotUARTSemaphore, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + +/*-----------------------------------------------------------*/ + +/* Define Test Group. */ +TEST_GROUP( TEST_IOT_UART ); + + +/*-----------------------------------------------------------*/ + +/** + * @brief Setup function called before each test in this group is executed. + */ +TEST_SETUP( TEST_IOT_UART ) +{ + xtestIotUARTSemaphore = xSemaphoreCreateCountingStatic( 10, 0, &xtestIotUARTCompleted ); + TEST_ASSERT_NOT_EQUAL( NULL, xtestIotUARTSemaphore ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Tear down function called after each test in this group is executed. + */ +TEST_TEAR_DOWN( TEST_IOT_UART ) +{ +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Function to define which tests to execute as part of this group. + */ +TEST_GROUP_RUNNER( TEST_IOT_UART ) +{ + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTWriteReadAsyncWithCallback ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTIoctlFuzzing ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTReadSyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTReadAsyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTWriteSyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTWriteAsyncFuzzing ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTCancel ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTIoctlWhenBusy ) + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTWriteAsyncReadAsyncLoopbackTest ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTIoctlGetSet ); + RUN_TEST_CASE( TEST_IOT_UART, AFQP_IotUARTOpenCloseCancelFuzzing ); +} +/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + +/** + * hardware loopback. The Tx and Rx pin on the vendor board are shorted with a + * connector and the test is run by transmitting some bytes on write sync and checking + * if same characters are read synchronously. + */ +TEST( TEST_IOT_UART, AFQP_AssistedIotUARTWriteReadSync ) +{ + uint8_t cpBuffer[ testIotUARTBUFFERSIZE ] = { 0 }; + uint8_t cpBufferRead[ testIotUARTBUFFERSIZE ] = { 0 }; + + strncpy( ( char * ) cpBuffer, ( char * ) testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + IotUARTHandle_t xUartHandle; + int32_t lRead, lWrite, lClose; + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lWrite = iot_uart_write_sync( xUartHandle, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lRead = iot_uart_read_sync( xUartHandle, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lRead ); + + TEST_ASSERT_EQUAL( 0, strncmp( ( char * ) cpBuffer, ( char * ) cpBufferRead, testIotUART_BUFFER_LENGTH ) ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to check UART Ioctl API specifications. + */ +TEST( TEST_IOT_UART, AFQP_IotUARTIoctlGetSet ) +{ + IotUARTHandle_t xUartHandle; + int32_t lIoctl, lClose, lTransferAmount; + IotUARTConfig_t xgetConfigBuffer, xConfigBuffer, xOriginalConfig; + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + /* Save original UART config */ + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, &xOriginalConfig ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + /* Initialze to a known value, then one by one change, and make sure it changes */ + memcpy( &xConfigBuffer, &xSampleConfig1, sizeof( IotUARTConfig_t ) ); + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + /* Test changing baudrate config */ + xConfigBuffer.ulBaudrate = xSampleConfig2.ulBaudrate; + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, &xgetConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_EQUAL( xSampleConfig2.ulBaudrate, xgetConfigBuffer.ulBaudrate ); + + /* Test changing control flow config */ + xConfigBuffer.ucFlowControl = xSampleConfig2.ucFlowControl; + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, &xgetConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_EQUAL( xSampleConfig2.ucFlowControl, xgetConfigBuffer.ucFlowControl ); + + /* Test changing stop bit config */ + xConfigBuffer.xStopbits = xSampleConfig2.xStopbits; + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, &xgetConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_EQUAL( xSampleConfig2.xStopbits, xgetConfigBuffer.xStopbits ); + + /* Test changing parity config */ + xConfigBuffer.xParity = xSampleConfig2.xParity; + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, &xgetConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_EQUAL( xSampleConfig2.xParity, xgetConfigBuffer.xParity ); + + /* Test changing Wordlength config */ + xConfigBuffer.ucWordlength = xSampleConfig2.ucWordlength; + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, &xgetConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_EQUAL( xSampleConfig2.ucWordlength, xgetConfigBuffer.ucWordlength ); + + /* Set config back to original */ + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xOriginalConfig ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + /* Getting transfer byte amount only works on an operation in flight. */ + lIoctl = iot_uart_ioctl( xUartHandle, eGetTxNoOfbytes, &lTransferAmount ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + lIoctl = iot_uart_ioctl( xUartHandle, eGetRxNoOfbytes, &lTransferAmount ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to check if UART can be configured to a different baudrate. + * Works by signal external device to change to a new baudrate. Sending and recieving a message. + * Then signals to return back to default baudrate. + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_AssistedIotUARTBaudChange ) +{ + IotUARTHandle_t xUartHandle; + int32_t lIoctl, lWrite, lRead, lClose; + uint8_t cpBuffer[ testIotUARTBUFFERSIZE ] = { 0 }; + uint8_t cpBufferRead[ testIotUARTBUFFERSIZE ] = { 0 }; + + strncpy( ( char * ) cpBuffer, ( char * ) testIotUART_BAUD_RATE_STRING, testIotUART_BAUD_RATE_BUFFER_TEST_LENGTH ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + /* Signal other device to change to new baudrate */ + lWrite = iot_uart_write_sync( xUartHandle, cpBuffer, testIotUART_BAUD_RATE_BUFFER_TEST_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + IotUARTConfig_t pvConfigBuffer; + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, &pvConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + pvConfigBuffer.ulBaudrate = testIotUART_TEST_BAUD_RATE; + + /* Configure a different baudrate */ + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &pvConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + /* Wait for other UART to change baudrate. */ + vTaskDelay( pdMS_TO_TICKS( testIotUART_DELAY ) ); + + memset( cpBuffer, 0, testIotUARTBUFFERSIZE ); + strncpy( ( char * ) cpBuffer, ( char * ) testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + + lWrite = iot_uart_write_sync( xUartHandle, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lRead = iot_uart_read_sync( xUartHandle, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lRead ); + + TEST_ASSERT_EQUAL( 0, strncmp( ( char * ) cpBuffer, ( char * ) cpBufferRead, testIotUART_BUFFER_LENGTH ) ); + + strncpy( ( char * ) cpBuffer, ( char * ) testIotUART_BAUD_RATE_DEFAULT_STRING, testIotUART_BAUD_RATE_BUFFER_DEFAULT_LENGTH ); + + /* Signal other device to revert to original baudrate */ + lWrite = iot_uart_write_sync( xUartHandle, cpBuffer, testIotUART_BAUD_RATE_BUFFER_DEFAULT_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + pvConfigBuffer.ulBaudrate = testIotUART_TEST_BAUD_RATE_DEFAULT; + + /* Reset baudrate back to default */ + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &pvConfigBuffer ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + + /* Wait for other UART to change baudrate. */ + vTaskDelay( pdMS_TO_TICKS( testIotUART_DELAY ) ); + + strncpy( ( char * ) cpBuffer, ( char * ) testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + + lWrite = iot_uart_write_sync( xUartHandle, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lRead = iot_uart_read_sync( xUartHandle, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lRead ); + + /* Baudrate reverted succesfully */ + TEST_ASSERT_EQUAL( 0, strncmp( ( char * ) cpBuffer, ( char * ) cpBufferRead, testIotUART_BUFFER_LENGTH ) ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/** + * @brief Test function to test the asynchronous read/write with UART by doing a + * hardware loopback. The Tx and Rx pin on the vendor board are shorted with a + * connector and the test is run by transmitting some bytes on write async and checking + * if same characters are read asynchronously. + * This test also checks if we are getting Tx bytes in flight. + */ +TEST( TEST_IOT_UART, AFQP_IotUARTWriteAsyncReadAsyncLoopbackTest ) +{ + IotUARTHandle_t xUartHandle; + int32_t lIoctl, lWrite, lClose, lRead, lTransferAmount; + + uint8_t cpBuffer[ testIotUART_BUFFER_LENGTH + 1 ] = { 0 }; + uint8_t cpBufferRead[ testIotUART_BUFFER_LENGTH + 1 ] = { 0 }; + uint8_t uStringCompare = 1; + + strncpy( ( char * ) cpBuffer, testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lWrite = iot_uart_write_async( xUartHandle, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lIoctl = iot_uart_ioctl( xUartHandle, eGetTxNoOfbytes, &lTransferAmount ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_GREATER_THAN( 0, lTransferAmount ); + + lRead = iot_uart_read_async( xUartHandle, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lRead ); + + /* Delay for 1 sec. */ + vTaskDelay( testIotUART_DELAY ); + + uStringCompare = memcmp( cpBuffer, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( 0, uStringCompare ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + +/** + * This is Assisted Test function to test the asynchronous read/write with UART by doing a + * loopback with RPI3. The Tx and Rx pin on the vendor board are connected to RX and TX of + * RPI3. Test is run by transmitting some bytes on write async and checking + * if same characters are read asynchronously on RPI3. Validation happens on RPI3 + * This test also checks if we are getting Tx bytes in flight. + */ +TEST( TEST_IOT_UART, AFQP_AssistedIotUARTWriteAsync ) +{ + IotUARTHandle_t xUartHandle; + int32_t lIoctl, lWrite, lClose, lTransferAmount_1, lTransferAmount_2; + uint8_t i; + uint8_t cpBufferLarge[ testIotUART_BUFFER_LENGTH_LARGE ] = { 0 }; + + for( i = 0; i < testIotUART_BUFFER_LENGTH_LARGE; i++ ) + { + cpBufferLarge[ i ] = 0xAA; + } + + cpBufferLarge[ testIotUART_BUFFER_LENGTH_LARGE - 1 ] = '\n'; + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lWrite = iot_uart_write_async( xUartHandle, cpBufferLarge, testIotUART_BUFFER_LENGTH_LARGE ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lIoctl = iot_uart_ioctl( xUartHandle, eGetTxNoOfbytes, &lTransferAmount_1 ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_GREATER_THAN( 0, lTransferAmount_1 ); + + /* Delay for 1 sec. */ + vTaskDelay( testIotUART_DELAY ); + + lIoctl = iot_uart_ioctl( xUartHandle, eGetTxNoOfbytes, &lTransferAmount_2 ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lIoctl ); + TEST_ASSERT_GREATER_THAN( lTransferAmount_1, lTransferAmount_2 ); + + /* Delay for 1 sec. */ + vTaskDelay( testIotUART_DELAY ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/** + * @brief Test function to test the asynchronous read with UART by doing a + * hardware loopback. The Tx and Rx pin on the vendor board are shorted with a + * connector and the test is run by transmitting some bytes on write async and checking + * if same characters are read aynchronously. + */ +TEST( TEST_IOT_UART, AFQP_IotUARTWriteReadAsyncWithCallback ) +{ + IotUARTHandle_t xUartHandle; + uint8_t cpBuffer[ testIotUARTBUFFERSIZE ] = { 0 }; + uint8_t cpBufferRead[ testIotUARTBUFFERSIZE ] = { 0 }; + + strncpy( ( char * ) cpBuffer, ( char * ) testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + int32_t lRead, lWrite, lClose; + BaseType_t xCallbackReturn; + uint8_t ucPort = ustestIotUartPort; + + xUartHandle = iot_uart_open( ucPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + iot_uart_set_callback( xUartHandle, prvReadWriteCallback, NULL ); + + lWrite = iot_uart_write_async( xUartHandle, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lRead = iot_uart_read_async( xUartHandle, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lRead ); + + xCallbackReturn = xSemaphoreTake( ( SemaphoreHandle_t ) &xtestIotUARTCompleted, testIotUART_DEFAULT_SEMPAHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, xCallbackReturn ); + + TEST_ASSERT_EQUAL( 0, strncmp( ( char * ) cpBuffer, ( char * ) cpBufferRead, testIotUART_BUFFER_LENGTH ) ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to test iot_uart_cancel + * + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_IotUARTCancel ) +{ + IotUARTHandle_t xUartHandle; + int32_t lWrite, lClose, lCancel; + BaseType_t xCallbackReturn; + + uint8_t cSmallBuf[ 2 ] = { 'H', 'I' }; + uint8_t cpBuffer[ testIotUARTBUFFERSIZE ] = { 0 }; + uint8_t uSmallBuflen = sizeof( cSmallBuf ) / sizeof( uint8_t ); + + strncpy( ( char * ) cpBuffer, testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + iot_uart_set_callback( xUartHandle, prvReadWriteCallback, NULL ); + + lWrite = iot_uart_write_async( xUartHandle, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lCancel = iot_uart_cancel( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lCancel ); + + /* Wait to make sure operation was really canceled. */ + xCallbackReturn = xSemaphoreTake( ( SemaphoreHandle_t ) &xtestIotUARTCompleted, testIotUART_DEFAULT_SEMPAHORE_DELAY ); + TEST_ASSERT_EQUAL( pdFALSE, xCallbackReturn ); + } + + lWrite = iot_uart_write_async( xUartHandle, cSmallBuf, uSmallBuflen ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + /* Wait to make sure operation has completed. */ + xCallbackReturn = xSemaphoreTake( ( SemaphoreHandle_t ) &xtestIotUARTCompleted, testIotUART_DEFAULT_SEMPAHORE_DELAY ); + TEST_ASSERT_EQUAL( pdTRUE, xCallbackReturn ); + + /* Since cSmallBuf is small buffer, write is already complete. Hence nothing to cancel */ + lCancel = iot_uart_cancel( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_NOTHING_TO_CANCEL, lCancel ); + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to fuzz iot_uart_write_async + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_IotUARTWriteAsyncFuzzing ) +{ + IotUARTHandle_t xUartHandle; + int32_t lClose, lWrite; + + uint8_t cpBuffer[ testIotUARTBUFFERSIZE ] = { 0 }; + + strncpy( ( char * ) cpBuffer, testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + + lWrite = iot_uart_write_async( NULL, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lWrite ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lWrite = iot_uart_write_async( xUartHandle, NULL, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lWrite ); + + lWrite = iot_uart_write_async( xUartHandle, cpBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lWrite ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to fuzz iot_uart_write_sync + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_IotUARTWriteSyncFuzzing ) +{ + IotUARTHandle_t xUartHandle; + int32_t lClose, lWrite; + + uint8_t cpBuffer[ testIotUARTBUFFERSIZE ] = { 0 }; + + strncpy( ( char * ) cpBuffer, testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + + lWrite = iot_uart_write_sync( NULL, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lWrite ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lWrite = iot_uart_write_sync( xUartHandle, NULL, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lWrite ); + + lWrite = iot_uart_write_sync( xUartHandle, cpBuffer, 0 ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lWrite ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to fuzz iot_uart_read_async + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_IotUARTReadAsyncFuzzing ) +{ + IotUARTHandle_t xUartHandle; + int32_t lClose, lRead; + + uint8_t cpBufferRead[ testIotUARTBUFFERSIZE ] = { 0 }; + + lRead = iot_uart_read_async( NULL, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lRead ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lRead = iot_uart_read_async( xUartHandle, NULL, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lRead ); + + lRead = iot_uart_read_async( xUartHandle, cpBufferRead, 0 ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lRead ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to fuzz iot_uart_read_sync + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_IotUARTReadSyncFuzzing ) +{ + IotUARTHandle_t xUartHandle; + int32_t lClose, lRead; + + uint8_t cpBufferRead[ testIotUARTBUFFERSIZE ] = { 0 }; + + lRead = iot_uart_read_sync( NULL, cpBufferRead, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lRead ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lRead = iot_uart_read_sync( xUartHandle, NULL, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lRead ); + + lRead = iot_uart_read_sync( xUartHandle, cpBufferRead, 0 ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lRead ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +/* @brief Test Function to fuzz iot_uart_ioctl + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_IotUARTIoctlFuzzing ) +{ + IotUARTHandle_t xUartHandle; + int32_t lIoctl, lClose; + IotUARTConfig_t xUartConfigTest; + + /* Call iot_uart_ioctl with NULL handle. Expect IOT_UART_INVALID_VALUE */ + lIoctl = iot_uart_ioctl( NULL, eUartSetConfig, &xUartConfigTest ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lIoctl ); + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + /* Call iot_uart_ioctl with valid handle, but with invalid enum (-1) request.Expect IOT_UART_INVALID_VALUE */ + lIoctl = iot_uart_ioctl( xUartHandle, -1, &xUartConfigTest ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lIoctl ); + + /* Call iot_uart_ioctl with enum eUartSetConfig, and NULL buffer.Expect IOT_UART_INVALID_VALUE */ + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, NULL ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lIoctl ); + + /* Call iot_uart_ioctl with enum eUartGetConfig, and NULL buffer.Expect IOT_UART_INVALID_VALUE */ + lIoctl = iot_uart_ioctl( xUartHandle, eUartGetConfig, NULL ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lIoctl ); + + /* Call iot_uart_ioctl with enum eGetTxNoOfbytes, and NULL buffer.Expect IOT_UART_INVALID_VALUE */ + lIoctl = iot_uart_ioctl( xUartHandle, eGetTxNoOfbytes, NULL ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lIoctl ); + + /* Call iot_uart_ioctl with enum eGetRxNoOfbytes, and NULL buffer.Expect IOT_UART_INVALID_VALUE */ + lIoctl = iot_uart_ioctl( xUartHandle, eGetRxNoOfbytes, NULL ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lIoctl ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + +/** + * @brief Test Function to check if UART can be configured when an operation is ongoing. + * If any asynchronous operation is in the process in UART, iot_uart_ioctl should fail. + */ +TEST( TEST_IOT_UART, AFQP_IotUARTIoctlWhenBusy ) +{ + IotUARTHandle_t xUartHandle; + int32_t lIoctl, lWrite, lClose; + BaseType_t xCallbackReturn; + uint8_t cpBuffer[ testIotUARTBUFFERSIZE ] = { 0 }; + + strncpy( ( char * ) cpBuffer, ( char * ) testIotUART_BUFFER_STRING, testIotUART_BUFFER_LENGTH ); + IotUARTConfig_t xUartConfig = { .ulBaudrate = testIotUART_TEST_BAUD_RATE_DEFAULT }; + + xUartHandle = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle ); + + if( TEST_PROTECT() ) + { + lWrite = iot_uart_write_async( xUartHandle, cpBuffer, testIotUART_BUFFER_LENGTH ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lWrite ); + + lIoctl = iot_uart_ioctl( xUartHandle, eUartSetConfig, &xUartConfig ); + TEST_ASSERT_EQUAL( IOT_UART_BUSY, lIoctl ); + } + + lClose = iot_uart_close( xUartHandle ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); +} +/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + +/* @brief Test Function to fuzz iot_uart_open and iot_uart_close + *-----------------------------------------------------------*/ +TEST( TEST_IOT_UART, AFQP_IotUARTOpenCloseCancelFuzzing ) +{ + IotUARTHandle_t xUartHandle_1, xUartHandle_2, xUartHandle_3; + int32_t lClose, lCancel; + + xUartHandle_1 = iot_uart_open( -1 ); + TEST_ASSERT_EQUAL( NULL, xUartHandle_1 ); + + lClose = iot_uart_close( NULL ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lClose ); + + xUartHandle_2 = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_NOT_EQUAL( NULL, xUartHandle_2 ); + + xUartHandle_3 = iot_uart_open( ustestIotUartPort ); + TEST_ASSERT_EQUAL( NULL, xUartHandle_3 ); + + lCancel = iot_uart_cancel( NULL ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lCancel ); + + lClose = iot_uart_close( xUartHandle_2 ); + TEST_ASSERT_EQUAL( IOT_UART_SUCCESS, lClose ); + + lClose = iot_uart_close( xUartHandle_2 ); + TEST_ASSERT_EQUAL( IOT_UART_INVALID_VALUE, lClose ); +} +/*-----------------------------------------------------------*/