diff --git a/drivers/PwmOut.h b/drivers/PwmOut.h index 1a90c3576ac..c94b8584fdd 100644 --- a/drivers/PwmOut.h +++ b/drivers/PwmOut.h @@ -21,6 +21,7 @@ #if defined (DEVICE_PWMOUT) || defined(DOXYGEN_ONLY) #include "hal/pwmout_api.h" #include "platform/mbed_critical.h" +#include "platform/mbed_sleep.h" namespace mbed { /** \addtogroup drivers */ @@ -56,12 +57,18 @@ class PwmOut { * * @param pin PwmOut pin to connect to */ - PwmOut(PinName pin) { + PwmOut(PinName pin) : _deep_sleep_locked(false) { core_util_critical_section_enter(); pwmout_init(&_pwm, pin); core_util_critical_section_exit(); } + ~PwmOut() { + core_util_critical_section_enter(); + unlock_deep_sleep(); + core_util_critical_section_exit(); + } + /** Set the ouput duty-cycle, specified as a percentage (float) * * @param value A floating-point value representing the output duty-cycle, @@ -71,6 +78,7 @@ class PwmOut { */ void write(float value) { core_util_critical_section_enter(); + lock_deep_sleep(); pwmout_write(&_pwm, value); core_util_critical_section_exit(); } @@ -177,7 +185,24 @@ class PwmOut { } protected: + /** Lock deep sleep only if it is not yet locked */ + void lock_deep_sleep() { + if (_deep_sleep_locked == false) { + sleep_manager_lock_deep_sleep(); + _deep_sleep_locked = true; + } + } + + /** Unlock deep sleep in case it is locked */ + void unlock_deep_sleep() { + if (_deep_sleep_locked == true) { + sleep_manager_unlock_deep_sleep(); + _deep_sleep_locked = false; + } + } + pwmout_t _pwm; + bool _deep_sleep_locked; }; } // namespace mbed diff --git a/drivers/Timer.cpp b/drivers/Timer.cpp index 12f9737ca46..8e3c406ba99 100644 --- a/drivers/Timer.cpp +++ b/drivers/Timer.cpp @@ -28,6 +28,15 @@ Timer::Timer(const ticker_data_t *data) : _running(), _start(), _time(), _ticker reset(); } +Timer::~Timer() { + core_util_critical_section_enter(); + if (_running) { + sleep_manager_unlock_deep_sleep(); + } + _running = 0; + core_util_critical_section_exit(); +} + void Timer::start() { core_util_critical_section_enter(); if (!_running) { diff --git a/drivers/Timer.h b/drivers/Timer.h index e353720b966..848f8087c39 100644 --- a/drivers/Timer.h +++ b/drivers/Timer.h @@ -53,6 +53,7 @@ class Timer : private NonCopyable { public: Timer(); Timer(const ticker_data_t *data); + ~Timer(); /** Start the timer */ diff --git a/features/FEATURE_BLE/ble/ArrayView.h b/features/FEATURE_BLE/ble/ArrayView.h new file mode 100644 index 00000000000..5cf7336c1dd --- /dev/null +++ b/features/FEATURE_BLE/ble/ArrayView.h @@ -0,0 +1,165 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_ARRAY_VIEW_H_ +#define BLE_ARRAY_VIEW_H_ + +#include +#include + +namespace ble { + +/** + * Immutable view to an array. + */ +template +struct ArrayView { + + /** + * construct an array view to an empty array + */ + ArrayView() : _array(0), _size(0) { } + + /** + * construct an array view from a pointer. + * and its size. + */ + ArrayView(T* array_ptr, size_t array_size) : + _array(array_ptr), _size(array_size) { } + + /** + * Construct an array view from the reference to an array. + */ + template + ArrayView(T (&elements)[Size]): + _array(elements), _size(Size) { } + + /** + * Return the size of the array viewed. + */ + size_t size() const { + return _size; + } + + /** + * Access to a mutable element of the array. + */ + T& operator[](size_t index) { + return _array[index]; + } + + /** + * Access to an immutable element of the array. + */ + const T& operator[](size_t index) const { + return _array[index]; + } + + /** + * Get the pointer to the array + */ + T* data() { + return _array; + } + + /** + * Get the pointer to the const array + */ + const T* data() const { + return _array; + } + + /** + * Equality operator + */ + friend bool operator==(const ArrayView& lhs, const ArrayView& rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + if (lhs.data() == rhs.data()) { + return true; + } + + return memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; + } + + /** + * Not equal operator + */ + friend bool operator!=(const ArrayView& lhs, const ArrayView& rhs) { + return !(lhs == rhs); + } + +private: + T* const _array; + const size_t _size; +}; + + +/** + * Generate an array view from a C/C++ array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param elements The array viewed. + * @return The array_view to elements. + */ +template +ArrayView make_ArrayView(T (&elements)[Size]) { + return ArrayView(elements); +} + +/** + * Generate an array view from a C/C++ pointer and the size of the array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param array_ptr The pointer to the array to view. + * @param array_size The size of the array. + * @return The array_view to array_ptr with a size of array_size. + */ +template +ArrayView make_ArrayView(T* array_ptr, size_t array_size) { + return ArrayView(array_ptr, array_size); +} + +/** + * Generate a const array view from a C/C++ array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param elements The array viewed. + * @return The ArrayView to elements. + */ +template +ArrayView make_const_ArrayView(T (&elements)[Size]) { + return ArrayView(elements); +} + +/** + * Generate a const array view from a C/C++ pointer and the size of the array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param array_ptr The pointer to the array to view. + * @param array_size The size of the array. + * @return The ArrayView to array_ptr with a size of array_size. + */ +template +ArrayView make_const_ArrayView(T* array_ptr, size_t array_size) { + return ArrayView(array_ptr, array_size); +} + +} // namespace ble + +#endif /* BLE_ARRAY_VIEW_H_ */ diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h new file mode 100644 index 00000000000..f20f03c432a --- /dev/null +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -0,0 +1,77 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_TYPES_H_ +#define BLE_TYPES_H_ + +#include +#include + +namespace ble { + +/** + * A connection handle is an unsigned integer capable of holding a pointer. + * The real type (either a pointer to an object or an integer) is opaque and + * platform dependent. + */ +typedef uintptr_t connection_handle_t; + +/** + * Model an attribute handle in a GATT database. + */ +typedef uint16_t attribute_handle_t; + + + /** + * Model an inclusive range of GATT attributes handles. + */ +struct attribute_handle_range_t { + attribute_handle_t begin; + attribute_handle_t end; + + friend bool operator==( + const attribute_handle_range_t& lhs, const attribute_handle_range_t& rhs + ) { + return (lhs.begin == rhs.begin) && (lhs.end == rhs.end); + } + + friend bool operator!=( + const attribute_handle_range_t& lhs, const attribute_handle_range_t& rhs + ) { + return !(lhs == rhs); + } +}; + + +/** + * Construct an attribute_handle_range_t from its start and end handle. + * @note This function is defined instead of a constructor to keep "POD-ness" + * of attribute_handle_range_t. + */ +static inline attribute_handle_range_t attribute_handle_range( + attribute_handle_t begin, + attribute_handle_t end +) { + attribute_handle_range_t result = { + begin, + end + }; + return result; +} + +} // namespace ble + +#endif /* BLE_TYPES_H_ */ diff --git a/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h b/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h index 0349318b79e..e50180809a3 100644 --- a/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h +++ b/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h @@ -70,6 +70,11 @@ class CharacteristicDescriptorDiscovery { * status of the discovery operation */ ble_error_t status; + + /** + * error code associated with the status if any. + */ + uint8_t error_code; }; /** diff --git a/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h b/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h index 3529c360ad8..4fcd719dc95 100644 --- a/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h +++ b/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h @@ -22,7 +22,7 @@ #include "GattAttribute.h" #include "GattClient.h" #include "CharacteristicDescriptorDiscovery.h" -#include "ble/DiscoveredCharacteristicDescriptor.h" +#include "DiscoveredCharacteristicDescriptor.h" /** * @brief Representation of a characteristic discovered during a GattClient diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 5a01e4e9a4b..1f8c62cb69f 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -17,6 +17,7 @@ #ifndef __GAP_H__ #define __GAP_H__ +#include "BLETypes.h" #include "ble/BLEProtocol.h" #include "GapAdvertisingData.h" #include "GapAdvertisingParams.h" @@ -171,7 +172,7 @@ class Gap { /** * Type for connection handle. */ - typedef uint16_t Handle_t; + typedef ble::connection_handle_t Handle_t; /** * Structure containing GAP connection parameters. When in peripheral role diff --git a/features/FEATURE_BLE/ble/GattAttribute.h b/features/FEATURE_BLE/ble/GattAttribute.h index 119c68c173d..1011bc0d53c 100644 --- a/features/FEATURE_BLE/ble/GattAttribute.h +++ b/features/FEATURE_BLE/ble/GattAttribute.h @@ -18,6 +18,7 @@ #define __GATT_ATTRIBUTE_H__ #include "UUID.h" +#include "BLETypes.h" /** * Instances of this class encapsulate the data that belongs to a Bluetooth Low @@ -29,7 +30,7 @@ class GattAttribute { * Type for the handle or ID of the attribute in the ATT table. These are * unique and are usually generated by the underlying BLE stack. */ - typedef uint16_t Handle_t; + typedef ble::attribute_handle_t Handle_t; /** * Define the value of an invalid attribute handle. */ diff --git a/features/FEATURE_BLE/ble/GattCallbackParamTypes.h b/features/FEATURE_BLE/ble/GattCallbackParamTypes.h index 40c1e61dd67..d8eb362235d 100644 --- a/features/FEATURE_BLE/ble/GattCallbackParamTypes.h +++ b/features/FEATURE_BLE/ble/GattCallbackParamTypes.h @@ -17,6 +17,16 @@ #ifndef __GATT_CALLBACK_PARAM_TYPES_H__ #define __GATT_CALLBACK_PARAM_TYPES_H__ +/** + * Parameter of the callback invoked on a write operation. + * This parameter is used whether a GattServer as received a write operation or + * if the GattClient has completed a write operation. + * + * @important The fields connHandle, handle and writeOp are used in both + * callbacks while: + * - offset, len and data are reserved for GattServer write callbacks. + * - status and error_code are reserved for GattClient write callbacks. + */ struct GattWriteCallbackParams { /** * Enumeration for write operations. @@ -34,22 +44,48 @@ struct GattWriteCallbackParams { Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event. */ GattAttribute::Handle_t handle; /**< Attribute Handle to which the write operation applies. */ WriteOp_t writeOp; /**< Type of write operation. */ - uint16_t offset; /**< Offset for the write operation. */ - uint16_t len; /**< Length (in bytes) of the data to write. */ + + // Note: offset is used in GattServer while status is used in GattClient + union { + uint16_t offset; /**< Offset for the GattServer write operation. */ + ble_error_t status; /**< Status of the GattClient Write operation */ + }; + + // Note: len is used in GattServer while error_code is used in GattClient + union { + uint16_t len; /**< Length (in bytes) of the data to write (GattServer). */ + uint8_t error_code; /**< Error code of the GattClient Write operation */ + }; + /** * Pointer to the data to write. * * @note Data might not persist beyond the callback; make a local copy if * needed. + * @note This field is not used by callbacks invoked by the GattClient module. */ const uint8_t *data; }; +/** + * Parameter of the callback invoked on a read operation. + * This parameter is used whether a GattServer as received a read operation or + * if the GattClient has completed a read operation. + * + * @important The fields connHandle, handle and offset are used in both + * callbacks while: + * - len and data are reserved for GattServer read callbacks. + * - status and error_code are reserved for GattClient read callbacks. + */ struct GattReadCallbackParams { Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event. */ GattAttribute::Handle_t handle; /**< Attribute Handle to which the read operation applies. */ uint16_t offset; /**< Offset for the read operation. */ - uint16_t len; /**< Length (in bytes) of the data to read. */ + union { + uint16_t len; /**< Length (in bytes) of the data to read. */ + uint8_t error_code; /**< Error code if any (GattClient) */ + }; + /** * Pointer to the data read. * @@ -57,6 +93,7 @@ struct GattReadCallbackParams { * needed. */ const uint8_t *data; + ble_error_t status; /**< Status of the operation BLE_ERROR_NONE in case of success or the error in case of error */ }; enum GattAuthCallbackReply_t { diff --git a/features/FEATURE_BLE/ble/GattClient.h b/features/FEATURE_BLE/ble/GattClient.h index dc194f50b36..5f043ebb22a 100644 --- a/features/FEATURE_BLE/ble/GattClient.h +++ b/features/FEATURE_BLE/ble/GattClient.h @@ -80,6 +80,9 @@ class GattClient { * The following functions are meant to be overridden in the platform-specific sub-class. */ public: + + virtual ~GattClient() { } + /** * Launch service discovery. Once launched, application callbacks will be * invoked for matching services or characteristics. isServiceDiscoveryActive() diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h new file mode 100644 index 00000000000..8b525e8d06e --- /dev/null +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -0,0 +1,154 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_BLE_GENERIC_GATT_CLIENT +#define MBED_BLE_GENERIC_GATT_CLIENT + +#include +#include "ble/GattClient.h" +#include "ble/pal/PalGattClient.h" + +// IMPORTANT: private header. Not part of the public interface. + +namespace ble { +namespace generic { + +// forward declarations +struct procedure_control_block_t; +struct discovery_control_block_t; +struct read_control_block_t; +struct write_control_block_t; +struct descriptor_discovery_control_block_t; + +/** + * Generic implementation of the GattClient. + * It requires a pal::GattClient injected at construction site. + * @important: Not part of the public interface of BLE API. + */ +class GenericGattClient : public GattClient { + + // give access to control block classes + friend struct procedure_control_block_t; + friend struct discovery_control_block_t; + friend struct read_control_block_t; + friend struct write_control_block_t; + friend struct descriptor_discovery_control_block_t; + +public: + /** + * Create a GenericGattClient from a pal::GattClient + */ + GenericGattClient(pal::GattClient* pal_client); + + /** + * @see GattClient::launchServiceDiscovery + */ + virtual ble_error_t launchServiceDiscovery( + Gap::Handle_t connection_handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + const UUID& matching_service_uuid, + const UUID& matching_characteristic_uuid + ); + + /** + * @see GattClient::isServiceDiscoveryActive + */ + virtual bool isServiceDiscoveryActive() const; + + /** + * @see GattClient::terminateServiceDiscovery + */ + virtual void terminateServiceDiscovery(); + + /** + * @see GattClient::read + */ + virtual ble_error_t read( + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + uint16_t offset + ) const; + + /** + * @see GattClient::write + */ + virtual ble_error_t write( + GattClient::WriteOp_t cmd, + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + size_t length, + const uint8_t* value + ) const; + + /** + * @see GattClient::onServiceDiscoveryTermination + */ + virtual void onServiceDiscoveryTermination( + ServiceDiscovery::TerminationCallback_t callback + ); + + /** + * @see GattClient::discoverCharacteristicDescriptors + */ + virtual ble_error_t discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback + ); + + /** + * @see GattClient::isCharacteristicDescriptorDiscoveryActive + */ + virtual bool isCharacteristicDescriptorDiscoveryActive( + const DiscoveredCharacteristic& characteristic + ) const; + + /** + * @see GattClient::terminateCharacteristicDescriptorDiscovery + */ + virtual void terminateCharacteristicDescriptorDiscovery( + const DiscoveredCharacteristic& characteristic + ); + + /** + * @see GattClient::reset + */ + virtual ble_error_t reset(void); + +private: + procedure_control_block_t* get_control_block(Gap::Handle_t connection); + const procedure_control_block_t* get_control_block(Gap::Handle_t connection) const; + void insert_control_block(procedure_control_block_t* cb) const; + void remove_control_block(procedure_control_block_t* cb) const; + + void on_termination(Gap::Handle_t connection_handle); + void on_server_message_received(connection_handle_t, const pal::AttServerMessage&); + void on_server_response(connection_handle_t, const pal::AttServerMessage&); + void on_server_event(connection_handle_t, const pal::AttServerMessage&); + void on_transaction_timeout(connection_handle_t); + + uint16_t get_mtu(Gap::Handle_t connection) const; + + pal::GattClient* const _pal_client; + ServiceDiscovery::TerminationCallback_t _termination_callback; + mutable procedure_control_block_t* control_blocks; +}; + +} +} + +#endif /* MBED_BLE_GENERIC_GATT_CLIENT */ diff --git a/features/FEATURE_BLE/ble/pal/AttClient.h b/features/FEATURE_BLE/ble/pal/AttClient.h new file mode 100644 index 00000000000..56bd1a2f062 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttClient.h @@ -0,0 +1,687 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_PAL_ATTCLIENT_H_ +#define BLE_PAL_ATTCLIENT_H_ + +#include "ble/UUID.h" +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" +#include "ble/blecommon.h" +#include "platform/Callback.h" +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Send attribute protocol requests to an ATT server. It also handle reception + * of ATT response and server indication/notification. + * + * Every request send and response or response event received is for a specified + * connection. + * + * @warning This class should not be used outside mbed BLE, availability is not + * guaranteed for all ports. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F + */ +struct AttClient { + /** + * Initialization of the instance. An implementation can use this function + * to initialise the subsystems needed to realize the ATT operations of this + * interface. + * + * This function has to be called before any other operations. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t initialize() = 0; + + /** + * Termination of the instance. An implementation can use this function + * to release the subsystems initialised to realise the ATT operations of + * this interface. + * + * After a call to this function, initialise should be called again to + * allow usage of the interface. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t terminate() = 0; + + /** + * Send an exchange MTU request which negotiate the size of the MTU used by + * the connection. + * + * First the client send to the server the maximum rx mtu that it can receive + * then the client reply with the maximum rx mtu it can receive. + * + * The mtu choosen for the connection is the minimum of the client Rx mtu + * and server Rx mtu values. + * + * If an error occured then the mtu used remains the default value. + * + * @param connection The handle of the connection to send this request to. + * + * @return BLE_ERROR_NONE if the request has been succesfully sent or the + * appropriate error otherwise. + * + * @see ble::pal::AttExchangeMTUResponse The type of response received from + * the server + * @see ble::pal::AttErrorResponse::REQUEST_NOT_SUPPORTED The error code + * returned by the server in case of error. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.2.1 + */ + virtual ble_error_t exchange_mtu_request(connection_handle_t connection) = 0; + + /** + * Acquire the size of the mtu for a given connection. + * + * @param connection The handle of the connection for which the the MTU size + * should be acquired. + * + * @param mtu_size Output parameter which will contain the MTU size. + * + * @return BLE_ERROR_NONE if the MTU size has been acquired or the + * appropriate error otherwise. + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) = 0; + + /** + * Send a find information request to a server in order to obtain the + * mapping of attribute handles with their associated types. + * + * The server will reply with a ble::pal::AttFindInformationResponse + * containing at least one [attribute handle, attribute type] pair. If the + * last handle in the response is not equal to the end handle of the finding + * range then this request can be issued again with an updated range (begin + * equal to last handle received + 1) to discover the remaining attributes. + * + * To discover the whole ATT server, the first find information request + * should have a discovery range of [0x0001 - 0xFFFF]. + * + * The server can send a ble::pal::AttErrorResponse with the code + * ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND if no attributes have + * been found in the range specified. The attribute handle in the response + * is then equal to the first handle of the discovery range. + * + * If the range is malformed the server will reply a + * ble::pal::AttErrorResponse with the error code ble::pal::INVALID_HANDLE. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param discovery_range The attribute range where handle-type informations + * should be discovered. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.1 + */ + virtual ble_error_t find_information_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) = 0; + + /** + * Send a Find By Type Value Request which retrieve the handles of attributes + * that have known 16-bit UUID attribute type and known attribute value. + * + * The server should reply with a ble::pal::AttFindByTypeValueResponse + * containing the handle (or handle range in case of grouping attributes) of + * the attribute found. + * + * If not all attributes can be contained in the response it is necessary to + * send again this request with an updated range to continue the discovery. + * + * The server can send a ble::pal::AttErrorResponse with the code + * ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND if no attributes have + * been found in the range specified. The attribute handle in the response + * is then equal to the first handle of the discovery range. + * + * If the range is malformed the server will reply a + * ble::pal::AttErrorResponse with the error code ble::pal::INVALID_HANDLE. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param discovery_range The handle range where attributes with type and + * value are searched. + * @param type The type of attribute to find (it is a 16 bit UUID). + * @param value The value of the attributes to found. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.3 + */ + virtual ble_error_t find_by_type_value_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range, + uint16_t type, + const ArrayView& value + ) = 0; + + /** + * Send a Read By Type Request used to obtain the values of attributes where + * the attribute type is known but the handle is not known. + * + * If attributes with the type requested are present in the range, the server + * should reply with a ble::pal::AttReadByTypeResponse. If the response does + * not cover the full range, the request should be sent again with an updated + * range. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND: If there is no + * attributes matching type in the range. + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the range is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param read_range The handle range where attributes with the given type + * should be read. + * @param type The type of attributes to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.1 + */ + virtual ble_error_t read_by_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& type + ) = 0; + + /** + * Send a Read Request to read the value of an attribute in the server. + * + * In case of success, the server will reply with a ble::pal::AttReadResponse. + * containing the value of the attribute. If the length of the value in the + * response is equal to (mtu - 1) then the remaining part of the value can + * be obtained by a read_blob_request. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the attribute handle + * is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.3 + */ + virtual ble_error_t read_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) = 0; + + /** + * Send a read blob request to a server to read a part of the value of an + * attribute at a given offset. + * + * In case of success, the server will reply with a ble::pal::AttReadBlobResponse + * containing the value read. If the value of the attribute starting at the + * offset requested is longer than (mtu - 1) octets then only the first + * (mtu - 1) octets will be present in the response. + * The remaining octets can be acquired by another Read Blob Request with an + * updated index. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the attribute handle + * is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * - ble::pal::AttErrorResponse::INVALID_OFFSET: If the offset is greater + * than the attribute length. + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_LONG: If the attribute + * value has a length that is less than or equal to (mtu - 1). + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to read. + * @param offset The offset of the first octet to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.5 + */ + virtual ble_error_t read_blob_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) = 0; + + /** + * Send a read multiple request to the server. It is used to read two or more + * attributes values at once. + * + * In case of success, the server will reply with a + * ble::pal::AttReadMultipleResponse containing the concatenation of the + * values read. Given that values are concatained, all attributes values + * should be of fixed size except for the last one. The concatained value + * is also truncated to (mtu - 1) if it doesn't fit in the response. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If any of the attribute + * handle is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to read any of the attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to read any of the attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to read any of the + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to read any of the attributes. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If any of the + * attributes value cannot be read. + * The first attribute causing the error is reporter in the handle_in_error + * field in the error response. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handles Set of attribute handles to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.7 + */ + virtual ble_error_t read_multiple_request( + connection_handle_t connection_handle, + const ArrayView& attribute_handles + ) = 0; + + /** + * Send a read by group type request to the server. It is used to get + * informations about grouping attribute of a given type on a server. + * + * The server will reply with a ble::pal::ReadByGroupTypeResponse containing + * informations about the grouping attribute found. Informations are: + * - handle of the grouping attribute. + * - last handle of the group . + * - attribute value. + * + * If the last handle received is not the last handle of the discovery range + * then it is necessary to send another request with a discovery range + * updated to: [last handle + 1 : end]. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the range of handle + * provided is invalid. + * - ble::pal::AttErrorResponse::UNSUPPORTED_GROUP_TYPE: if the group type + * is not a supported grouping attribute. + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND: If no attribute with + * the given type exists within the range provided. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to read the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to read the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to read the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to read the requested attributes. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If any of the + * attributes value cannot be read. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param read_range Range where this request apply. + * @param group_type Type of the grouping attribute to find and read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.9 + */ + virtual ble_error_t read_by_group_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& group_type + ) = 0; + + /** + * Send a write request to the server to write the value of an attribute. + * + * In case of success, the server will reply with a + * ble::pal::AttWriteResponse to acknowledge that the write operation went + * well. + * + * If the attribute value has a variable length, then the attribute value + * shall be truncated or lengthened to match the length of the value in the + * request. + * + * If the attribute value has a fixed length and the Attribute Value parameter length + * is less than or equal to the length of the attribute value, the octets of the + * attribute value parameter length shall be written; all other octets in this attribute + * value shall be unchanged. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the handle to write is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to write the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to write the requested attributes. + * - ble::pal::AttErrorResponse::WRITE_NOT_PERMITTED: If the attribute + * value cannot be written due to permission. + * - ble::pal::AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: If the + * value to write exceeds the maximum valid length or of the attribute + * value; whether the attribute has a variable length value or a fixed + * length value. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 3). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.1 + */ + virtual ble_error_t write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a write command to the server. A write command is similar to a write + * request except that it won't receive any response from the server + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 3). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.3 + */ + virtual ble_error_t write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a signed write command to the server. Behaviour is similar to a write + * command except that 12 bytes of the mtu are reserved for the authentication + * signature. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 15). + * + * @note the authentication signature to send with this request is + * computed by the implementation following the rules defined in BLUETOOTH + * SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.1. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.4 + */ + virtual ble_error_t signed_write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * The Prepare Write Request is used to request the server to prepare to + * write the value of an attribute. The client can send multiple prepare + * write request which will be put in a queue until the client send an + * Execute Write Request which will execute sequentially the write request + * in the queue. + * + * In case of success the server will respond with a + * ble::pal::AttPrepareWriteResponse containing the values (attribute handle, + * offset and value) present in the write request. + * + * If a prepare write request is rejected by the server, the state queue of + * the prepare write request queue remains unaltered. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the handle to write is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to write the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to write the requested attributes. + * - ble::pal::AttErrorResponse::WRITE_NOT_PERMITTED: If the attribute + * value cannot be written due to permission. + * - ble::pal::PREPARE_QUEUE_FULL: If the queue of prepare write request + * is full. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to be written. + * @param offset The offset of the first octet to be written. + * @param value The value of the attribute to be written. It can't be longer + * than (mtu - 5). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.1 + * + */ + virtual ble_error_t prepare_write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset, + const ArrayView& value + ) = 0; + + /** + * Send an Execute Write Request to the server. This request will instruct + * the server to execute or cancel the prepare write requests currently held + * in the prepare queue from this client. + * + * If the execute parameter is set to true, the server should execute the + * request held in the queue. If the parameter is equal to false then the + * server should cancel the requests in the queue. + * + * In case of success, the server will respond with a + * ble::pal::AttExecuteWriteResponse indicating that the request was correctly + * handled. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_OFFSET: If the value offset is + * greater than the current length of the attribute to write. + * - ble::pal::AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: If the + * length of the value write exceeds the length of the attribute value + * about to be written. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * The error response will contains the attribute handle which as caused the + * error and the remaining of the prepare queue is discarded. The state of + * the attributes that were to be written from the prepare queue is not + * defined in this case. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param execute Boolean indicating if the prepare queue should be executed + * or cleared. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.3 + */ + virtual ble_error_t execute_write_request( + connection_handle_t connection_handle, + bool execute + ) = 0; + + /** + * Register a callback which will handle messages from the server. + * + * @param cb The callback object which will handle messages from the server. + * It accept two parameters in input: The handle of the connection where the + * message was received and the message received. Real type of the message + * can be obtained from its opcode. + */ + void when_server_message_received( + mbed::Callback cb + ) { + _server_message_cb = cb; + } + + /** + * Register a callback handling transaction timeout. + * + * @param cb The callback handling timeout of a transaction. It accepts as + * a parameter the connection handle involved in the timeout. + * + * @note No more attribute protocol requests, commands, indication or + * notification shall be sent over a connection implied in a transaction + * timeout. To send a new ATT message, the conenction should be + * reestablished. + */ + void when_transaction_timeout( + mbed::Callback cb + ) { + _transaction_timeout_cb = cb; + } + +protected: + AttClient() { } + + virtual ~AttClient() { } + + /** + * Upon server message reception an implementation shall call this function. + * + * @param connection_handle The handle of the connection which has received + * the server message. + * @param server_message The message received from the server. + */ + void on_server_event( + connection_handle_t connection_handle, + const AttServerMessage& server_message + ) { + if (_server_message_cb) { + _server_message_cb(connection_handle, server_message); + } + } + + /** + * Upon transaction timeout an implementation shall call this function. + * + * @param connection_handle The handle of the connection of the transaction + * which has times out. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.3 + */ + void on_transaction_timeout( + connection_handle_t connection_handle + ) { + if (_transaction_timeout_cb) { + _transaction_timeout_cb(connection_handle); + } + } + +private: + /** + * Callback called when the client receive a message from the server. + */ + mbed::Callback _server_message_cb; + + /** + * Callback called when a transaction times out. + */ + mbed::Callback _transaction_timeout_cb; + + // Disallow copy construction and copy assignment. + AttClient(const AttClient&); + AttClient& operator=(const AttClient&); +}; + + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_ATTCLIENT_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h new file mode 100644 index 00000000000..d99a55e4978 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h @@ -0,0 +1,297 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ +#define BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ + +#include "AttClient.h" +#include "PalGattClient.h" + +namespace ble { +namespace pal { + +/** + * Adapt a pal::AttClient into a pal::GattClient. + * + * This class let vendors define their abstraction layer in term of an AttClient + * and adapt any AttClient into a GattClient. + */ +class AttClientToGattClientAdapter : public GattClient { + +public: + static const uint16_t END_ATTRIBUTE_HANDLE = 0xFFFF; + static const uint16_t SERVICE_TYPE_UUID = 0x2800; + static const uint16_t INCLUDE_TYPE_UUID = 0x2802; + static const uint16_t CHARACTERISTIC_TYPE_UUID = 0x2803; + + /** + * Construct an instance of GattClient from an instance of AttClient. + * @param client The client to adapt. + */ + AttClientToGattClientAdapter(AttClient& client) : + GattClient(), _client(client) { + _client.when_server_message_received( + mbed::callback(this, &AttClientToGattClientAdapter::on_server_event) + ); + _client.when_transaction_timeout( + mbed::callback( + this, &AttClientToGattClientAdapter::on_transaction_timeout + ) + ); + } + + /** + * @see ble::pal::GattClient::exchange_mtu + */ + virtual ble_error_t exchange_mtu(connection_handle_t connection) { + return _client.exchange_mtu_request(connection); + } + + /** + * @see ble::pal::GattClient::get_mtu_size + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) { + return _client.get_mtu_size(connection_handle, mtu_size); + } + + /** + * @see ble::pal::GattClient::discover_primary_service + */ + virtual ble_error_t discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining + ) { + return _client.read_by_group_type_request( + connection, + attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE), + SERVICE_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_primary_service_by_service_uuid + */ + virtual ble_error_t discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_begining, + const UUID& uuid + ) { + return _client.find_by_type_value_request( + connection_handle, + attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE), + SERVICE_TYPE_UUID, + ArrayView( + uuid.getBaseUUID(), + (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) ? 2 : UUID::LENGTH_OF_LONG_UUID + ) + ); + } + + /** + * @see ble::pal::GattClient::find_included_service + */ + virtual ble_error_t find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range + ) { + return _client.read_by_type_request( + connection_handle, + service_range, + INCLUDE_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_characteristics_of_a_service + */ + virtual ble_error_t discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) { + return _client.read_by_type_request( + connection_handle, + discovery_range, + CHARACTERISTIC_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_characteristics_descriptors + */ + virtual ble_error_t discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range + ) { + return _client.find_information_request( + connection_handle, + descriptors_discovery_range + ); + } + + /** + * @see ble::pal::GattClient::read_attribute_value + */ + virtual ble_error_t read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) { + return _client.read_request( + connection_handle, + attribute_handle + ); + } + + /** + * @see ble::pal::GattClient::read_using_characteristic_uuid + */ + virtual ble_error_t read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid + ) { + return _client.read_by_type_request( + connection_handle, + read_range, + uuid + ); + } + + /** + * @see ble::pal::GattClient::read_attribute_blob + */ + virtual ble_error_t read_attribute_blob( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) { + return _client.read_blob_request( + connection_handle, + attribute_handle, + offset + ); + } + + /** + * @see ble::pal::GattClient::read_multiple_characteristic_values + */ + virtual ble_error_t read_multiple_characteristic_values( + connection_handle_t connection_handle, + const ArrayView& characteristic_value_handles + ) { + return _client.read_multiple_request( + connection_handle, + characteristic_value_handles + ); + } + + /** + * @see ble::pal::GattClient::write_without_response + */ + virtual ble_error_t write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) { + return _client.write_command( + connection_handle, + characteristic_value_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::signed_write_without_response + */ + virtual ble_error_t signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) { + return _client.signed_write_command( + connection_handle, + characteristic_value_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::write_attribute + */ + virtual ble_error_t write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + return _client.write_request( + connection_handle, + attribute_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::queue_prepare_write + */ + virtual ble_error_t queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ) { + return _client.prepare_write_request( + connection_handle, + characteristic_value_handle, + offset, + value + ); + } + + /** + * @see ble::pal::GattClient::execute_write_queue + */ + virtual ble_error_t execute_write_queue( + connection_handle_t connection_handle, + bool execute + ) { + return _client.execute_write_request(connection_handle, execute); + } + + /** + * @see ble::pal::GattClient::initialize + */ + virtual ble_error_t initialize() { + return _client.initialize(); + } + + /** + * @see ble::pal::GattClient::terminate + */ + virtual ble_error_t terminate() { + return _client.initialize(); + } + +private: + AttClient& _client; +}; + +} // namespace pal +} // namespace ble + + +#endif /* BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/AttServerMessage.h b/features/FEATURE_BLE/ble/pal/AttServerMessage.h new file mode 100644 index 00000000000..1862549673d --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttServerMessage.h @@ -0,0 +1,771 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_PAL_ATT_SERVER_MESSAGE_H_ +#define BLE_PAL_ATT_SERVER_MESSAGE_H_ + +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" + +namespace ble { +namespace pal { + +/** + * Operation code defined for attribute operations + * @note see: BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.8 + */ +struct AttributeOpcode { + enum Code { + ERROR_RESPONSE = 0x01, /// Opcode of an AttErrorResponse + EXCHANGE_MTU_REQUEST = 0x02, + EXCHANGE_MTU_RESPONSE = 0x03, /// OpCode of an AttExchangeMTUResponse + FIND_INFORMATION_REQUEST = 0x04, + FIND_INFORMATION_RESPONSE = 0x05, /// OpCode of an AttFindInformationResponse + FIND_BY_TYPE_VALUE_REQUEST = 0x06, + FIND_BY_VALUE_TYPE_RESPONSE = 0x07, /// OpCode of an AttFindByTypeValueResponse + READ_BY_TYPE_REQUEST = 0x08, + READ_BY_TYPE_RESPONSE = 0x09, /// Opcode of an AttReadByTypeResponse + READ_REQUEST = 0x0A, + READ_RESPONSE = 0x0B, /// Opcode of an AttReadResponse + READ_BLOB_REQUEST = 0x0C, + READ_BLOB_RESPONSE = 0x0D, /// Opcode of an AttReadBlobResponse + READ_MULTIPLE_REQUEST = 0x0E, + READ_MULTIPLE_RESPONSE = 0x0F, /// Opcode of an AttReadMultipleResponse + READ_BY_GROUP_TYPE_REQUEST = 0x10, + READ_BY_GROUP_TYPE_RESPONSE = 0x11, /// Opcode of an AttReadByGroupTypeResponse + WRITE_REQUEST = 0x12, + WRITE_RESPONSE = 0x13, /// Opcode of an AttWriteResponse + WRITE_COMMAND = 0x52, + SIGNED_WRITE_COMMAND = 0xD2, + PREPARE_WRITE_REQUEST = 0x16, + PREPARE_WRITE_RESPONSE = 0x17, /// Opcode of an AttPrepareWriteResponse + EXECUTE_WRITE_REQUEST = 0x18, + EXECUTE_WRITE_RESPONSE = 0x19, /// Opcode of an AttExecuteWriteResponse + HANDLE_VALUE_NOTIFICATION = 0x1B, + HANDLE_VALUE_INDICATION = 0x1D + }; + + /** + * Construct an AttributeOpcode from a Code. + */ + AttributeOpcode(Code value) : _value(value) { } + + /** + * Equality comparison operator between two AttributeOpcode + */ + friend bool operator==(AttributeOpcode lhs, AttributeOpcode rhs) { + return lhs._value == rhs._value; + } + + /** + * Non equality comparison operator between two AttributeOpcode + */ + friend bool operator!=(AttributeOpcode lhs, AttributeOpcode rhs) { + return lhs._value != rhs._value; + } + + /** + * implicit cast to uint8_t. + * Allows AttributeOpcode to be used in switch statements. + */ + operator uint8_t() const { + return _value; + } + +private: + uint8_t _value; +}; + + +/** + * Base class for Attribute Server Message. + * The correct type of the instance can be determined with the attribute opcode. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.1 + */ +struct AttServerMessage { + /** + * Op code used to identify the type of the attribute response. + */ + const AttributeOpcode opcode; + +protected: + /** + * Construction of an AttResponse is reserved for descendent of the class + */ + AttServerMessage(AttributeOpcode opcode_) : opcode(opcode_) { } +}; + + +/** + * Response to a request which can't be performed + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.1.1 + * for details about error response. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.9 + * which details possible error response by requests. + */ +struct AttErrorResponse : public AttServerMessage { + /** + * Construct an attribute error response. + * + * @param request_opcode_ The Attribute opcode of the request that generated + * the error. + * @param handle_in_error_ The attribute handle that generated this error + * response. + * @param error_code The reason why the request has generated an error. + */ + AttErrorResponse( + AttributeOpcode request_opcode_, + attribute_handle_t handle_in_error_, + uint8_t error_code_ + ) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE), + request_opcode(request_opcode_), + handle_in_error(handle_in_error_), error_code(error_code_) { + } + + /** + * Construct an attribute error response in the case where there was no + * attribute handle in the original response or if the request is not + * supported. + * + * @param request_opcode_ The Attribute opcode of the request that generated + * the error. + * @param error_code The reason why the request has generated an error. + */ + AttErrorResponse( + AttributeOpcode request_opcode_, + uint8_t error_code_ + ) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE), + request_opcode(request_opcode_), + handle_in_error(0x0000), error_code(error_code_) { + } + + /** + * The opcode of the request that generated this error response. + */ + const AttributeOpcode request_opcode; + + /** + * The attribute handle that generated this error response. + * If there was no attribute handle in the original request or if the + * request is not supported, then this field is equal to 0x0000. + */ + const attribute_handle_t handle_in_error; + + /** + * The reason why the request has generated an error response + */ + const uint8_t error_code; + + /** + * List of Error codes for the ATT protocol + */ + enum AttributeErrorCode { + /** The attribute handle given was not valid on this server. */ + INVALID_HANDLE = 0x01, + + /** The attribute cannot be read. */ + READ_NOT_PERMITTED = 0x02, + + /** The attribute cannot be written. */ + WRITE_NOT_PERMITTED = 0x03, + + /** The attribute PDU was invalid. */ + INVALID_PDU = 0x04, + + /** The attribute requires authentication before it can be read or + * written. + */ + INSUFFICIENT_AUTHENTICATION = 0x05, + + /** Attribute server does not support the request received from the + * client. + */ + REQUEST_NOT_SUPPORTED = 0x06, + + /** Offset specified was past the end of the attribute. */ + INVALID_OFFSET = 0x07, + + /** The attribute requires authorization before it can be read or written. */ + INSUFFICIENT_AUTHORIZATION = 0x08, + + /** Too many prepare writes have been queued. */ + PREPARE_QUEUE_FULL = 0x09, + + /** No attribute found within the given attribute handle range. */ + ATTRIBUTE_NOT_FOUND = 0x0A, + + /** The attribute cannot be read using the Read Blob Request. */ + ATTRIBUTE_NOT_LONG = 0x0B, + + /** The Encryption Key Size used for encrypting this link is + * insufficient. + */ + INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0x0C, + + /** The attribute value length is invalid for the operation. */ + INVALID_ATTRIBUTE_VALUE_LENGTH = 0x0D, + + /** The attribute request that was requested has encountered an error + * that was unlikely, and therefore could not be completed as requested. + */ + UNLIKELY_ERROR = 0x0E, + + /** The attribute requires encryption before it can be read or written. */ + INSUFFICIENT_ENCRYPTION = 0x0F, + + /** The attribute type is not a supported grouping attribute as defined + * by a higher layer specification. + */ + UNSUPPORTED_GROUP_TYPE = 0x10, + + /** Insufficient Resources to complete the request. */ + INSUFFICIENT_RESOURCES = 0x11, + + /* 0x12 - 0x7F => reserved for future use */ + + /* 0x80 - 0x9F => Application Error */ + + /* 0xA0 0xDF => Reserved for future use */ + + /* 0xE0 - 0xFF Common Profile and service Error Codes */ + + /** The Write Request Rejected error code is used when a requested write + * operation cannot be fulfilled for reasons other than permissions. + */ + WRITE_REQUEST_REJECTED = 0xFC, + + /** The Client Characteristic Configuration Descriptor Improperly + * Configured error code is used when a Client Characteristic + * Configuration descriptor is not configured according to the + * requirements of the profile or service. + */ + CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_IMPROPERLY_CONFIGURED = 0xFD, + + /** The Procedure Already in Progress error code is used when a profile + * or service request cannot be serviced because an operation that has + * been previously triggered is still in progress + */ + PROCEDURE_ALREADY_IN_PROGRESS = 0xFE, + + /** The Out of Range error code is used when an attribute value is out + * of range as defined by a profile or service specification. + */ + OUT_OF_RANGE = 0xFF + }; +}; + + +/** + * The Exchange MTU Request is used by the client to inform the server of the + * client’s maximum receive MTU size and request the server to respond with its + * maximum rx MTU size. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.2.2 + */ +struct AttExchangeMTUResponse : public AttServerMessage { + /** + * Construct an exchange mtu response containing the max rx mtu of the + * server. + * + * @param server_rx_mtu_ The max rx mtu the server can handle. + */ + AttExchangeMTUResponse(uint16_t server_rx_mtu_) : + AttServerMessage(AttributeOpcode::EXCHANGE_MTU_RESPONSE), + server_rx_mtu(server_rx_mtu_) { + } + + /** + * The max rx mtu the server can handle. + */ + const uint16_t server_rx_mtu; +}; + + +/** + * The Find Information Response is sent in reply to a received Find Information + * Request and contains information about this server. + * + * The Find Information Response contains a sequence of handle-uuid pairs in + * ascending order if attribute handles. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.2 + */ +struct AttFindInformationResponse : public AttServerMessage { + + /** handle-uuid pair */ + struct information_data_t { + attribute_handle_t handle; + UUID uuid; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttFindInformationResponse() : + AttServerMessage(AttributeOpcode::FIND_INFORMATION_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttFindInformationResponse() { } + + /** + * Returns the number of information_data_t present in the response. + */ + virtual size_t size() const = 0; + + /** + * Access to information_data_t elements present in the response. + * @note Out of range access is undefined. + */ + virtual information_data_t operator[](size_t index) const = 0; +}; + + +/** + * Find by type value responses are sent in response to find by type value + * request. + * + * The response contains a sequence of Found Attribute Handle, Group End Handle + * pair where: + * - Found Attribute Handle is the handle of an attribute matching the type + * and the value requested. + * - Group End Handle is the end of the attribute group if the attribute found + * is a grouping attribute or the same value as Found Attribute Handle if + * the attribute is not a grouping attribute. + * + * This class should be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.4 + */ +struct AttFindByTypeValueResponse : public AttServerMessage { + /** + * Base constructor, setup the OpCode of the response. + */ + AttFindByTypeValueResponse() : + AttServerMessage(AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttFindByTypeValueResponse() { } + + /** + * Returns the number of attribute_handle_range_t present in the response. + */ + virtual std::size_t size() const = 0; + + /** + * Access to the attribute range present in the response. + * @note Out of range access is undefined. + */ + virtual attribute_handle_range_t operator[](size_t index) const = 0; +}; + + +/** + * Response to a Read By Type request. + * + * It contains a list of handle-value pairs where: + * - handle is the handle of the attribute matching the rype requested. + * - value is the value of the attribute found. If the value is longer than + * (mtu - 4) then it can be truncated and read blob request should be used + * to read the remaining octet of the attribute. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.2 + */ +struct AttReadByTypeResponse : public AttServerMessage { + /** + * handle-value pair + */ + struct attribute_data_t { + attribute_handle_t handle; + ArrayView value; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttReadByTypeResponse() : + AttServerMessage(AttributeOpcode::READ_BY_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttReadByTypeResponse() { } + + /** + * Return the number of attribute_data_t presents in the response. + */ + virtual size_t size() const = 0; + + /** + * Return the attribute data at index. + * @note Out of range access is undefined. + */ + virtual attribute_data_t operator[](size_t index) const = 0; +}; + + +/** + * The read response is sent in reply to a received Read Request and contains + * the value of the attribute that has been read. + * + * The attribute value shall be set to the value of the attribute identified by + * the attribute handle in the request. If the attribute value is longer than + * (ATT_MTU-1) then the first (ATT_MTU-1) octets shall be included in this + * response. + * + * @note The Read Blob Request would be used to read the remaining octets of a + * long attribute value. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.4 + */ +struct AttReadResponse : public AttServerMessage { + /** + * Construct a Read Response from an array of bytes. + */ + AttReadResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + + /** + * Return the pointer to the actual data + */ + const uint8_t* data() const { + return _data.data(); + } + +private: + const ArrayView _data; +}; + + +/** + * The Read Blob Response is sent in reply to a received Read Blob Request and + * contains part of the value of the attribute that has been read. + * + * If the offset requested is equal to the length of the attribute then the + * response contains no data and the size of the data returned is equal to 0. + * + * If the value of the attribute starting at the offset requested is longer than + * (mtu - 1) octets then the first (mtu - 1) will be present in the response. + * The remaining octets will be acquired by another Read Blob Request with an + * updated index. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.6 + */ +struct AttReadBlobResponse : public AttServerMessage { + /** + * Construct a read blob response from the value responded. + */ + AttReadBlobResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_BLOB_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response value. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet of the value read at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + + /** + * Return the pointer to the actual data + */ + const uint8_t* data() const { + return _data.data(); + } + +private: + const ArrayView _data; +}; + + +/** + * Response to a Read Multiple Request. It contains the values of the attributes + * that have been read. + * + * If the set of values that has been read is longer than (mtu - 1) then only + * the first (mtu - 1) octets are included in the response. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.8 + */ +struct AttReadMultipleResponse : public AttServerMessage { + /** + * Construct a Resd Multiple Response from the set of value received. + */ + AttReadMultipleResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_MULTIPLE_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response set of value. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet of the set of value read at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + +private: + const ArrayView _data; +}; + + +/** + * The Read By Group Type Response is sent in reply to a received Read By + * Group Type Request and contains the handles and values of the attributes that + * have been read. + * + * The response is a list of group range-value pair where: + * - group range: The range of the group found where begin is the grouping + * attribute handle and end is the handle of the end of the group. + * - value: The value of the grouping attribute. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note The value responded can be trucated if it doesn't fit in the response, + * in that case a Read Blob Request could be used to read the remaining octets. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.10 + */ +struct AttReadByGroupTypeResponse : public AttServerMessage { + /** + * Data read from the grouping attribute. + * It includes the range of the group and the value of the attribute. + */ + struct attribute_data_t { + attribute_handle_range_t group_range; + ArrayView value; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttReadByGroupTypeResponse() : + AttServerMessage(AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttReadByGroupTypeResponse() { } + + /** + * Return the number of attribute_data_t present in the response. + */ + virtual size_t size() const = 0; + + /** + * Return the attribute data read at the index specified. + * @note Out of range access is undefined. + */ + virtual attribute_data_t operator[](size_t index) const = 0; +}; + + +/** + * The Write Response is sent in reply to a valid Write Request and + * acknowledges that the attribute has been successfully written. + * It is just a placeholder which indicates the client that the write request + * was successful. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.2 + */ +struct AttWriteResponse : public AttServerMessage { + /** + * Construct a write response. + */ + AttWriteResponse() : AttServerMessage(AttributeOpcode::WRITE_RESPONSE) { } +}; + + +/** + * Response to a Prepare Write Request. It acknowledges the client that the + * value has been successfully received and placed in the write queue. + * + * The response contains the same values as the one present in the request. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.2 + */ +struct AttPrepareWriteResponse : public AttServerMessage { + /** + * Construct a prepare write response. + * @param handle_ The handle of the attribute to be written. + * @param offset_: The offset of the first octet to be writen. + * @param value_: The value of the attribute to be written at the offset + * indicated. + */ + AttPrepareWriteResponse( + attribute_handle_t handle_, + uint16_t offset_, + ArrayView value_ + ) : AttServerMessage(AttributeOpcode::PREPARE_WRITE_RESPONSE), + attribute_handle(handle_), + offset(offset_), + partial_value(value_) { + } + + /** + * The handle of the attribute to be written. + */ + const attribute_handle_t attribute_handle; + + /** + * The offset of the first octet to be writen. + */ + const uint16_t offset; + + /** + * The value of the attribute to be written at the offset indicated. + */ + const ArrayView partial_value; +}; + + +/** + * The Execute Write Response is sent in response to a received Execute Write + * Request. + * + * It is just a placeholder which indicates the client that the execution of the + * write request has been successfull. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.4 + */ +struct AttExecuteWriteResponse : public AttServerMessage { + /** + * Construct an execute write response object. + */ + AttExecuteWriteResponse() : + AttServerMessage(AttributeOpcode::EXECUTE_WRITE_RESPONSE) { + } +}; + + +/** + * Notification of an attribute's value sent by the server. + * + * It contains the handle of the attribute and its value. + * + * If the attribute value is longer than (mtu - 3) then the value is truncated + * to (mtu - 3) octets to fit in the response and the client will have to use + * a read blob request to read the remaining octets of the attribute. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.1 + */ +struct AttHandleValueNotification : public AttServerMessage { + /** + * Construct an Handle Value Notification from the attribute handle and its + * value notified. + */ + AttHandleValueNotification( + attribute_handle_t attribute_handle, + ArrayView attribute_value + ) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_NOTIFICATION), + attribute_handle(attribute_handle), + attribute_value(attribute_value) { + } + + /** + * Handle of the attribute + */ + const attribute_handle_t attribute_handle; + + /** + * The current value of the attribute. + */ + const ArrayView attribute_value; +}; + + +/** + * Indication of an attribute's value sent by the server. + * + * It contains the handle of the attribute and its value. The client should + * respond with and handle value confirmation. + * + * If the attribute value is longer than (mtu - 3) then the value is truncated + * to (mtu - 3) octets to fit in the response and the client will have to use + * a read blob request to read the remaining octets of the attribute. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.2 + */ +struct AttHandleValueIndication : public AttServerMessage { + /** + * Construct an Handle Value Indication from the attribute handle and its + * value indicated. + */ + AttHandleValueIndication( + attribute_handle_t handle, ArrayView value + ) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_INDICATION), + attribute_handle(handle), attribute_value(value) { + } + + /** + * Handle of the attribute + */ + const attribute_handle_t attribute_handle; + + /** + * The current value of the attribute. + */ + const ArrayView attribute_value; +}; + + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_ATT_SERVER_MESSAGE_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h new file mode 100644 index 00000000000..2152c428f43 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -0,0 +1,642 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_PAL_GATT_CLIENT_H_ +#define BLE_PAL_GATT_CLIENT_H_ + +#include "ble/UUID.h" +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" +#include "ble/blecommon.h" + +#include "platform/Callback.h" + +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Adaptation layer for a GATT client. + * + * Define the primitive necessary to implement a proper GATT client. These + * primitives are sometime GATT procedure, ATT procedure or a bit of both. + * + * In general, discovery procedures follow strictly GATT formulation while + * attribute manipulation procedures (read/write) follow the ATT formulation + * to avoid multiple identical implementation for characteristic values and + * characteristic descriptors value, it also fill a hole leave by the + * specification which doesn't define any GATT procedure to get the UUID of an + * included service with a 128 bit UUID. + * + * Complementary informations around ATT procedures can be found in the Section + * 3.4 of the Vol3, Part F of the Bluetooth specification while more informations + * around the GATT procedures can be found in the Section 4 of the Vol 3, Part + * G of the Bluetooth specification. + * + * Complete and compliant Gatt Client used by developer is realized at an higher + * level using the primitives defined in this adaptation layer. + * + * If a stack expose the complete ATT layer then it is possible to provide an + * implementation for GattClient by subclassing the AttClient class and use + * the class AttClientToGattClientAdapter + */ +class GattClient { + +public: + /** + * Initialisation of the instance. An implementation can use this function + * to initialise the subsystems needed to realize the operations of this + * interface. + * + * This function has to be called before any other operations. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t initialize() = 0; + + /** + * Termination of the instance. An implementation can use this function + * to release the subsystems initialised to realise the operations of + * this interface. + * + * After a call to this function, initialise should be called again to + * allow usage of the interface. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t terminate() = 0; + + /** + * Negotiate the mtu to use by this connection. + * First the client send to the server the maximum rx mtu that it can receive + * then the client reply with the maximum rx mtu it can receive. + * The mtu chosen for the connection is the minimum of the client Rx mtu + * and server Rx mtu values. + * + * If an error occurred then the mtu used remains the default value. + * + * The server will reply to this request with an AttExchangeMTUResponse in + * case of success or AttErrorResponse in case of failure. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.3.1 + * + * @param connection The handle of the connection to send this request to. + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t exchange_mtu(connection_handle_t connection) = 0; + + /** + * Acquire the size of the mtu for a given connection. + * + * @param connection The handle of the connection for which the the MTU size + * should be acquired. + * + * @param mtu_size Output parameter which will contain the MTU size. + * + * @return BLE_ERROR_NONE if the MTU size has been acquired or the + * appropriate error otherwise. + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) = 0; + + /** + * Discover primary services in the range [begin - 0xFFFF]. + * + * If services exists in the range provided, the server will reply with a + * ReadByGoupType response where for each attribute_data exposed: + * - attribute_handle is the service attribute handle + * - end_group_handle is the last handle of the service + * - attribute_value is the UUID of the service. + * + * If the end of the range is not reached, this procedure can be relaunched + * with the last handle of the last service discovered plus one as the + * beginning of the discovery range. + * + * If there is not services left to discover in the range, the server can + * either: + * * Reply with an ErrorResponse with the Error code set to ATTRIBUTE_NOT_FOUND + * * Set the end handle of the last service to 0xFFFF. + * + * @note This function realize a partial implementation of the Discover All + * Primary Services procedure. The complete implementation of the procedure + * is realized at an higher level. + * @note This function issue a Read By Group Type ATT request where the + * type parameter is equal to Primary Service and the Ending Handle parameter + * is equal to 0xFFFF. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.1 + * + * @param connection The handle of the connection to send this request to. + * @param begin The beginning of the discovery range. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining + ) = 0; + + /** + * Discover primary services by UUID in the range [discovery_range_begining - 0xFFFF]. + * + * If services exists in the range provided, the server will reply with a + * FindByTypeValueResponse containing the attribute range of each service + * discovered. + * + * If the end of the range is not reached, this procedure can be relaunched + * with the last handle of the last service discovered plus one as the + * beginning of the discovery range. + * + * If there is not services left to discover in the range, the server can + * either: + * * Reply with an ErrorResponse with the Error code set to ATTRIBUTE_NOT_FOUND + * * Set the end handle of the last service to 0xFFFF. + * + * @note This function realize a partial implementation of the Discover + * Primary Service by Service UUID procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Find By Type Value ATT request where the + * type parameter is equal to Primary Service and the Ending Handle + * parameter is equal to 0xFFFF. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.2 + * + * @param connection The handle of the connection to send this request to. + * @param begin The beginning of the discovery range. + * @param uuid The UUID of the service to discover. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_beginning, + const UUID& uuid + ) = 0; + + /** + * Find included services within a service. + * + * If services are included in the service range then the server will reply + * with a ReadByTypeResponse where for each attribute record: + * - attribute_handle The handle where the service is included within the + * service definition. + * - attribute_data Contains two handles defining the range of the included. + * If the service found have a 16 bit uuid then its UUID is also included + * in the attribute data. + * + * If the end of the service range is not reached, this procedure can be + * relaunched with the handle of the last included service discovered plus + * one as the beginning of the new discovery range. + * + * The procedure is complete when either: + * - The server reply with an ErrorResponse with the Error code set to + * ATTRIBUTE_NOT_FOUND + * - An included service handle returned is equal to the end of the range. + * + * If the service UUID is a 128 bits one then it is necessary to issue a read + * attribute request on the first handle of the service discovered to get it. + * + * @note This function realize a partial implementation of the Find Included + * Services procedure. The complete implementation of the procedure is + * realized at an higher level. + * @note This function issue a Read By Type ATT request where the + * type parameter is equal to Include. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.5.1 + * + * @param connection The handle of the connection to send this request to. + * @param service_range The range of the service where service inclusion has + * to be discovered. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range + ) = 0; + + /** + * Find characteristic declarations within a service definition. + * + * If characteristic declarations are found within the range then the server + * should reply with a ReadByTypeResponse where for each attribute record: + * - attribute_handle is the handle of the characteristic definition + * - attribute_data contains the the following values attached to the + * characteristic : + * + properties: the properties of the characteristic. + * + value handle: the handle of the value of the characteristic. + * + uuid: the UUID of the characteristic. + * + * The procedure is considered complete when the server send an ErrorResponse + * with the ErrorCode set to ATTRIBUTE_NOT_FOUND or a ReadByType response + * has an attribute_handle set to the end of the discovery range. + * + * If the procedure is not complete after a server response, it should be + * relaunched with an updated range starting at the last attribute_handle + * discovered plus one. + * + * @note This function realize a partial implementation of the Discover All + * Characteristics of a Service procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Read By Type ATT request where the type + * parameter is equal to Characteristic. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.6.1 + * + * @note The GATT procedure Discover Characteristics by UUID is implemented + * at a higher level using this function as a base. + * + * @param connection The handle of the connection to send this request to. + * @param discovery_range The range of attributes where the characteristics + * are discovered. It should be contained within a service. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) = 0; + + /** + * Discover characteristic descriptors of a characteristic. + * + * If descriptors are found within the range provided then the server should + * reply with a FindInformationResponse containing a list of + * attribute_handle_t, UUID pairs where the attribute handle is the + * descriptor handle and UUID is the UUID of the descriptor. + * + * The procedure is complete when the server send an ErrorResponse with the + * error code ATTRIBUTE_NOT_FOUND or the FindInformationResponse has an + * attribute handle that is equal to the end handle of the discovery range. + * + * @note This function realize a partial implementation of the Discover All + * Characteristics Descriptors procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Find Information ATT request.. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.7.1 + * + * @note It should be possible to use this function to issue a regular + * ATT Find Information Request. + * + * @param connection The handle of the connection to send this request to. + * @param descriptors_discovery_range The range of attributes where the + * descriptors are discovered. The first handle shall be no less than the + * characteristic value handle plus one and the last handle shall be no more + * than the last handle of the characteristic. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range + ) = 0; + + /** + * Read the value of an attribute. + * + * The server will reply with an AttReadResponse. In case of error, the + * server will reply with an AttErrorResponse. + * + * @note This function issue an ATT Read Request. + * + * @note: This function is the base function for the read Characteristic + * Value and Read Characteristic Descriptor GATT procedures. It can also + * be used to read the 128 bit UUID of a service discovered with + * find_included_service. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.1 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.1 + * + * @param connection The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) = 0; + + /** + * Read a characteristic value using its UUID (type). + * + * The server will respond a ReadByTypeResponse containing a sequence of + * attribute handle and attribute value pairs. + * To read remaining attributes, the client should launch a new request + * with an updated range. + * + * The procedure is considered complete when the server respond with an + * ErrorResponse containing the ErrorCode ATTRIBUTE_NOT_FOUND or when an + * handle in the ReadByTypeResponse is equal to the end of the discovered + * range. + * + * @note This function realize a partial implementation of the Read Using + * Characteristics Characteristic procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Read By Type ATT request. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.2 + * + * @note It should be possible to use this function to issue a regular + * ATT Read By Type Request. + * + * @param connection The handle of the connection to send this request to. + * @param attribute_range Range of the handle where an attribute with + * uuid as type is present. + * @param uuid UUID of the characteristic(s) to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid + ) = 0; + + /** + * Read a partial value of an attribute. + * + * The server will respond with a ReadBlobResponse containing the data read + * or an ErrorResponse in case of error. + * + * The procedure is not complete as long as the value in response have the + * same size as the mtu minus one. If the procedure is not complete, it can + * be launch again with an updated offset to read the remaining part of the + * attribute value. + * + * @note This function issue an ATT Read Blob Request. + * + * @note: This function is the base function for the Read Long + * Characteristic Value and Read Long Characteristic Descriptor GATT + * procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.2 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to read. + * @param offset Beginning offset for the read operation. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_attribute_blob( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) = 0; + + /** + * Read atomically multiple characteristics values. + * + * The server will respond with a ReadMultiple response containing the + * concatenation of the values of the characteristics. + * + * @note values might be truncated + * + * In case of error, the server should respond a with an ErrorResponse. + * + * @note This function issue an ATT Read Multiple Request. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.4 + * + * @param connection_handle The handle of the connection to send this request to. + * @param characteristic_value_handles Handle of the characteristic values + * to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_multiple_characteristic_values( + connection_handle_t connection_handle, + const ArrayView& characteristic_value_handles + ) = 0; + + /** + * Send a write command to the server. + * + * @note This function issue an ATT Write Command. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.1 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) = 0; + + /** + * Send a Signed Write without Response command to the server. + * + * @note This function issue an ATT Write Command with the signed flag and + * the signature. + * + * @note signature is calculated by the stack. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.2 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) = 0; + + /** + * Send a write request to the server. + * + * The server should respond with a WriteResponse in case of success or an + * ErrorResponse in case of error. + * + * @note This function issue an ATT Write Request. + * + * @note: This function is the base function for the Write Characteristic + * Value and Write Characteristic Descriptors GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.3 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a prepare write request to the server. + * + * The write request will go into a queue until the client execute or cancel + * the request with an execute write request which will write all the values + * in the queue atomically. + * + * The server should respond with a PrepareWriteResponse containing the + * content of the request in case of success and an ErrorResponse in case of + * error. + * + * If an ErrorResponse is received it doesn't invalidate what is already in + * the queue. + * + * @note This function issue an ATT Prepare Write Request. + * + * @note: This function is one of the base function for the Write Long + * Characteristic Value and Reliable Writes GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.4 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.5 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * @param offset offset where the value should be written. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ) = 0; + + /** + * Send a request to the server to execute the queue of prepared write + * requests. + * + * The server should respond with an ExecuteWriteResponse in case of success + * and an Error response in case of failure. + * + * @note This function issue an ATT Execute Write Request. + * + * @note: This function is one of the base function for the Write Long + * Characteristic Value and Reliable Writes GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.4 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.5 + * + * @param connection_handle The handle of the connection to send this request to. + * @param execute If true, execute the write request queue otherwise cancel it. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t execute_write_queue( + connection_handle_t connection_handle, + bool execute + ) = 0; + + /** + * Register a callback which will handle messages from the server. + * + * @param cb The callback object which will handle messages from the server. + * It accept two parameters in input: The handle of the connection where the + * message was received and the message received. Real type of the message + * can be obtained from its opcode. + */ + void when_server_message_received( + mbed::Callback cb + ) { + _server_message_cb = cb; + } + + /** + * Register a callback handling transaction timeout. + * + * @param cb The callback handling timeout of a transaction. It accepts as + * a parameter the connection handle involved in the timeout. + * + * @note No more attribute protocol requests, commands, indication or + * notification shall be sent over a connection implied in a transaction + * timeout. To send a new ATT message, the conenction should be + * reestablished. + */ + void when_transaction_timeout( + mbed::Callback cb + ) { + _transaction_timeout_cb = cb; + } + +protected: + GattClient() { } + + virtual ~GattClient() { } + + /** + * Upon server message reception an implementation shall call this function. + * + * @param connection_handle The handle of the connection which has received + * the server message. + * @param server_message The message received from the server. + */ + void on_server_event( + connection_handle_t connection_handle, + const AttServerMessage& server_message + ) { + if (_server_message_cb) { + _server_message_cb(connection_handle, server_message); + } + } + + /** + * Upon transaction timeout an implementation shall call this function. + * + * @param connection_handle The handle of the connection of the transaction + * which has times out. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.14 + */ + void on_transaction_timeout( + connection_handle_t connection_handle + ) { + if (_transaction_timeout_cb) { + _transaction_timeout_cb(connection_handle); + } + } + +private: + /** + * Callback called when the client receive a message from the server. + */ + mbed::Callback _server_message_cb; + + /** + * Callback called when a transaction times out. + */ + mbed::Callback _transaction_timeout_cb; + + // Disallow copy construction and copy assignment. + GattClient(const GattClient&); + GattClient& operator=(const GattClient&); +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_GATT_CLIENT_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h b/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h new file mode 100644 index 00000000000..a0f3346dead --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h @@ -0,0 +1,232 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ +#define BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ + +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Simple implementation of ble::pal::AttFindInformationResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttFindInformationResponse : public AttFindInformationResponse { + /** + * Format of the UUID in the response. + */ + enum Format { + FORMAT_16_BIT_UUID = 0x01,//!< FORMAT_16_BIT_UUID + FORMAT_128_BIT_UUID = 0x02//!< FORMAT_128_BIT_UUID + }; + + /** + * Construct an AttFindInformationResponse from format and an array of bytes + * containing the information data. + * @param format The format of the information data. + * @param information_data The information data whose format is determined + * by the Format field + */ + SimpleAttFindInformationResponse( + Format format, ArrayView information_data + ) : AttFindInformationResponse(), + _format(format), _information_data(information_data), + _item_size(information_data_item_size()) { + } + + /** + * @see ble::pal::AttFindInformationResponse::size + */ + virtual size_t size() const { + return _information_data.size() / _item_size; + } + + /** + * @see ble::pal::AttFindInformationResponse::operator[] + */ + virtual information_data_t operator[](size_t index) const { + const uint8_t* item = &_information_data[index * _item_size]; + + information_data_t result; + memcpy(&result.handle, item, sizeof(result.handle)); + + if (_format == FORMAT_16_BIT_UUID) { + uint16_t short_uuid = 0; + memcpy(&short_uuid, item + 2, sizeof(short_uuid)); + result.uuid = UUID(short_uuid); + } else { + result.uuid = UUID(item + 2, UUID::LSB); + } + + return result; + } + +private: + size_t information_data_item_size() const { + return sizeof(attribute_handle_t) + ((_format == FORMAT_16_BIT_UUID) ? 2 : 16); + } + + const Format _format; + const ArrayView _information_data; + const size_t _item_size; +}; + + +/** + * Simple implementation of ble::pal::AttFindByTypeValueResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttFindByTypeValueResponse : public AttFindByTypeValueResponse { + /** + * Construct a AttFindByTypeValueResponse from a raw array containing the + * Handle Informations. + * @param handles raw array containing one or more Handle Informations. + */ + SimpleAttFindByTypeValueResponse(ArrayView handles) : + AttFindByTypeValueResponse(), _handles(handles) { + } + + /** + * @see ble::pal::AttFindByTypeValueResponse::size + */ + virtual std::size_t size() const { + return _handles.size() / item_size; + } + + /** + * @see ble::pal::AttFindByTypeValueResponse::operator[] + */ + virtual attribute_handle_range_t operator[](size_t index) const { + attribute_handle_range_t result; + const uint8_t* item = &_handles[index * item_size]; + memcpy(&result.begin, item, sizeof(result.begin)); + memcpy(&result.end, item + sizeof(result.begin), sizeof(result.end)); + return result; + } + +private: + static const size_t item_size = 4; + const ArrayView _handles; +}; + + +/** + * Simple implementation of ble::pal::AttReadByTypeResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttReadByTypeResponse : public AttReadByTypeResponse { + /** + * Construct an AttReadByTypeResponse from the size of each attribute + * handle-value pair and a list of attribute data. + * @param element_size The size of each attribute-handle pair. + * @param attribute_data Raw bytes array containing the list of attribute + * data. + */ + SimpleAttReadByTypeResponse( + uint8_t element_size, ArrayView attribute_data + ) : AttReadByTypeResponse(), + _attribute_data(attribute_data), _element_size(element_size) { + } + + /** + * @see ble::pal::AttReadByTypeResponse::size + */ + virtual size_t size() const { + return _attribute_data.size() / _element_size; + } + + /** + * @see ble::pal::AttReadByTypeResponse::operator[] + */ + virtual attribute_data_t operator[](size_t index) const { + const uint8_t* item = &_attribute_data[index * _element_size]; + uint16_t handle; + memcpy(&handle, item, sizeof(handle)); + + attribute_data_t result = { + handle, + ArrayView( + item + sizeof(handle), + _element_size - sizeof(handle) + ) + }; + + return result; + } + +private: + ArrayView _attribute_data; + uint8_t _element_size; +}; + + +/** + * Simple implementation of ble::pal::AttReadByGroupTypeResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttReadByGroupTypeResponse : public AttReadByGroupTypeResponse { + /** + * Construct an instance of AttReadByGroupTypeResponse from the size of each + * attribute data and a byte array containing the list of attribute data. + * @param element_size The size of each Attribute Data + * @param attribute_data Byte array containing the list of Attribute Data. + */ + SimpleAttReadByGroupTypeResponse( + uint8_t element_size, ArrayView attribute_data + ) : AttReadByGroupTypeResponse(), + _attribute_data(attribute_data), _element_size(element_size) { + } + + /** + * @see ble::pal::AttReadByGroupTypeResponse::size + */ + virtual size_t size() const { + return _attribute_data.size() / _element_size; + } + + /** + * @see ble::pal::AttReadByGroupTypeResponse::operator[] + */ + virtual attribute_data_t operator[](size_t index) const { + const uint8_t* item = &_attribute_data[index * _element_size]; + uint16_t begin; + uint16_t end; + + memcpy(&begin, item, sizeof(begin)); + memcpy(&end, item + sizeof(begin), sizeof(end)); + + attribute_data_t result = { + { begin, end }, + ArrayView( + item + sizeof(begin) + sizeof(end), + _element_size - (sizeof(begin) + sizeof(end)) + ) + }; + + return result; + } + +private: + ArrayView _attribute_data; + uint8_t _element_size; +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ */ diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp new file mode 100644 index 00000000000..595babcccc0 --- /dev/null +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -0,0 +1,1342 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include "ble/generic/GenericGattClient.h" +#include "ble/blecommon.h" +#include + +using ble::pal::AttServerMessage; +using ble::pal::AttReadResponse; +using ble::pal::AttReadBlobResponse; +using ble::pal::AttReadByTypeResponse; +using ble::pal::AttReadByGroupTypeResponse; +using ble::pal::AttFindByTypeValueResponse; +using ble::pal::AttErrorResponse; +using ble::pal::AttributeOpcode; +using ble::pal::AttWriteResponse; +using ble::pal::AttPrepareWriteResponse; +using ble::pal::AttExecuteWriteResponse; +using ble::pal::AttHandleValueIndication; +using ble::pal::AttHandleValueNotification; +using ble::pal::AttFindInformationResponse; + +namespace ble { +namespace generic { + +/* + * Type of procedures which can be launched by the client. + */ +enum procedure_type_t { + COMPLETE_DISCOVERY_PROCEDURE, + READ_PROCEDURE, + WRITE_PROCEDURE, + DESCRIPTOR_DISCOVERY_PROCEDURE +}; + + +/* + * Base class for a procedure control block + */ +struct procedure_control_block_t { + /* + * Base constructor for procedure control block. + */ + procedure_control_block_t(procedure_type_t type, Gap::Handle_t handle) : + type(type), connection_handle(handle), next(NULL) { } + + virtual ~procedure_control_block_t() { } + + /* + * Entry point of the control block stack machine. + */ + virtual void handle(GenericGattClient* client, const AttServerMessage& message) = 0; + + /* + * Function call in case of timeout + */ + virtual void handle_timeout_error(GenericGattClient* client) = 0; + + procedure_type_t type; + Gap::Handle_t connection_handle; + procedure_control_block_t* next; +}; + + +/* + * Procedure control block for the discovery process. + */ +struct discovery_control_block_t : public procedure_control_block_t { + discovery_control_block_t( + Gap::Handle_t handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + UUID matching_service_uuid, + UUID matching_characteristic_uuid + ) : procedure_control_block_t(COMPLETE_DISCOVERY_PROCEDURE, handle), + service_callback(service_callback), + characteristic_callback(characteristic_callback), + matching_service_uuid(matching_service_uuid), + matching_characteristic_uuid(matching_characteristic_uuid), + services_discovered(NULL), + done(false) { + } + + virtual ~discovery_control_block_t() { + while(services_discovered) { + service_t* tmp = services_discovered->next; + delete services_discovered; + services_discovered = tmp; + } + } + + virtual void handle_timeout_error(GenericGattClient* client) { + terminate(client); + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + // if end of discovery has been requested, ends it immediately + if (done) { + terminate(client); + return; + } + + switch(message.opcode) { + case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE: + handle_service_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE: + handle_service_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::READ_BY_TYPE_RESPONSE: + handle_characteristic_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::ERROR_RESPONSE: { + const AttErrorResponse& error = static_cast(message); + if (error.error_code != AttErrorResponse::ATTRIBUTE_NOT_FOUND) { + terminate(client); + } + + switch (error.request_opcode) { + case AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST: + case AttributeOpcode::FIND_BY_TYPE_VALUE_REQUEST: + start_characteristic_discovery(client); + break; + case AttributeOpcode::READ_BY_TYPE_REQUEST: + handle_all_characteristics_discovered(client); + break; + default: + // error + break; + } + } break; + default: + // error + break; + } + } + + template + void handle_service_discovered(GenericGattClient* client, const Response& response) { + if (!response.size()) { + terminate(client); + return; + } + + uint16_t end_handle = 0x0000; + for (size_t i = 0; i < response.size(); ++i) { + uint16_t start_handle = get_start_handle(response[i]); + end_handle = get_end_handle(response[i]); + UUID uuid = get_uuid(response[i]); + + if (!characteristic_callback) { + DiscoveredService discovered_service; + discovered_service.setup(uuid, start_handle, end_handle); + service_callback(&discovered_service); + } else { + service_t* discovered_service = new (std::nothrow) service_t( + start_handle, end_handle, uuid + ); + + if (discovered_service == NULL) { + terminate(client); + return; + } + + insert_service(discovered_service); + } + } + + if (end_handle == 0xFFFF) { + start_characteristic_discovery(client); + } else { + ble_error_t err = client->_pal_client->discover_primary_service( + connection_handle, end_handle + 1 + ); + + if (err) { + terminate(client); + } + } + } + + void start_characteristic_discovery(GenericGattClient* client) { + if (!services_discovered) { + terminate(client); + return; + } + + if (!characteristic_callback) { + terminate(client); + return; + } + + if (service_callback) { + DiscoveredService discovered_service; + discovered_service.setup( + services_discovered->uuid, + services_discovered->begin, + services_discovered->end + ); + service_callback(&discovered_service); + } + + last_characteristic = characteristic_t(); + client->_pal_client->discover_characteristics_of_a_service( + connection_handle, + attribute_handle_range( + services_discovered->begin, + services_discovered->end + ) + ); + } + + void handle_characteristic_discovered(GenericGattClient* client, const AttReadByTypeResponse& response) { + for (size_t i = 0; i < response.size(); ++i) { + if (last_characteristic.is_valid() == false) { + last_characteristic.set_last_handle(response[i].handle - 1); + if (matching_characteristic_uuid == UUID() + || last_characteristic.getUUID() == matching_characteristic_uuid) { + characteristic_callback(&last_characteristic); + } + } + + last_characteristic = characteristic_t( + client, connection_handle, response[i].handle, response[i].value + ); + } + + // check if all the characteristics of the service has been discovered + if (last_characteristic.getValueHandle() == services_discovered->end) { + handle_all_characteristics_discovered(client); + } else { + ble_error_t err = client->_pal_client->discover_characteristics_of_a_service( + connection_handle, + attribute_handle_range( + last_characteristic.getValueHandle() + 1, + services_discovered->end + ) + ); + + if (err) { + terminate(client); + } + } + } + + void handle_all_characteristics_discovered(GenericGattClient* client) { + if (last_characteristic.is_valid() == false) { + if (matching_characteristic_uuid == UUID() + || matching_characteristic_uuid == last_characteristic.getUUID()) { + last_characteristic.set_last_handle(services_discovered->end); + characteristic_callback(&last_characteristic); + } + } + + service_t* old = services_discovered; + services_discovered = services_discovered->next; + delete old; + + if (!services_discovered) { + terminate(client); + } else { + start_characteristic_discovery(client); + } + } + + void terminate(GenericGattClient* client) { + // unknown error, terminate the procedure immediately + client->remove_control_block(this); + Gap::Handle_t handle = connection_handle; + delete this; + client->on_termination(handle); + } + + uint16_t get_start_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { + return data.group_range.begin; + } + + uint16_t get_start_handle(const attribute_handle_range_t& range) { + return range.begin; + } + + uint16_t get_end_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { + return data.group_range.end; + } + + uint16_t get_end_handle(const attribute_handle_range_t& range) { + return range.end; + } + + UUID get_uuid(const AttReadByGroupTypeResponse::attribute_data_t& data) { + if (data.value.size() == 2) { + return UUID(data.value[0] | data.value[1] << 8); + } else { + return UUID(data.value.data(), UUID::LSB); + } + } + + UUID get_uuid(const attribute_handle_range_t& range) { + return matching_service_uuid; + } + + struct service_t { + service_t(uint16_t begin, uint16_t end, const UUID& uuid) : + begin(begin), end(end), uuid(uuid), next(NULL) { } + uint16_t begin; + uint16_t end; + UUID uuid; + service_t* next; + }; + + struct characteristic_t : DiscoveredCharacteristic { + characteristic_t() : DiscoveredCharacteristic() { + lastHandle = 0x0001; + } + + characteristic_t( + GattClient* client, + Gap::Handle_t connection_handle, + uint16_t decl_handle, + const ArrayView value + ) : DiscoveredCharacteristic() { + gattc = client; + uuid = get_uuid(value); + props = get_properties(value); + declHandle = decl_handle; + valueHandle = get_value_handle(value); + lastHandle = 0x0000; + connHandle = connection_handle; + } + + static UUID get_uuid(const ArrayView& value) { + if (value.size() == 5) { + return UUID(value[3] | (value[4] << 8)); + } else { + return UUID(value.data() + 3, UUID::LSB); + } + } + + static DiscoveredCharacteristic::Properties_t get_properties(const ArrayView& value) { + uint8_t raw_properties = value[0]; + DiscoveredCharacteristic::Properties_t result; + result._broadcast = (raw_properties & (1 << 0)) ? true : false; + result._read = (raw_properties & (1 << 1)) ? true : false; + result._writeWoResp = (raw_properties & (1 << 2)) ? true : false; + result._write = (raw_properties & (1 << 3)) ? true : false; + result._notify = (raw_properties & (1 << 4)) ? true : false; + result._indicate = (raw_properties & (1 << 5)) ? true : false; + result._authSignedWrite = (raw_properties & (1 << 6)) ? true : false; + return result; + } + + static uint16_t get_value_handle(const ArrayView& value) { + return value[1] | (value[2] << 8); + } + + void set_last_handle(uint16_t last_handle) { + lastHandle = last_handle; + } + + bool is_valid() const { + return lastHandle != 0x0000; + } + }; + + void insert_service(service_t* service) { + if (services_discovered == NULL) { + services_discovered = service; + return; + } + + service_t* current = services_discovered; + while (current->next) { + current = current->next; + } + current->next = service; + } + + ServiceDiscovery::ServiceCallback_t service_callback; + ServiceDiscovery::CharacteristicCallback_t characteristic_callback; + UUID matching_service_uuid; + UUID matching_characteristic_uuid; + service_t* services_discovered; + characteristic_t last_characteristic; + bool done; +}; + + +struct read_control_block_t : public procedure_control_block_t { + read_control_block_t( + Gap::Handle_t connection_handle, uint16_t attribute_handle, uint16_t offset + ) : procedure_control_block_t(READ_PROCEDURE, connection_handle), + attribute_handle(attribute_handle), + offset(offset), current_offset(offset), data(NULL) { + } + + virtual ~read_control_block_t() { + if (data != NULL) { + free(data); + } + } + + virtual void handle_timeout_error(GenericGattClient* client) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } + + void terminate(GenericGattClient* client, const GattReadCallbackParams& response) { + client->remove_control_block(this); + client->processReadResponse(&response); + delete this; + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + break; + + case AttributeOpcode::READ_RESPONSE: + handle_read_response(client, static_cast(message)); + break; + + case AttributeOpcode::READ_BLOB_RESPONSE: + handle_read_response(client, static_cast(message)); + break; + + default: { + // should not happen, terminate the procedure and notify client with an error + // in such case + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + AttErrorResponse::UNLIKELY_ERROR, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } break; + } + } + + template + void handle_read_response(GenericGattClient* client, const ResponseType& read_response) { + uint16_t mtu_size = client->get_mtu(connection_handle); + + // end of responses ? + if ((uint16_t) read_response.size() < (mtu_size - 1)) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + 0, // size of 0 + NULL, // no data + BLE_ERROR_NONE, + }; + + // is it the first response, or is there any other response already + // in the object ? + if (data == NULL) { + response.len = (uint16_t) read_response.size(); + response.data = read_response.data(); + } else { + // copy the data in the existing buffer + memcpy(data + (current_offset - offset), read_response.data(), read_response.size()); + response.len = (current_offset + read_response.size()) - offset; + response.data = data; + } + terminate(client, response); + } else { + // allocation which will contain the response data plus the next one. + data = (uint8_t*) realloc(data, (current_offset - offset) + ((mtu_size - 1) * 2)); + if (data == NULL) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + AttErrorResponse::INSUFFICIENT_RESOURCES, + NULL, + BLE_ERROR_NO_MEM, + }; + terminate(client, response); + return; + } + + memcpy(data + (current_offset - offset), read_response.data(), read_response.size()); + current_offset = current_offset + read_response.size(); + ble_error_t err = client->_pal_client->read_attribute_blob( + connection_handle, + attribute_handle, + current_offset + ); + + if (err) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + AttErrorResponse::UNLIKELY_ERROR, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + ble_error_t status = BLE_ERROR_UNSPECIFIED; + + switch (error.error_code) { + case AttErrorResponse::INVALID_HANDLE: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INSUFFICIENT_AUTHORIZATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_AUTHENTICATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::READ_NOT_PERMITTED: + status = BLE_ERROR_OPERATION_NOT_PERMITTED; + break; + case AttErrorResponse::INVALID_OFFSET: + status = BLE_ERROR_PARAM_OUT_OF_RANGE; + break; + case AttErrorResponse::ATTRIBUTE_NOT_LONG: + status = BLE_ERROR_PARAM_OUT_OF_RANGE; + break; + default: + status = BLE_ERROR_UNSPECIFIED; + break; + } + + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + error.error_code, + /* data */ NULL, + status + }; + + terminate(client, response); + } + + uint16_t attribute_handle; + uint16_t offset; + uint16_t current_offset; + uint8_t* data; +}; + +/* + * Control block for the write process + */ +struct write_control_block_t : public procedure_control_block_t { + write_control_block_t( + Gap::Handle_t connection_handle, uint16_t attribute_handle, + uint8_t* data, uint16_t len + ) : procedure_control_block_t(WRITE_PROCEDURE, connection_handle), + attribute_handle(attribute_handle), len(len), offset(0), data(data), + prepare_success(false), status(BLE_ERROR_UNSPECIFIED), error_code(0xFF) { + } + + virtual ~write_control_block_t() { + free(data); + } + + virtual void handle_timeout_error(GenericGattClient* client) { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_UNSPECIFIED, + 0x00 + }; + terminate(client, response); + } + + void terminate(GenericGattClient* client, const GattWriteCallbackParams& response) { + client->remove_control_block(this); + client->processWriteResponse(&response); + delete this; + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + break; + + case AttributeOpcode::WRITE_RESPONSE: + handle_write_response(client, static_cast(message)); + break; + + case AttributeOpcode::PREPARE_WRITE_RESPONSE: + handle_prepare_write_response(client, static_cast(message)); + break; + + case AttributeOpcode::EXECUTE_WRITE_RESPONSE: + handle_execute_write_response(client, static_cast(message)); + break; + + default: { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_UNSPECIFIED, + AttErrorResponse::UNLIKELY_ERROR + }; + + terminate(client, response); + } break; + } + } + + void handle_write_response(GenericGattClient* client, const AttWriteResponse& write_response) { + GattWriteCallbackParams response = { + connection_handle, attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_NONE, 0x00 + }; + + terminate(client, response); + } + + void handle_prepare_write_response(GenericGattClient* client, const AttPrepareWriteResponse& write_response) { + ble_error_t err = BLE_ERROR_UNSPECIFIED; + + uint16_t mtu_size = client->get_mtu(connection_handle); + offset = write_response.offset + write_response.partial_value.size(); + if (offset < len) { + err = client->_pal_client->queue_prepare_write( + connection_handle, attribute_handle, + make_const_ArrayView( + data + offset, + std::min((len - offset), (mtu_size - 5)) + ), + offset + ); + } else { + err = client->_pal_client->execute_write_queue( + connection_handle, true + ); + } + + if (err) { + clear_prepare_queue(client, err, AttErrorResponse::UNLIKELY_ERROR); + } + } + + void handle_execute_write_response(GenericGattClient* client, const AttExecuteWriteResponse& execute_response) { + if (prepare_success) { + status = BLE_ERROR_NONE; + error_code = 0x00; + } + + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + status, + error_code + }; + + terminate(client, response); + } + + void clear_prepare_queue(GenericGattClient* client, ble_error_t s, uint8_t e) { + prepare_success = false; + status = s; + error_code = e; + ble_error_t err = client->_pal_client->execute_write_queue( + connection_handle, false + ); + + if (err) { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + err, + AttErrorResponse::UNLIKELY_ERROR + }; + + terminate(client, response); + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + ble_error_t status = BLE_ERROR_UNSPECIFIED; + + switch (error.error_code) { + case AttErrorResponse::INVALID_HANDLE: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INSUFFICIENT_AUTHORIZATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_AUTHENTICATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::WRITE_NOT_PERMITTED: + status = BLE_ERROR_OPERATION_NOT_PERMITTED; + break; + default: + status = BLE_ERROR_UNSPECIFIED; + break; + } + + if (error.request_opcode == AttributeOpcode(AttributeOpcode::PREPARE_WRITE_REQUEST)) { + clear_prepare_queue(client, status, error.error_code); + } else { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + status, + error.error_code + }; + + terminate(client, response); + } + } + + uint16_t attribute_handle; + uint16_t len; + uint16_t offset; + uint8_t* data; + bool prepare_success; + ble_error_t status; + uint8_t error_code; +}; + +/* + * Control block for the descriptor discovery process + */ +struct descriptor_discovery_control_block_t : public procedure_control_block_t { + descriptor_discovery_control_block_t( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback + ) : procedure_control_block_t(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()), + characteristic(characteristic), + discovery_cb(discoveryCallback), + termination_cb(terminationCallback), + next_handle(characteristic.getValueHandle() + 1), + done(false) { + } + + virtual ~descriptor_discovery_control_block_t() { } + + ble_error_t start(GenericGattClient* client) { + return client->_pal_client->discover_characteristics_descriptors( + connection_handle, + attribute_handle_range( + next_handle, + characteristic.getLastHandle() + ) + ); + } + + virtual void handle_timeout_error(GenericGattClient* client) { + terminate(client, BLE_ERROR_UNSPECIFIED); + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + if (done) { + terminate(client, BLE_ERROR_NONE); + return; + } + + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + return; + + case AttributeOpcode::FIND_INFORMATION_RESPONSE: + handle_response(client, static_cast(message)); + return; + + default: + break; + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + if (error.error_code == AttErrorResponse::ATTRIBUTE_NOT_FOUND) { + terminate(client, BLE_ERROR_NONE); + } else { + terminate(client, BLE_ERROR_UNSPECIFIED, error.error_code); + } + } + + void handle_response(GenericGattClient* client, const AttFindInformationResponse& response) { + for (size_t i = 0; i < response.size(); ++i) { + DiscoveredCharacteristicDescriptor descriptor( + client, connection_handle, response[i].handle, response[i].uuid + ); + CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = { + characteristic, + descriptor + }; + discovery_cb(¶ms); + if (done) { + terminate(client, BLE_ERROR_NONE); + return; + } + + if (response[i].handle == characteristic.getLastHandle()) { + terminate(client, BLE_ERROR_NONE); + return; + } + next_handle = response[i].handle + 1; + } + + ble_error_t err = start(client); + if (err) { + terminate(client, err, AttErrorResponse::UNLIKELY_ERROR); + } + } + + void terminate(GenericGattClient* client, ble_error_t status, uint8_t error_code = 0x00) { + client->remove_control_block(this); + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + characteristic, + status, + error_code + }; + termination_cb(¶ms); + delete this; + } + + DiscoveredCharacteristic characteristic; + CharacteristicDescriptorDiscovery::DiscoveryCallback_t discovery_cb; + CharacteristicDescriptorDiscovery::TerminationCallback_t termination_cb; + uint16_t next_handle; + bool done; +}; + + +GenericGattClient::GenericGattClient(pal::GattClient* pal_client) : + _pal_client(pal_client), + _termination_callback(), + control_blocks(NULL) { + _pal_client->when_server_message_received( + mbed::callback(this, &GenericGattClient::on_server_message_received) + ); + _pal_client->when_transaction_timeout( + mbed::callback(this, &GenericGattClient::on_transaction_timeout) + ); +} + +ble_error_t GenericGattClient::launchServiceDiscovery( + Gap::Handle_t connection_handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + const UUID& matching_service_uuid, + const UUID& matching_characteristic_uuid +) { + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + // terminate and return if there is no callback to call + if (!service_callback && !characteristic_callback) { + on_termination(connection_handle); + return BLE_ERROR_NONE; + } + + discovery_control_block_t* discovery_pcb = new(std::nothrow) discovery_control_block_t( + connection_handle, + service_callback, + characteristic_callback, + matching_service_uuid, + matching_characteristic_uuid + ); + + if (discovery_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + // note: control block inserted prior the request because they are part of + // of the transaction and the callback can be call synchronously + insert_control_block(discovery_pcb); + + // launch the request + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (matching_service_uuid == UUID()) { + err = _pal_client->discover_primary_service( + connection_handle, + 0x0001 + ); + } else { + err = _pal_client->discover_primary_service_by_service_uuid( + connection_handle, + 0x0001, + matching_service_uuid + ); + } + + if (err) { + remove_control_block(discovery_pcb); + delete discovery_pcb; + } + + return err; +} + +bool GenericGattClient::isServiceDiscoveryActive() const { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { + return true; + } + pcb = pcb->next; + } + + return false; +} + +void GenericGattClient::terminateServiceDiscovery() +{ + procedure_control_block_t* pcb = control_blocks; + while (pcb) { + if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { + static_cast(pcb)->done = true; + } + pcb = pcb->next; + } +} + +ble_error_t GenericGattClient::read( + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + uint16_t offset) const +{ + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + read_control_block_t* read_pcb = new(std::nothrow) read_control_block_t( + connection_handle, + attribute_handle, + offset + ); + + if (read_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + insert_control_block(read_pcb); + + ble_error_t err = BLE_ERROR_NONE; + + if (offset == 0) { + err = _pal_client->read_attribute_value( + connection_handle, attribute_handle + ); + } else { + err = _pal_client->read_attribute_blob( + connection_handle, attribute_handle, offset + ); + } + + if (err) { + remove_control_block(read_pcb); + delete read_pcb; + } + + return err; +} + +ble_error_t GenericGattClient::write( + GattClient::WriteOp_t cmd, + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + size_t length, + const uint8_t* value +) const { + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + uint16_t mtu = get_mtu(connection_handle); + + if (cmd == GattClient::GATT_OP_WRITE_CMD) { + if (length > (uint16_t)(mtu - 3)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + return _pal_client->write_without_response( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } else { + uint8_t* data = NULL; + + if (length > (uint16_t)(mtu - 3)) { + data = (uint8_t*) malloc(length); + if (data == NULL) { + return BLE_ERROR_NO_MEM; + } + memcpy(data, value, length); + } + + write_control_block_t* write_pcb = new(std::nothrow) write_control_block_t( + connection_handle, + attribute_handle, + data, + length + ); + + if (write_pcb == NULL) { + free(data); + return BLE_ERROR_NO_MEM; + } + + insert_control_block(write_pcb); + + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (data) { + err = _pal_client->queue_prepare_write( + connection_handle, + attribute_handle, + make_const_ArrayView(value, mtu - 5), + /* offset */ 0 + ); + } else { + err = _pal_client->write_attribute( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } + + if (err) { + remove_control_block(write_pcb); + delete write_pcb; + } + + return err; + } + + return BLE_ERROR_NOT_IMPLEMENTED; +} + +void GenericGattClient::onServiceDiscoveryTermination( + ServiceDiscovery::TerminationCallback_t callback +) { + _termination_callback = callback; +} + +ble_error_t GenericGattClient::discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback +) { + // verify that there is no other procedures going on this connection + if (get_control_block(characteristic.getConnectionHandle())) { + return BLE_ERROR_INVALID_STATE; + } + + if (characteristic.getValueHandle() == characteristic.getLastHandle()) { + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + characteristic, + BLE_ERROR_NONE, + /* error code */ 0x00 + }; + + terminationCallback(¶ms); + return BLE_ERROR_NONE; + } + + descriptor_discovery_control_block_t* discovery_pcb = + new(std::nothrow) descriptor_discovery_control_block_t( + characteristic, + discoveryCallback, + terminationCallback + ); + + if (discovery_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + insert_control_block(discovery_pcb); + + ble_error_t err = discovery_pcb->start(this); + + if (err) { + remove_control_block(discovery_pcb); + delete discovery_pcb; + } + + return err; +} + +bool GenericGattClient::isCharacteristicDescriptorDiscoveryActive( + const DiscoveredCharacteristic& characteristic +) const { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE && + static_cast(pcb)->characteristic == characteristic) { + return true; + } + pcb = pcb->next; + } + + return false; +} + +void GenericGattClient::terminateCharacteristicDescriptorDiscovery( + const DiscoveredCharacteristic& characteristic +) { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) { + descriptor_discovery_control_block_t* dpcb = + static_cast(pcb); + if (dpcb->characteristic == characteristic) { + dpcb->done = true; + return; + } + } + + pcb = pcb->next; + } + +} + +ble_error_t GenericGattClient::reset(void) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +void GenericGattClient::on_termination(Gap::Handle_t connection_handle) { + if (_termination_callback) { + _termination_callback(connection_handle); + } +} + +void GenericGattClient::on_server_message_received( + connection_handle_t connection_handle, + const AttServerMessage& message +) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + case AttributeOpcode::EXCHANGE_MTU_RESPONSE: + case AttributeOpcode::FIND_INFORMATION_RESPONSE: + case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE: + case AttributeOpcode::READ_BY_TYPE_RESPONSE: + case AttributeOpcode::READ_RESPONSE: + case AttributeOpcode::READ_BLOB_RESPONSE: + case AttributeOpcode::READ_MULTIPLE_RESPONSE: + case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE: + case AttributeOpcode::WRITE_RESPONSE: + case AttributeOpcode::PREPARE_WRITE_RESPONSE: + case AttributeOpcode::EXECUTE_WRITE_RESPONSE: { + on_server_response(connection_handle, message); + } break; + + case AttributeOpcode::HANDLE_VALUE_INDICATION: + case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: { + on_server_event(connection_handle, message); + } break; + + default: + // invalid message receive + return; + } +} + +void GenericGattClient::on_server_response( + connection_handle_t connection, + const AttServerMessage& message +) { + procedure_control_block_t* pcb = get_control_block(connection); + if (pcb == NULL) { + return; + } + + pcb->handle(this, message); +} + +void GenericGattClient::on_server_event(connection_handle_t connection, const AttServerMessage& message) { + GattHVXCallbackParams callbacks_params = { + (Gap::Handle_t) connection, 0 + }; + + switch (message.opcode) { + case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: { + const AttHandleValueNotification& notification = + static_cast(message); + callbacks_params.handle = notification.attribute_handle; + callbacks_params.type = BLE_HVX_NOTIFICATION; + callbacks_params.len = notification.attribute_value.size(); + callbacks_params.data = notification.attribute_value.data(); + } break; + + case AttributeOpcode::HANDLE_VALUE_INDICATION: { + const AttHandleValueIndication& indication = + static_cast(message); + callbacks_params.handle = indication.attribute_handle; + callbacks_params.type = BLE_HVX_INDICATION; + callbacks_params.len = indication.attribute_value.size(); + callbacks_params.data = indication.attribute_value.data(); + } break; + + default: + return; + } + + processHVXEvent(&callbacks_params); +} + +void GenericGattClient::on_transaction_timeout(connection_handle_t connection) { + procedure_control_block_t* pcb = get_control_block(connection); + if (pcb == NULL) { + return; + } + + pcb->handle_timeout_error(this); +} + +procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) { + procedure_control_block_t* it = control_blocks; + while (it && it->connection_handle != connection) { + it = it->next; + } + return it; +} + +const procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) const { + procedure_control_block_t* it = control_blocks; + while (it && it->connection_handle != connection) { + it = it->next; + } + return it; +} + +void GenericGattClient::insert_control_block(procedure_control_block_t* cb) const { + if (control_blocks == NULL) { + control_blocks = cb; + return; + } + + procedure_control_block_t* current = control_blocks; + while (current->next) { + current = current->next; + } + current->next = cb; +} + +void GenericGattClient::remove_control_block(procedure_control_block_t* cb) const { + if (control_blocks == NULL) { + return; + } + + if (cb == control_blocks) { + control_blocks = control_blocks->next; + return; + } + + procedure_control_block_t* current = control_blocks; + while (current->next && current->next != cb) { + current = current->next; + } + + if (current->next == NULL) { + return; + } + + current->next = cb->next; + cb->next = NULL; +} + +uint16_t GenericGattClient::get_mtu(Gap::Handle_t connection) const { + uint16_t result = 23; + if(_pal_client->get_mtu_size((connection_handle_t) connection, result) != BLE_ERROR_NONE) { + result = 23; + } + return result; +} + +} // namespace pal +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp index 299b029f4ec..057b151edac 100644 --- a/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp @@ -367,11 +367,11 @@ void ArmGattServer::attCback(attEvt_t *pEvt) uint8_t ArmGattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) { GattReadCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .offset = offset, - .len = *pAttr->pLen, - .data = pAttr->pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .offset = */ offset, + /* .len = */ *pAttr->pLen, + /* .data = */ pAttr->pValue }; getInstance().handleDataReadEvent(&cbParams); @@ -410,12 +410,12 @@ uint8_t ArmGattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_ } GattWriteCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .writeOp = writeOp, - .offset = offset, - .len = len, - .data = pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .writeOp = */ writeOp, + /* .offset = */ offset, + /* .len = */ len, + /* .data = */ pValue }; getInstance().handleDataWrittenEvent(&cbParams); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h new file mode 100644 index 00000000000..da4b345a628 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -0,0 +1,153 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_BLE_H_ +#define CORDIO_BLE_H_ + +#include "ble/BLE.h" +#include "ble/blecommon.h" +#include "ble/BLEInstanceBase.h" + +#include "CordioHCIDriver.h" +#include "CordioGap.h" +#include "CordioGattServer.h" +#include "CordioSecurityManager.h" +#include "CordioPalAttClient.h" +#include "ble/pal/AttClientToGattClientAdapter.h" +#include "ble/generic/GenericGattClient.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * @see BLEInstanceBase + */ +class BLE : public ::BLEInstanceBase { + /** + * Construction with an HCI driver. + */ + BLE(CordioHCIDriver& hci_driver); + + /** + * Destructor + */ + virtual ~BLE(); + +public: + + /** + * Access to the singleton containing the implementation of BLEInstanceBase + * for the Cordio stack. + */ + static BLE& deviceInstance(); + + /** + * @see BLEInstanceBase::init + */ + virtual ble_error_t init( + ::BLE::InstanceID_t instanceID, + FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> initCallback + ); + + /** + * @see BLEInstanceBase::hasInitialized + */ + virtual bool hasInitialized() const; + + /** + * @see BLEInstanceBase::shutdown + */ + virtual ble_error_t shutdown(); + + /** + * @see BLEInstanceBase::getVersion + */ + virtual const char *getVersion(); + + /** + * @see BLEInstanceBase::getGap + */ + virtual Gap& getGap(); + + /** + * @see BLEInstanceBase::getGap + */ + virtual const Gap& getGap() const; + + /** + * @see BLEInstanceBase::getGattServer + */ + virtual GattServer &getGattServer(); + + /** + * @see BLEInstanceBase::getGattServer + */ + virtual const GattServer &getGattServer() const; + + /** + * @see BLEInstanceBase::getGattClient + */ + virtual ::GattClient &getGattClient(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual SecurityManager &getSecurityManager(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual const SecurityManager &getSecurityManager() const; + + /** + * @see BLEInstanceBase::waitForEvent + */ + virtual void waitForEvent(); + + /** + * @see BLEInstanceBase::processEvents + */ + virtual void processEvents(); + +private: + static void stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg); + static void device_manager_cb(dmEvt_t* dm_event); + static void connection_handler(dmEvt_t* dm_event); + static void timeoutCallback(); + + void stack_setup(); + void start_stack_reset(); + void callDispatcher(); + + static CordioHCIDriver* _hci_driver; + static FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> _init_callback; + + enum { + NOT_INITIALIZED, + INITIALIZING, + INITIALIZED + } initialization_status; + + ::BLE::InstanceID_t instanceID; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + + +#endif /* CORDIO_BLE_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h new file mode 100644 index 00000000000..ab139d5b908 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h @@ -0,0 +1,262 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_GAP_H_ +#define CORDIO_GAP_H_ + +#include +#include "ble/blecommon.h" +#include "ble/GapAdvertisingParams.h" +#include "ble/GapAdvertisingData.h" +#include "ble/Gap.h" +#include "ble/GapScanningParams.h" +#include "dm_api.h" +#include "att_api.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * @see ::Gap + */ +class Gap : public ::Gap +{ +public: + /** + * Return the Gap singleton implementing ::Gap for the Cordio stac. + */ + static Gap &getInstance(); + + /** + * This function shall be called once the stack has been initialized + */ + void initialize(); + + /** + * @see ::Gap::setAddress + */ + virtual ble_error_t setAddress(AddressType_t type, const Address_t address); + + /** + * @see ::Gap::getAddress + */ + virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); + + /** + * @see ::Gap::setAdvertisingData + */ + virtual ble_error_t setAdvertisingData( + const GapAdvertisingData&, const GapAdvertisingData& + ); + + /** + * @see ::Gap::connect + */ + virtual ble_error_t connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams + ); + + /** + * @see ::Gap::getMinAdvertisingInterval + */ + virtual uint16_t getMinAdvertisingInterval() const; + + /** + * @see ::Gap::getMinNonConnectableAdvertisingInterval + */ + virtual uint16_t getMinNonConnectableAdvertisingInterval() const; + + /** + * @see ::Gap::getMaxAdvertisingInterval + */ + virtual uint16_t getMaxAdvertisingInterval() const; + + /** + * @see ::Gap::startAdvertising + */ + virtual ble_error_t startAdvertising(const GapAdvertisingParams &); + + /** + * @see ::Gap::stopAdvertising + */ + virtual ble_error_t stopAdvertising(); + + /** + * @see ::Gap::disconnect + */ + virtual ble_error_t disconnect( + Handle_t connectionHandle, + DisconnectionReason_t reason + ); + + /** + * @see ::Gap::disconnect + */ + virtual ble_error_t disconnect(DisconnectionReason_t reason); + + /** + * @see ::Gap::setDeviceName + */ + virtual ble_error_t setDeviceName(const uint8_t *deviceName); + + /** + * @see ::Gap::getDeviceName + */ + virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP); + + /** + * @see ::Gap::setAppearance + */ + virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance); + + /** + * @see ::Gap::getAppearance + */ + virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP); + + /** + * @see ::Gap::setTxPower + */ + virtual ble_error_t setTxPower(int8_t txPower); + + /** + * @see ::Gap::getPermittedTxPowerValues + */ + virtual void getPermittedTxPowerValues( + const int8_t **valueArrayPP, size_t *countP + ); + + /** + * Set the internal connection handle + */ + void setConnectionHandle(uint16_t m_connectionHandle); + + /** + * Get the current connection handle + */ + uint16_t getConnectionHandle(); + + /** + * @see ::Gap::getPreferredConnectionParams + */ + virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params); + + /** + * @see ::Gap::setPreferredConnectionParams + */ + virtual ble_error_t setPreferredConnectionParams( + const ConnectionParams_t *params + ); + + /** + * @see ::Gap::updateConnectionParams + */ + virtual ble_error_t updateConnectionParams( + Handle_t handle, const ConnectionParams_t *params + ); + + /** + * @see ::Gap::startRadioScan + */ + virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); + + /** + * @see ::Gap::stopScan + */ + virtual ble_error_t stopScan(); + + /** + * Called when advertising is stopped. + */ + void advertisingStopped(); + + // Whitelist management + + /** + * @see ::Gap::getMaxWhitelistSize + */ + virtual uint8_t getMaxWhitelistSize(void) const; + + /** + * @see ::Gap::getWhitelist + */ + virtual ble_error_t getWhitelist(Whitelist_t &whitelist) const; + + /** + * @see ::Gap::setWhitelist + */ + virtual ble_error_t setWhitelist(const Whitelist_t &whitelist); + + /** + * @see ::Gap::setAdvertisingPolicyMode + */ + virtual ble_error_t setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode); + + /** + * @see ::Gap::getAdvertisingPolicyMode + */ + virtual AdvertisingPolicyMode_t getAdvertisingPolicyMode(void) const; + + /** + * @see ::Gap::setScanningPolicyMode + */ + virtual ble_error_t setScanningPolicyMode(ScanningPolicyMode_t mode); + + /** + * @see ::Gap::getScanningPolicyMode + */ + virtual ScanningPolicyMode_t getScanningPolicyMode(void) const; + + /** + * @see ::Gap::setInitiatorPolicyMode + */ + virtual ble_error_t setInitiatorPolicyMode(InitiatorPolicyMode_t mode); + + /** + * @see ::Gap::getInitiatorPolicyMode + */ + virtual InitiatorPolicyMode_t getInitiatorPolicyMode(void) const; + + /** + * @see ::Gap::reset + */ + virtual ble_error_t reset(void); + +private: + Gap(); + + Gap(Gap const &); + void operator=(Gap const &); + + uint16_t m_connectionHandle; + addr_type_t m_type; + Address_t m_addr; + + AdvertisingPolicyMode_t advertising_policy_mode; + ScanningPolicyMode_t scanning_policy_mode; + InitiatorPolicyMode_t initiator_policy_mode; + Whitelist_t whitelist; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_GAP_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h new file mode 100644 index 00000000000..26dc08a78e8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -0,0 +1,217 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_GATT_SERVER_H_ +#define CORDIO_GATT_SERVER_H_ + +#include +#include "ble/blecommon.h" +#include "ble/GattServer.h" +#include "ble/Gap.h" +#include "wsf_types.h" +#include "att_api.h" + +/*! client characteristic configuration descriptors settings */ +#define MAX_CCC_CNT 20 + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Cordio implementation of ::GattServer + */ +class GattServer : public ::GattServer +{ +public: + /** + * Return the singleton of the Cordio implementation of ::GattServer. + */ + static GattServer &getInstance(); + + /** + * Initialize the GattServer and add mandatory services (generic access and + * generic attribute service). + */ + void initialize(); + + /** + * @see ::GattServer::addService + */ + virtual ble_error_t addService(GattService &); + + /** + * @see ::GattServer::read + */ + virtual ble_error_t read( + GattAttribute::Handle_t attributeHandle, + uint8_t buffer[], + uint16_t *lengthP + ); + + /** + * @see ::GattServer::read + */ + virtual ble_error_t read( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t attributeHandle, + uint8_t buffer[], uint16_t *lengthP + ); + + /** + * @see ::GattServer::write + */ + virtual ble_error_t write( + GattAttribute::Handle_t, + const uint8_t[], uint16_t, + bool localOnly = false + ); + + /** + * @see ::GattServer::write + */ + virtual ble_error_t write( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t, + const uint8_t[], + uint16_t, + bool localOnly = false + ); + + /** + * @see ::GattServer::areUpdatesEnabled + */ + virtual ble_error_t areUpdatesEnabled( + const GattCharacteristic &characteristic, bool *enabledP + ); + + /** + * @see ::GattServer::areUpdatesEnabled + */ + virtual ble_error_t areUpdatesEnabled( + Gap::Handle_t connectionHandle, + const GattCharacteristic &characteristic, + bool *enabledP + ); + + /** + * @see ::GattServer::isOnDataReadAvailable + */ + virtual bool isOnDataReadAvailable() const; + + /** + * @see ::GattServer::getPreferredConnectionParams + */ + virtual ::Gap::ConnectionParams_t getPreferredConnectionParams(); + + /** + * @see ::GattServer::setPreferredConnectionParams + */ + virtual void setPreferredConnectionParams(const ::Gap::ConnectionParams_t& params); + + /** + * @see ::GattServer::setDeviceName + */ + virtual ble_error_t setDeviceName(const uint8_t *deviceName); + + /** + * @see ::GattServer::getDeviceName + */ + virtual void getDeviceName(const uint8_t*& name, uint16_t& length); + + /** + * @see ::GattServer::setAppearance + */ + virtual void setAppearance(GapAdvertisingData::Appearance appearance); + + /** + * @see ::GattServer::getAppearance + */ + virtual GapAdvertisingData::Appearance getAppearance(); + + /** + * @see ::GattServer::reset + */ + virtual ble_error_t reset(void); + +private: + static void cccCback(attsCccEvt_t *pEvt); + static void attCback(attEvt_t *pEvt); + static uint8_t attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr); + static uint8_t attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr); + void add_generic_access_service(); + void add_generic_attribute_service(); + void* alloc_block(size_t block_size); + + struct alloc_block_t { + alloc_block_t* next; + uint8_t data[1]; + }; + + struct internal_char_t { + uint16_t descLen; + }; + + struct internal_service_t { + uint16_t uuidLen; + internal_char_t *chars; + attsGroup_t *attGroup; + internal_service_t *next; + }; + + attsCccSet_t cccSet[MAX_CCC_CNT]; + uint16_t cccValues[MAX_CCC_CNT]; + uint16_t cccHandles[MAX_CCC_CNT]; + uint8_t cccCnt; + + struct { + attsGroup_t service; + attsAttr_t attributes[7]; + uint8_t device_name_declaration_value[5]; + uint16_t device_name_length; + uint8_t appearance_declaration_value[5]; + uint16_t appearance; + uint8_t ppcp_declaration_value[5]; + uint8_t ppcp[8]; + + uint8_t*& device_name_value() { + return attributes[2].pValue; + } + } generic_access_service; + + struct { + attsGroup_t service; + attsAttr_t attributes[4]; + uint8_t service_changed_declaration[5]; + } generic_attribute_service; + + internal_service_t* registered_service; + alloc_block_t* allocated_blocks; + + uint16_t currentHandle; + +private: + GattServer(); + + GattServer(const GattServer &); + const GattServer& operator=(const GattServer &); +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_GATT_SERVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h new file mode 100644 index 00000000000..401cffa8b83 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -0,0 +1,622 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_PAL_ATT_CLIENT_ +#define CORDIO_PAL_ATT_CLIENT_ + +#include "ble/pal/AttClient.h" +#include "ble/pal/SimpleAttServerMessage.h" +#include "att_api.h" +#include "att_defs.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace cordio { + +class CordioAttClient : public ::ble::pal::AttClient { + +public: + CordioAttClient() : ::ble::pal::AttClient() { } + virtual ~CordioAttClient() { } + + /** + * @see ble::pal::AttClient::exchange_mtu_request + */ + virtual ble_error_t exchange_mtu_request(connection_handle_t connection) + { + AttcMtuReq(connection, pAttCfg->mtu); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::GattClient::get_mtu_size + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) { + mtu_size = AttGetMtu(connection_handle); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::find_information_request + */ + virtual ble_error_t find_information_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) { + AttcFindInfoReq( + connection_handle, + discovery_range.begin, + discovery_range.end, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::find_by_type_value_request + */ + virtual ble_error_t find_by_type_value_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range, + uint16_t type, + const ArrayView& value + ) { + AttcFindByTypeValueReq( + connection_handle, + discovery_range.begin, + discovery_range.end, + type, + value.size(), + const_cast(value.data()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_by_type_request + */ + virtual ble_error_t read_by_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& type + ) { + AttcReadByTypeReq( + connection_handle, + read_range.begin, + read_range.end, + type.getLen(), + const_cast(type.getBaseUUID()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_request + */ + virtual ble_error_t read_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) { + AttcReadReq(connection_handle, attribute_handle); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_blob_request + */ + virtual ble_error_t read_blob_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) { + AttcReadLongReq( + connection_handle, + attribute_handle, + offset, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_multiple_request + */ + virtual ble_error_t read_multiple_request( + connection_handle_t connection_handle, + const ArrayView& attribute_handles + ) { + AttcReadMultipleReq( + connection_handle, + attribute_handles.size(), + const_cast(attribute_handles.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_by_group_type_request + */ + virtual ble_error_t read_by_group_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& group_type + ) { + AttcReadByGroupTypeReq( + connection_handle, + read_range.begin, + read_range.end, + group_type.getLen(), + const_cast(group_type.getBaseUUID()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::write_request + */ + virtual ble_error_t write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcWriteReq( + connection_handle, + attribute_handle, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::write_command + */ + virtual ble_error_t write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcWriteCmd( + connection_handle, + attribute_handle, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::signed_write_command + */ + virtual ble_error_t signed_write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcSignedWriteCmd( + connection_handle, + attribute_handle, + /* sign counter from flash or AttsGetSignCounter() ? */ 0, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::prepare_write_request + */ + virtual ble_error_t prepare_write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset, + const ArrayView& value + ) { + AttcPrepareWriteReq( + connection_handle, + attribute_handle, + offset, + value.size(), + const_cast(value.data()), + false, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::execute_write_request + */ + virtual ble_error_t execute_write_request( + connection_handle_t connection_handle, + bool execute + ) { + AttcExecuteWriteReq( + connection_handle, + execute + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::initialize + */ + virtual ble_error_t initialize() + { + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::terminate + */ + virtual ble_error_t terminate() + { + return BLE_ERROR_NONE; + } + + // singleton of the ARM Cordio client + static CordioAttClient& get_client() + { + static CordioAttClient _client; + return _client; + } + +private: + // convert an array of byte to an uint16_t + static uint16_t to_uint16_t(const uint8_t* array) + { + uint16_t result; + memcpy(&result, array, sizeof(result)); + return result; + } + + /** + * Type of an event handler. + * @param The event to handle + * @return true if the event has been handled and false otherwise. + */ + typedef bool (*event_handler_t)(const attEvt_t*); + +public: + /** + * Callback which handle attEvt_t and forward them to on_server_event. + */ + static void att_client_handler(const attEvt_t* event) + { + // all handlers are stored in a static array + static const event_handler_t handlers[] = { + &timeout_event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler + }; + + // event->hdr.param: connection handle + // event->header.event: opcode from the request + // event->header.status: success or error code ... + // event->pValue: starting after opcode for response; starting after opcode + handle for server initiated responses. + // event->handle: handle for server initiated responses + + // traverse all handlers and execute them with the event in input. + // exit if an handler has handled the event. + for(size_t i = 0; i < (sizeof(handlers)/sizeof(handlers[0])); ++i) { + if (handlers[i](event)) { + return; + } + } + } + +private: + /** + * Event handler generator. + * @tparam Description of an event converter. It contains two static member + * function: + * - bool can_convert(const attEvt_t* event): return true if the event can + * be converted by the converter + * - convert(const attEvt_t* event): return the + * AttServerMessage converted from event. + * @param event + * @return + */ + template + static bool event_handler(const attEvt_t* event) + { + if (T::can_convert(event)) { + generated_handler(event, T::convert); + return true; + } + return false; + } + + static bool timeout_event_handler(const attEvt_t* event) + { + if(event->hdr.status != ATT_ERR_TIMEOUT) { + return false; + } + + get_client().on_transaction_timeout(event->hdr.param); + return true; + } + + template + static void generated_handler( + const attEvt_t* event, ResultType (*convert)(const attEvt_t*) + ) { + get_client().on_server_event( + event->hdr.param, + convert(event) + ); + } + + /** + * Traits defining can_convert for non ErrorResponse events. + */ + template + struct ResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status == ATT_SUCCESS && event->hdr.event == RequestID) { + return true; + } + return false; + } + }; + + /** + * Converter for an AttErrorResponse. + */ + struct ErrorResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status != ATT_SUCCESS) { + return true; + } + return false; + } + + static AttErrorResponse convert(const attEvt_t* event) + { + return AttErrorResponse( + static_cast(event->hdr.event * 2), + event->handle, + event->hdr.status + ); + } + }; + + /** + * Converter for an AttExchangeMTUResponse. + */ + struct ExchangeMtuResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status == ATT_SUCCESS && + event->hdr.event == ATT_MTU_UPDATE_IND) { + return true; + } + return false; + } + + static AttExchangeMTUResponse convert(const attEvt_t* event) + { + return AttExchangeMTUResponse(event->mtu); + } + }; + + /** + * Converter for a SimpleAttFindInformationResponse. + */ + struct FindInformationResponseConverter : ResponseConverter { + static SimpleAttFindInformationResponse convert(const attEvt_t* event) + { + return SimpleAttFindInformationResponse( + static_cast(event->pValue[0]), + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a SimpleAttFindByTypeValueResponse. + */ + struct FindByTypeValueResponseConverter : ResponseConverter { + static SimpleAttFindByTypeValueResponse convert(const attEvt_t* event) + { + return SimpleAttFindByTypeValueResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a SimpleAttReadByTypeResponse. + */ + struct ReadByTypeResponseConverter : ResponseConverter { + static SimpleAttReadByTypeResponse convert(const attEvt_t* event) + { + return SimpleAttReadByTypeResponse( + event->pValue[0], + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a AttReadResponse. + */ + struct ReadResponseConverter : ResponseConverter { + static AttReadResponse convert(const attEvt_t* event) + { + return AttReadResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttReadBlobResponse. + */ + struct ReadBlobResponseConverter : ResponseConverter { + static AttReadBlobResponse convert(const attEvt_t* event) + { + return AttReadBlobResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttReadMultipleResponse. + */ + struct ReadMultipleResponseConverter : ResponseConverter { + static AttReadMultipleResponse convert(const attEvt_t* event) + { + return AttReadMultipleResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a SimpleAttReadByGroupTypeResponse. + */ + struct ReadBygroupTypeResponseConverter : ResponseConverter { + static SimpleAttReadByGroupTypeResponse convert(const attEvt_t* event) + { + return SimpleAttReadByGroupTypeResponse( + event->pValue[0], + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a AttWriteResponse. + */ + struct WriteResponseConverter : ResponseConverter { + static AttWriteResponse convert(const attEvt_t* event) + { + return AttWriteResponse(); + } + }; + + /** + * Converter for a AttPrepareWriteResponse. + */ + struct PrepareWriteResponseConverter : ResponseConverter { + static AttPrepareWriteResponse convert(const attEvt_t* event) + { + // WARNING: Not sure if correct, the stack erase the length parameter + return AttPrepareWriteResponse( + event->handle, + to_uint16_t(event->pValue + 2), + // FIXME: the stack set the lenght to 0, the data won't be seen ... + make_const_ArrayView( + event->pValue + 4, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttExecuteWriteResponse. + */ + struct ExecuteWriteResponseConverter : ResponseConverter { + static AttExecuteWriteResponse convert(const attEvt_t* event) + { + return AttExecuteWriteResponse(); + } + }; + + /** + * Converter for a AttHandleValueNotification. + */ + struct HandleValueNotificationConverter : ResponseConverter { + static AttHandleValueNotification convert(const attEvt_t* event) + { + return AttHandleValueNotification( + event->handle, + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttHandleValueIndication. + */ + struct HandleValueIndicationConverter : ResponseConverter { + static AttHandleValueIndication convert(const attEvt_t* event) + { + return AttHandleValueIndication( + event->handle, + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; +}; + +} // cordio +} // vendor +} // pal +} // ble + +#endif /* CORDIO_PAL_ATT_CLIENT_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h new file mode 100644 index 00000000000..6522a0f50b3 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h @@ -0,0 +1,48 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_SECURITY_MANAGER_H_ +#define CORDIO_SECURITY_MANAGER_H_ + +#include + +#include "ble/SecurityManager.h" + +namespace ble { +namespace vendor { +namespace cordio { + +class SecurityManager : public ::SecurityManager +{ +public: + static SecurityManager &getInstance() + { + static SecurityManager m_instance; + return m_instance; + } + +public: + SecurityManager() + { + /* empty */ + } +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_SECURITY_MANAGER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md new file mode 100644 index 00000000000..b6c208d2dc7 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md @@ -0,0 +1,29 @@ +# BLE API Cordio Implementation + +The BLE API Cordio implementation allows Cordio licensee to easily deliver a +complete and up to date implementation of mbed BLE to their custommers using +mbed OS. + +To deliver a BLE port, vendors simply have to provide an HCI driver taillored +for the BLE module present on the board they want to support. + +## Source Organization + +The root contains the public header of the classes implementing BLE API public +interface. + +* `doc`: Documentation such as the HCI extension guide and the +porting guide. +* `driver`: HCI driver and transport interfaces. Also contains standard driver +implementation. +* `sources`: BLE API Implementation files +* `stack`: Cordio stack + * `cordio_stack`: Headerd of the cordio stack + * `lib`: precompiled libraries of the cordio stack + * `mbed_os_adaptation`: Headers of the interface responsible for the bridge + between BLE API and the Cordio stack. + +## Documentation + +* [HCI architecture](doc/HCIAbstraction.md) +* [Porting guide](doc/PortingGuide.md) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md new file mode 100644 index 00000000000..1a69a0d44c1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md @@ -0,0 +1,44 @@ +# HCI abstraction architecture + +The HCI driver is split into two interfaces: +* `CordioHCIDriver`: It is the driver for a BLE controller. It contains +the primitive necessary to start and initialize the controller. +* `CordioHCITransport`: It is the transport interface which is used by the HCI +driver to communicate with the controller. + +A `CordioHCITransport` is injected into a `CordioHCIDriver` at construction +time. A `CordioHCIDriver` is also injected at construction time of a `BLECordio` +instance. + +This can be summarized in the following diagram: + +![](resources/architecture.png) + +## CordioHCITransportDriver + +The single responsabilities of this a driver is to handle the communication with +the Bluetooth module. Basically, sending and reading bytes. + +Given that the Bluetooth specification define standard transport interface, an +implementation of the H4 interface is bundled in this port. It might be extended +in the future with an implementation of the H5 interface. However there is no +plan to provide the SDIO implementation at the moment. + +This interface is defined in the header file +[CordioHCITransportDriver.h](../driver/CordioHCITransportDriver.h) + +## CordioHCIDriver + +The responsibilities of this driver are: +* Provide the memory which will used by the Bluetooth stack. +* Initialize the bluetooth controller. +* Handle the reset/startup sequence of the bluetooth controller. + +This interface is defined in the header file +[CordioHCIDriver.h](../driver/CordioHCIDriver.h) + +A partial implementation is present in the file +[CordioHCIDriver.cpp](../driver/CordioHCIDriver.cpp). It defines the function +delivering memory to the stack and a complete reset sequence. However it does +not define any initialization for the Bluetooth controller, this part being +specific to the controller used. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md new file mode 100644 index 00000000000..dea13bcdf02 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md @@ -0,0 +1,551 @@ +# Porting guide + +Enabling the mbed BLE Cordio port for a given target is a two step process: +* The target shall be configured to include Cordio BLE port and Cordio libraries +during the build process. +* An implementation of the `CordioHCIDriver` class targeting the bluetooth +controller used shall be provided. + +## Target configuration + +This step happens in the file defining all mbed os targets. The file is located +in `targets/target.json`. + +### Add BLE feature + +First of all support for BLE has to be added to the target. This is achieved by +adding the string `BLE` in the list of `features` of the target. Once this +value has been added the sources of BLE api are added to the list of sources +compiled for the target. + +```json + "TARGET_NAME": { + "features": ["target features ...", "BLE"] + } +``` + +### Include Cordio BLE implementation + +The target should also compile the sources of the BLE Cordio port. It is +achieved by adding the string `CORDIO` in the list of the `extra_labels` +property of the target. + +```json + "TARGET_NAME": { + "extra_labels": ["target extra labels ...", "CORDIO"], + "features": ["target features ...", "BLE"] + } +``` + +### Include prebuilt libraries + +Last, the target shall also include the cordio libraries into the build. + +Four prebuilt libraries are provided: +* `wscore`: which contains the base component used by the Cordio stack. +* `wsstack`: The BLE stack itself, if contains the GAP and GATT layer as well as +the Security manager implementation. +* `wssec`: The low level implementation of the security layer. +* `wshci`: The HCI layer. + +The `wssec` and `wshci` libraries are delivered in feature folders. It allows +vendors to override those library if necessary. This can be required if the port +use specific crypto routine or require an highly modified HCI layer. + +To include the default library in the target, the features have to be added in +this list of the features of the target: +* `WSSEC`: Include the default `wssec` library. +* `WSHCI`: Include the default `wshci` library. + +The target should also compile the sources of the BLE Cordio port. It is +achieved by adding the string `CORDIO` in the list of the `extra_labels` +property of the target. + +```json + "TARGET_NAME": { + "extra_labels": ["target extra labels ...", "CORDIO"], + "features": ["target features ...", "BLE", "WSHCI", "WSSEC"] + } +``` + +## CordioHCIDriver implementation: + +A port shall include an HCI driver for the BLE module used by the target and +a factory function which create the BLE instance used by the user of BLE API. + +### Create source folder + +The port shall live in the folder of BLE API which host targets port : +`features/FEATURE_BLE/targets`. + +To isolate the port code from other code a folder containing the port code has +to be created. The name of this folder shall start with `TARGET_` and end with +the target name in capital. + +### Create the HCI driver + +The HCI driver is split in two entities: one which handle HCI communication with +the Bluetooth module and the other handling the initialization, reset sequence +and memory dedicated for the Bluetooth controller. + +More information about the architecture can be found in the +[HCI abstraction architecture](HCIAbstraction.md) document. + +#### HCITransport + +> **Note:** If the Bluetooth controller uses an H4 communication interface, this +step can be skipped. + +An empty transport driver can be coded as: + +```c++ +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace target_name { + +class TransportDriver : public cordio::CordioHCITransportDriver { +public: + TransportDriver(/* specific constructor arguments*/); + + virtual ~TransportDriver(); + + virtual void initialize(); + + virtual void terminate(); + + virtual uint16_t write(uint8_t packet_type, uint16_t len, uint8_t *data); + +private: + // private driver declarations +}; + +} // namespace target_name +} // namespace vendor +} // namespace ble +``` + +It shall inherits publicly from the base class `CordioHCITransportDriver`. + +* **Initialization/termination:** The functions `initialize` and `terminate` are +responsible for initializing and terminating the transport driver. It is not +necessary to initialize the transport in the constructor. + +* **Sending data** The function `write` shall sends data in input to the +Bluetooth controller and return the number of bytes in the `data` buffer sent. +Depending on the type of transport being implemented, the packet `type` might +have to be sent to the controller before the packet data. + +* **Receiving data**: HCI data from the Bluetooth controller shall be injected +in the system by invoking the function `on_data_received`. This function is +a static one and is provided by the base class. Its prototype is: + +```c++ +void on_data_received(uint8_t* data_received, uint16_t length_of_data_received); +``` + +#### HCIDriver + +The skeleton of driver is: + +```c++ +#include "CordioHCIDriver.h" + +namespace ble { +namespace vendor { +namespace target_name { + +class HCIDriver : public cordio::CordioHCIDriver { +public: + HCIDriver( + cordio::CordioHCITransportDriver& transport_driver, + /* specific constructor arguments*/ + ); + + virtual ~HCIDriver(); + + virtual void do_initialize(); + + virtual void do_terminate(); + + virtual buf_pool_desc_t get_buffer_pool_description(); + + virtual void start_reset_sequence(); + + virtual void handle_reset_sequence(uint8_t *msg); +private: + // private driver declarations +}; + +} // namespace target_name +} // namespace vendor +} // namespace ble +``` + +##### Initialization process + +The initialization/termination process is achieved by the couple of functions +`do_initialize` and `do_terminate`. Those function manages the state of the +bluetooth controller. + +> **Important:** It is unnecessary to initialize or terminate the hci transport +in those function because it is handled by the base class. The HCI transport is +initialized right before the call to `do_initialize` and is terminated right +after the call to `do_terminate`. + +##### Memory pool + +The implementation of the function `get_buffer_pool_description` in the base +class will return a buffer of 1040 bytes divided in different memory pools: + +| Chunk size (bytes) | Number of chunks | +|--------------------|------------------| +| 16 | 8 | +| 32 | 4 | +| 64 | 2 | +| 128 | 2 | +| 272 | 1 | + +A port shall override this function if the memory provided by the base class +doesn't match what is required by the Bluetooth controller driven. + +```c++ +buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() { + static uint8_t buffer[/* buffer size */]; + static const wsfBufPoolDesc_t pool_desc[] = { + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + }; + + return buf_pool_desc_t(buffer, pool_desc); +} +``` + +##### Reset sequence + +The reset sequence process is handled by three functions: + +* `start_reset_sequence`: This function start the process. The basic +implementation sends an HCI reset command to the Bluetooth controller. The +function shall be overridden in the driver if the bluetooth controller requires +more than just sending the standard reset command. + +* `handle_reset_sequence`: Entry point to the state machine handling the reset +process. Every time an HCI packet is received during the reset sequence, this +function is called with the HCI packet received. It's purpose is to prepare the +Bluetooth controller and set the parameters the stack needs to operate properly. +This function can be overridden if necessary. + +* `signal_reset_sequence_done`: This function shall be called once the reset +sequence is achieved. It cannot be overridden. + +###### Controller parameters to set + +This instruct the controller which events are relevant for the stack. + +The following parameters should be set in the controller (if supported): +* event mask: The reset sequence should issue the call +`HciSetEventMaskCmd((uint8_t *) hciEventMask)` +* LE event mask: The call `HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask)` +should be issued. +* 2nd page of events mask: Can be achieved by invoking +`HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2)`. + + +###### Stack runtime parameters + +Some stack parameters shall be acquired at runtime from the controller: + +* Bluetooth address: Can be queried with `HciReadBdAddrCmd`. Response shall be +copied into `hciCoreCb.bdAddr` with `BdaCpy`. +* Buffer size of the controller: Can be obtained by `HciLeReadBufSizeCmd`. The +return parameter *HC_ACL_Data_Packet_Length* shall be copied into +`hciCoreCb.bufSize` and the response parameter +`HC_Synchronous_Data_Packet_Length`shall be copied into `hciCoreCb.numBufs`. +The value of `hciCoreCb.availBufs` shall be initialized with `hciCoreCb.numBufs`. +* Supported state: Queried with `HciLeReadSupStatesCmd`, the response shall go +into `hciCoreCb.leStates`. +* Whitelist size: Queried with `HciLeReadWhiteListSizeCmd` the response shall go +into `hciCoreCb.whiteListSize`. +* LE features supported: Obtained with `HciLeReadLocalSupFeatCmd`. The response +shall be stored into `hciCoreCb.leSupFeat`. +* Resolving list size: Obtained with `hciCoreReadResolvingListSize`. The response +shall go into `hciCoreCb.resListSize`. +* Max data length: Acquired with `hciCoreReadMaxDataLen`. The response parameter +`supportedMaxTxOctets` and `supportedMaxTxTime` shall be pass to the function +`HciLeWriteDefDataLen`. + + +The default implementation is: + +```c++ +void HCIDriver::handle_reset_sequence(uint8_t *pMsg) { + // only accept command complete event: + if (*pMsg != HCI_CMD_CMPL_EVT) { + return; + } + + uint16_t opcode; + static uint8_t randCnt; + + /* parse parameters */ + pMsg += HCI_EVT_HDR_LEN; + pMsg++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg); // copy opcode + pMsg++; /* skip status */ + + /* decode opcode */ + switch (opcode) + { + case HCI_OPCODE_RESET: + /* initialize rand command count */ + randCnt = 0; + // set the event mask to control which events are generated by the + // controller for the host + HciSetEventMaskCmd((uint8_t *) hciEventMask); + break; + + case HCI_OPCODE_SET_EVENT_MASK: + // set the event mask to control which LE events are generated by + // the controller for the host + HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask); + break; + + case HCI_OPCODE_LE_SET_EVENT_MASK: + // set the event mask to control which events are generated by the + // controller for the host (2nd page of flags ) + HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2); + break; + + case HCI_OPCODE_SET_EVENT_MASK_PAGE2: + // Ask the Bluetooth address of the controller + HciReadBdAddrCmd(); + break; + + case HCI_OPCODE_READ_BD_ADDR: + // Store the Bluetooth address in the stack runtime parameter + BdaCpy(hciCoreCb.bdAddr, pMsg); + + // Read the size of the buffer of the controller + HciLeReadBufSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_BUF_SIZE: + // Store the buffer parameters in the stack runtime parameters + BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); + BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); + + /* initialize ACL buffer accounting */ + hciCoreCb.availBufs = hciCoreCb.numBufs; + + // read the states and state combinations supported by the link + // layer of the controller + HciLeReadSupStatesCmd(); + break; + + case HCI_OPCODE_LE_READ_SUP_STATES: + // store supported state and combination in the runtime parameters + // of the stack + memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); + + // read the total of whitelist entries that can be stored in the + // controller. + HciLeReadWhiteListSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: + // store the number of whitelist entries in the stack runtime + // parameters + BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); + + // Read the LE features supported by the controller + HciLeReadLocalSupFeatCmd(); + break; + + case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: + // Store the set of LE features supported by the controller + BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); + + // read the total number of address translation entries which can be + // stored in the controller resolving list. + hciCoreReadResolvingListSize(); + break; + + case HCI_OPCODE_LE_READ_RES_LIST_SIZE: + // store the number of address translation entries in the stack + // runtime parameter + BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); + + // read the Controller’s maximum supported payload octets and packet + // duration times for transmission and reception + hciCoreReadMaxDataLen(); + break; + + case HCI_OPCODE_LE_READ_MAX_DATA_LEN: + { + // store payload definition in the runtime stack parameters. + uint16_t maxTxOctets; + uint16_t maxTxTime; + + BSTREAM_TO_UINT16(maxTxOctets, pMsg); + BSTREAM_TO_UINT16(maxTxTime, pMsg); + + /* use Controller's maximum supported payload octets and packet duration times + * for transmission as Host's suggested values for maximum transmission number + * of payload octets and maximum packet transmission time for new connections. + */ + HciLeWriteDefDataLen(maxTxOctets, maxTxTime); + } + break; + + case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: + if (hciCoreCb.extResetSeq) + { + /* send first extended command */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + else + { + /* initialize extended parameters */ + hciCoreCb.maxAdvDataLen = 0; + hciCoreCb.numSupAdvSets = 0; + hciCoreCb.perAdvListSize = 0; + + /* send next command in sequence */ + HciLeRandCmd(); + } + break; + + case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: + case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: + case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: + // handle extended command + if (hciCoreCb.extResetSeq) + { + /* send next extended command in sequence */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + break; + + case HCI_OPCODE_LE_RAND: + /* check if need to send second rand command */ + if (randCnt < (HCI_RESET_RAND_CNT-1)) + { + randCnt++; + HciLeRandCmd(); + } + else + { + /* last command in sequence; set resetting state and call callback */ + signal_reset_sequence_done(); + } + break; + + default: + break; + } +} + +static void hciCoreReadMaxDataLen(void) +{ + /* if LE Data Packet Length Extensions is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) + { + /* send next command in sequence */ + HciLeReadMaxDataLen(); + } + else + { + /* send next command in sequence */ + HciLeRandCmd(); + } +} + +static void hciCoreReadResolvingListSize(void) +{ + /* if LL Privacy is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) + { + /* send next command in sequence */ + HciLeReadResolvingListSize(); + } + else + { + hciCoreCb.resListSize = 0; + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + } +} +``` + + + +### HCI accessor function + +The HCI driver is injected in the `CordioBLE` class at construction site. +Given that the CordioBLE class doesn't know what class shall be used to +construct the driver nor it knows how to construct it, the port shall provide a +function returning a reference to the HCI driver. + +This function lives in the global namespace and its signature is: + +```c++ +ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver(); +``` + +A common implementation might be: + +```c++ +ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() { + static ble::vendor::target_name::TransportDriver transport_driver( + /* transport parameters */ + ); + + static ble::vendor::target_name::HCIDriver hci_driver( + transport_driver, /* other hci driver parameters */ + ); + + return hci_driver; +} +``` + +## Examples + +Implementation examples might be found for: +* [ST BlueNRG module](../../TARGET_NUCLEO_F401RE/BlueNrgHCIDriver.cpp): It uses +a custom transport driver and a vendor specific is sent right after the answer +to the reset command to switch the controller to link layer mode only. +* [EM9301 module](../../TARGET_Maxim/TARGET_MAX32620HSP/EM9301HCIDriver.cpp): +it uses a custom transport driver and doesn't doesn't send the command *Set +Event Mask Page 2* to the controller during the reset sequence because this +command is not supported by the controller. +* [PAN1326](../../TARGET_Maxim/TARGET_MAX32630FTHR/CC2564HCIDriver.cpp): It +uses the H4 transport driver. The reset sequence start by sending a +*service pack* then once the service pack has been transferred it continue +with the regular reset sequence. + + + + + + + + + + + + + + + + + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png new file mode 100644 index 00000000000..f3bc8634c6c Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png new file mode 100644 index 00000000000..7e765aa2604 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp new file mode 100644 index 00000000000..9ca29a336ed --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp @@ -0,0 +1,261 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "CordioHCIDriver.h" +#include "hci_api.h" +#include "hci_cmd.h" +#include "hci_core.h" +#include "bstream.h" +#include "hci_mbed_os_adaptation.h" + +#define HCI_RESET_RAND_CNT 4 + +namespace ble { +namespace vendor { +namespace cordio { + +namespace { + +static void hciCoreReadMaxDataLen(void) +{ + /* if LE Data Packet Length Extensions is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) { + /* send next command in sequence */ + HciLeReadMaxDataLen(); + } else { + /* send next command in sequence */ + HciLeRandCmd(); + } +} + +static void hciCoreReadResolvingListSize(void) +{ + /* if LL Privacy is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) { + /* send next command in sequence */ + HciLeReadResolvingListSize(); + } else { + hciCoreCb.resListSize = 0; + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + } +} + +} // end of anonymous namespace + + +CordioHCIDriver::CordioHCIDriver(CordioHCITransportDriver& transport_driver) : + _transport_driver(transport_driver) { } + +void CordioHCIDriver::initialize() +{ + _transport_driver.initialize(); + do_initialize(); +} + +void CordioHCIDriver::terminate() +{ + do_terminate(); + _transport_driver.terminate(); +} + +buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() +{ + static union { + uint8_t buffer[2250]; + uint64_t align; + }; + static const wsfBufPoolDesc_t pool_desc[] = { + { 16, 16 }, + { 32, 16 }, + { 64, 8 }, + { 128, 4 }, + { 272, 1 } + }; + + return buf_pool_desc_t(buffer, pool_desc); +} + +void CordioHCIDriver::start_reset_sequence() +{ + /* send an HCI Reset command to start the sequence */ + HciResetCmd(); +} + +void CordioHCIDriver::handle_reset_sequence(uint8_t *pMsg) +{ + uint16_t opcode; + static uint8_t randCnt; + + /* if event is a command complete event */ + if (*pMsg == HCI_CMD_CMPL_EVT) { + /* parse parameters */ + pMsg += HCI_EVT_HDR_LEN; + pMsg++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg); + pMsg++; /* skip status */ + + /* decode opcode */ + switch (opcode) { + case HCI_OPCODE_RESET: + /* initialize rand command count */ + randCnt = 0; + + /* send next command in sequence */ + HciSetEventMaskCmd((uint8_t *) hciEventMask); + break; + + case HCI_OPCODE_SET_EVENT_MASK: + /* send next command in sequence */ + HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask); + break; + + case HCI_OPCODE_LE_SET_EVENT_MASK: + /* send next command in sequence */ + HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2); + break; + + case HCI_OPCODE_SET_EVENT_MASK_PAGE2: + /* send next command in sequence */ + HciReadBdAddrCmd(); + break; + + case HCI_OPCODE_READ_BD_ADDR: + /* parse and store event parameters */ + BdaCpy(hciCoreCb.bdAddr, pMsg); + + /* send next command in sequence */ + HciLeReadBufSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_BUF_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); + BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); + + /* initialize ACL buffer accounting */ + hciCoreCb.availBufs = hciCoreCb.numBufs; + + /* send next command in sequence */ + HciLeReadSupStatesCmd(); + break; + + case HCI_OPCODE_LE_READ_SUP_STATES: + /* parse and store event parameters */ + memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); + + /* send next command in sequence */ + HciLeReadWhiteListSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); + + /* send next command in sequence */ + HciLeReadLocalSupFeatCmd(); + break; + + case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); + + /* send next command in sequence */ + hciCoreReadResolvingListSize(); + break; + + case HCI_OPCODE_LE_READ_RES_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + break; + + case HCI_OPCODE_LE_READ_MAX_DATA_LEN: { + uint16_t maxTxOctets; + uint16_t maxTxTime; + + BSTREAM_TO_UINT16(maxTxOctets, pMsg); + BSTREAM_TO_UINT16(maxTxTime, pMsg); + + /* use Controller's maximum supported payload octets and packet duration times + * for transmission as Host's suggested values for maximum transmission number + * of payload octets and maximum packet transmission time for new connections. + */ + HciLeWriteDefDataLen(maxTxOctets, maxTxTime); + } break; + + case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: + if (hciCoreCb.extResetSeq) { + /* send first extended command */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } else { + /* initialize extended parameters */ + hciCoreCb.maxAdvDataLen = 0; + hciCoreCb.numSupAdvSets = 0; + hciCoreCb.perAdvListSize = 0; + + /* send next command in sequence */ + HciLeRandCmd(); + } + break; + + case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: + case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: + case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: + if (hciCoreCb.extResetSeq) { + /* send next extended command in sequence */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + break; + + case HCI_OPCODE_LE_RAND: + /* check if need to send second rand command */ + if (randCnt < (HCI_RESET_RAND_CNT-1)) { + randCnt++; + HciLeRandCmd(); + } else { + /* last command in sequence; set resetting state and call callback */ + signal_reset_sequence_done(); + } + break; + + default: + break; + } + } +} + +void CordioHCIDriver::signal_reset_sequence_done() +{ + hci_mbed_os_signal_reset_sequence_done(); +} + +uint16_t CordioHCIDriver::write(uint8_t type, uint16_t len, uint8_t *pData) +{ + return _transport_driver.write(type, len, pData); +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h new file mode 100644 index 00000000000..10ac769c82c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h @@ -0,0 +1,145 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_HCI_DRIVER_H_ +#define CORDIO_HCI_DRIVER_H_ + +#include +#include +#include "wsf_buf.h" +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Contain description of the memory pool used by the Cordio stack. + */ +struct buf_pool_desc_t { + /** + * Create a new memory pool description + * @param buffer the Buffer used by the memory pool. + * @param pool_desc How the memory is split + */ + template + buf_pool_desc_t( + uint8_t (&buffer)[BufferSize], + const wsfBufPoolDesc_t (&pool_desc)[PoolCount] + ) : buffer_memory(buffer), buffer_size(BufferSize), + pool_description(pool_desc), pool_count(PoolCount) + { + } + + uint8_t* buffer_memory; /// Pointer to the buffer memory + size_t buffer_size; /// Size of the buffer + const wsfBufPoolDesc_t* pool_description; /// Pointer to the first element describing the pool + size_t pool_count; /// Number of pools +}; + +/** + * Base class of the HCI driver use by the BLE port of the Cordio stack. + * This class provide to the stack: + * - The buffer necessary to run BLE API + * - The reset sequence of the BLE module + * - Access to the write function of the underlying HCITransport driver. + */ +class CordioHCIDriver { +public: + /** + * Construct a new instance of an HCI driver. + * @param transport_driver The driver used to communicate with the chip. + */ + CordioHCIDriver(CordioHCITransportDriver& transport_driver); + + /** + * Driver destructor + */ + virtual ~CordioHCIDriver() { } + + /** + * Return the set of memory pool which will be used by the Cordio stack + */ + virtual buf_pool_desc_t get_buffer_pool_description(); + + /** + * Initialize the HCI driver. + * This function start by initializing the transport driver then it delegates + * what's remain of the initialization to the function do_initialize. + */ + void initialize(); + + /** + * Termination of the driver. + * It call in sequence: + * - do_terminate + * - terminate the transport driver. + */ + void terminate(); + + /** + * Start the reset sequence of the BLE module. + */ + virtual void start_reset_sequence(); + + /** + * Handle HCI messages received during the reset sequence. + * + * @param msg The HCI message received. + * @note The driver should signal to the stack that the initialization + * sequence is done by calling the function: signal_reset_sequence_done. + */ + virtual void handle_reset_sequence(uint8_t *msg); + + /** + * Signal to the stack that the reset sequence has been done. + */ + void signal_reset_sequence_done(); + + /** + * Write data in the transport channel. + * + * @param type The type of packet to transmit. It might be an HCI command + * packet, ACL packet or EVT packet. Depending on the type of transport + * it can prefix the packet itself. + * @param len Number of bytes to transmit. + * @param pData pointer to the data to transmit. + * + * @return The number of bytes which have been transmited. + */ + uint16_t write(uint8_t type, uint16_t len, uint8_t *pData); + +private: + /** + * Initialize the chip. + * The transport is up at that time. + */ + virtual void do_initialize() = 0; + + /** + * Terminate the driver + */ + virtual void do_terminate() = 0; + + CordioHCITransportDriver& _transport_driver; +}; + + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_HCI_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp new file mode 100644 index 00000000000..01b0b1016a8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp @@ -0,0 +1,33 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CordioHCITransportDriver.h" +#include "CordioHCIDriver.h" + +extern "C" void hciTrSerialRxIncoming(uint8_t *pBuf, uint8_t len); + +namespace ble { +namespace vendor { +namespace cordio { + +void CordioHCITransportDriver::on_data_received(uint8_t* data, uint16_t len) +{ + hciTrSerialRxIncoming(data, len); +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h new file mode 100644 index 00000000000..a7e7499f210 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_HCI_TRANSPORT_DRIVER_H_ +#define CORDIO_HCI_TRANSPORT_DRIVER_H_ + +#include + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Base class of the HCI transport driver. + * It allow the stack to write data in the HCI channel. + */ +class CordioHCITransportDriver { +public: + /** + * Driver destructor. + */ + virtual ~CordioHCITransportDriver() { } + + /** + * Inialization of the transport. + */ + virtual void initialize() = 0; + + /** + * termination of the transport. + */ + virtual void terminate() = 0; + + /** + * Write data in the transport channel. + * + * @param type The type of packet to transmit. It might be an HCI command + * packet, ACL packet or EVT packet. Depending on the type of transport + * it can prefix the packet itself. + * @param len Number of bytes to transmit. + * @param pData pointer to the data to transmit. + * + * @return The number of bytes which have been transmited. + */ + virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData) = 0; + + /** + * The driver shall call this function whenever data bytes are received. + * + * @param data Pointer to the data received. + * @param len Number of bytes received. + */ + static void on_data_received(uint8_t* data, uint16_t len); +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_HCI_TRANSPORT_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp new file mode 100644 index 00000000000..5ceff2b12ed --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp @@ -0,0 +1,70 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "H4TransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +H4TransportDriver::H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud) : + uart(tx, rx, baud), cts(cts), rts(rts) { } + +void H4TransportDriver::initialize() +{ + uart.format( + /* bits */ 8, + /* parity */ SerialBase::None, + /* stop bit */ 1 + ); + + uart.set_flow_control( + /* flow */ SerialBase::RTSCTS, + /* rts */ rts, + /* cts */ cts + ); + + uart.attach( + callback(this, &H4TransportDriver::on_controller_irq), + SerialBase::RxIrq + ); +} + +void H4TransportDriver::terminate() { } + +uint16_t H4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData) +{ + uint16_t i = 0; + while (i < len + 1) { + uint8_t to_write = i == 0 ? type : pData[i - 1]; + while (uart.writeable() == 0); + uart.putc(to_write); + ++i; + } + return len; +} + +void H4TransportDriver::on_controller_irq() +{ + while (uart.readable()) { + uint8_t char_received = uart.getc(); + on_data_received(&char_received, 1); + } +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h new file mode 100644 index 00000000000..6e6e1d4b011 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h @@ -0,0 +1,76 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORDIO_H4_TRANSPORT_DRIVER_H_ +#define CORDIO_H4_TRANSPORT_DRIVER_H_ + +#include +#include "mbed.h" +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Implementation of the H4 driver. + */ +class H4TransportDriver : public CordioHCITransportDriver { +public: + /** + * Initialize the transport driver. + * + * @param tx tx pin name. + * @param rx rx pin name + * @param cts cts pin name + * @param rts rts pin name. + * @param baud baud use to communicate with the ble module + */ + H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud); + + /** + * Destructor + */ + virtual ~H4TransportDriver() { } + + /** + * @see CordioHCITransportDriver::initialize + */ + virtual void initialize(); + + /** + * @see CordioHCITransportDriver::terminate + */ + virtual void terminate(); + + /** + * @see CordioHCITransportDriver::write + */ + virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData); + +private: + void on_controller_irq(); + + Serial uart; + PinName cts; + PinName rts; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_H4_TRANSPORT_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp new file mode 100644 index 00000000000..ba2d5e15bd0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -0,0 +1,452 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "us_ticker_api.h" +#include "BLE.h" +#include "wsf_types.h" +#include "wsf_msg.h" +#include "wsf_os.h" +#include "wsf_buf.h" +#include "wsf_timer.h" +#include "hci_handler.h" +#include "dm_handler.h" +#include "l2c_handler.h" +#include "att_handler.h" +#include "smp_handler.h" +#include "l2c_api.h" +#include "att_api.h" +#include "smp_api.h" +#include "hci_drv.h" +#include "CordioBLE.h" +#include "mbed_assert.h" + +#include "CordioPalAttClient.h" + +/*! WSF handler ID */ +wsfHandlerId_t stack_handler_id; + +/* Store the Event signaling state */ +bool isEventsSignaled = false; + +/** + * Weak definition of ble_cordio_get_hci_driver. + * A runtime error is generated if the user does not define any + * ble_cordio_get_hci_driver. + */ +MBED_WEAK ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() +{ + error("Please provide an implementation for the HCI driver"); + ble::vendor::cordio::CordioHCIDriver* bad_instance = NULL; + return *bad_instance; +} + +/** + * Low level HCI interface between Cordio stack and the port. + */ +extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData) +{ + return ble_cordio_get_hci_driver().write(type, len, pData); +} + +extern "C" void hci_mbed_os_start_reset_sequence(void) +{ + ble_cordio_get_hci_driver().start_reset_sequence(); +} + +extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t* msg) +{ + ble_cordio_get_hci_driver().handle_reset_sequence(msg); +} + +/* + * This function will signal to the user code by calling signalEventsToProcess. + * It is registered and called into the Wsf Stack. + */ +extern "C" void wsf_mbed_ble_signal_event(void) +{ + if(isEventsSignaled == false) { + isEventsSignaled = true; + ble::vendor::cordio::BLE::deviceInstance().signalEventsToProcess(::BLE::DEFAULT_INSTANCE); + } +} + +/** + * BLE-API requires an implementation of the following function in order to + * obtain its transport handle. + */ +BLEInstanceBase *createBLEInstance() +{ + return (&(ble::vendor::cordio::BLE::deviceInstance())); +} + +namespace ble { +namespace vendor { +namespace cordio { + +BLE::BLE(CordioHCIDriver& hci_driver) : + initialization_status(NOT_INITIALIZED), + instanceID(::BLE::DEFAULT_INSTANCE) +{ + _hci_driver = &hci_driver; + stack_setup(); +} + +BLE::~BLE() { } + +/** + * The singleton which represents the BLE transport for the BLE. + */ +BLE& BLE::deviceInstance() +{ + static BLE instance( + ble_cordio_get_hci_driver() + ); + return instance; +} + +ble_error_t BLE::init( + ::BLE::InstanceID_t instanceID, + FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext *> initCallback) +{ + + switch (initialization_status) { + case NOT_INITIALIZED: + _init_callback = initCallback; + start_stack_reset(); + return BLE_ERROR_NONE; + + case INITIALIZING: + return BLE_ERROR_INITIALIZATION_INCOMPLETE; + + case INITIALIZED: + return BLE_ERROR_NONE; + + default: + return BLE_ERROR_UNSPECIFIED; + } +} + +bool BLE::hasInitialized() const +{ + return initialization_status == INITIALIZED; +} + +ble_error_t BLE::shutdown() +{ + if (initialization_status != INITIALIZED) { + return BLE_ERROR_INITIALIZATION_INCOMPLETE; + } + + initialization_status = NOT_INITIALIZED; + _hci_driver->terminate(); + + getGattServer().reset(); + getGattClient().reset(); + getGap().reset(); + + return BLE_ERROR_NONE; +} + +const char* BLE::getVersion() +{ + static const char version[] = "generic-cordio"; + return version; +} + +Gap& BLE::getGap() +{ + return cordio::Gap::getInstance(); +} + +const Gap& BLE::getGap() const +{ + return cordio::Gap::getInstance(); +} + +GattServer& BLE::getGattServer() +{ + return cordio::GattServer::getInstance(); +} + +const GattServer& BLE::getGattServer() const +{ + return cordio::GattServer::getInstance(); +} + +::GattClient& BLE::getGattClient() +{ + static pal::AttClientToGattClientAdapter pal_client( + pal::vendor::cordio::CordioAttClient::get_client() + ); + static generic::GenericGattClient client(&pal_client); + + return client; +} + +SecurityManager& BLE::getSecurityManager() +{ + return cordio::SecurityManager::getInstance(); +} + +const SecurityManager& BLE::getSecurityManager() const +{ + return cordio::SecurityManager::getInstance(); +} + +void BLE::waitForEvent() +{ + static Timeout nextTimeout; + timestamp_t nextTimestamp; + bool_t pTimerRunning; + + callDispatcher(); + + if (wsfOsReadyToSleep()) { + // setup an mbed timer for the next cordio timeout + nextTimestamp = (timestamp_t)(WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000; + if (pTimerRunning) { + nextTimeout.attach_us(timeoutCallback, nextTimestamp); + } + } +} + +void BLE::processEvents() +{ + if (isEventsSignaled) { + isEventsSignaled = false; + callDispatcher(); + } + } + + void BLE::stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg) + { + if (msg == NULL) { + return; + } + + switch(msg->event) { + case DM_RESET_CMPL_IND: { + ::BLE::InitializationCompleteCallbackContext context = { + ::BLE::Instance(::BLE::DEFAULT_INSTANCE), + BLE_ERROR_NONE + }; + deviceInstance().getGattServer().initialize(); + deviceInstance().getGap().initialize(); + deviceInstance().initialization_status = INITIALIZED; + _init_callback.call(&context); + } break; + + case DM_ADV_START_IND: + break; + + case DM_ADV_STOP_IND: + Gap::getInstance().advertisingStopped(); + break; + + case DM_SCAN_REPORT_IND: { + hciLeAdvReportEvt_t *scan_report = (hciLeAdvReportEvt_t*) msg; + Gap::getInstance().processAdvertisementReport( + scan_report->addr, + scan_report->rssi, + (scan_report->eventType == DM_RPT_SCAN_RESPONSE) ? true : false, + (GapAdvertisingParams::AdvertisingType_t) scan_report->eventType, + scan_report->len, + scan_report->pData + ); + } break; + + case DM_CONN_OPEN_IND: { + hciLeConnCmplEvt_t* conn_evt = (hciLeConnCmplEvt_t*) msg; + dmConnId_t connection_id = conn_evt->hdr.param; + Gap::getInstance().setConnectionHandle(connection_id); + Gap::AddressType_t own_addr_type; + Gap::Address_t own_addr; + Gap::getInstance().getAddress(&own_addr_type, own_addr); + + Gap::ConnectionParams_t params = { + conn_evt->connInterval, + conn_evt->connInterval, + conn_evt->connLatency, + conn_evt->supTimeout + }; + + Gap::getInstance().processConnectionEvent( + connection_id, + (conn_evt->role == DM_ROLE_MASTER) ? Gap::CENTRAL : Gap::PERIPHERAL, + (Gap::AddressType_t) conn_evt->addrType, + conn_evt->peerAddr, + own_addr_type, + own_addr, + ¶ms + ); + } break; + + case DM_CONN_CLOSE_IND: { + dmEvt_t *disconnect_evt = (dmEvt_t*) msg; + Gap::getInstance().setConnectionHandle(DM_CONN_ID_NONE); + Gap::getInstance().processDisconnectionEvent( + disconnect_evt->hdr.param, + (Gap::DisconnectionReason_t) disconnect_evt->connClose.reason + ); + } break; + + default: + break; + } +} + +void BLE::device_manager_cb(dmEvt_t* dm_event) +{ + BLE::deviceInstance().stack_handler(0, &dm_event->hdr); +} + +/* + * AttServerInitDeInitCback callback is used to Initialize/Deinitialize + * the CCC Table of the ATT Server when a remote peer requests to Open + * or Close the connection. + */ + void BLE::connection_handler(dmEvt_t* dm_event) + { + dmConnId_t connId = (dmConnId_t)dm_event->hdr.param; + + switch (dm_event->hdr.event) { + case DM_CONN_OPEN_IND: + /* set up CCC table with uninitialized (all zero) values */ + AttsCccInitTable(connId, NULL); + break; + case DM_CONN_CLOSE_IND: + /* clear CCC table on connection close */ + AttsCccClearTable(connId); + break; + default: + break; + } +} + +void BLE::timeoutCallback() +{ + wsf_mbed_ble_signal_event(); +} + +void BLE::stack_setup() +{ + MBED_ASSERT(_hci_driver != NULL); + + wsfHandlerId_t handlerId; + + buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description(); + + // Initialize buffers with the ones provided by the HCI driver + uint16_t bytes_used = WsfBufInit( + buf_pool_desc.buffer_size, buf_pool_desc.buffer_memory, + buf_pool_desc.pool_count, buf_pool_desc.pool_description + ); + + MBED_ASSERT(bytes_used != 0); + + WsfTimerInit(); + SecInit(); + + // Note: enable once security is supported +#if 0 + SecAesInit(); + SecCmacInit(); + SecEccInit(); +#endif + + handlerId = WsfOsSetNextHandler(HciHandler); + HciHandlerInit(handlerId); + + handlerId = WsfOsSetNextHandler(DmHandler); + DmAdvInit(); + DmScanInit(); + DmConnInit(); + DmConnMasterInit(); + DmConnSlaveInit(); + DmSecInit(); + + // Note: enable once security is supported +#if 0 + DmSecLescInit(); + DmPrivInit(); +#endif + DmHandlerInit(handlerId); + + handlerId = WsfOsSetNextHandler(L2cSlaveHandler); + L2cSlaveHandlerInit(handlerId); + L2cInit(); + L2cSlaveInit(); + L2cMasterInit(); + + handlerId = WsfOsSetNextHandler(AttHandler); + AttHandlerInit(handlerId); + AttsInit(); + AttsIndInit(); + AttcInit(); + + handlerId = WsfOsSetNextHandler(SmpHandler); + SmpHandlerInit(handlerId); + SmprScInit(); + SmpiInit(); + + stack_handler_id = WsfOsSetNextHandler(&BLE::stack_handler); + + DmRegister(BLE::device_manager_cb); + DmConnRegister(DM_CLIENT_ID_APP, BLE::device_manager_cb); + AttConnRegister(BLE::connection_handler); + AttRegister((attCback_t) ble::pal::vendor::cordio::CordioAttClient::att_client_handler); +} + +void BLE::start_stack_reset() +{ + _hci_driver->initialize(); + DmDevReset(); +} + +void BLE::callDispatcher() +{ + static uint32_t lastTimeUs = us_ticker_read(); + uint32_t currTimeUs, deltaTimeMs; + + // Update the current cordio time + currTimeUs = us_ticker_read(); + deltaTimeMs = (currTimeUs - lastTimeUs) / 1000; + if (deltaTimeMs > 0) { + WsfTimerUpdate(deltaTimeMs / WSF_MS_PER_TICK); + lastTimeUs += deltaTimeMs * 1000; + } + + wsfOsDispatcher(); + + if (wsfOsReadyToSleep()) { + static Timeout nextTimeout; + // setup an mbed timer for the next Cordio timeout + bool_t pTimerRunning; + timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000; + if (pTimerRunning) { + nextTimeout.attach_us(timeoutCallback, nextTimestamp); + } + } +} + +CordioHCIDriver* BLE::_hci_driver = NULL; + +FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> BLE::_init_callback; + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp new file mode 100644 index 00000000000..450a2def4bc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp @@ -0,0 +1,543 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "CordioGap.h" +#include "mbed.h" +#include "dm_api.h" +#include "CordioGattServer.h" +#include "hci_core.h" + +/**< Minimum Advertising interval in 625 us units, i.e. 20 ms. */ +#define BLE_GAP_ADV_INTERVAL_MIN 0x0020 + +/**< Minimum Advertising interval in 625 us units for non connectable mode, i.e. 100 ms. */ +#define BLE_GAP_ADV_NONCON_INTERVAL_MIN 0x00A0 + +/**< Maximum Advertising interval in 625 us units, i.e. 10.24 s. */ +#define BLE_GAP_ADV_INTERVAL_MAX 0x4000 + +namespace ble { +namespace vendor { +namespace cordio { + +Gap &Gap::getInstance() +{ + static Gap m_instance; + return m_instance; +} + +void Gap::initialize() +{ + uint8_t whitelist_size = HciGetWhiteListSize(); + + if (whitelist_size == 0) { + return; + } + + whitelist.addresses = new(std::nothrow) BLEProtocol::Address_t[whitelist_size]; + if (whitelist.addresses == NULL) { + return; + } + + whitelist.size = 0; + whitelist.capacity = hciCoreCb.whiteListSize; +} + +ble_error_t Gap::setAddress(AddressType_t type, const Address_t address) +{ + switch (type) { + case BLEProtocol::AddressType::PUBLIC: + // TODO: use vendor specific commands from the driver + return BLE_ERROR_OPERATION_NOT_PERMITTED; + + // See bluetooth 5, Vol 6 part, part B, 1.3.2 + case BLEProtocol::AddressType::RANDOM_STATIC: + if ((address[5] >> 6) != 3) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + m_type = type; + BdaCpy(m_addr, address); + DmDevSetRandAddr(m_addr); + break; + + // should not be here, generation is supposed to be handled by the controller. + case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: + case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: + m_type = type; + return BLE_ERROR_NONE; + + default: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + DmAdvSetAddrType(m_type); + DmConnSetAddrType(m_type); + DmScanSetAddrType(m_type); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::getAddress(AddressType_t *typeP, Address_t address) +{ + *typeP = m_type; + + if(m_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE || + m_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { + return BLE_ERROR_NONE; + } + + BdaCpy(address, m_addr); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) +{ + /* Make sure we don't exceed the advertising payload length */ + if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + /* Make sure we have a payload! */ + if (advData.getPayloadLen() == 0) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* set advertising and scan response data for discoverable mode */ + DmAdvSetData(DM_ADV_HANDLE_DEFAULT, HCI_ADV_DATA_OP_COMP_FRAG, DM_DATA_LOC_ADV, advData.getPayloadLen(), (uint8_t*)advData.getPayload()); + DmAdvSetData(DM_ADV_HANDLE_DEFAULT, HCI_ADV_DATA_OP_COMP_FRAG, DM_DATA_LOC_SCAN, scanResponse.getPayloadLen(), (uint8_t*)scanResponse.getPayload()); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams +) { + // prepare the scan interval + if (scanParams != NULL) { + DmConnSetScanInterval(scanParams->getInterval(), scanParams->getWindow()); + } + + if (connectionParams != NULL) { + hciConnSpec_t conn_spec = { + /* connIntervalMin */ connectionParams->minConnectionInterval, + /* connIntervalMax */ connectionParams->maxConnectionInterval, + /* connLatency */ connectionParams->slaveLatency, + /* supTimeout */ connectionParams->connectionSupervisionTimeout, + /* minCeLen */ DM_GAP_CONN_EST_MIN_CE_LEN, + /* maxCeLen */ DM_GAP_CONN_EST_MAX_CE_LEN + }; + DmConnSetConnSpec(&conn_spec); + } + + DmScanStop(); + dmConnId_t connection_id = DmConnOpen( + DM_CLIENT_ID_APP, + HCI_INIT_PHY_LE_1M_BIT, + peerAddrType, + (uint8_t*) peerAddr + ); + + if (connection_id == DM_CONN_ID_NONE) { + return BLE_ERROR_INTERNAL_STACK_FAILURE; + } + + return BLE_ERROR_NONE; +} + +uint16_t Gap::getMinAdvertisingInterval() const +{ + return BLE_GAP_ADV_INTERVAL_MIN; +} + +uint16_t Gap::getMinNonConnectableAdvertisingInterval() const +{ + return BLE_GAP_ADV_NONCON_INTERVAL_MIN; +} + +uint16_t Gap::getMaxAdvertisingInterval() const +{ + return BLE_GAP_ADV_INTERVAL_MAX; +} + +ble_error_t Gap::startAdvertising(const GapAdvertisingParams ¶ms) +{ + /* Make sure we support the advertising type */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { + /* ToDo: This requires a proper security implementation, etc. */ + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /* Check interval range */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { + /* Min delay is slightly longer for unconnectable devices */ + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } else { + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + + /* Check timeout is zero for Connectable Directed */ + if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { + /* Timeout must be 0 with this type, although we'll never get here */ + /* since this isn't implemented yet anyway */ + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Check timeout for other advertising types */ + if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && + (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + uint16_t adv_interval_min = params.getIntervalInADVUnits(); + if (adv_interval_min == GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX) { + --adv_interval_min; + } + uint16_t adv_interval_max = adv_interval_min + 1; + + DmAdvSetInterval(DM_ADV_HANDLE_DEFAULT, adv_interval_min, adv_interval_max); + + /* Peer Addr Type 0 = Public */ + uint8_t peerAddrType = 0; + uint8_t peerAddr[6] = { 0 }; + DmAdvConfig(DM_ADV_HANDLE_DEFAULT, params.getAdvertisingType(), peerAddrType, peerAddr); + + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + uint16_t adv_durations[] = { (uint16_t) (params.getTimeout() * 1000) }; + uint8_t max_ea_events[] = { 0 }; + DmAdvStart(1, adv_handles, adv_durations, max_ea_events); + + state.advertising = 1; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::stopAdvertising(void) +{ + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + DmAdvStop(1, adv_handles); + + state.advertising = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) +{ + DmConnClose(DM_CLIENT_ID_APP, connectionHandle, reason); + + state.advertising = 0; + state.connected = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::disconnect(DisconnectionReason_t reason) +{ + DmConnClose(DM_CLIENT_ID_APP, m_connectionHandle, reason); + + state.advertising = 0; + state.connected = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setDeviceName(const uint8_t *deviceName) +{ + return GattServer::getInstance().setDeviceName(deviceName); +} + +ble_error_t Gap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) +{ + const uint8_t* name = NULL; + uint16_t length = 0; + + GattServer::getInstance().getDeviceName(name, length); + + if (deviceName != NULL) { + memcpy(deviceName, name, std::min((uint16_t) *lengthP, length)); + } + + *lengthP = length; + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAppearance(GapAdvertisingData::Appearance appearance) +{ + GattServer::getInstance().setAppearance(appearance); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::getAppearance(GapAdvertisingData::Appearance *appearanceP) +{ + *appearanceP = GattServer::getInstance().getAppearance(); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setTxPower(int8_t txPower) +{ +#if 0 + HciVsSetTxPower(txPower); + return BLE_ERROR_NONE; +#else + return BLE_ERROR_NOT_IMPLEMENTED; +#endif +} + +void Gap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) +{ + *valueArrayPP = NULL; + *countP = 0; +} + +void Gap::setConnectionHandle(uint16_t connectionHandle) +{ + m_connectionHandle = connectionHandle; +} + +uint16_t Gap::getConnectionHandle(void) +{ + return m_connectionHandle; +} + +ble_error_t Gap::getPreferredConnectionParams(ConnectionParams_t *params) +{ + *params = GattServer::getInstance().getPreferredConnectionParams(); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setPreferredConnectionParams(const ConnectionParams_t *params) +{ + // ensure that parameters are correct + // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] + // section 12.3 PERIPHERAL PREFERRED CONNECTION PARAMETERS CHARACTERISTIC + if (((0x0006 > params->minConnectionInterval) || (params->minConnectionInterval > 0x0C80)) && + params->minConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((params->minConnectionInterval > params->maxConnectionInterval) || (params->maxConnectionInterval > 0x0C80)) && + params->maxConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (params->slaveLatency > 0x01F3) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((0x000A > params->connectionSupervisionTimeout) || (params->connectionSupervisionTimeout > 0x0C80)) && + params->connectionSupervisionTimeout != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + GattServer::getInstance().setPreferredConnectionParams(*params); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) +{ + if (DmConnCheckIdle(handle) != 0) { + return BLE_STACK_BUSY; + } + + hciConnSpec_t connSpec; + connSpec.connIntervalMin = newParams->minConnectionInterval; + connSpec.connIntervalMax = newParams->maxConnectionInterval; + connSpec.connLatency = newParams->slaveLatency; + connSpec.supTimeout = newParams->connectionSupervisionTimeout; + DmConnUpdate(handle, &connSpec); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::startRadioScan(const GapScanningParams &scanningParams) +{ + // not needed to start scanning if the whitelist is empty and the scanning + // policy filter all the advertising packets + if ((whitelist.size == 0) && (scanning_policy_mode == Gap::SCAN_POLICY_FILTER_ALL_ADV)) { + return BLE_ERROR_INVALID_STATE; + } + + uint16_t scan_intervals[] = { scanningParams.getInterval() }; + uint16_t scan_windows[] = { scanningParams.getWindow() }; + + DmScanSetInterval(HCI_SCAN_PHY_LE_1M_BIT, scan_intervals, scan_windows); + + uint8_t scanType = scanningParams.getActiveScanning() ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE; + uint32_t duration = (uint32_t)scanningParams.getTimeout() * 1000; + if (duration > 0xFFFF) { + // saturate to 16-bits + duration = 0xFFFF; + } + + DmScanStart(HCI_SCAN_PHY_LE_1M_BIT, DM_DISC_MODE_NONE, &scanType, TRUE, duration, 0); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::stopScan(void) +{ + DmScanStop(); + return BLE_ERROR_NONE; +} + +void Gap::advertisingStopped(void) +{ + /* If advertising stopped due to a call to stopAdvertising(), state.advertising will + * be '0.' Otherwise, advertising must have stopped due to a timeout + */ + if (state.advertising) { + processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); + } +} + +uint8_t Gap::getMaxWhitelistSize(void) const +{ + return whitelist.capacity; +} + +ble_error_t Gap::getWhitelist(Whitelist_t &other) const +{ + // i is a shorthand for other.size + uint8_t& i = other.size; + + for (i = 0; (i < whitelist.capacity) && (i < other.capacity); ++i) { + other.addresses[i] = whitelist.addresses[i]; + } + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setWhitelist(const Whitelist_t& other) +{ + if (other.capacity > whitelist.capacity) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + // note : can be improved by sending the diff instead of the full list + + DmDevWhiteListClear(); + + // alias i to whitelist.size + uint8_t& i = whitelist.size; + + for (i = 0; (i < other.capacity) && (i < whitelist.capacity); ++i) { + whitelist.addresses[i] = other.addresses[i]; + DmDevWhiteListAdd( + (whitelist.addresses[i].type > 1) ? 0xFF : whitelist.addresses[i].type, + whitelist.addresses[i].address + ); + } + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_ADV, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + advertising_policy_mode = mode; + return BLE_ERROR_NONE; +} + +Gap::AdvertisingPolicyMode_t Gap::getAdvertisingPolicyMode(void) const +{ + return advertising_policy_mode; +} + +ble_error_t Gap::setScanningPolicyMode(ScanningPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_SCAN, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + scanning_policy_mode = mode; + return BLE_ERROR_NONE; + +} + +Gap::ScanningPolicyMode_t Gap::getScanningPolicyMode(void) const +{ + return scanning_policy_mode; +} + +ble_error_t Gap::setInitiatorPolicyMode(InitiatorPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_INIT, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + initiator_policy_mode = mode; + return BLE_ERROR_NONE; +} + +Gap::InitiatorPolicyMode_t Gap::getInitiatorPolicyMode(void) const +{ + return initiator_policy_mode; +} + +ble_error_t Gap::reset(void) +{ + this->::Gap::reset(); + delete[] whitelist.addresses; + whitelist.addresses = NULL; + whitelist.size = 0; + whitelist.capacity = 0; + return BLE_ERROR_NONE; +} + +Gap::Gap() : + ::Gap(), + m_connectionHandle(DM_CONN_ID_NONE), + m_type(BLEProtocol::AddressType::RANDOM_STATIC), + m_addr(), + advertising_policy_mode(ADV_POLICY_IGNORE_WHITELIST), + scanning_policy_mode(SCAN_POLICY_IGNORE_WHITELIST), + initiator_policy_mode(INIT_POLICY_IGNORE_WHITELIST), + whitelist() +{ +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp new file mode 100644 index 00000000000..6f1a68da17f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -0,0 +1,763 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "CordioGattServer.h" +#include "CordioGap.h" +#include "mbed.h" +#include "wsf_types.h" +#include "att_api.h" + +static UUID cccUUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG); +static const uint16_t cccSize = sizeof(uint16_t); + +namespace ble { +namespace vendor { +namespace cordio { + +GattServer &GattServer::getInstance() +{ + static GattServer m_instance; + return m_instance; +} + +void GattServer::initialize() +{ + add_generic_access_service(); + add_generic_attribute_service(); +} + +ble_error_t GattServer::addService(GattService &service) +{ + ++currentHandle; + uint16_t startHandle = currentHandle; + + internal_service_t *internal_service = new internal_service_t; + + if (registered_service) { + internal_service->next = registered_service; + } else { + internal_service->next = NULL; + } + + registered_service = internal_service; + + // Create cordio attribute group + internal_service->attGroup = new attsGroup_t; + + // Determine the attribute list length + unsigned int attListLen = 1; + for (int i = 0; i < service.getCharacteristicCount(); i++) { + attListLen += 2; + GattCharacteristic *p_char = service.getCharacteristic(i); + + attListLen += p_char->getDescriptorCount(); + if (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) { + // add a CCCD + attListLen++; + } + } + + // Create cordio attribute list + internal_service->attGroup->pAttr = (attsAttr_t*)alloc_block(attListLen * sizeof(attsAttr_t)); + if (internal_service->attGroup->pAttr == NULL) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + // Create characteristics + internal_service->chars = new internal_char_t [service.getCharacteristicCount()]; + + attsAttr_t *currAtt = internal_service->attGroup->pAttr; + + /* Service */ + currAtt->pUuid = attPrimSvcUuid; + if (service.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + internal_service->uuidLen = UUID::LENGTH_OF_LONG_UUID; + } else { + internal_service->uuidLen = sizeof(UUID::ShortUUIDBytes_t); + } + currAtt->pValue = (uint8_t*)alloc_block(internal_service->uuidLen); + memcpy(currAtt->pValue, service.getUUID().getBaseUUID(), internal_service->uuidLen); + currAtt->maxLen = internal_service->uuidLen; + currAtt->pLen = &internal_service->uuidLen; + currAtt->settings = 0; + currAtt->permissions = ATTS_PERMIT_READ; + + currAtt++; + + /* Add characteristics to the service */ + for (int i = 0; i < service.getCharacteristicCount(); i++) { + GattCharacteristic *p_char = service.getCharacteristic(i); + + /* Skip any incompletely defined, read-only characteristics. */ + if ((p_char->getValueAttribute().getValuePtr() == NULL) && + (p_char->getValueAttribute().getLength() == 0) && + (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { + continue; + } + + // Create Characteristic Attribute + currentHandle += 2; + currAtt->pUuid = attChUuid; + + p_char->getValueAttribute().setHandle(currentHandle); + internal_service->chars[i].descLen = 1 + sizeof(currentHandle) + p_char->getValueAttribute().getUUID().getLen(); + currAtt->pValue = (uint8_t*) alloc_block(internal_service->chars[i].descLen); + uint8_t *pValue = currAtt->pValue; + *pValue++ = p_char->getProperties(); + memcpy(pValue, ¤tHandle, sizeof(currentHandle)); + pValue += sizeof(currentHandle); + memcpy(pValue, p_char->getValueAttribute().getUUID().getBaseUUID(), p_char->getValueAttribute().getUUID().getLen()); + + currAtt->pLen = &internal_service->chars[i].descLen; + currAtt->maxLen = internal_service->chars[i].descLen; + currAtt->settings = 0; + currAtt->permissions = ATTS_PERMIT_READ; + currAtt++; + + // Create Value Attribute + currAtt->pUuid = p_char->getValueAttribute().getUUID().getBaseUUID(); + currAtt->maxLen = p_char->getValueAttribute().getMaxLength(); + currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); + *currAtt->pLen = p_char->getValueAttribute().getLength(); + currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); + memcpy(currAtt->pValue, p_char->getValueAttribute().getValuePtr(), *currAtt->pLen); + memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); + + currAtt->settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK; + if (p_char->getValueAttribute().getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + currAtt->settings |= ATTS_SET_UUID_128; + } + if (p_char->getValueAttribute().hasVariableLength()) { + currAtt->settings |= ATTS_SET_VARIABLE_LEN; + } + + currAtt->permissions = 0; + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) { currAtt->permissions |= ATTS_PERMIT_READ; } + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) { currAtt->permissions |= ATTS_PERMIT_WRITE; } + currAtt++; + + bool cccCreated = false; + + for (int i = 0; i < p_char->getDescriptorCount(); i++) { + GattAttribute *p_att = p_char->getDescriptor(i); + + currentHandle++; + + p_att->setHandle(currentHandle); + + currAtt->pUuid = p_att->getUUID().getBaseUUID(); + currAtt->maxLen = p_att->getMaxLength(); + currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); + *currAtt->pLen = p_att->getLength(); + currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); + memcpy(currAtt->pValue, p_att->getValuePtr(), *currAtt->pLen); + memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); + + currAtt->settings = 0; + currAtt->permissions = ATTS_PERMIT_READ | ATTS_PERMIT_WRITE; + if (p_att->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + currAtt->settings |= ATTS_SET_UUID_128; + } + if (p_att->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) { + cccCreated = true; + currAtt->settings |= ATTS_SET_CCC; + currAtt->permissions |= ATTS_PERMIT_READ; + currAtt->permissions |= ATTS_PERMIT_WRITE; + + if (cccCnt < MAX_CCC_CNT) { + cccSet[cccCnt].handle = currentHandle; + cccSet[cccCnt].valueRange = 0; + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; + cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); + cccCnt++; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + if (p_att->hasVariableLength()) { + currAtt->settings |= ATTS_SET_VARIABLE_LEN; + } + currAtt++; + } + + if (!cccCreated && (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) { + /* There was not a CCCD included in the descriptors, but this + * characteristic is notifiable and/or indicatable. A CCCD is + * required so create one now. + */ + if (cccCnt >= MAX_CCC_CNT) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + currentHandle++; + + currAtt->pUuid = cccUUID.getBaseUUID(); + currAtt->pValue = (uint8_t*)&cccValues[cccCnt]; + currAtt->pLen = (uint16_t*)&cccSize; + currAtt->maxLen = sizeof(uint16_t); + currAtt->settings = ATTS_SET_CCC; + currAtt->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); + + cccSet[cccCnt].handle = currentHandle; + cccSet[cccCnt].valueRange = 0; + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; + cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); + + cccCnt++; + currAtt++; + } + } + + internal_service->attGroup->pNext = NULL; + internal_service->attGroup->readCback = attsReadCback; + internal_service->attGroup->writeCback = attsWriteCback; + internal_service->attGroup->startHandle = startHandle; + internal_service->attGroup->endHandle = currentHandle; + AttsAddGroup(internal_service->attGroup); + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + + service.setHandle(startHandle); + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t * lengthP) +{ + uint16_t attribute_length = 0; + uint8_t* attribute_value = NULL; + + if (AttsGetAttr(attributeHandle, &attribute_length, &attribute_value) != ATT_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (buffer) { + memcpy(buffer, attribute_value, std::min(*lengthP, attribute_length)); + } + + *lengthP = attribute_length; + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) +{ + // Check to see if this is a CCCD + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (attributeHandle == cccSet[idx].handle) { + if (connectionHandle == DM_CONN_ID_NONE) { // CCCDs are always 16 bits + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + *((uint16_t*)buffer) = AttsCccGet(connectionHandle, idx); + *lengthP = 2; // CCCDs are always 16 bits + return BLE_ERROR_NONE; + } + } + + // This is not a CCCD. Use the non-connection specific update method. + return read(attributeHandle, buffer, lengthP); +} + +ble_error_t GattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) +{ + uint16_t connectionHandle = Gap::getInstance().getConnectionHandle(); + + if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (!localOnly) { + if (connectionHandle != DM_CONN_ID_NONE) { + + // Check to see if this characteristic has a CCCD attribute + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (attributeHandle == cccHandles[idx]) { + break; + } + } + if (idx < cccCnt) { + // This characteristic has a CCCD attribute. Handle notifications and indications. + uint16_t cccEnabled = AttsCccEnabled(connectionHandle, idx); + if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { + AttsHandleValueNtf(connectionHandle, attributeHandle, len, (uint8_t*)buffer); + } + if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { + AttsHandleValueInd(connectionHandle, attributeHandle, len, (uint8_t*)buffer); + } + } + } + } + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) +{ + // Check to see if this is a CCCD + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (attributeHandle == cccSet[idx].handle) { + if ((connectionHandle == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + AttsCccSet(connectionHandle, idx, *((uint16_t*)buffer)); + return BLE_ERROR_NONE; + } + } + + // This is not a CCCD. Use the non-connection specific update method. + return write(attributeHandle, buffer, len, localOnly); +} + +ble_error_t GattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) +{ + uint16_t connectionHandle = Gap::getInstance().getConnectionHandle(); + + if (connectionHandle != DM_CONN_ID_NONE) { + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (characteristic.getValueHandle() == cccHandles[idx]) { + uint16_t cccValue = AttsCccGet(connectionHandle, idx); + if (cccValue & ATT_CLIENT_CFG_NOTIFY) { + *enabledP = true; + } else { + *enabledP = false; + } + return BLE_ERROR_NONE; + } + } + } + + return BLE_ERROR_PARAM_OUT_OF_RANGE; +} + +ble_error_t GattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) +{ + if (connectionHandle != DM_CONN_ID_NONE) { + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (characteristic.getValueHandle() == cccHandles[idx]) { + uint16_t cccValue = AttsCccGet(connectionHandle, idx); + if (cccValue & ATT_CLIENT_CFG_NOTIFY) { + *enabledP = true; + } else { + *enabledP = false; + } + return BLE_ERROR_NONE; + } + } + } + + return BLE_ERROR_PARAM_OUT_OF_RANGE; +} + +bool GattServer::isOnDataReadAvailable() const +{ + return true; +} + +::Gap::ConnectionParams_t GattServer::getPreferredConnectionParams() +{ + ::Gap::ConnectionParams_t params = { 0 }; + memcpy(¶ms.minConnectionInterval, generic_access_service.ppcp, 2); + memcpy(¶ms.maxConnectionInterval, generic_access_service.ppcp + 2, 2); + memcpy(¶ms.slaveLatency, generic_access_service.ppcp + 4, 2); + memcpy(¶ms.connectionSupervisionTimeout, generic_access_service.ppcp + 6, 2); + return params; +} + +void GattServer::setPreferredConnectionParams(const ::Gap::ConnectionParams_t& params) +{ + memcpy(generic_access_service.ppcp, ¶ms.minConnectionInterval, 2); + memcpy(generic_access_service.ppcp + 2, ¶ms.maxConnectionInterval, 2); + memcpy(generic_access_service.ppcp + 4, ¶ms.slaveLatency, 2); + memcpy(generic_access_service.ppcp + 6, ¶ms.connectionSupervisionTimeout, 2); +} + +ble_error_t GattServer::setDeviceName(const uint8_t *deviceName) +{ + size_t length = 0; + + if (deviceName != NULL) { + length = strlen((const char*)deviceName); + } + + if (length == 0) { + free(generic_access_service.device_name_value()); + } else { + uint8_t* res = (uint8_t*) realloc(generic_access_service.device_name_value(), length); + if (res == NULL) { + return BLE_ERROR_NO_MEM; + } + + generic_access_service.device_name_value() = res; + memcpy(res, deviceName, length); + } + + generic_access_service.device_name_length = length; + + return BLE_ERROR_NONE; +} + +void GattServer::getDeviceName(const uint8_t*& name, uint16_t& length) +{ + length = generic_access_service.device_name_length; + name = generic_access_service.device_name_value(); +} + +void GattServer::setAppearance(GapAdvertisingData::Appearance appearance) +{ + generic_access_service.appearance = appearance; +} + +GapAdvertisingData::Appearance GattServer::getAppearance() +{ + return (GapAdvertisingData::Appearance) generic_access_service.appearance; +} + +ble_error_t GattServer::reset(void) +{ + this->::GattServer::reset(); + + while (registered_service) { + internal_service_t* s = registered_service; + registered_service = s->next; + AttsRemoveGroup(s->attGroup->startHandle); + delete s->attGroup; + delete[] s->chars; + delete s; + } + + while (allocated_blocks) { + alloc_block_t* b = allocated_blocks; + allocated_blocks = b->next; + free(b); + } + + AttsRemoveGroup(generic_access_service.service.startHandle); + AttsRemoveGroup(generic_attribute_service.service.startHandle); + free(generic_access_service.device_name_value()); + + currentHandle = 0; + cccCnt = 0; + + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + + return BLE_ERROR_NONE; +} + +void GattServer::cccCback(attsCccEvt_t *pEvt) +{ + if (pEvt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, pEvt->handle); + } else { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, pEvt->handle); + } +} + +void GattServer::attCback(attEvt_t *pEvt) +{ + // TODO enable again + if (pEvt->hdr.status == ATT_SUCCESS) { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, pEvt->handle); + } +} + +uint8_t GattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) +{ + GattReadCallbackParams cbParams = { + connId, + handle, + offset, + *pAttr->pLen, + pAttr->pValue, + /* status */ BLE_ERROR_NONE, + }; + getInstance().handleDataReadEvent(&cbParams); + + return ATT_SUCCESS; +} + +uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr) +{ + uint8_t err; + + /* TODO: offset is not handled properly */ + if ((err = AttsSetAttr(handle, len, pValue)) != ATT_SUCCESS) { + return err; + } + + GattWriteCallbackParams::WriteOp_t writeOp; + switch (operation) { + case ATT_PDU_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_WRITE_REQ; + break; + case ATT_PDU_WRITE_CMD: + writeOp = GattWriteCallbackParams::OP_WRITE_CMD; + break; + case ATT_PDU_SIGNED_WRITE_CMD: + writeOp = GattWriteCallbackParams::OP_SIGN_WRITE_CMD; + break; + case ATT_PDU_PREP_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_PREP_WRITE_REQ; + break; + case ATT_PDU_EXEC_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_EXEC_WRITE_REQ_NOW; + break; + default: + writeOp = GattWriteCallbackParams::OP_INVALID; + break; + } + + GattWriteCallbackParams cbParams = { + connId, + handle, + writeOp, + offset, + len, + pValue + }; + getInstance().handleDataWrittenEvent(&cbParams); + + return ATT_SUCCESS; +} + +void GattServer::add_generic_access_service() +{ + ++currentHandle; + generic_access_service.service.pNext = NULL; + generic_access_service.service.startHandle = currentHandle; + generic_access_service.service.readCback = attsReadCback; + generic_access_service.service.writeCback = attsWriteCback; + + // bind attributes to the service + generic_access_service.service.pAttr = generic_access_service.attributes; + + attsAttr_t* current_attribute = generic_access_service.attributes; + + // service attribute + current_attribute->pUuid = attPrimSvcUuid; + current_attribute->pValue = (uint8_t*) attGapSvcUuid; + current_attribute->maxLen = sizeof(attGapSvcUuid); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // device name declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.device_name_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.device_name_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.device_name_declaration_value + 3, attDnChUuid, sizeof(attDnChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.device_name_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.device_name_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // device name value + ++current_attribute; + generic_access_service.device_name_length = 0; + current_attribute->pUuid = attDnChUuid; + current_attribute->maxLen = 248; + current_attribute->pLen = &generic_access_service.device_name_length; + current_attribute->pValue = NULL; + current_attribute->settings = ATTS_SET_VARIABLE_LEN; + current_attribute->permissions = ATTS_PERMIT_READ; + + // appearance declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.appearance_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.appearance_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.appearance_declaration_value + 3, attApChUuid, sizeof(attApChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.appearance_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.appearance_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // appearance value + ++current_attribute; + generic_access_service.appearance = 0; // unknown appearance + current_attribute->pUuid = attApChUuid; + current_attribute->maxLen = sizeof(generic_access_service.appearance); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = (uint8_t*) &generic_access_service.appearance; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + + // peripheral prefered connection parameters declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.ppcp_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.ppcp_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.ppcp_declaration_value + 3, attPpcpChUuid, sizeof(attPpcpChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.ppcp_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.ppcp_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // peripheral prefered connection parameters value + ++current_attribute; + const uint8_t default_ppcp_value[] = { + 0xFF, 0xFF, // no specific min connection interval + 0xFF, 0xFF, // no specific max connection interval + 0x00, 0x00, // no slave latency + 0xFF, 0xFF // no specific connection supervision timeout + }; + memcpy(&generic_access_service.ppcp, default_ppcp_value, sizeof(default_ppcp_value)); + current_attribute->pUuid = attPpcpChUuid; + current_attribute->maxLen = sizeof(generic_access_service.ppcp); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = generic_access_service.ppcp; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + generic_access_service.service.endHandle = currentHandle; + AttsAddGroup(&generic_access_service.service); +} + +void GattServer::add_generic_attribute_service() +{ + ++currentHandle; + generic_attribute_service.service.pNext = NULL; + generic_attribute_service.service.startHandle = currentHandle; + generic_attribute_service.service.readCback = attsReadCback; + generic_attribute_service.service.writeCback = attsWriteCback; + + // bind attributes to the service + generic_attribute_service.service.pAttr = generic_attribute_service.attributes; + + attsAttr_t* current_attribute = generic_attribute_service.attributes; + + // service attribute + current_attribute->pUuid = attPrimSvcUuid; + current_attribute->pValue = (uint8_t*) attGattSvcUuid; + current_attribute->maxLen = sizeof(attGattSvcUuid); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // service changed declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_attribute_service.service_changed_declaration[0] = ATT_PROP_INDICATE; + // set value handle + memcpy(generic_attribute_service.service_changed_declaration + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_attribute_service.service_changed_declaration + 3, attScChUuid, sizeof(attScChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_attribute_service.service_changed_declaration; + current_attribute->maxLen = sizeof(generic_attribute_service.service_changed_declaration); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // service changed value + ++current_attribute; + current_attribute->pUuid = attScChUuid; + current_attribute->maxLen = 0; + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = NULL; + current_attribute->settings = 0; + current_attribute->permissions = 0; + + // CCCD + ++current_attribute; + current_attribute->pUuid = attCliChCfgUuid; + current_attribute->pValue = (uint8_t*)&cccValues[cccCnt]; + current_attribute->maxLen = 2; + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = ATTS_SET_CCC; + current_attribute->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); + + cccSet[cccCnt].handle = currentHandle; + cccSet[cccCnt].valueRange = ATT_CLIENT_CFG_INDICATE; + cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; + cccHandles[cccCnt] = currentHandle - 1; + cccCnt++; + + generic_attribute_service.service.endHandle = currentHandle; + AttsAddGroup(&generic_attribute_service.service); + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); +} + +void* GattServer::alloc_block(size_t block_size) { + alloc_block_t* block = (alloc_block_t*) malloc(sizeof(alloc_block_t) + block_size); + if (block == NULL) { + return NULL; + } + + if (allocated_blocks) { + block->next = allocated_blocks; + } else { + block->next = NULL; + } + + allocated_blocks = block; + + return block->data; +} + +GattServer::GattServer() : + ::GattServer(), cccSet(), cccValues(), cccHandles(), cccCnt(0), + generic_access_service(), generic_attribute_service(), + registered_service(NULL), allocated_blocks(NULL), + currentHandle(0) +{ +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c new file mode 100644 index 00000000000..f42dff73f54 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c @@ -0,0 +1,28 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wsf_mbed_os_adaptation.h" +#include "mbed_critical.h" + +void wsf_mbed_os_critical_section_enter(void) +{ + core_util_critical_section_enter(); +} + +void wsf_mbed_os_critical_section_exit(void) +{ + core_util_critical_section_exit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt new file mode 100644 index 00000000000..9a4f65e654f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt @@ -0,0 +1,49 @@ +Permissive Binary License + +Version 1.0, September 2015 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named “DEPENDENCIES” and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h new file mode 100644 index 00000000000..3ae594c3dbb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h @@ -0,0 +1,45 @@ +/*************************************************************************************************/ +/*! + * \file hci_core_ps.h + * + * \brief HCI core platform-specific interfaces for dual-chip. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CORE_PS_H +#define HCI_CORE_PS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCoreResetSequence(uint8_t *pMsg); +void hciCoreNumCmplPkts(uint8_t *pMsg); +void hciCoreRecv(uint8_t msgType, uint8_t *pCoreRecvMsg); +uint8_t hciCoreVsCmdCmplRcvd(uint16_t opcode, uint8_t *pMsg, uint8_t len); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CORE_PS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h new file mode 100644 index 00000000000..33b5098d5bf --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h @@ -0,0 +1,46 @@ +/*************************************************************************************************/ +/*! + * \file hci_cmd.h + * + * \brief HCI command module. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CMD_H +#define HCI_CMD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCmdSend(uint8_t *pData); +uint8_t *hciCmdAlloc(uint16_t opcode, uint16_t len); +void hciCmdInit(void); +void hciCmdTimeout(wsfMsgHdr_t *pMsg); +void hciCmdRecvCmpl(uint8_t numCmdPkts); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CMD_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h new file mode 100644 index 00000000000..74ad361b8a6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h @@ -0,0 +1,129 @@ +/*************************************************************************************************/ +/*! + * \file hci_core.h + * + * \brief HCI core interfaces. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CORE_H +#define HCI_CORE_H + +#include "hci_core_ps.h" +#include "wsf_queue.h" +#include "wsf_os.h" +#include "hci_api.h" +#include "cfg_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +typedef void(*hciResetSeq_t)(uint8_t *pMsg, uint16_t opcode); + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Per-connection structure for ACL packet accounting */ +typedef struct +{ + uint8_t *pTxAclPkt; /* Fragmenting TX ACL packet pointer */ + uint8_t *pNextTxFrag; /* Next TX ACL packet fragment */ + uint8_t *pRxAclPkt; /* RX ACL packet pointer */ + uint8_t *pNextRxFrag; /* Next RX ACL packet fragment */ + uint16_t handle; /* Connection handle */ + uint16_t txAclRemLen; /* Fragmenting TX ACL packet remaining length */ + uint16_t rxAclRemLen; /* Fragmented RX ACL packet remaining length */ + bool_t fragmenting; /* TRUE if fragmenting a TX ACL packet */ + bool_t flowDisabled; /* TRUE if data flow disabled */ + uint8_t queuedBufs; /* Queued ACL buffers on this connection */ + uint8_t outBufs; /* Outstanding ACL buffers sent to controller */ +} hciCoreConn_t; + +/* Main control block for dual-chip implementation */ +typedef struct +{ + hciCoreConn_t conn[DM_CONN_MAX]; /* Connection structures */ + uint8_t leStates[HCI_LE_STATES_LEN]; /* Controller LE supported states */ + bdAddr_t bdAddr; /* Bluetooth device address */ + wsfQueue_t aclQueue; /* HCI ACL TX queue */ + hciCoreConn_t *pConnRx; /* Connection struct for current transport RX packet */ + uint16_t maxRxAclLen; /* Maximum reassembled RX ACL packet length */ + uint16_t bufSize; /* Controller ACL data buffer size */ + uint8_t aclQueueHi; /* Disable flow when this many ACL buffers queued */ + uint8_t aclQueueLo; /* Enable flow when this many ACL buffers queued */ + uint8_t availBufs; /* Current avail ACL data buffers */ + uint8_t numBufs; /* Controller number of ACL data buffers */ + uint8_t whiteListSize; /* Controller white list size */ + uint8_t numCmdPkts; /* Controller command packed count */ + uint16_t leSupFeat; /* Controller LE supported features */ + int8_t advTxPwr; /* Controller advertising TX power */ + uint8_t resListSize; /* Controller resolving list size */ + uint16_t maxAdvDataLen; /* Controller maximum advertisement (or scan response) data length */ + uint8_t numSupAdvSets; /* Controller maximum number of advertising sets */ + uint8_t perAdvListSize; /* Controller periodic advertising list size */ + hciResetSeq_t extResetSeq; /* HCI extended reset sequence callback */ +} hciCoreCb_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/* Control block */ +extern hciCoreCb_t hciCoreCb; + +/* Event mask */ +extern const uint8_t hciEventMask[HCI_EVT_MASK_LEN]; + +/* LE event mask */ +extern const uint8_t hciLeEventMask[HCI_LE_EVT_MASK_LEN]; + +/* Event mask page 2 */ +extern const uint8_t hciEventMaskPage2[HCI_EVT_MASK_LEN]; + +/* LE supported features configuration mask */ +extern uint16_t hciLeSupFeatCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCoreInit(void); +void hciCoreResetStart(void); +void hciCoreConnOpen(uint16_t handle); +void hciCoreConnClose(uint16_t handle); +hciCoreConn_t *hciCoreConnByHandle(uint16_t handle); +void hciCoreSendAclData(hciCoreConn_t *pConn, uint8_t *pData); +void hciCoreTxReady(uint8_t bufs); +void hciCoreTxAclStart(hciCoreConn_t *pConn, uint16_t len, uint8_t *pData); +bool_t hciCoreTxAclContinue(hciCoreConn_t *pConn); +void hciCoreTxAclComplete(hciCoreConn_t *pConn, uint8_t *pData); +uint8_t *hciCoreAclReassembly(uint8_t *pData); +bool_t hciCoreTxAclDataFragmented(hciCoreConn_t *pConn); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CORE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h new file mode 100644 index 00000000000..b0b6e562d5d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h @@ -0,0 +1,83 @@ +/*************************************************************************************************/ +/*! + * \file hci_drv.h + * + * \brief HCI driver interface. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2012-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_DRV_H +#define HCI_DRV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn hciDrvWrite + * + * \brief Write data the driver. + * + * \param type HCI packet type + * \param len Number of bytes to write. + * \param pData Byte array to write. + * + * \return Return actual number of data bytes written. + * + * \note The type parameter allows the driver layer to prepend the data with a header on the + * same write transaction. + */ +/*************************************************************************************************/ +uint16_t hciDrvWrite(uint8_t type, uint16_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn hciDrvRead + * + * \brief Read data bytes from the driver. + * + * \param len Number of bytes to read. + * \param pData Byte array to store data. + * + * \return Return actual number of data bytes read. + */ +/*************************************************************************************************/ +uint16_t hciDrvRead(uint16_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn hciDrvReadyToSleep + * + * \brief Returns TRUE if driver allows MCU to enter low power sleep mode. + * + * \return TRUE if ready to sleep, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t hciDrvReadyToSleep(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_DRV_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h new file mode 100644 index 00000000000..6e94e7f7985 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h @@ -0,0 +1,64 @@ +/*************************************************************************************************/ +/*! + * \file hci_evt.h + * + * \brief HCI event module. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_EVT_H +#define HCI_EVT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* HCI event statistics */ +typedef struct +{ + uint16_t numDiscCmplEvt; + uint16_t numEncChangeEvt; + uint16_t numReadRemoteVerInfoCmpEvt; + uint16_t numCmdCmplEvt; + uint16_t numCmdStatusEvt; + uint16_t numHwErrorEvt; + uint16_t numCmplPktsEvt; + uint16_t numDataBufOverflowEvt; + uint16_t numEncKeyRefreshCmplEvt; + uint16_t numLeMetaEvt; + uint16_t numVendorSpecEvt; + uint16_t numAuthToEvt; +} hciEvtStats_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciEvtProcessMsg(uint8_t *pEvt); +hciEvtStats_t *hciEvtGetStats(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_EVT_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h new file mode 100644 index 00000000000..e91baa3ed6f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h @@ -0,0 +1,45 @@ +/*************************************************************************************************/ +/*! + * \file hci_tr.h + * + * \brief HCI transport interface. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_TR_H +#define HCI_TR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciTrSendAclData(void *pContext, uint8_t *pAclData); +void hciTrSendCmd(uint8_t *pCmdData); +bool_t hciTrInit(uint8_t port, uint32_t baudRate, bool_t flowControl); +void hciTrShutdown(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_TR_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h new file mode 100644 index 00000000000..d16cbb4dd61 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h @@ -0,0 +1,246 @@ +/*************************************************************************************************/ +/*! + * \file sec_api.h + * + * \brief AES and random number security service API. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SEC_API_H +#define SEC_API_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! CMAC algorithm key length */ +#define SEC_CMAC_KEY_LEN 16 + +/*! CMAC algorithm result length */ +#define SEC_CMAC_HASH_LEN 16 + +/*! ECC algorithm key length */ +#define SEC_ECC_KEY_LEN 32 + +/*! Invalid AES Token */ +#define SEC_TOKEN_INVALID 0xFF + +/************************************************************************************************** + Data Types +**************************************************************************************************/ +/*! AES Security callback parameters structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! header */ + uint8_t *pCiphertext; /*! pointer to 16 bytes of ciphertext data */ +} secMsg_t; + +/*! AES Security callback are the same as secMsg_t */ +typedef secMsg_t secAes_t; + +/*! CMAC Security callback are the same as secMsg_t */ +typedef secMsg_t secCmacMsg_t; + +/*! ECC Security public/private key pair */ +typedef struct +{ + uint8_t pubKey_x[SEC_ECC_KEY_LEN]; /*! x component of ecc public key */ + uint8_t pubKey_y[SEC_ECC_KEY_LEN]; /*! y component of ecc public key */ + uint8_t privKey[SEC_ECC_KEY_LEN]; /*! ecc private key */ +} secEccKey_t; + +/*! ECC security DH Key shared secret */ +typedef struct +{ + uint8_t secret[SEC_ECC_KEY_LEN]; /*! DH Key Shared secret */ +} secEccSharedSec_t; + + +/*! ECC Security callback parameters structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! header */ + union + { + secEccSharedSec_t sharedSecret; /*! shared secret */ + secEccKey_t key; /*! ecc public/private key pair */ + } data; +} secEccMsg_t; + + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SecInit + * + * \brief Initialize the security service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecRandInit + * + * \brief Initialize the random number service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecRandInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecAesInit + * + * \brief Initialize the AES service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecAesInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecCmacInit + * + * \brief Called to initialize CMAC security. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecCmacInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecEccInit + * + * \brief Called to initialize ECC security. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecEccInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecAes + * + * \brief Execute an AES calculation. When the calculation completes, a WSF message will be + * sent to the specified handler. This function returns a token value that + * the client can use to match calls to this function with messages. + * + * \param pKey Pointer to 16 byte key. + * \param pPlaintext Pointer to 16 byte plaintext. + * \param handlerId WSF handler ID. + * \param param Client-defined parameter returned in message. + * \param event Event for client's WSF handler. + * + * \return Token value. + */ +/*************************************************************************************************/ +uint8_t SecAes(uint8_t *pKey, uint8_t *pPlaintext, wsfHandlerId_t handlerId, + uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecAesCmac + * + * \brief Execute the CMAC algorithm. + * + * \param pKey Key used in CMAC operation. + * \param pPlaintext Data to perform CMAC operation over + * \param len Size of pPlaintext in bytes. + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecCmac(const uint8_t *pKey, uint8_t *pPlaintext, uint8_t textLen, wsfHandlerId_t handlerId, + uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecEccGenKey + * + * \brief Generate an ECC key. + * + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecEccGenKey(wsfHandlerId_t handlerId, uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecEccGenSharedSecret + * + * \brief Generate an ECC key. + * + * \param pKey ECC Key structure. + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecEccGenSharedSecret(secEccKey_t *pKey, wsfHandlerId_t handlerId, uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecRand + * + * \brief This function returns up to 16 bytes of random data to a buffer provided by the + * client. + * + * \param pRand Pointer to returned random data. + * \param randLen Length of random data. + * + * \return None. + */ +/*************************************************************************************************/ +void SecRand(uint8_t *pRand, uint8_t randLen); + +#ifdef __cplusplus +}; +#endif + +#endif /* SEC_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h new file mode 100644 index 00000000000..8cc4bc47aef --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h @@ -0,0 +1,103 @@ +/*************************************************************************************************/ +/*! + * \file cfg_stack.h + * + * \brief Stack configuration. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef CFG_STACK_H +#define CFG_STACK_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + HCI +**************************************************************************************************/ + +/*! Vendor specific targets */ +#define HCI_VS_GENERIC 0 +#define HCI_VS_EMM 1 + +/*! Vendor specific target configuration */ +#ifndef HCI_VS_TARGET +#define HCI_VS_TARGET HCI_VS_GENERIC +#endif + +/* Extra byte allocation required for LL operations (i.e. MIC) in single-chip implementation */ +#ifndef HCI_TX_DATA_TAILROOM +#define HCI_TX_DATA_TAILROOM 0 +#endif + +/************************************************************************************************** + DM +**************************************************************************************************/ + +/*! Maximum number of connections */ +#ifndef DM_CONN_MAX +#define DM_CONN_MAX 3 +#endif + +/*! Number of supported advertising sets: must be set to 1 for legacy advertising */ +#ifndef DM_NUM_ADV_SETS +#define DM_NUM_ADV_SETS 1 +#endif + +/*! Number of scanner and initiator PHYs (LE 1M, LE 2M and LE Coded): must be set to 1 for + legacy scanner and initiator */ +#ifndef DM_NUM_PHYS +#define DM_NUM_PHYS 1 +#endif + +/************************************************************************************************** + L2C +**************************************************************************************************/ + +/*! Maximum number of connection oriented channels */ +#ifndef L2C_COC_CHAN_MAX +#define L2C_COC_CHAN_MAX 8 +#endif + +/*! Maximum number of connection oriented channel registered clients */ +#ifndef L2C_COC_REG_MAX +#define L2C_COC_REG_MAX 4 +#endif + +/************************************************************************************************** + ATT +**************************************************************************************************/ + +/*! Maximum number of simultanous ATT notifications */ +#ifndef ATT_NUM_SIMUL_NTF +#define ATT_NUM_SIMUL_NTF 1 +#endif + +/************************************************************************************************** + SMP +**************************************************************************************************/ + + +#ifdef __cplusplus +}; +#endif + +#endif /* CFG_STACK_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h new file mode 100644 index 00000000000..ba81dd509da --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h @@ -0,0 +1,1111 @@ +/*************************************************************************************************/ +/*! + * \file att_api.h + * + * \brief Attribute protocol client and server API. + * + * $Date: 2017-03-03 17:46:38 -0600 (Fri, 03 Mar 2017) $ + * $Revision: 11375 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_API_H +#define ATT_API_H + +#include "wsf_timer.h" +#include "att_defs.h" +#include "att_uuid.h" +#include "dm_api.h" +#include "cfg_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! ATT server attribute settings */ +#define ATTS_SET_UUID_128 0x01 /*! Set if the UUID is 128 bits in length */ +#define ATTS_SET_WRITE_CBACK 0x02 /*! Set if the group callback is executed when + this attribute is written by a client device */ +#define ATTS_SET_READ_CBACK 0x04 /*! Set if the group callback is executed when + this attribute is read by a client device */ +#define ATTS_SET_VARIABLE_LEN 0x08 /*! Set if the attribute has a variable length */ +#define ATTS_SET_ALLOW_OFFSET 0x10 /*! Set if writes are allowed with an offset */ +#define ATTS_SET_CCC 0x20 /*! Set if the attribute is a client characteristic + configuration descriptor */ +#define ATTS_SET_ALLOW_SIGNED 0x40 /*! Set if signed writes are allowed */ +#define ATTS_SET_REQ_SIGNED 0x80 /*! Set if signed writes are required if link + is not encrypted */ + +/*! ATT server attribute permissions */ +#define ATTS_PERMIT_READ 0x01 /*! Set if attribute can be read */ +#define ATTS_PERMIT_READ_AUTH 0x02 /*! Set if attribute read requires authentication */ +#define ATTS_PERMIT_READ_AUTHORIZ 0x04 /*! Set if attribute read requires authorization */ +#define ATTS_PERMIT_READ_ENC 0x08 /*! Set if attribute read requires encryption */ +#define ATTS_PERMIT_WRITE 0x10 /*! Set if attribute can be written */ +#define ATTS_PERMIT_WRITE_AUTH 0x20 /*! Set if attribute write requires authentication */ +#define ATTS_PERMIT_WRITE_AUTHORIZ 0x40 /*! Set if attribute write requires authorization */ +#define ATTS_PERMIT_WRITE_ENC 0x80 /*! Set if attribute write requires encryption */ + +/*! ATT client characteristic discovery and configuration settings */ +#define ATTC_SET_UUID_128 0x01 /*! Set if the UUID is 128 bits in length */ +#define ATTC_SET_REQUIRED 0x02 /*! Set if characteristic must be discovered */ +#define ATTC_SET_DESCRIPTOR 0x04 /*! Set if this is a characteristic descriptor */ + +/*! ATT callback events */ +#define ATT_CBACK_START 0x02 /*! ATT callback event starting value */ +enum /*! Internal note: event values match method values */ +{ + /*! ATT client callback events */ + ATTC_FIND_INFO_RSP = ATT_CBACK_START, /*! Find information response */ + ATTC_FIND_BY_TYPE_VALUE_RSP, /*! Find by type value response */ + ATTC_READ_BY_TYPE_RSP, /*! Read by type value response */ + ATTC_READ_RSP, /*! Read response */ + ATTC_READ_LONG_RSP, /*! Read long response */ + ATTC_READ_MULTIPLE_RSP, /*! Read multiple response */ + ATTC_READ_BY_GROUP_TYPE_RSP, /*! Read group type response */ + ATTC_WRITE_RSP, /*! Write response */ + ATTC_WRITE_CMD_RSP, /*! Write command response */ + ATTC_PREPARE_WRITE_RSP, /*! Prepare write response */ + ATTC_EXECUTE_WRITE_RSP, /*! Execute write response */ + ATTC_HANDLE_VALUE_NTF, /*! Handle value notification */ + ATTC_HANDLE_VALUE_IND, /*! Handle value indication */ + /*! ATT server callback events */ + ATTS_HANDLE_VALUE_CNF, /*! Handle value confirmation */ + ATTS_CCC_STATE_IND, /*! Client chracteristic configuration state change */ + /*! ATT common callback events */ + ATT_MTU_UPDATE_IND /*! Negotiated MTU value */ +}; + +/*! ATT callback events */ +#define ATT_CBACK_END ATT_MTU_UPDATE_IND /*! ATT callback event ending value */ + +/*! Base value for HCI error status values passed through ATT */ +#define ATT_HCI_ERR_BASE 0x20 + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Configurable parameters */ +typedef struct +{ + wsfTimerTicks_t discIdleTimeout; /*! ATT server service discovery connection idle timeout in seconds */ + uint16_t mtu; /*! desired ATT MTU */ + uint8_t transTimeout; /*! transcation timeout in seconds */ + uint8_t numPrepWrites; /*! number of queued prepare writes supported by server */ +} attCfg_t; + +/*! + * Attribute server data types + */ + +/*! Attribute structure */ +typedef struct +{ + uint8_t const *pUuid; /*! Pointer to the attribute's UUID */ + uint8_t *pValue; /*! Pointer to the attribute's value */ + uint16_t *pLen; /*! Pointer to the length of the attribute's value */ + uint16_t maxLen; /*! Maximum length of attribute's value */ + uint8_t settings; /*! Attribute settings */ + uint8_t permissions; /*! Attribute permissions */ +} attsAttr_t; + +/*! Attribute group read callback */ +typedef uint8_t (*attsReadCback_t)(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, attsAttr_t *pAttr); + +/*! Attribute group write callback */ +typedef uint8_t (*attsWriteCback_t)(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, uint16_t len, uint8_t *pValue, + attsAttr_t *pAttr); + +/*! Attribute group */ +typedef struct attsGroup_tag +{ + struct attsGroup_tag *pNext; /*! For internal use only */ + attsAttr_t *pAttr; /*! Pointer to attribute list for this group */ + attsReadCback_t readCback; /*! Read callback function */ + attsWriteCback_t writeCback; /*! Write callback function */ + uint16_t startHandle; /*! The handle of the first attribute in this group */ + uint16_t endHandle; /*! The handle of the last attribute in this group */ +} attsGroup_t; + +/*! Client characteristc configuration settings */ +typedef struct +{ + uint16_t handle; /*! Client characteristc configuration descriptor handle */ + uint16_t valueRange; /*! Acceptable value range of the descriptor value */ + uint8_t secLevel; /*! Security level of characteristic value */ +} attsCccSet_t; + +/*! ATT client structure for characteristic and descriptor discovery */ +typedef struct attcDiscChar_tag +{ + uint8_t const *pUuid; /*! Pointer to UUID */ + uint8_t settings; /*! Characteristic discovery settings */ +} attcDiscChar_t; + +/*! ATT client structure for characteristic and descriptor configuration */ +typedef struct +{ + uint8_t const *pValue; /*! Pointer to default value or NULL */ + uint8_t valueLen; /*! Default value length */ + uint8_t hdlIdx; /*! Index of its handle in handle list */ +} attcDiscCfg_t; + +/*! ATT client discovery control block */ +typedef struct +{ + attcDiscChar_t **pCharList; /*! Characterisic list for discovery */ + uint16_t *pHdlList; /*! Characteristic handle list */ + attcDiscCfg_t *pCfgList; /*! Characterisic list for configuration */ + uint8_t charListLen; /*! Characteristic and handle list length */ + uint8_t cfgListLen; /*! Configuration list length */ + + /* the following are for internal use only */ + uint16_t svcStartHdl; + uint16_t svcEndHdl; + uint8_t charListIdx; + uint8_t endHdlIdx; +} attcDiscCb_t; + +/*! + * ATT callback parameters: + * + * \param hdr.event Callback event + * \param hdr.param DM connection ID + * \param hdr.status Event status: ATT_SUCCESS or error status + * \param pValue Pointer to value data, valid if valueLen > 0 + * \param valueLen Length of value data + * \param handle Attribute handle + * \param continuing TRUE if more response packets expected + * \param mtu Negotiated MTU value + */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint8_t *pValue; /*! Value */ + uint16_t valueLen; /*! Value length */ + uint16_t handle; /*! Attribute handle */ + bool_t continuing; /*! TRUE if more response packets expected */ + uint16_t mtu; /*! Negotiated MTU value */ +} attEvt_t; + +/*! ATTS client characteristic configuration callback structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t handle; /*! CCCD handle */ + uint16_t value; /*! CCCD value */ + uint8_t idx; /*! CCCD settings index */ +} attsCccEvt_t; + +/*! ATT callback type */ +typedef void (*attCback_t)(attEvt_t *pEvt); + +/*! ATTS authorization callback type */ +typedef uint8_t (*attsAuthorCback_t)(dmConnId_t connId, uint8_t permit, uint16_t handle); + +/*! ATTS client characteristic configuration callback */ +typedef void (*attsCccCback_t)(attsCccEvt_t *pEvt); + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! Configuration pointer */ +extern attCfg_t *pAttCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn AttRegister + * + * \brief Register a callback with ATT. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttRegister(attCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttConnRegister + * + * \brief Register a connection callback with ATT. The callback is typically used to + * manage the attribute server database. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttConnRegister(dmCback_t cback); + + +/*************************************************************************************************/ +/*! + * \fn AttGetMtu + * + * \brief Get the attribute protocol MTU of a connection. + * + * \param connId DM connection ID. + * + * \return MTU of the connection. + */ +/*************************************************************************************************/ +uint16_t AttGetMtu(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttsInit + * + * \brief Initialize ATT server. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsIndInit + * + * \brief Initialize ATT server for indications/notifications. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsIndInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsSignInit + * + * \brief Initialize ATT server for data signing. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSignInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsAuthorRegister + * + * \brief Register an authorization callback with the attribute server. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsAuthorRegister(attsAuthorCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttsAddGroup + * + * \brief Add an attribute group to the attribute server. + * + * \param pGroup Pointer to an attribute group structure. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsAddGroup(attsGroup_t *pGroup); + +/*************************************************************************************************/ +/*! + * \fn AttsRemoveGroup + * + * \brief Remove an attribute group from the attribute server. + * + * \param startHandle Start handle of attribute group to be removed. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsRemoveGroup(uint16_t startHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsSetAttr + * + * \brief Set an attribute value in the attribute server. + * + * \param handle Attribute handle. + * \param valueLen Attribute length. + * \param pValue Attribute value. + * + * \return ATT_SUCCESS if successful otherwise error. + */ +/*************************************************************************************************/ +uint8_t AttsSetAttr(uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsGetAttr + * + * \brief Get an attribute value in the attribute server. + * + * \param handle Attribute handle. + * \param pLen Returned attribute length pointer. + * \param pValue Returned attribute value pointer. + * + * \return ATT_SUCCESS if successful otherwise error. + * \return This function returns the attribute length in pLen and a pointer to the attribute + * value in pValue. + */ +/*************************************************************************************************/ +uint8_t AttsGetAttr(uint16_t handle, uint16_t *pLen, uint8_t **pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueInd + * + * \brief Send an attribute protocol Handle Value Indication. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueInd(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueNtf + * + * \brief Send an attribute protocol Handle Value Notification. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueNtf(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueIndZeroCpy + * + * \brief Send an attribute protocol Handle Value Indication without copying the attribute + * value data. + * + * Note: attribute value buffer 'pValue' must be allocated with AttMsgAlloc(). + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueIndZeroCpy(dmConnId_t connId, uint16_t handle, uint16_t valueLen, + uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueNtfZeroCpy + * + * \brief Send an attribute protocol Handle Value Notification without copying the attribute + * value data. + * + * Note: attribute value buffer 'pValue' must be allocated with AttMsgAlloc(). + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueNtfZeroCpy(dmConnId_t connId, uint16_t handle, uint16_t valueLen, + uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsCccRegister + * + * \brief Register the utility service for managing client characteristic + * configuration descriptors. This function is typically called once on + * system initialization. + * + * \param setLen Length of settings array. + * \param pSet Array of CCC descriptor settings. + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccRegister(uint8_t setLen, attsCccSet_t *pSet, attsCccCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttsCccInitTable + * + * \brief Initialize the client characteristic configuration descriptor value table for a + * connection. The table is initialized with the values from pCccTbl. If pCccTbl + * is NULL the table will be initialized to zero. + * + * This function must be called when a connection is established or when a + * device is bonded. + * + * \param connId DM connection ID. + * \param pCccTbl Pointer to the descriptor value array. The length of the array + * must equal the value of setLen passed to AttsCccRegister(). + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccInitTable(dmConnId_t connId, uint16_t *pCccTbl); + +/*************************************************************************************************/ +/*! + * \fn AttsCccClearTable + * + * \brief Clear and deallocate the client characteristic configuration descriptor value + * table for a connection. This function must be called when a connection is closed. + * + * \param connId DM connection ID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccClearTable(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttsCccGet + * + * \brief Get the value of a client characteristic configuration descriptor by its index. + * If not found, return zero. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * + * \return Value of the descriptor. + */ +/*************************************************************************************************/ +uint16_t AttsCccGet(dmConnId_t connId, uint8_t idx); + +/*************************************************************************************************/ +/*! + * \fn AttsCccSet + * + * \brief Set the value of a client characteristic configuration descriptor by its index. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * \param value Value of the descriptor. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccSet(dmConnId_t connId, uint8_t idx, uint16_t value); + +/*************************************************************************************************/ +/*! + * \fn AttsCccEnabled + * + * \brief Check if a client characteristic configuration descriptor is enabled and if + * the characteristic's security level has been met. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * + * \return Value of the descriptor if security level is met, otherwise zero. + */ +/*************************************************************************************************/ +uint16_t AttsCccEnabled(dmConnId_t connId, uint8_t idx); + +/*************************************************************************************************/ +/*! + * \fn AttsSetCsrk + * + * \brief Set the peer's data signing key on this connection. This function + * is typically called from the ATT connection callback when the connection is + * established. The caller is responsible for maintaining the memory that + * contains the key. + * + * \param connId DM connection ID. + * \param pCsrk Pointer to data signing key (CSRK). + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk); + +/*************************************************************************************************/ +/*! + * \fn AttsSetSignCounter + * + * \brief Set the peer's sign counter on this connection. This function + * is typically called from the ATT connection callback when the connection is + * established. ATT maintains the value of the sign counter internally and + * sets the value when a signed packet is successfully received. + * + * \param connId DM connection ID. + * \param signCounter Sign counter. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSetSignCounter(dmConnId_t connId, uint32_t signCounter); + +/*************************************************************************************************/ +/*! + * \fn AttsGetSignCounter + * + * \brief Get the current value peer's sign counter on this connection. This function + * is typically called from the ATT connection callback when the connection is + * closed so the application can store the sign counter for use on future + * connections. + * + * \param connId DM connection ID. + * + * \return Sign counter. + */ +/*************************************************************************************************/ +uint32_t AttsGetSignCounter(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttcInit + * + * \brief Initialize ATT client. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttcSignInit + * + * \brief Initialize ATT client for data signing. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcSignInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttcFindInfoReq + * + * \brief Initiate an attribute protocol Find Information Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcFindInfoReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcFindByTypeValueReq + * + * \brief Initiate an attribute protocol Find By Type Value Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuid16 16-bit UUID to find. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcFindByTypeValueReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint16_t uuid16, uint16_t valueLen, uint8_t *pValue, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadByTypeReq + * + * \brief Initiate an attribute protocol Read By Type Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuidLen Length of UUID (2 or 16). + * \param pUuid Pointer to UUID data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadByTypeReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint8_t uuidLen, uint8_t *pUuid, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadReq + * + * \brief Initiate an attribute protocol Read Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadReq(dmConnId_t connId, uint16_t handle); + +/*************************************************************************************************/ +/*! + * \fn AttcReadLongReq + * + * \brief Initiate an attribute protocol Read Long Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param offset Read attribute data starting at this offset. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadLongReq(dmConnId_t connId, uint16_t handle, uint16_t offset, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadMultipleReq + * + * \brief Initiate an attribute protocol Read Multiple Request. + * + * \param connId DM connection ID. + * \param numHandles Number of handles in attribute handle list. + * \param pHandles List of attribute handles. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadMultipleReq(dmConnId_t connId, uint8_t numHandles, uint16_t *pHandles); + +/*************************************************************************************************/ +/*! + * \fn AttcReadByGroupTypeReq + * + * \brief Initiate an attribute protocol Read By Group Type Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuidLen Length of UUID (2 or 16). + * \param pUuid Pointer to UUID data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadByGroupTypeReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint8_t uuidLen, uint8_t *pUuid, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcWriteReq + * + * \brief Initiate an attribute protocol Write Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcWriteReq(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcWriteCmd + * + * \brief Initiate an attribute protocol Write Command. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcWriteCmd(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcSignedWriteCmd + * + * \brief Initiate an attribute protocol signed Write Command. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param signCounter Value of the sign counter. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcSignedWriteCmd(dmConnId_t connId, uint16_t handle, uint32_t signCounter, + uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcPrepareWriteReq + * + * \brief Initiate an attribute protocol Prepare Write Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param offset Write attribute data starting at this offset. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * \param valueByRef TRUE if pValue data is accessed by reference rather than copied. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcPrepareWriteReq(dmConnId_t connId, uint16_t handle, uint16_t offset, uint16_t valueLen, + uint8_t *pValue, bool_t valueByRef, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcExecuteWriteReq + * + * \brief Initiate an attribute protocol Execute Write Request. + * + * \param connId DM connection ID. + * \param writeAll TRUE to write all queued writes, FALSE to cancel all queued writes. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcExecuteWriteReq(dmConnId_t connId, bool_t writeAll); + +/*************************************************************************************************/ +/*! + * \fn AttcCancelReq + * + * \brief Cancel an attribute protocol request in progress. + * + * \param connId DM connection ID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcCancelReq(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscService + * + * \brief This utility function discovers the given service on a peer device. Function + * AttcFindByTypeValueReq() is called to initiate the discovery procedure. + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * \param uuidLen Length of service UUID (2 or 16). + * \param pUuid Pointer to service UUID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcDiscService(dmConnId_t connId, attcDiscCb_t *pCb, uint8_t uuidLen, uint8_t *pUuid); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscServiceCmpl + * + * \brief This utility function processes a service discovery result. It should be called + * when an ATTC_FIND_BY_TYPE_VALUE_RSP callback event is received after service + * discovery is initiated by calling AttcDiscService(). + * + * \param pCb Pointer to discovery control block. + * \param pMsg ATT callback event message. + * + * \return ATT_SUCCESS if successful otherwise error. + */ +/*************************************************************************************************/ +uint8_t AttcDiscServiceCmpl(attcDiscCb_t *pCb, attEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscCharStart + * + * \brief This utility function starts characteristic and characteristic descriptor + * discovery for a service on a peer device. The service must have been previously + * discovered by calling AttcDiscService() and AttcDiscServiceCmpl(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcDiscCharStart(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscCharCmpl + * + * \brief This utility function processes a characteristic discovery result. It should be + * called when an ATTC_READ_BY_TYPE_RSP or ATTC_FIND_INFO_RSP callback event is + * received after characteristic discovery is initiated by calling AttcDiscCharStart(). + * + * \param pCb Pointer to discovery control block. + * \param pMsg ATT callback event message. + * + * \return ATT_CONTINUING if successful and the discovery procedure is continuing. + * ATT_SUCCESS if the discovery procedure completed successfully. + * Otherwise the discovery procedure failed. + */ +/*************************************************************************************************/ +uint8_t AttcDiscCharCmpl(attcDiscCb_t *pCb, attEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigStart + * + * \brief This utility function starts characteristic configuration for characteristics on a + * peer device. The characteristics must have been previously discovered by calling + * AttcDiscCharStart() and AttcDiscCharCmpl(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if nothing to configure. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigStart(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigCmpl + * + * \brief This utility function initiates the next characteristic configuration procedure. + * It should be called when an ATTC_READ_RSP or ATTC_WRITE_RSP callback event is received + * after characteristic configuration is initiated by calling AttcDiscConfigStart(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if configuration procedure completed successfully. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigCmpl(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigResume + * + * \brief This utility function resumes the characteristic configuration procedure. It can + * be called when an ATTC_READ_RSP or ATTC_WRITE_RSP callback event is received + * with failure status to attempt the read or write procedure again. + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if configuration procedure completed successfully. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigResume(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcMtuReq + * + * \brief For internal use only. + * + * \param connId DM connection ID. + * \param mtu Attribute protocol MTU. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcMtuReq(dmConnId_t connId, uint16_t mtu); + +/*************************************************************************************************/ +/*! + * \fn AttsErrorTest + * + * \brief For testing purposes only. + * + * \param status ATT status + * + * \return None. + */ +/*************************************************************************************************/ +void AttsErrorTest(uint8_t status); + +/*************************************************************************************************/ +/*! + * \fn AttMsgAlloc + * + * \brief Allocate an ATT message buffer to be sent with the ATT attribute protocol + * zero-copy APIs. + * + * \param len Message length in bytes. + * \param opcode Opcode for ATT message. + * + * \return Pointer to message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *AttMsgAlloc(uint16_t len, uint8_t opcode); + +/*************************************************************************************************/ +/*! + * \fn AttMsgFree + * + * \brief Free an ATT message buffer allocated with AttMsgAlloc(). + * + * \param pMsg Pointer to message buffer. + * \param opcode Opcode for ATT message. + * + * \return None. + */ +/*************************************************************************************************/ +void AttMsgFree(void *pMsg, uint8_t opcode); + +/*************************************************************************************************/ +/*! + * \fn AttsDynInit + * + * \brief Initialize the Dynamic ATT Service subsystem. + * + * \param None. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsDynCreateGroup + * + * \brief Dynamically create an ATT Service at runtime. + * + * \param startHandle Starting attribute handle in the service + * \param endHandle Last attribute handle in the service + * + * \return Service Handle. + */ +/*************************************************************************************************/ +void *AttsDynCreateGroup(uint16_t startHandle, uint16_t endHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsDynDeleteGroup + * + * \brief Dynamically delete an ATT Service at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynDeleteGroup(void *pSvcHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsDynRegister + * + * \brief Register callback functions for a dynamic ATT Service at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynRegister(void *pSvcHandle, attsReadCback_t readCback, attsWriteCback_t writeCback); + +/*************************************************************************************************/ +/*! + * \fn AttsDynAddAttr + * + * \brief Dynamically add an attribute to a dynamic ATT Services at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * \param pUuid Constant UUID + * \param pValue Initial value of attribute (copied into attribute memory) + * \param len Length of pValue in bytes + * \param maxLen Maximum length of the attribute in bytes + * \param settings Attribute settings + * \param permissions Attribute permissions + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynAddAttr(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValue, uint16_t len, + const uint16_t maxLen, uint8_t settings, uint8_t permissions); + +/*************************************************************************************************/ +/*! + * \fn AttsDynAddAttrConst + * + * \brief Dynamically add an attribute with a constant value to a dynamic ATT Services at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * \param pUuid Constant UUID + * \param pValue Pointer to constant attribute memory + * \param len Length of pValue in bytes + * \param settings Attribute settings + * \param permissions Attribute permissions + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynAddAttrConst(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValue, + const uint16_t len, uint8_t settings, uint8_t permissions); + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h new file mode 100644 index 00000000000..cbb5250c17c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h @@ -0,0 +1,225 @@ +/*************************************************************************************************/ +/*! + * \file att_defs.h + * + * \brief Attribute protocol constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_DEFS_H +#define ATT_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Attribute PDU format */ +#define ATT_HDR_LEN 1 /*! Attribute PDU header length */ +#define ATT_AUTH_SIG_LEN 12 /*! Authentication signature length */ +#define ATT_DEFAULT_MTU 23 /*! Default value of ATT_MTU */ +#define ATT_MAX_MTU 517 /*! Maximum value of ATT_MTU */ +#define ATT_DEFAULT_PAYLOAD_LEN 20 /*! Default maximum payload length for most PDUs */ + +/*! Attribute value parameters */ +#define ATT_VALUE_MAX_LEN 512 /*! Maximum attribute value length */ +#define ATT_VALUE_MAX_OFFSET 511 /*! Maximum attribute value offset */ + +/*! Transaction timeout */ +#define ATT_MAX_TRANS_TIMEOUT 30 /*! Maximum transaction timeout in seconds */ + +/*! Error codes */ +#define ATT_SUCCESS 0x00 /*! Operation successful */ +#define ATT_ERR_HANDLE 0x01 /*! Invalid handle */ +#define ATT_ERR_READ 0x02 /*! Read not permitted */ +#define ATT_ERR_WRITE 0x03 /*! Write not permitted */ +#define ATT_ERR_INVALID_PDU 0x04 /*! Invalid pdu */ +#define ATT_ERR_AUTH 0x05 /*! Insufficient authentication */ +#define ATT_ERR_NOT_SUP 0x06 /*! Request not supported */ +#define ATT_ERR_OFFSET 0x07 /*! Invalid offset */ +#define ATT_ERR_AUTHOR 0x08 /*! Insufficient authorization */ +#define ATT_ERR_QUEUE_FULL 0x09 /*! Prepare queue full */ +#define ATT_ERR_NOT_FOUND 0x0A /*! Attribute not found */ +#define ATT_ERR_NOT_LONG 0x0B /*! Attribute not long */ +#define ATT_ERR_KEY_SIZE 0x0C /*! Insufficient encryption key size */ +#define ATT_ERR_LENGTH 0x0D /*! Invalid attribute value length */ +#define ATT_ERR_UNLIKELY 0x0E /*! Other unlikely error */ +#define ATT_ERR_ENC 0x0F /*! Insufficient encryption */ +#define ATT_ERR_GROUP_TYPE 0x10 /*! Unsupported group type */ +#define ATT_ERR_RESOURCES 0x11 /*! Insufficient resources */ +#define ATT_ERR_CCCD 0xFD /*! CCCD improperly configured */ +#define ATT_ERR_IN_PROGRESS 0xFE /*! Procedure already in progress */ +#define ATT_ERR_RANGE 0xFF /*! Value out of range */ + +/*! Proprietary internal error codes */ +#define ATT_ERR_MEMORY 0x70 /*! Out of memory */ +#define ATT_ERR_TIMEOUT 0x71 /*! Transaction timeout */ +#define ATT_ERR_OVERFLOW 0x72 /*! Transaction overflow */ +#define ATT_ERR_INVALID_RSP 0x73 /*! Invalid response PDU */ +#define ATT_ERR_CANCELLED 0x74 /*! Request cancelled */ +#define ATT_ERR_UNDEFINED 0x75 /*! Other undefined error */ +#define ATT_ERR_REQ_NOT_FOUND 0x76 /*! Required characteristic not found */ +#define ATT_ERR_MTU_EXCEEDED 0x77 /*! Attribute PDU length exceeded MTU size */ +#define ATT_CONTINUING 0x78 /*! Procedure continuing */ + +/*! Application error codes */ +#define ATT_ERR_VALUE_RANGE 0x80 /*! Value out of range */ + +/*! PDU types */ +#define ATT_PDU_ERR_RSP 0x01 /*! Error response */ +#define ATT_PDU_MTU_REQ 0x02 /*! Exchange mtu request */ +#define ATT_PDU_MTU_RSP 0x03 /*! Exchange mtu response */ +#define ATT_PDU_FIND_INFO_REQ 0x04 /*! Find information request */ +#define ATT_PDU_FIND_INFO_RSP 0x05 /*! Find information response */ +#define ATT_PDU_FIND_TYPE_REQ 0x06 /*! Find by type value request */ +#define ATT_PDU_FIND_TYPE_RSP 0x07 /*! Find by type value response */ +#define ATT_PDU_READ_TYPE_REQ 0x08 /*! Read by type request */ +#define ATT_PDU_READ_TYPE_RSP 0x09 /*! Read by type response */ +#define ATT_PDU_READ_REQ 0x0A /*! Read request */ +#define ATT_PDU_READ_RSP 0x0B /*! Read response */ +#define ATT_PDU_READ_BLOB_REQ 0x0C /*! Read blob request */ +#define ATT_PDU_READ_BLOB_RSP 0x0D /*! Read blob response */ +#define ATT_PDU_READ_MULT_REQ 0x0E /*! Read multiple request */ +#define ATT_PDU_READ_MULT_RSP 0x0F /*! Read multiple response */ +#define ATT_PDU_READ_GROUP_TYPE_REQ 0x10 /*! Read by group type request */ +#define ATT_PDU_READ_GROUP_TYPE_RSP 0x11 /*! Read by group type response */ +#define ATT_PDU_WRITE_REQ 0x12 /*! Write request */ +#define ATT_PDU_WRITE_RSP 0x13 /*! Write response */ +#define ATT_PDU_WRITE_CMD 0x52 /*! Write command */ +#define ATT_PDU_SIGNED_WRITE_CMD 0xD2 /*! Signed write command */ +#define ATT_PDU_PREP_WRITE_REQ 0x16 /*! Prepare write request */ +#define ATT_PDU_PREP_WRITE_RSP 0x17 /*! Prepare write response */ +#define ATT_PDU_EXEC_WRITE_REQ 0x18 /*! Execute write request */ +#define ATT_PDU_EXEC_WRITE_RSP 0x19 /*! Execute write response */ +#define ATT_PDU_VALUE_NTF 0x1B /*! Handle value notification */ +#define ATT_PDU_VALUE_IND 0x1D /*! Handle value indication */ +#define ATT_PDU_VALUE_CNF 0x1E /*! Handle value confirmation */ +#define ATT_PDU_MAX 0x1F /*! PDU Maximum */ + +/*! Length of PDU fixed length fields */ +#define ATT_ERR_RSP_LEN 5 +#define ATT_MTU_REQ_LEN 3 +#define ATT_MTU_RSP_LEN 3 +#define ATT_FIND_INFO_REQ_LEN 5 +#define ATT_FIND_INFO_RSP_LEN 2 +#define ATT_FIND_TYPE_REQ_LEN 7 +#define ATT_FIND_TYPE_RSP_LEN 1 +#define ATT_READ_TYPE_REQ_LEN 5 +#define ATT_READ_TYPE_RSP_LEN 2 +#define ATT_READ_REQ_LEN 3 +#define ATT_READ_RSP_LEN 1 +#define ATT_READ_BLOB_REQ_LEN 5 +#define ATT_READ_BLOB_RSP_LEN 1 +#define ATT_READ_MULT_REQ_LEN 1 +#define ATT_READ_MULT_RSP_LEN 1 +#define ATT_READ_GROUP_TYPE_REQ_LEN 5 +#define ATT_READ_GROUP_TYPE_RSP_LEN 2 +#define ATT_WRITE_REQ_LEN 3 +#define ATT_WRITE_RSP_LEN 1 +#define ATT_WRITE_CMD_LEN 3 +#define ATT_SIGNED_WRITE_CMD_LEN (ATT_WRITE_CMD_LEN + ATT_AUTH_SIG_LEN) +#define ATT_PREP_WRITE_REQ_LEN 5 +#define ATT_PREP_WRITE_RSP_LEN 5 +#define ATT_EXEC_WRITE_REQ_LEN 2 +#define ATT_EXEC_WRITE_RSP_LEN 1 +#define ATT_VALUE_NTF_LEN 3 +#define ATT_VALUE_IND_LEN 3 +#define ATT_VALUE_CNF_LEN 1 + +/*! Find information response format */ +#define ATT_FIND_HANDLE_16_UUID 0x01 /*! Handle and 16 bit UUID */ +#define ATT_FIND_HANDLE_128_UUID 0x02 /*! Handle and 128 bit UUID */ + +/*! Execute write request flags */ +#define ATT_EXEC_WRITE_CANCEL 0x00 /*! Cancel all prepared writes */ +#define ATT_EXEC_WRITE_ALL 0x01 /*! Write all pending prepared writes */ + +/*! PDU masks */ +#define ATT_PDU_MASK_SERVER 0x01 /*! Server bit mask */ +#define ATT_PDU_MASK_COMMAND 0x40 /*! Command bit mask */ +#define ATT_PDU_MASK_SIGNED 0x80 /*! Auth signature bit mask */ + +/*! Handles */ +#define ATT_HANDLE_NONE 0x0000 +#define ATT_HANDLE_START 0x0001 +#define ATT_HANDLE_MAX 0xFFFF + +/*! UUID lengths */ +#define ATT_NO_UUID_LEN 0 /*! Length when no UUID is present ;-) */ +#define ATT_16_UUID_LEN 2 /*! Length in bytes of a 16 bit UUID */ +#define ATT_128_UUID_LEN 16 /*! Length in bytes of a 128 bit UUID */ + +/*! GATT characteristic properties */ +#define ATT_PROP_BROADCAST 0x01 /*! Permit broadcasts */ +#define ATT_PROP_READ 0x02 /*! Permit reads */ +#define ATT_PROP_WRITE_NO_RSP 0x04 /*! Permit writes without response */ +#define ATT_PROP_WRITE 0x08 /*! Permit writes with response */ +#define ATT_PROP_NOTIFY 0x10 /*! Permit notifications */ +#define ATT_PROP_INDICATE 0x20 /*! Permit indications */ +#define ATT_PROP_AUTHENTICATED 0x40 /*! Permit signed writes */ +#define ATT_PROP_EXTENDED 0x80 /*! More properties defined in extended properties */ + +/*! GATT characteristic extended properties */ +#define ATT_EXT_PROP_RELIABLE_WRITE 0x0001 /*! Permit reliable writes */ +#define ATT_EXT_PROP_WRITEABLE_AUX 0x0002 /*! Permit write to characteristic descriptor */ + +/*! GATT client characteristic configuration */ +#define ATT_CLIENT_CFG_NOTIFY 0x0001 /*! Notify the value */ +#define ATT_CLIENT_CFG_INDICATE 0x0002 /*! Indicate the value */ + +/*! GATT server characteristic configuration */ +#define ATT_SERVER_CFG_BROADCAST 0x0001 /*! Broadcast the value */ + +/*! GATT characteristic format */ +#define ATT_FORMAT_BOOLEAN 0x01 /*! Boolean */ +#define ATT_FORMAT_2BIT 0x02 /*! Unsigned 2 bit integer */ +#define ATT_FORMAT_NIBBLE 0x03 /*! Unsigned 4 bit integer */ +#define ATT_FORMAT_UINT8 0x04 /*! Unsigned 8 bit integer */ +#define ATT_FORMAT_UINT12 0x05 /*! Unsigned 12 bit integer */ +#define ATT_FORMAT_UINT16 0x06 /*! Unsigned 16 bit integer */ +#define ATT_FORMAT_UINT24 0x07 /*! Unsigned 24 bit integer */ +#define ATT_FORMAT_UINT32 0x08 /*! Unsigned 32 bit integer */ +#define ATT_FORMAT_UINT48 0x09 /*! Unsigned 48 bit integer */ +#define ATT_FORMAT_UINT64 0x0A /*! Unsigned 64 bit integer */ +#define ATT_FORMAT_UINT128 0x0B /*! Unsigned 128 bit integer */ +#define ATT_FORMAT_SINT8 0x0C /*! Signed 8 bit integer */ +#define ATT_FORMAT_SINT12 0x0D /*! Signed 12 bit integer */ +#define ATT_FORMAT_SINT16 0x0E /*! Signed 16 bit integer */ +#define ATT_FORMAT_SINT24 0x0F /*! Signed 24 bit integer */ +#define ATT_FORMAT_SINT32 0x10 /*! Signed 32 bit integer */ +#define ATT_FORMAT_SINT48 0x11 /*! Signed 48 bit integer */ +#define ATT_FORMAT_SINT64 0x12 /*! Signed 64 bit integer */ +#define ATT_FORMAT_SINT128 0x13 /*! Signed 128 bit integer */ +#define ATT_FORMAT_FLOAT32 0x14 /*! IEEE-754 32 bit floating point */ +#define ATT_FORMAT_FLOAT64 0x15 /*! IEEE-754 64 bit floating point */ +#define ATT_FORMAT_SFLOAT 0x16 /*! IEEE-11073 16 bit SFLOAT */ +#define ATT_FORMAT_FLOAT 0x17 /*! IEEE-11073 32 bit FLOAT */ +#define ATT_FORMAT_DUINT16 0x18 /*! IEEE-20601 format */ +#define ATT_FORMAT_UTF8 0x19 /*! UTF-8 string */ +#define ATT_FORMAT_UTF16 0x1A /*! UTF-16 string */ +#define ATT_FORMAT_STRUCT 0x1B /*! Opaque structure */ + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h new file mode 100644 index 00000000000..a88edbf91b6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file att_handler.h + * + * \brief Interface to ATT event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_HANDLER_H +#define ATT_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn AttHandlerInit + * + * \brief ATT handler init function called during system initialization. + * + * \param handlerID WSF handler ID for ATT. + * + * \return None. + */ +/*************************************************************************************************/ +void AttHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn AttHandler + * + * \brief WSF event handler for ATT. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void AttHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h new file mode 100644 index 00000000000..177a52e0a21 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h @@ -0,0 +1,475 @@ +/*************************************************************************************************/ +/*! + * \file att_uuid.h + * + * \brief Attribute protocol UUIDs from the Bluetooth specification. + * + * $Date: 2017-03-08 12:55:18 -0600 (Wed, 08 Mar 2017) $ + * $Revision: 11435 $ + * + * Copyright (c) 2011-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_UUID_H +#define ATT_UUID_H + +#include "att_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Service UUIDs */ +#define ATT_UUID_GAP_SERVICE 0x1800 /*! Generic Access Profile Service */ +#define ATT_UUID_GATT_SERVICE 0x1801 /*! Generic Attribute Profile Service */ +#define ATT_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /*! Immediate Alert Service */ +#define ATT_UUID_LINK_LOSS_SERVICE 0x1803 /*! Link Loss Service */ +#define ATT_UUID_TX_POWER_SERVICE 0x1804 /*! Tx Power Service */ +#define ATT_UUID_CURRENT_TIME_SERVICE 0x1805 /*! Current Time Service */ +#define ATT_UUID_REF_TIME_UPDATE_SERVICE 0x1806 /*! Reference Time Update Service */ +#define ATT_UUID_DST_CHANGE_SERVICE 0x1807 /*! Next DST Change Service */ +#define ATT_UUID_GLUCOSE_SERVICE 0x1808 /*! Glucose Service */ +#define ATT_UUID_HEALTH_THERM_SERVICE 0x1809 /*! Health Thermometer Service */ +#define ATT_UUID_DEVICE_INFO_SERVICE 0x180A /*! Device Information Service */ +#define ATT_UUID_NETWORK_AVAIL_SERVICE 0x180B /*! Network Availability Service */ +#define ATT_UUID_WATCHDOG_SERVICE 0x180C /*! Watchdog Service */ +#define ATT_UUID_HEART_RATE_SERVICE 0x180D /*! Heart Rate Service */ +#define ATT_UUID_PHONE_ALERT_SERVICE 0x180E /*! Phone Alert Status Service */ +#define ATT_UUID_BATTERY_SERVICE 0x180F /*! Battery Service */ +#define ATT_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /*! Blood Pressure Service */ +#define ATT_UUID_ALERT_NOTIF_SERVICE 0x1811 /*! Alert Notification Service */ +#define ATT_UUID_HID_SERVICE 0x1812 /*! Human Interface Device Service */ +#define ATT_UUID_SCAN_PARAM_SERVICE 0x1813 /*! Scan Parameter Service */ +#define ATT_UUID_RUNNING_SPEED_SERVICE 0x1814 /*! Running Speed Service */ +#define ATT_UUID_CYCLING_SPEED_SERVICE 0x1816 /*! Cycling Speed Service */ +#define ATT_UUID_CYCLING_POWER_SERVICE 0x1818 /*! Cycling Power Service */ +#define ATT_UUID_USER_DATA_SERVICE 0x181C /*! User Data Service */ +#define ATT_UUID_IP_SUPPORT_SERVICE 0x1820 /*! IP Support Service */ +#define ATT_UUID_PULSE_OXIMITER_SERVICE 0x1822 /*! Pulse Oximeter Service */ + +/*! GATT UUIDs */ +#define ATT_UUID_PRIMARY_SERVICE 0x2800 /*! Primary Service */ +#define ATT_UUID_SECONDARY_SERVICE 0x2801 /*! Secondary Service */ +#define ATT_UUID_INCLUDE 0x2802 /*! Include */ +#define ATT_UUID_CHARACTERISTIC 0x2803 /*! Characteristic */ + +/*! Descriptor UUIDs */ +#define ATT_UUID_CHARACTERISTIC_EXT 0x2900 /*! Characteristic Extended Properties */ +#define ATT_UUID_CHAR_USER_DESC 0x2901 /*! Characteristic User Description */ +#define ATT_UUID_CLIENT_CHAR_CONFIG 0x2902 /*! Client Characteristic Configuration */ +#define ATT_UUID_SERVER_CHAR_CONFIG 0x2903 /*! Server Characteristic Configuration */ +#define ATT_UUID_CHAR_PRES_FORMAT 0x2904 /*! Characteristic Presentation Format */ +#define ATT_UUID_AGGREGATE_FORMAT 0x2905 /*! Characteristic Aggregate Format */ +#define ATT_UUID_VALID_RANGE 0x2906 /*! Valid Range */ +#define ATT_UUID_HID_EXT_REPORT_MAPPING 0x2907 /*! HID External Report ID Mapping */ +#define ATT_UUID_HID_REPORT_ID_MAPPING 0x2908 /*! HID Report ID Mapping */ + +/*! Characteristic UUIDs */ +#define ATT_UUID_DEVICE_NAME 0x2A00 /*! Device Name */ +#define ATT_UUID_APPEARANCE 0x2A01 /*! Appearance */ +#define ATT_UUID_PERIPH_PRIVACY_FLAG 0x2A02 /*! Peripheral Privacy Flag */ +#define ATT_UUID_RECONN_ADDR 0x2A03 /*! Reconnection Address */ +#define ATT_UUID_PREF_CONN_PARAM 0x2A04 /*! Peripheral Preferred Connection Parameters */ +#define ATT_UUID_SERVICE_CHANGED 0x2A05 /*! Service Changed */ +#define ATT_UUID_ALERT_LEVEL 0x2A06 /*! Alert Level */ +#define ATT_UUID_TX_POWER_LEVEL 0x2A07 /*! Tx Power Level */ +#define ATT_UUID_DATE_TIME 0x2A08 /*! Date Time */ +#define ATT_UUID_DAY_OF_WEEK 0x2A09 /*! Day of Week */ +#define ATT_UUID_DAY_DATE_TIME 0x2A0A /*! Day Date Time */ +#define ATT_UUID_EXACT_TIME_100 0x2A0B /*! Exact Time 100 */ +#define ATT_UUID_EXACT_TIME_256 0x2A0C /*! Exact Time 256 */ +#define ATT_UUID_DST_OFFSET 0x2A0D /*! DST Offset */ +#define ATT_UUID_TIME_ZONE 0x2A0E /*! Time Zone */ +#define ATT_UUID_LOCAL_TIME_INFO 0x2A0F /*! Local Time Information */ +#define ATT_UUID_SECONDARY_TIME_ZONE 0x2A10 /*! Secondary Time Zone */ +#define ATT_UUID_TIME_WITH_DST 0x2A11 /*! Time with DST */ +#define ATT_UUID_TIME_ACCURACY 0x2A12 /*! Time Accuracy */ +#define ATT_UUID_TIME_SOURCE 0x2A13 /*! Time Source */ +#define ATT_UUID_REFERENCE_TIME_INFO 0x2A14 /*! Reference Time Information */ +#define ATT_UUID_TIME_BROADCAST 0x2A15 /*! Time Broadcast */ +#define ATT_UUID_TIME_UPDATE_CP 0x2A16 /*! Time Update Control Point */ +#define ATT_UUID_TIME_UPDATE_STATE 0x2A17 /*! Time Update State */ +#define ATT_UUID_GLUCOSE_MEAS 0x2A18 /*! Glucose Measurement */ +#define ATT_UUID_BATTERY_LEVEL 0x2A19 /*! Battery Level */ +#define ATT_UUID_BATTERY_POWER_STATE 0x2A1A /*! Battery Power State */ +#define ATT_UUID_BATTERY_LEVEL_STATE 0x2A1B /*! Battery Level State */ +#define ATT_UUID_TEMP_MEAS 0x2A1C /*! Temperature Measurement */ +#define ATT_UUID_TEMP_TYPE 0x2A1D /*! Temperature Type */ +#define ATT_UUID_INTERMEDIATE_TEMP 0x2A1E /*! Intermediate Temperature */ +#define ATT_UUID_TEMP_C 0x2A1F /*! Temperature Celsius */ +#define ATT_UUID_TEMP_F 0x2A20 /*! Temperature Fahrenheit */ +#define ATT_UUID_MEAS_INTERVAL 0x2A21 /*! Measurement Interval */ +#define ATT_UUID_HID_BOOT_KEYBOARD_IN 0x2A22 /*! HID Boot Keyboard In */ +#define ATT_UUID_SYSTEM_ID 0x2A23 /*! System ID */ +#define ATT_UUID_MODEL_NUMBER 0x2A24 /*! Model Number String */ +#define ATT_UUID_SERIAL_NUMBER 0x2A25 /*! Serial Number String */ +#define ATT_UUID_FIRMWARE_REV 0x2A26 /*! Firmware Revision String */ +#define ATT_UUID_HARDWARE_REV 0x2A27 /*! Hardware Revision String */ +#define ATT_UUID_SOFTWARE_REV 0x2A28 /*! Software Revision String */ +#define ATT_UUID_MANUFACTURER_NAME 0x2A29 /*! Manufacturer Name String */ +#define ATT_UUID_11073_CERT_DATA 0x2A2A /*! IEEE 11073-20601 Regulatory Certification Data List */ +#define ATT_UUID_CURRENT_TIME 0x2A2B /*! Current Time */ +#define ATT_UUID_ELEVATION 0x2A2C /*! Elevation */ +#define ATT_UUID_LATITUDE 0x2A2D /*! Latitude */ +#define ATT_UUID_LONGITUDE 0x2A2E /*! Longitude */ +#define ATT_UUID_POSITION_2D 0x2A2F /*! Position 2D */ +#define ATT_UUID_POSITION_3D 0x2A30 /*! Position 3D */ +#define ATT_UUID_VENDOR_ID 0x2A31 /*! Vendor ID */ +#define ATT_UUID_HID_BOOT_KEYBOARD_OUT 0x2A32 /*! HID Boot Keyboard Out */ +#define ATT_UUID_HID_BOOT_MOUSE_IN 0x2A33 /*! HID Boot Mouse In */ +#define ATT_UUID_GLUCOSE_MEAS_CONTEXT 0x2A34 /*! Glucose Measurement Context */ +#define ATT_UUID_BP_MEAS 0x2A35 /*! Blood Pressure Measurement */ +#define ATT_UUID_INTERMEDIATE_BP 0x2A36 /*! Intermediate Cuff Pressure */ +#define ATT_UUID_HR_MEAS 0x2A37 /*! Heart Rate Measurement */ +#define ATT_UUID_HR_SENSOR_LOC 0x2A38 /*! Body Sensor Location */ +#define ATT_UUID_HR_CP 0x2A39 /*! Heart Rate Control Point */ +#define ATT_UUID_REMOVABLE 0x2A3A /*! Removable */ +#define ATT_UUID_SERVICE_REQ 0x2A3B /*! Service Required */ +#define ATT_UUID_SCI_TEMP_C 0x2A3C /*! Scientific Temperature in Celsius */ +#define ATT_UUID_STRING 0x2A3D /*! String */ +#define ATT_UUID_NETWORK_AVAIL 0x2A3E /*! Network Availability */ +#define ATT_UUID_ALERT_STATUS 0x2A3F /*! Alert Status */ +#define ATT_UUID_RINGER_CP 0x2A40 /*! Ringer Control Point */ +#define ATT_UUID_RINGER_SETTING 0x2A41 /*! Ringer Setting */ +#define ATT_UUID_ALERT_CAT_ID_MASK 0x2A42 /*! Alert Category ID Bit Mask */ +#define ATT_UUID_ALERT_CAT_ID 0x2A43 /*! Alert Category ID */ +#define ATT_UUID_ALERT_NOTIF_CP 0x2A44 /*! Alert Notification Control Point */ +#define ATT_UUID_UNREAD_ALERT_STATUS 0x2A45 /*! Unread Alert Status */ +#define ATT_UUID_NEW_ALERT 0x2A46 /*! New Alert */ +#define ATT_UUID_SUP_NEW_ALERT_CAT 0x2A47 /*! Supported New Alert Category */ +#define ATT_UUID_SUP_UNREAD_ALERT_CAT 0x2A48 /*! Supported Unread Alert Category */ +#define ATT_UUID_BP_FEATURE 0x2A49 /*! Blood Pressure Feature */ +#define ATT_UUID_HID_INFORMATION 0x2A4A /*! HID Information */ +#define ATT_UUID_HID_REPORT_MAP 0x2A4B /*! HID Report Map */ +#define ATT_UUID_HID_CONTROL_POINT 0x2A4C /*! HID Control Point */ +#define ATT_UUID_HID_REPORT 0x2A4D /*! HID Report */ +#define ATT_UUID_HID_PROTOCOL_MODE 0x2A4E /*! HID Protocol Mode */ +#define ATT_UUID_SCAN_INT_WIND 0x2A4F /*! Scan Interval Window */ +#define ATT_UUID_PNP_ID 0x2A50 /*! PnP ID */ +#define ATT_UUID_GLUCOSE_FEATURE 0x2A51 /*! Glucose Feature */ +#define ATT_UUID_RACP 0x2A52 /*! Record Access Control Point */ +#define ATT_UUID_CAR 0x2AA6 /*! Central Address Resolution */ +#define ATT_UUID_RUNNING_SPEED_FEATURE 0x2A54 /*! Running Speed Feature */ +#define ATT_UUID_RUNNING_SPEED_MEASUREMENT 0x2A53 /*! Running Speed Measurement */ +#define ATT_UUID_PULSE_OX_FEATURES 0x2A60 /*! Pulse Oximeter Features */ +#define ATT_UUID_PULSE_OX_SPOT_CHECK 0x2A5E /*! Pulse Oximeter Features */ +#define ATT_UUID_PULSE_OX_CONTINUOUS 0x2A5F /*! Pulse Oximeter Features */ +#define ATT_UUID_CYCLING_POWER_FEATURE 0x2A65 /*! Cycling Power Feature */ +#define ATT_UUID_CYCLING_POWER_MEASUREMENT 0x2A63 /*! Cycling Power Measurement */ +#define ATT_UUID_CYCLING_SPEED_FEATURE 0x2A5C /*! Cycling Speed Feature */ +#define ATT_UUID_CYCLING_SPEED_MEASUREMENT 0x2A5B /*! Cycling Speed Measurement */ +#define ATT_UUID_SENSOR_LOCATION 0x2A5D /*! Sensor Location */ +#define ATT_UUID_DB_CHANGE_INCREMENT 0x2A99 /*! Database Change Increment */ +#define ATT_UUID_USER_INDEX 0x2A9A /*! User Index */ +#define ATT_UUID_USER_CONTROL_POINT 0x2A9F /*! User Control Point */ +#define ATT_UUID_RPAO 0x2AC9 /*! Resolvable Prviate Address Only */ + +/* remove when adopted */ +#define ATT_UUID_GENERIC_CTRL_SERVICE 0xF011 +#define ATT_UUID_COMMAND_ENUM 0xE010 /*! Command Enumeration */ +#define ATT_UUID_GENERIC_COMMAND_CP 0xE011 /*! Generic Command Control Point */ +#define ATT_UUID_WEIGHT_SCALE_SERVICE 0x181D /*! Weight Scale Service */ +#define ATT_UUID_WEIGHT_MEAS 0x2A9D /*! Weight Measurement */ +#define ATT_UUID_WEIGHT_SCALE_FEATURE 0x2A9E /*! Weight Scale Feature */ + +/*! Unit UUIDs */ +#define ATT_UUID_UNITLESS 0x2700 /*! unitless */ +#define ATT_UUID_LENGTH_M 0x2701 /*! length metre */ +#define ATT_UUID_MASS_KG 0x2702 /*! mass kilogram */ +#define ATT_UUID_TIME_SEC 0x2703 /*! time second */ +#define ATT_UUID_ELECTRIC_CURRENT_AMP 0x2704 /*! electric current ampere */ +#define ATT_UUID_THERMO_TEMP_K 0x2705 /*! thermodynamic temperature kelvin */ +#define ATT_UUID_AMOUNT_OF_SUBSTANCE_MOLE 0x2706 /*! amount of substance mole */ +#define ATT_UUID_LUMINOUS_INTENSITY_CAND 0x2707 /*! luminous intensity candela */ +#define ATT_UUID_AREA_SQ_M 0x2710 /*! area square metres */ +#define ATT_UUID_VOLUME_CU_M 0x2711 /*! volume cubic metres */ +#define ATT_UUID_VELOCITY_MPS 0x2712 /*! velocity metres per second */ +#define ATT_UUID_ACCELERATION_MPS_SQ 0x2713 /*! acceleration metres per second squared */ +#define ATT_UUID_WAVENUMBER_RECIPROCAL_M 0x2714 /*! wavenumber reciprocal metre */ +#define ATT_UUID_DENSITY_KG_PER_CU_M 0x2715 /*! density kilogram per cubic metre */ +#define ATT_UUID_SURFACE_DENS_KG_PER_SQ_M 0x2716 /*! surface density kilogram per square metre */ +#define ATT_UUID_SPECIFIC_VOL_CU_M_PER_KG 0x2717 /*! specific volume cubic metre per kilogram */ +#define ATT_UUID_CURRENT_DENS_AMP_PER_SQ_M 0x2718 /*! current density ampere per square metre */ +#define ATT_UUID_MAG_FIELD_STR_AMP_PER_M 0x2719 /*! magnetic field strength ampere per metre */ +#define ATT_UUID_AMOUNT_CONC_MOLE_PER_CU_M 0x271A /*! amount concentration mole per cubic metre */ +#define ATT_UUID_MASS_CONC_KG_PER_CU_M 0x271B /*! mass concentration kilogram per cubic metre */ +#define ATT_UUID_LUM_CAND_PER_SQ_M 0x271C /*! luminance candela per square metre */ +#define ATT_UUID_REFRACTIVE_INDEX 0x271D /*! refractive index */ +#define ATT_UUID_RELATIVE_PERMEABILITY 0x271E /*! relative permeability */ +#define ATT_UUID_PLANE_ANGLE_R 0x2720 /*! plane angle radian */ +#define ATT_UUID_SOLID_ANGLE_STER 0x2721 /*! solid angle steradian */ +#define ATT_UUID_FREQUENCY_HERTZ 0x2722 /*! frequency hertz */ +#define ATT_UUID_FORCE_NEWT 0x2723 /*! force newton */ +#define ATT_UUID_PRESSURE_PASCAL 0x2724 /*! pressure pascal */ +#define ATT_UUID_ENERGY_J 0x2725 /*! energy joule */ +#define ATT_UUID_POWER_W 0x2726 /*! power watt */ +#define ATT_UUID_ELECTRIC_CHG_C 0x2727 /*! electric charge coulomb */ +#define ATT_UUID_ELECTRIC_POTENTIAL_VOLT 0x2728 /*! electric potential difference volt */ +#define ATT_UUID_CAPACITANCE_F 0x2729 /*! capacitance farad */ +#define ATT_UUID_ELECTRIC_RESISTANCE_OHM 0x272A /*! electric resistance ohm */ +#define ATT_UUID_ELECTRIC_COND_SIEMENS 0x272B /*! electric conductance siemens */ +#define ATT_UUID_MAGNETIC_FLEX_WEBER 0x272C /*! magnetic flex weber */ +#define ATT_UUID_MAGNETIC_FLEX_DENS_TESLA 0x272D /*! magnetic flex density tesla */ +#define ATT_UUID_INDUCTANCE_H 0x272E /*! inductance henry */ +#define ATT_UUID_C_TEMP_DEG_C 0x272F /*! Celsius temperature degree Celsius */ +#define ATT_UUID_LUMINOUS_FLUX_LUMEN 0x2730 /*! luminous flux lumen */ +#define ATT_UUID_ILLUMINANCE_LUX 0x2731 /*! illuminance lux */ +#define ATT_UUID_RADIONUCLIDE_BECQUEREL 0x2732 /*! activity referred to a radionuclide becquerel */ +#define ATT_UUID_ABSORBED_DOSE_GRAY 0x2733 /*! absorbed dose gray */ +#define ATT_UUID_DOSE_EQUIVALENT_SIEVERT 0x2734 /*! dose equivalent sievert */ +#define ATT_UUID_CATALYTIC_ACTIVITY_KATAL 0x2735 /*! catalytic activity katal */ +#define ATT_UUID_DYNAMIC_VISC_PASCAL_SEC 0x2740 /*! dynamic viscosity pascal second */ +#define ATT_UUID_MOMENT_OF_FORCE_NEWT_M 0x2741 /*! moment of force newton metre */ +#define ATT_UUID_SURFACE_TENSION_NEWT_PER_M 0x2742 /*! surface tension newton per metre */ +#define ATT_UUID_ANG_VELOCITY_R_PER_SEC 0x2743 /*! angular velocity radian per second */ +#define ATT_UUID_ANG_ACCEL_R_PER_SEC_SQD 0x2744 /*! angular acceleration radian per second squared */ +#define ATT_UUID_HEAT_FLUX_DEN_W_PER_SQ_M 0x2745 /*! heat flux density watt per square metre */ +#define ATT_UUID_HEAT_CAP_J_PER_K 0x2746 /*! heat capacity joule per kelvin */ +#define ATT_UUID_SPEC_HEAT_CAP_J_PER_KG_K 0x2747 /*! specific heat capacity joule per kilogram kelvin */ +#define ATT_UUID_SPEC_ENERGY_J_PER_KG 0x2748 /*! specific energy joule per kilogram */ +#define ATT_UUID_THERMAL_COND_W_PER_M_K 0x2749 /*! thermal conductivity watt per metre kelvin */ +#define ATT_UUID_ENERGY_DENSITY_J_PER_CU_M 0x274A /*! energy density joule per cubic metre */ +#define ATT_UUID_ELEC_FIELD_STR_VOLT_PER_M 0x274B /*! electric field strength volt per metre */ +#define ATT_UUID_ELEC_CHG_DENS_C_PER_CU_M 0x274C /*! electric charge density coulomb per cubic metre */ +#define ATT_UUID_SURF_CHG_DENS_C_PER_SQ_M 0x274D /*! surface charge density coulomb per square metre */ +#define ATT_UUID_ELEC_FLUX_DENS_C_PER_SQ_M 0x274E /*! electric flux density coulomb per square metre */ +#define ATT_UUID_PERMITTIVITY_F_PER_M 0x274F /*! permittivity farad per metre */ +#define ATT_UUID_PERMEABILITY_H_PER_M 0x2750 /*! permeability henry per metre */ +#define ATT_UUID_MOLAR_ENERGY_J_PER_MOLE 0x2751 /*! molar energy joule per mole */ +#define ATT_UUID_MOLAR_ENTROPY_J_PER_MOLE_K 0x2752 /*! molar entropy joule per mole kelvin */ +#define ATT_UUID_EXPOSURE_C_PER_KG 0x2753 /*! exposure coulomb per kilogram */ +#define ATT_UUID_DOSE_RATE_GRAY_PER_SEC 0x2754 /*! absorbed dose rate gray per second */ +#define ATT_UUID_RT_INTENSITY_W_PER_STER 0x2755 /*! radiant intensity watt per steradian */ +#define ATT_UUID_RCE_W_PER_SQ_METER_STER 0x2756 /*! radiance watt per square meter steradian */ +#define ATT_UUID_CATALYTIC_KATAL_PER_CU_M 0x2757 /*! catalytic activity concentration katal per cubic metre */ +#define ATT_UUID_TIME_MIN 0x2760 /*! time minute */ +#define ATT_UUID_TIME_HR 0x2761 /*! time hour */ +#define ATT_UUID_TIME_DAY 0x2762 /*! time day */ +#define ATT_UUID_PLANE_ANGLE_DEG 0x2763 /*! plane angle degree */ +#define ATT_UUID_PLANE_ANGLE_MIN 0x2764 /*! plane angle minute */ +#define ATT_UUID_PLANE_ANGLE_SEC 0x2765 /*! plane angle second */ +#define ATT_UUID_AREA_HECTARE 0x2766 /*! area hectare */ +#define ATT_UUID_VOLUME_L 0x2767 /*! volume litre */ +#define ATT_UUID_MASS_TONNE 0x2768 /*! mass tonne */ +#define ATT_UUID_PRESSURE_BAR 0x2780 /*! pressure bar */ +#define ATT_UUID_PRESSURE_MM 0x2781 /*! pressure millimetre of mercury */ +#define ATT_UUID_LENGTH_ANGSTROM 0x2782 /*! length angstrom */ +#define ATT_UUID_LENGTH_NAUTICAL_MILE 0x2783 /*! length nautical mile */ +#define ATT_UUID_AREA_BARN 0x2784 /*! area barn */ +#define ATT_UUID_VELOCITY_KNOT 0x2785 /*! velocity knot */ +#define ATT_UUID_LOG_RADIO_QUANT_NEPER 0x2786 /*! logarithmic radio quantity neper */ +#define ATT_UUID_LOG_RADIO_QUANT_BEL 0x2787 /*! logarithmic radio quantity bel */ +#define ATT_UUID_LOG_RADIO_QUANT_DB 0x2788 /*! logarithmic radio quantity decibel */ +#define ATT_UUID_LENGTH_YARD 0x27A0 /*! length yard */ +#define ATT_UUID_LENGTH_PARSEC 0x27A1 /*! length parsec */ +#define ATT_UUID_LENGTH_IN 0x27A2 /*! length inch */ +#define ATT_UUID_LENGTH_FOOT 0x27A3 /*! length foot */ +#define ATT_UUID_LENGTH_MILE 0x27A4 /*! length mile */ +#define ATT_UUID_PRESSURE_POUND_PER_SQ_IN 0x27A5 /*! pressure pound-force per square inch */ +#define ATT_UUID_VELOCITY_KPH 0x27A6 /*! velocity kilometre per hour */ +#define ATT_UUID_VELOCITY_MPH 0x27A7 /*! velocity mile per hour */ +#define ATT_UUID_ANG_VELOCITY_RPM 0x27A8 /*! angular velocity revolution per minute */ +#define ATT_UUID_ENERGY_GRAM_CALORIE 0x27A9 /*! energy gram calorie */ +#define ATT_UUID_ENERGY_KG_CALORIE 0x27AA /*! energy kilogram calorie */ +#define ATT_UUID_ENERGY_KILOWATT_HR 0x27AB /*! energy kilowatt hour */ +#define ATT_UUID_THERM_TEMP_F 0x27AC /*! thermodynamic temperature degree Fahrenheit */ +#define ATT_UUID_PERCENTAGE 0x27AD /*! percentage */ +#define ATT_UUID_PER_MILLE 0x27AE /*! per mille */ +#define ATT_UUID_PERIOD_BEATS_PER_MIN 0x27AF /*! period beats per minute */ +#define ATT_UUID_ELECTRIC_CHG_AMP_HRS 0x27B0 /*! electric charge ampere hours */ +#define ATT_UUID_MASS_DENSITY_MG_PER_DL 0x27B1 /*! mass density milligram per decilitre */ +#define ATT_UUID_MASS_DENSITY_MMOLE_PER_L 0x27B2 /*! mass density millimole per litre */ +#define ATT_UUID_TIME_YEAR 0x27B3 /*! time year */ +#define ATT_UUID_TIME_MONTH 0x27B4 /*! time month */ + +/*! ARM Ltd. proprietary UUIDs */ + +/*! Base UUID: E0262760-08C2-11E1-9073-0E8AC72EXXXX */ +#define ATT_UUID_ARM_BASE 0x2E, 0xC7, 0x8A, 0x0E, 0x73, 0x90, \ + 0xE1, 0x11, 0xC2, 0x08, 0x60, 0x27, 0x26, 0xE0 + +/*! Macro for building ARM Ltd. UUIDs */ +#define ATT_UUID_ARM_BUILD(part) UINT16_TO_BYTES(part), ATT_UUID_ARM_BASE + +/*! Partial proprietary service UUIDs */ +#define ATT_UUID_P1_SERVICE_PART 0x1001 /*! Proprietary service P1 */ + +/*! Partial proprietary characteristic UUIDs */ +#define ATT_UUID_D1_DATA_PART 0x0001 /*! Proprietary data D1 */ + +/* Proprietary services */ +#define ATT_UUID_P1_SERVICE ATT_UUID_ARM_BUILD(ATT_UUID_P1_SERVICE_PART) + +/* Proprietary characteristics */ +#define ATT_UUID_D1_DATA ATT_UUID_ARM_BUILD(ATT_UUID_D1_DATA_PART) + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! Service UUIDs */ +extern const uint8_t attGapSvcUuid[ATT_16_UUID_LEN]; /*! Generic Access Profile Service */ +extern const uint8_t attGattSvcUuid[ATT_16_UUID_LEN]; /*! Generic Attribute Profile Service */ +extern const uint8_t attIasSvcUuid[ATT_16_UUID_LEN]; /*! Immediate Alert Service */ +extern const uint8_t attLlsSvcUuid[ATT_16_UUID_LEN]; /*! Link Loss Service */ +extern const uint8_t attTpsSvcUuid[ATT_16_UUID_LEN]; /*! Tx Power Service */ +extern const uint8_t attCtsSvcUuid[ATT_16_UUID_LEN]; /*! Current Time Service */ +extern const uint8_t attRtusSvcUuid[ATT_16_UUID_LEN]; /*! Reference Time Update Service */ +extern const uint8_t attNdcsSvcUuid[ATT_16_UUID_LEN]; /*! Next DST Change Service */ +extern const uint8_t attGlsSvcUuid[ATT_16_UUID_LEN]; /*! Glucose Service */ +extern const uint8_t attHtsSvcUuid[ATT_16_UUID_LEN]; /*! Health Thermometer Service */ +extern const uint8_t attDisSvcUuid[ATT_16_UUID_LEN]; /*! Device Information Service */ +extern const uint8_t attNwaSvcUuid[ATT_16_UUID_LEN]; /*! Network Availability Service */ +extern const uint8_t attWdsSvcUuid[ATT_16_UUID_LEN]; /*! Watchdog Service */ +extern const uint8_t attHrsSvcUuid[ATT_16_UUID_LEN]; /*! Heart Rate Service */ +extern const uint8_t attPassSvcUuid[ATT_16_UUID_LEN]; /*! Phone Alert Status Service */ +extern const uint8_t attBasSvcUuid[ATT_16_UUID_LEN]; /*! Battery Service */ +extern const uint8_t attBpsSvcUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Service */ +extern const uint8_t attAnsSvcUuid[ATT_16_UUID_LEN]; /*! Alert Notification Service */ +extern const uint8_t attHidSvcUuid[ATT_16_UUID_LEN]; /*! Human Interface Device Service */ +extern const uint8_t attSpsSvcUuid[ATT_16_UUID_LEN]; /*! Scan Parameter Service */ +extern const uint8_t attPlxsSvcUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Service */ +extern const uint8_t attUdsSvcUuid[ATT_16_UUID_LEN]; /*! User Data Service */ + +/*! GATT UUIDs */ +extern const uint8_t attPrimSvcUuid[ATT_16_UUID_LEN]; /*! Primary Service */ +extern const uint8_t attSecSvcUuid[ATT_16_UUID_LEN]; /*! Secondary Service */ +extern const uint8_t attIncUuid[ATT_16_UUID_LEN]; /*! Include */ +extern const uint8_t attChUuid[ATT_16_UUID_LEN]; /*! Characteristic */ + +/*! Descriptor UUIDs */ +extern const uint8_t attChExtUuid[ATT_16_UUID_LEN]; /*! Characteristic Extended Properties */ +extern const uint8_t attChUserDescUuid[ATT_16_UUID_LEN]; /*! Characteristic User Description */ +extern const uint8_t attCliChCfgUuid[ATT_16_UUID_LEN]; /*! Client Characteristic Configuration */ +extern const uint8_t attSrvChCfgUuid[ATT_16_UUID_LEN]; /*! Server Characteristic Configuration */ +extern const uint8_t attChPresFmtUuid[ATT_16_UUID_LEN]; /*! Characteristic Presentation Format */ +extern const uint8_t attAggFmtUuid[ATT_16_UUID_LEN]; /*! Characteristic Aggregate Format */ +extern const uint8_t attHidErmUuid[ATT_16_UUID_LEN]; /*! HID External Report Reference */ +extern const uint8_t attHidRimUuid[ATT_16_UUID_LEN]; /*! HID Report ID Mapping */ +extern const uint8_t attValRangeUuid[ATT_16_UUID_LEN]; /*! Valid Range */ + +/*! Characteristic UUIDs */ +extern const uint8_t attDnChUuid[ATT_16_UUID_LEN]; /*! Device Name */ +extern const uint8_t attApChUuid[ATT_16_UUID_LEN]; /*! Appearance */ +extern const uint8_t attPpfChUuid[ATT_16_UUID_LEN]; /*! Peripheral Privacy Flag */ +extern const uint8_t attRaChUuid[ATT_16_UUID_LEN]; /*! Reconnection Address */ +extern const uint8_t attPpcpChUuid[ATT_16_UUID_LEN]; /*! Peripheral Preferred Connection Parameters */ +extern const uint8_t attScChUuid[ATT_16_UUID_LEN]; /*! Service Changed */ +extern const uint8_t attAlChUuid[ATT_16_UUID_LEN]; /*! Alert Level */ +extern const uint8_t attTxpChUuid[ATT_16_UUID_LEN]; /*! Tx Power Level */ +extern const uint8_t attDtChUuid[ATT_16_UUID_LEN]; /*! Date Time */ +extern const uint8_t attDwChUuid[ATT_16_UUID_LEN]; /*! Day of Week */ +extern const uint8_t attDdtChUuid[ATT_16_UUID_LEN]; /*! Day Date Time */ +extern const uint8_t attEt100ChUuid[ATT_16_UUID_LEN]; /*! Exact Time 100 */ +extern const uint8_t attEt256ChUuid[ATT_16_UUID_LEN]; /*! Exact Time 256 */ +extern const uint8_t attDstoChUuid[ATT_16_UUID_LEN]; /*! DST Offset */ +extern const uint8_t attTzChUuid[ATT_16_UUID_LEN]; /*! Time Zone */ +extern const uint8_t attLtiChUuid[ATT_16_UUID_LEN]; /*! Local Time Information */ +extern const uint8_t attStzChUuid[ATT_16_UUID_LEN]; /*! Secondary Time Zone */ +extern const uint8_t attTdstChUuid[ATT_16_UUID_LEN]; /*! Time with DST */ +extern const uint8_t attTaChUuid[ATT_16_UUID_LEN]; /*! Time Accuracy */ +extern const uint8_t attTsChUuid[ATT_16_UUID_LEN]; /*! Time Source */ +extern const uint8_t attRtiChUuid[ATT_16_UUID_LEN]; /*! Reference Time Information */ +extern const uint8_t attTbChUuid[ATT_16_UUID_LEN]; /*! Time Broadcast */ +extern const uint8_t attTucpChUuid[ATT_16_UUID_LEN]; /*! Time Update Control Point */ +extern const uint8_t attTusChUuid[ATT_16_UUID_LEN]; /*! Time Update State */ +extern const uint8_t attGlmChUuid[ATT_16_UUID_LEN]; /*! Glucose Measurement */ +extern const uint8_t attBlChUuid[ATT_16_UUID_LEN]; /*! Battery Level */ +extern const uint8_t attBpsChUuid[ATT_16_UUID_LEN]; /*! Battery Power State */ +extern const uint8_t attBlsChUuid[ATT_16_UUID_LEN]; /*! Battery Level State */ +extern const uint8_t attTmChUuid[ATT_16_UUID_LEN]; /*! Temperature Measurement */ +extern const uint8_t attTtChUuid[ATT_16_UUID_LEN]; /*! Temperature Type */ +extern const uint8_t attItChUuid[ATT_16_UUID_LEN]; /*! Intermediate Temperature */ +extern const uint8_t attTcelChUuid[ATT_16_UUID_LEN]; /*! Temperature Celsius */ +extern const uint8_t attTfahChUuid[ATT_16_UUID_LEN]; /*! Temperature Fahrenheit */ +extern const uint8_t attSidChUuid[ATT_16_UUID_LEN]; /*! System ID */ +extern const uint8_t attMnsChUuid[ATT_16_UUID_LEN]; /*! Model Number String */ +extern const uint8_t attSnsChUuid[ATT_16_UUID_LEN]; /*! Serial Number String */ +extern const uint8_t attFrsChUuid[ATT_16_UUID_LEN]; /*! Firmware Revision String */ +extern const uint8_t attHrsChUuid[ATT_16_UUID_LEN]; /*! Hardware Revision String */ +extern const uint8_t attSrsChUuid[ATT_16_UUID_LEN]; /*! Software Revision String */ +extern const uint8_t attMfnsChUuid[ATT_16_UUID_LEN]; /*! Manufacturer Name String */ +extern const uint8_t attIeeeChUuid[ATT_16_UUID_LEN]; /*! IEEE 11073-20601 Regulatory Certification Data List */ +extern const uint8_t attCtChUuid[ATT_16_UUID_LEN]; /*! Current Time */ +extern const uint8_t attElChUuid[ATT_16_UUID_LEN]; /*! Elevation */ +extern const uint8_t attLatChUuid[ATT_16_UUID_LEN]; /*! Latitude */ +extern const uint8_t attLongChUuid[ATT_16_UUID_LEN]; /*! Longitude */ +extern const uint8_t attP2dChUuid[ATT_16_UUID_LEN]; /*! Position 2D */ +extern const uint8_t attP3dChUuid[ATT_16_UUID_LEN]; /*! Position 3D */ +extern const uint8_t attVidChUuid[ATT_16_UUID_LEN]; /*! Vendor ID */ +extern const uint8_t attGlmcChUuid[ATT_16_UUID_LEN]; /*! Glucose Measurement Context */ +extern const uint8_t attBpmChUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Measurement */ +extern const uint8_t attIcpChUuid[ATT_16_UUID_LEN]; /*! Intermediate Cuff Pressure */ +extern const uint8_t attHrmChUuid[ATT_16_UUID_LEN]; /*! Heart Rate Measurement */ +extern const uint8_t attBslChUuid[ATT_16_UUID_LEN]; /*! Body Sensor Location */ +extern const uint8_t attHrcpChUuid[ATT_16_UUID_LEN]; /*! Heart Rate Control Point */ +extern const uint8_t attRemChUuid[ATT_16_UUID_LEN]; /*! Removable */ +extern const uint8_t attSrChUuid[ATT_16_UUID_LEN]; /*! Service Required */ +extern const uint8_t attStcChUuid[ATT_16_UUID_LEN]; /*! Scientific Temperature in Celsius */ +extern const uint8_t attStrChUuid[ATT_16_UUID_LEN]; /*! String */ +extern const uint8_t attNwaChUuid[ATT_16_UUID_LEN]; /*! Network Availability */ +extern const uint8_t attAsChUuid[ATT_16_UUID_LEN]; /*! Alert Status */ +extern const uint8_t attRcpChUuid[ATT_16_UUID_LEN]; /*! Ringer Control Point */ +extern const uint8_t attRsChUuid[ATT_16_UUID_LEN]; /*! Ringer Setting */ +extern const uint8_t attAcbmChUuid[ATT_16_UUID_LEN]; /*! Alert Category ID Bit Mask */ +extern const uint8_t attAcChUuid[ATT_16_UUID_LEN]; /*! Alert Category ID */ +extern const uint8_t attAncpChUuid[ATT_16_UUID_LEN]; /*! Alert Notification Control Point */ +extern const uint8_t attUasChUuid[ATT_16_UUID_LEN]; /*! Unread Alert Status */ +extern const uint8_t attNaChUuid[ATT_16_UUID_LEN]; /*! New Alert */ +extern const uint8_t attSnacChUuid[ATT_16_UUID_LEN]; /*! Supported New Alert Category */ +extern const uint8_t attSuacChUuid[ATT_16_UUID_LEN]; /*! Supported Unread Alert Category */ +extern const uint8_t attBpfChUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Feature */ +extern const uint8_t attHidBmiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidBkiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidBkoChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidRmChUuid[ATT_16_UUID_LEN]; /*! Report Map */ +extern const uint8_t attHidcpChUuid[ATT_16_UUID_LEN]; /*! HID Control Point */ +extern const uint8_t attHidRepChUuid[ATT_16_UUID_LEN]; /*! Report */ +extern const uint8_t attHidPmChUuid[ATT_16_UUID_LEN]; /*! Protocol Mode */ +extern const uint8_t attSiwChUuid[ATT_16_UUID_LEN]; /*! Scan Interval Window */ +extern const uint8_t attPnpChUuid[ATT_16_UUID_LEN]; /*! PnP ID */ +extern const uint8_t attGlfChUuid[ATT_16_UUID_LEN]; /*! Glucose Feature */ +extern const uint8_t attRacpChUuid[ATT_16_UUID_LEN]; /*! Record Access Control Point */ +extern const uint8_t attCarChUuid[ATT_16_UUID_LEN]; /*! Central Address Resolution */ +extern const uint8_t attRsfChUuid[ATT_16_UUID_LEN]; /*! Running Speed Features */ +extern const uint8_t attRsmChUuid[ATT_16_UUID_LEN]; /*! Running Speed Measurement */ +extern const uint8_t attCpfChUuid[ATT_16_UUID_LEN]; /*! Cycling Power Features */ +extern const uint8_t attCpmChUuid[ATT_16_UUID_LEN]; /*! Cycling Power Measurement */ +extern const uint8_t attCsfChUuid[ATT_16_UUID_LEN]; /*! Cycling Speed Features */ +extern const uint8_t attCsmChUuid[ATT_16_UUID_LEN]; /*! Cycling Speed Measurement */ +extern const uint8_t attSlChUuid[ATT_16_UUID_LEN]; /*! Sensor Location */ +extern const uint8_t attPlxfChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Features */ +extern const uint8_t attPlxscmChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Spot Check Measurement */ +extern const uint8_t attPlxcmChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Continuous Measurement */ +extern const uint8_t attRpaoChUuid[ATT_16_UUID_LEN]; /*! Resolvable Private Address Only */ +extern const uint8_t attDbciChUuid[ATT_16_UUID_LEN]; /*! Database Change Increment */ +extern const uint8_t attUiChUuid[ATT_16_UUID_LEN]; /*! User Index */ +extern const uint8_t attUcpChUuid[ATT_16_UUID_LEN]; /*! User Control Point */ + +/* remove when adopted */ +extern const uint8_t attWssSvcUuid[ATT_16_UUID_LEN]; /*! Weight scale service */ +extern const uint8_t attWmChUuid[ATT_16_UUID_LEN]; /*! Weight measurement */ +extern const uint8_t attWsfChUuid[ATT_16_UUID_LEN]; /*! Weight scale feature */ + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_UUID_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h new file mode 100644 index 00000000000..ad01975349d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h @@ -0,0 +1,2423 @@ +/*************************************************************************************************/ +/*! + * \file dm_api.h + * + * \brief Device Manager subsystem API. + * + * $Date: 2017-02-09 11:58:21 -0600 (Thu, 09 Feb 2017) $ + * $Revision: 11135 $ + * + * Copyright (c) 2016-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef DM_API_H +#define DM_API_H + +#include "hci_api.h" +#include "cfg_stack.h" +#include "smp_defs.h" +#include "sec_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Device role */ +#define DM_ROLE_MASTER HCI_ROLE_MASTER /*! Role is master */ +#define DM_ROLE_SLAVE HCI_ROLE_SLAVE /*! Role is slave */ + +/*! The GAP discovery mode */ +#define DM_DISC_MODE_NONE 0 /*! GAP non-discoverable */ +#define DM_DISC_MODE_LIMITED 1 /*! GAP limited discoverable mode */ +#define DM_DISC_MODE_GENERAL 2 /*! GAP general discoverable mode */ + +/*! The type of connectable or discoverable of advertising */ +#define DM_ADV_CONN_UNDIRECT 0 /*! Connectable and scannable undirected advertising */ +#define DM_ADV_CONN_DIRECT 1 /*! Connectable directed advertising */ +#define DM_ADV_SCAN_UNDIRECT 2 /*! Scannable undirected advertising */ +#define DM_ADV_NONCONN_UNDIRECT 3 /*! Non-connectable and non-scannable undirected advertising */ +#define DM_ADV_CONN_DIRECT_LO_DUTY 4 /*! Connectable directed low duty cycle advertising */ + +/*! The type of extended advertising -- only applicable to AE */ +#define DM_EXT_ADV_CONN_UNDIRECT 5 /*! Connectable undirected advertising */ +#define DM_EXT_ADV_NONCONN_DIRECT 6 /*! Non-connectable and non-scannable directed advertising */ +#define DM_EXT_ADV_SCAN_DIRECT 7 /*! Scannable directed advertising */ +#define DM_ADV_NONE 255 /*! For internal use only */ + +/*! The type of advertising report */ +#define DM_RPT_CONN_UNDIRECT 0 /*! Connectable and scannable undirected advertising */ +#define DM_RPT_CONN_DIRECT 1 /*! Connectable directed advertising */ +#define DM_RPT_SCAN_UNDIRECT 2 /*! Scannable undirected advertising */ +#define DM_RPT_NONCONN_UNDIRECT 3 /*! Non-connectable undirected advertising */ +#define DM_RPT_SCAN_RESPONSE 4 /*! Scan response */ + +/*! Whether data is located in the advertising data or the scan response data */ +#define DM_DATA_LOC_ADV 0 /*! Locate data in the advertising data */ +#define DM_DATA_LOC_SCAN 1 /*! Locate data in the scan response data */ + +/*! The scan type */ +#define DM_SCAN_TYPE_PASSIVE 0 /*! Passive scan */ +#define DM_SCAN_TYPE_ACTIVE 1 /*! Active scan */ + +/*! Advertising channel map */ +#define DM_ADV_CHAN_37 HCI_ADV_CHAN_37 /*! Advertising channel 37 */ +#define DM_ADV_CHAN_38 HCI_ADV_CHAN_38 /*! Advertising channel 38 */ +#define DM_ADV_CHAN_39 HCI_ADV_CHAN_39 /*! Advertising channel 39 */ +#define DM_ADV_CHAN_ALL (HCI_ADV_CHAN_37 | HCI_ADV_CHAN_38 | HCI_ADV_CHAN_39) + +/*! The client ID parameter to function DmConnRegister() */ +#define DM_CLIENT_ID_ATT 0 /*! Identifier for attribute protocol, for internal use only */ +#define DM_CLIENT_ID_SMP 1 /*! Identifier for security manager protocol, for internal use only */ +#define DM_CLIENT_ID_DM 2 /*! Identifier for device manager, for internal use only */ +#define DM_CLIENT_ID_APP 3 /*! Identifier for the application */ +#define DM_CLIENT_ID_L2C 4 /*! Identifier for L2CAP */ +#define DM_CLIENT_ID_MAX 5 /*! For internal use only */ + +/*! Unknown connection ID or other error */ +#define DM_CONN_ID_NONE 0 + +/*! The address type */ +#define DM_ADDR_PUBLIC 0x00 /*! Public device address */ +#define DM_ADDR_RANDOM 0x01 /*! Random device address */ +#define DM_ADDR_PUBLIC_IDENTITY 0x02 /*! Public identity address (corresponds to resolved private address) */ +#define DM_ADDR_RANDOM_IDENTITY 0x03 /*! Random (static) identity address (corresponds to resolved private address) */ +#define DM_ADDR_RANDOM_UNRESOLVED 0xFE /*! Random device address (Controller unable to resolve) */ +#define DM_ADDR_NONE 0xFF /*! No address provided (anonymous) */ + +/*! Advertising data types */ +#define DM_ADV_TYPE_FLAGS 0x01 /*! Flag bits */ +#define DM_ADV_TYPE_16_UUID_PART 0x02 /*! Partial list of 16 bit UUIDs */ +#define DM_ADV_TYPE_16_UUID 0x03 /*! Complete list of 16 bit UUIDs */ +#define DM_ADV_TYPE_32_UUID_PART 0x04 /*! Partial list of 32 bit UUIDs */ +#define DM_ADV_TYPE_32_UUID 0x05 /*! Complete list of 32 bit UUIDs */ +#define DM_ADV_TYPE_128_UUID_PART 0x06 /*! Partial list of 128 bit UUIDs */ +#define DM_ADV_TYPE_128_UUID 0x07 /*! Complete list of 128 bit UUIDs */ +#define DM_ADV_TYPE_SHORT_NAME 0x08 /*! Shortened local name */ +#define DM_ADV_TYPE_LOCAL_NAME 0x09 /*! Complete local name */ +#define DM_ADV_TYPE_TX_POWER 0x0A /*! TX power level */ +#define DM_ADV_TYPE_SM_TK_VALUE 0x10 /*! Security manager TK value */ +#define DM_ADV_TYPE_SM_OOB_FLAGS 0x11 /*! Security manager OOB flags */ +#define DM_ADV_TYPE_CONN_INTERVAL 0x12 /*! Slave preferred connection interval */ +#define DM_ADV_TYPE_SIGNED_DATA 0x13 /*! Signed data */ +#define DM_ADV_TYPE_16_SOLICIT 0x14 /*! Service soliticiation list of 16 bit UUIDs */ +#define DM_ADV_TYPE_128_SOLICIT 0x15 /*! Service soliticiation list of 128 bit UUIDs */ +#define DM_ADV_TYPE_SERVICE_DATA 0x16 /*! Service data - 16-bit UUID */ +#define DM_ADV_TYPE_PUBLIC_TARGET 0x17 /*! Public target address */ +#define DM_ADV_TYPE_RANDOM_TARGET 0x18 /*! Random target address */ +#define DM_ADV_TYPE_APPEARANCE 0x19 /*! Device appearance */ +#define DM_ADV_TYPE_ADV_INTERVAL 0x1A /*! Advertising interval */ +#define DM_ADV_TYPE_BD_ADDR 0x1B /*! LE Bluetooth device address */ +#define DM_ADV_TYPE_ROLE 0x1C /*! LE role */ +#define DM_ADV_TYPE_32_SOLICIT 0x1F /*! Service soliticiation list of 32 bit UUIDs */ +#define DM_ADV_TYPE_SVC_DATA_32 0x20 /*! Service data - 32-bit UUID */ +#define DM_ADV_TYPE_SVC_DATA_128 0x21 /*! Service data - 128-bit UUID */ +#define DM_ADV_TYPE_LESC_CONFIRM 0x22 /*! LE Secure Connections confirm value */ +#define DM_ADV_TYPE_LESC_RANDOM 0x23 /*! LE Secure Connections random value */ +#define DM_ADV_TYPE_URI 0x24 /*! URI */ +#define DM_ADV_TYPE_MANUFACTURER 0xFF /*! Manufacturer specific data */ + +/*! Bit mask for flags advertising data type */ +#define DM_FLAG_LE_LIMITED_DISC 0x01 /*! Limited discoverable flag */ +#define DM_FLAG_LE_GENERAL_DISC 0x02 /*! General discoverable flag */ +#define DM_FLAG_LE_BREDR_NOT_SUP 0x04 /*! BR/EDR not supported flag */ + +/*! Advertising data element indexes */ +#define DM_AD_LEN_IDX 0 /*! Advertising data element len */ +#define DM_AD_TYPE_IDX 1 /*! Advertising data element type */ +#define DM_AD_DATA_IDX 2 /*! Advertising data element data */ + +/*! Advertising URI Scheme */ +#define DM_URI_SCHEME_HTTP 0x16 /*! URI HTTP Scheme */ +#define DM_URI_SCHEME_HTTPS 0x17 /*! URI HTTPS Scheme */ + +/*! Timeouts defined by the GAP specification; in units of milliseconds */ +#define DM_GAP_LIM_ADV_TIMEOUT 180000 /*! Maximum advertising duration in limited discoverable mode */ +#define DM_GAP_GEN_DISC_SCAN_MIN 10240 /*! Minimum scan duration for general discovery */ +#define DM_GAP_LIM_DISC_SCAN_MIN 10240 /*! Minimum scan duration for limited discovery */ +#define DM_GAP_CONN_PARAM_TIMEOUT 30000 /*! Connection parameter update timeout */ +#define DM_GAP_SCAN_FAST_PERIOD 30720 /*! Minimum time to perform scanning when user initiated */ +#define DM_GAP_ADV_FAST_PERIOD 30000 /*! Minimum time to perform advertising when user initiated */ + +/*! + * Advertising, scanning, and connection parameters defined in the GAP specification for the LE 1M PHY. + * In units of 625 microseconds. + */ +#define DM_GAP_SCAN_FAST_INT_MIN 48 /*! Minimum scan interval when user initiated */ +#define DM_GAP_SCAN_FAST_INT_MAX 96 /*! Maximum scan interval when user initiated */ +#define DM_GAP_SCAN_FAST_WINDOW 48 /*! Scan window when user initiated */ +#define DM_GAP_SCAN_SLOW_INT_1 2048 /*! Scan interval 1 when background scannning */ +#define DM_GAP_SCAN_SLOW_WINDOW_1 18 /*! Scan window 1 when background scanning */ +#define DM_GAP_SCAN_SLOW_INT_2 4096 /*! Scan interval 2 when background scannning */ +#define DM_GAP_SCAN_SLOW_WINDOW_2 36 /*! Scan window 2 when background scanning */ +#define DM_GAP_ADV_FAST_INT_MIN_1 48 /*! Minimum advertising interval 1 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MAX_1 96 /*! Maximum advertising interval 1 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MIN_2 160 /*! Minimum advertising interval 2 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MAX_2 240 /*! Maximum advertising interval 2 when user initiated */ +#define DM_GAP_ADV_SLOW_INT_MIN 1600 /*! Minimum advertising interval when background advertising */ +#define DM_GAP_ADV_SLOW_INT_MAX 1920 /*! Maximum advertising interval when background advertising */ + + /*! + * Advertising, scanning, and connection parameters defined in the GAP specification for the LE Coded PHY. + * In units of 625 microseconds. + */ +#define DM_GAP_SCAN_CODED_FAST_INT_MIN 144 /*! Minimum scan interval when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_FAST_INT_MAX 288 /*! Maximum scan interval when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_FAST_WINDOW 144 /*! Scan window when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_INT_1 6144 /*! Scan interval 1 when background scannning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_WINDOW_1 54 /*! Scan window 1 when background scanning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_INT_2 12288 /*! Scan interval 2 when background scannning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_WINDOW_2 108 /*! Scan window 2 when background scanning on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MIN_1 144 /*! Minimum advertising interval 1 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MAX_1 288 /*! Maximum advertising interval 1 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MIN_2 480 /*! Minimum advertising interval 2 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MAX_2 720 /*! Maximum advertising interval 2 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_SLOW_INT_MIN 4800 /*! Minimum advertising interval when background advertising on LE Coded PHY */ +#define DM_GAP_ADV_CODED_SLOW_INT_MAX 5760 /*! Maximum advertising interval when background advertising on LE Coded PHY */ + +/*! GAP connection establishment latency */ +#define DM_GAP_CONN_EST_LATENCY 0 + +/*! GAP connection intervals in 1.25ms units */ +#define DM_GAP_INITIAL_CONN_INT_MIN 24 /*! Minimum initial connection interval */ +#define DM_GAP_INITIAL_CONN_INT_MAX 40 /*! Maximum initial onnection interval */ + +/*! GAP connection establishment minimum and maximum connection event lengths */ +#define DM_GAP_CONN_EST_MIN_CE_LEN 0 +#define DM_GAP_CONN_EST_MAX_CE_LEN 0 + +/*! GAP peripheral privacy flag characteristic values */ +#define DM_GAP_PRIV_DISABLED 0 +#define DM_GAP_PRIV_ENABLED 1 + +/*! Connection establishment supervision timeout default, in 10ms units */ +#define DM_DEFAULT_EST_SUP_TIMEOUT 2000 + +/*! Pairing authentication/security properties bit mask */ +#define DM_AUTH_BOND_FLAG SMP_AUTH_BOND_FLAG /*! Bonding requested */ +#define DM_AUTH_MITM_FLAG SMP_AUTH_MITM_FLAG /*! MITM (authenticated pairing) requested */ +#define DM_AUTH_SC_FLAG SMP_AUTH_SC_FLAG /*! LE Secure Connections requested */ +#define DM_AUTH_KP_FLAG SMP_AUTH_KP_FLAG /*! Keypress notifications requested */ + +/*! Key distribution bit mask */ +#define DM_KEY_DIST_LTK SMP_KEY_DIST_ENC /*! Distribute LTK used for encryption */ +#define DM_KEY_DIST_IRK SMP_KEY_DIST_ID /*! Distribute IRK used for privacy */ +#define DM_KEY_DIST_CSRK SMP_KEY_DIST_SIGN /*! Distribute CSRK used for signed data */ + +/*! Key type used in DM_SEC_KEY_IND */ +#define DM_KEY_LOCAL_LTK 0x01 /*! LTK generated locally for this device */ +#define DM_KEY_PEER_LTK 0x02 /*! LTK received from peer device */ +#define DM_KEY_IRK 0x04 /*! IRK and identity info of peer device */ +#define DM_KEY_CSRK 0x08 /*! CSRK of peer device */ + +/*! Base value for HCI error status values for DM_SEC_PAIR_CMPL_IND */ +#define DM_SEC_HCI_ERR_BASE 0x20 + +#define DM_SEC_LEVEL_NONE 0 /*! Connection has no security */ +#define DM_SEC_LEVEL_ENC 1 /*! Connection is encrypted with unauthenticated key */ +#define DM_SEC_LEVEL_ENC_AUTH 2 /*! Connection is encrypted with authenticated key */ +#define DM_SEC_LEVEL_ENC_LESC 3 /*! Connection is encrypted with LE Secure Connections */ + +/*! Random address types */ +#define DM_RAND_ADDR_STATIC 0xC0 /*! Static address */ +#define DM_RAND_ADDR_RESOLV 0x40 /*! Resolvable private address */ +#define DM_RAND_ADDR_NONRESOLV 0x00 /*! Non-resolvable private address */ + +/*! Privacy modes */ +#define DM_PRIV_MODE_NETWORK 0x00 /*! Network privacy mode (default) */ +#define DM_PRIV_MODE_DEVICE 0x01 /*! Device privacy mode */ + +/*! Get the type of random address */ +#define DM_RAND_ADDR_GET(addr) ((addr)[5] & 0xC0) + +/*! Set the type of random address */ +#define DM_RAND_ADDR_SET(addr, type) {(addr)[5] = ((addr)[5] & 0x3F) | (type);} + +/*! Check for Resolvable Random Address */ +#define DM_RAND_ADDR_RPA(addr, type) (((type) == DM_ADDR_RANDOM) && \ + (DM_RAND_ADDR_GET((addr)) == DM_RAND_ADDR_RESOLV)) + +/*! Connection busy/idle state */ +#define DM_CONN_IDLE 0 /*! Connection is idle */ +#define DM_CONN_BUSY 1 /*! Connection is busy */ + +/*! Connection busy/idle state bitmask */ +#define DM_IDLE_SMP_PAIR 0x0001 /*! SMP pairing in progress */ +#define DM_IDLE_DM_ENC 0x0002 /*! DM Encryption setup in progress */ +#define DM_IDLE_ATTS_DISC 0x0004 /*! ATTS service discovery in progress */ +#define DM_IDLE_APP_DISC 0x0008 /*! App framework service discovery in progress */ +#define DM_IDLE_USER_1 0x0010 /*! For use by user application */ +#define DM_IDLE_USER_2 0x0020 /*! For use by user application */ +#define DM_IDLE_USER_3 0x0040 /*! For use by user application */ +#define DM_IDLE_USER_4 0x0080 /*! For use by user application */ + +/*! Filter policy modes */ +#define DM_FILT_POLICY_MODE_ADV 0 /*! Advertising filter policy mode */ +#define DM_FILT_POLICY_MODE_SCAN 1 /*! Scanning filter policy mode */ +#define DM_FILT_POLICY_MODE_INIT 2 /*! Initiator filter policy mode */ + +/*! Proprietary internal error codes */ +#define DM_ERR_SMP_RX_PDU_LEN_EXCEEDED 0x01 /*! LESC key length exceeded maximum RX PDU length */ +#define DM_ERR_ATT_RX_PDU_LEN_EXCEEDED 0x02 /*! Configured ATT MTU exceeded maximum RX PDU length */ +#define DM_ERR_L2C_RX_PDU_LEN_EXCEEDED 0x03 /*! Registered COC MPS exceeded maximum RX PDU length */ + +/*! Advertising handle */ +#define DM_ADV_HANDLE_DEFAULT 0 /*! Default advertising handle for legacy advertising */ + +/*! DM callback events */ +#define DM_CBACK_START 0x20 /*! DM callback event starting value */ +enum +{ + DM_RESET_CMPL_IND = DM_CBACK_START, /*! Reset complete */ + DM_ADV_START_IND, /*! Advertising started */ + DM_ADV_STOP_IND, /*! Advertising stopped */ + DM_ADV_NEW_ADDR_IND, /*! New resolvable address has been generated */ + DM_SCAN_START_IND, /*! Scanning started */ + DM_SCAN_STOP_IND, /*! Scanning stopped */ + DM_SCAN_REPORT_IND, /*! Scan data received from peer device */ + DM_CONN_OPEN_IND, /*! Connection opened */ + DM_CONN_CLOSE_IND, /*! Connection closed */ + DM_CONN_UPDATE_IND, /*! Connection update complete */ + DM_SEC_PAIR_CMPL_IND, /*! Pairing completed successfully */ + DM_SEC_PAIR_FAIL_IND, /*! Pairing failed or other security failure */ + DM_SEC_ENCRYPT_IND, /*! Connection encrypted */ + DM_SEC_ENCRYPT_FAIL_IND, /*! Encryption failed */ + DM_SEC_AUTH_REQ_IND, /*! PIN or OOB data requested for pairing */ + DM_SEC_KEY_IND, /*! Security key indication */ + DM_SEC_LTK_REQ_IND, /*! LTK requested for encyption */ + DM_SEC_PAIR_IND, /*! Incoming pairing request from master */ + DM_SEC_SLAVE_REQ_IND, /*! Incoming security request from slave */ + DM_SEC_CALC_OOB_IND, /*! Result of OOB Confirm Calculation Generation */ + DM_SEC_ECC_KEY_IND, /*! Result of ECC Key Generation */ + DM_SEC_COMPARE_IND, /*! Result of Just Works/Numeric Comparison Compare Value Calculation */ + DM_SEC_KEYPRESS_IND, /*! Keypress indication from peer in passkey security */ + DM_PRIV_RESOLVED_ADDR_IND, /*! Private address resolved */ + DM_CONN_READ_RSSI_IND, /*! Connection RSSI read */ + DM_PRIV_ADD_DEV_TO_RES_LIST_IND, /*! Device added to resolving list */ + DM_PRIV_REM_DEV_FROM_RES_LIST_IND, /*! Device removed from resolving list */ + DM_PRIV_CLEAR_RES_LIST_IND, /*! Resolving list cleared */ + DM_PRIV_READ_PEER_RES_ADDR_IND, /*! Peer resolving address read */ + DM_PRIV_READ_LOCAL_RES_ADDR_IND, /*! Local resolving address read */ + DM_PRIV_SET_ADDR_RES_ENABLE_IND, /*! Address resolving enable set */ + DM_REM_CONN_PARAM_REQ_IND, /*! Remote connection parameter requested */ + DM_CONN_DATA_LEN_CHANGE_IND, /*! Data length changed */ + DM_CONN_WRITE_AUTH_TO_IND, /*! Write authenticated payload complete */ + DM_CONN_AUTH_TO_EXPIRED_IND, /*! Authenticated payload timeout expired */ + DM_PHY_READ_IND, /*! Read PHY */ + DM_PHY_SET_DEF_IND, /*! Set default PHY */ + DM_PHY_UPDATE_IND, /*! PHY update */ + DM_ADV_SET_START_IND, /*! Advertising set(s) started */ + DM_ADV_SET_STOP_IND, /*! Advertising set(s) stopped */ + DM_SCAN_REQ_RCVD_IND, /*! Scan request received */ + DM_EXT_SCAN_START_IND, /*! Extended scanning started */ + DM_EXT_SCAN_STOP_IND, /*! Extended scanning stopped */ + DM_EXT_SCAN_REPORT_IND, /*! Extended scan data received from peer device */ + DM_PER_ADV_SET_START_IND, /*! Periodic advertising set started */ + DM_PER_ADV_SET_STOP_IND, /*! Periodic advertising set stopped */ + DM_PER_ADV_SYNC_EST_IND, /*! Periodic advertising sync established */ + DM_PER_ADV_SYNC_LOST_IND, /*! Periodic advertising sync lost */ + DM_PER_ADV_REPORT_IND, /*! Periodic advertising data received from peer device */ + DM_REMOTE_FEATURES_IND, /*! Remote features from peer device */ + DM_ERROR_IND, /*! General error */ + DM_VENDOR_SPEC_IND, /*! Vendor specific event */ +}; + +#define DM_CBACK_END DM_VENDOR_SPEC_IND /*! DM callback event ending value */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection identifier */ +typedef uint8_t dmConnId_t; + +/*! Configuration structure */ +typedef struct +{ + uint8_t dummy; +} dmCfg_t; + +/*! LTK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; + uint8_t rand[SMP_RAND8_LEN]; + uint16_t ediv; +} dmSecLtk_t; + +/*! IRK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; + bdAddr_t bdAddr; + uint8_t addrType; +} dmSecIrk_t; + +/*! CSRK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; +} dmSecCsrk_t; + +/*! union of key types */ +typedef union +{ + dmSecLtk_t ltk; + dmSecIrk_t irk; + dmSecCsrk_t csrk; +} dmSecKey_t; + +/*! Data type for DM_SEC_PAIR_CMPL_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ +} dmSecPairCmplIndEvt_t; + +/*! Data type for DM_SEC_ENCRYPT_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bool_t usingLtk; /*! TRUE if connection encrypted with LTK */ +} dmSecEncryptIndEvt_t; + +/*! Data type for DM_SEC_AUTH_REQ_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bool_t oob; /*! Out-of-band data requested */ + bool_t display; /*! TRUE if pin is to be displayed */ +} dmSecAuthReqIndEvt_t; + +/*! Data type for DM_SEC_PAIR_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ + bool_t oob; /*! Out-of-band pairing data present or not present */ + uint8_t iKeyDist; /*! Initiator key distribution flags */ + uint8_t rKeyDist; /*! Responder key distribution flags */ +} dmSecPairIndEvt_t; + +/*! Data type for DM_SEC_SLAVE_REQ_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ +} dmSecSlaveIndEvt_t; + +/*! Data type for DM_SEC_KEY_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + dmSecKey_t keyData; /*! Key data */ + uint8_t type; /*! Key type */ + uint8_t secLevel; /*! Security level of pairing when key was exchanged */ + uint8_t encKeyLen; /*! Length of encryption key used when data was transferred */ +} dmSecKeyIndEvt_t; + +/*! Data type for DM_SEC_COMPARE_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t confirm[SMP_CONFIRM_LEN]; /*! Confirm value */ +} dmSecCnfIndEvt_t; + +/*! Data type for DM_SEC_KEYPRESS_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t notificationType; /*! Type of keypress notification */ +} dmSecKeypressIndEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t confirm[SMP_CONFIRM_LEN]; /*! Local confirm value */ + uint8_t random[SMP_RAND_LEN]; /*! Local random value */ +} dmSecOobCalcIndEvt_t; + +/*! Data type for DM_ADV_NEW_ADDR_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bdAddr_t addr; /*! New resolvable private address */ + bool_t firstTime; /*! TRUE when address is generated for the first time */ +} dmAdvNewAddrIndEvt_t; + +/* Data structure for DM_ADV_SET_START_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t numSets; /*! Number of advertising sets */ + uint8_t advHandle[DM_NUM_ADV_SETS];/*! Advertising handle array */ +} dmAdvSetStartEvt_t; + +/* Data structure for DM_PER_ADV_SET_START_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t advHandle; /*! Advertising handle */ +} dmPerAdvSetStartEvt_t; + +/* Data structure for DM_PER_ADV_SET_STOP_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t advHandle; /*! Advertising handle */ +} dmPerAdvSetStopEvt_t; + +/*! Union of DM callback event data types */ +typedef union +{ + wsfMsgHdr_t hdr; /*! Common header */ + /*! common header used by DM_RESET_CMPL_IND */ + /*! common header used by DM_ADV_START_IND */ + /*! common header used by DM_ADV_STOP_IND */ + dmAdvNewAddrIndEvt_t advNewAddr; /*! DM_ADV_NEW_ADDR_IND */ + /*! common header used by DM_SCAN_START_IND */ + /*! common header used by DM_SCAN_STOP_IND */ + hciLeAdvReportEvt_t scanReport; /*! DM_SCAN_REPORT_IND */ + hciLeConnCmplEvt_t connOpen; /*! DM_CONN_OPEN_IND */ + hciDisconnectCmplEvt_t connClose; /*! DM_CONN_CLOSE_IND */ + hciLeConnUpdateCmplEvt_t connUpdate; /*! DM_CONN_UPDATE_IND */ + dmSecPairCmplIndEvt_t pairCmpl; /*! DM_SEC_PAIR_CMPL_IND */ + /*! common header used by DM_SEC_PAIR_FAIL_IND */ + dmSecEncryptIndEvt_t encryptInd; /*! DM_SEC_ENCRYPT_IND */ + /*! common header used by DM_SEC_ENCRYPT_FAIL_IND */ + dmSecAuthReqIndEvt_t authReq; /*! DM_SEC_AUTH_REQ_IND */ + dmSecKeyIndEvt_t keyInd; /*! DM_SEC_KEY_IND */ + hciLeLtkReqEvt_t ltkReqInd; /*! DM_SEC_LTK_REQ_IND */ + dmSecPairIndEvt_t pairInd; /*! DM_SEC_PAIR_IND */ + dmSecSlaveIndEvt_t slaveInd; /*! DM_SEC_SLAVE_REQ_IND */ + dmSecOobCalcIndEvt_t oobCalcInd; /*! DM_SEC_CALC_OOB_IND */ + secEccMsg_t eccMsg; /*! DM_SEC_ECC_KEY_IND */ + dmSecCnfIndEvt_t cnfInd; /*! DM_SEC_COMPARE_IND */ + dmSecKeypressIndEvt_t keypressInd; /*! DM_SEC_KEYPRESS_IND */ + /*! common header used by DM_PRIV_RESOLVED_ADDR_IND */ + hciReadRssiCmdCmplEvt_t readRssi; /*! DM_CONN_READ_RSSI_IND */ + hciLeAddDevToResListCmdCmplEvt_t addDevToResList; /*! DM_PRIV_ADD_DEV_TO_RES_LIST_IND */ + hciLeRemDevFromResListCmdCmplEvt_t remDevFromResList;/*! DM_PRIV_REM_DEV_FROM_RES_LIST_IND */ + hciLeClearResListCmdCmplEvt_t clearResList; /*! DM_PRIV_CLEAR_RES_LIST_IND */ + hciLeReadPeerResAddrCmdCmplEvt_t readPeerResAddr; /*! DM_PRIV_READ_PEER_RES_ADDR_IND */ + hciLeReadLocalResAddrCmdCmplEvt_t readLocalResAddr; /*! DM_PRIV_READ_LOCAL_RES_ADDR_IND */ + hciLeSetAddrResEnableCmdCmplEvt_t setAddrResEnable; /*! DM_PRIV_SET_ADDR_RES_ENABLE_IND */ + hciLeRemConnParamReqEvt_t remConnParamReq; /*! DM_REM_CONN_PARAM_REQ_IND */ + hciLeDataLenChangeEvt_t dataLenChange; /*! DM_CONN_DATA_LEN_CHANGE_IND */ + hciWriteAuthPayloadToCmdCmplEvt_t writeAuthTo; /*! DM_CONN_WRITE_AUTH_TO_IND */ + hciAuthPayloadToExpiredEvt_t authToExpired; /*! DM_CONN_AUTH_TO_EXPIRED_IND */ + hciLeReadPhyCmdCmplEvt_t readPhy; /*! DM_PHY_READ_IND */ + hciLeSetDefPhyCmdCmplEvt_t setDefPhy; /*! DM_PHY_SET_DEF_IND */ + hciLePhyUpdateEvt_t phyUpdate; /*! DM_PHY_UPDATE_IND */ + dmAdvSetStartEvt_t advSetStart; /*! DM_ADV_SET_START_IND */ + hciLeAdvSetTermEvt_t advSetStop; /*! DM_ADV_SET_STOP_IND */ + hciLeScanReqRcvdEvt_t scanReqRcvd; /*! DM_SCAN_REQ_RCVD_IND */ + /*! common header used by DM_EXT_SCAN_START_IND */ + /*! common header used by DM_EXT_SCAN_STOP_IND */ + hciLeExtAdvReportEvt_t extScanReport; /*! DM_EXT_SCAN_REPORT_IND */ + dmPerAdvSetStartEvt_t perAdvSetStart; /*! DM_PER_ADV_SET_START_IND */ + dmPerAdvSetStopEvt_t perAdvSetStop; /*! DM_PER_ADV_SET_STOP_IND */ + hciLePerAdvSyncEstEvt_t perAdvSyncEst; /*! DM_PER_ADV_SYNC_EST_IND */ + hciLePerAdvSyncLostEvt_t perAdvSyncLost; /*! DM_PER_ADV_SYNC_LOST_IND */ + hciLePerAdvReportEvt_t perAdvReport; /*! DM_PER_ADV_REPORT_IND */ + hciLeReadRemoteFeatCmplEvt_t readRemoteFeat; /*! DM_REMOTE_FEATURES_IND */ + /*! common header used by DM_ERROR_IND */ + hciVendorSpecEvt_t vendorSpec; /*! DM_VENDOR_SPEC_IND */ +} dmEvt_t; + +/*! Data type for DmSecSetOob */ +typedef struct +{ + uint8_t localRandom[SMP_RAND_LEN]; /*! Random value of the local device */ + uint8_t localConfirm[SMP_CONFIRM_LEN]; /*! Confirm value of the local device */ + uint8_t peerRandom[SMP_RAND_LEN]; /*! Random value of the peer device */ + uint8_t peerConfirm[SMP_CONFIRM_LEN]; /*! Confirm value of the peer device */ +} dmSecLescOobCfg_t; + +/*! Callback type */ +typedef void (*dmCback_t)(dmEvt_t *pDmEvt); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn DmRegister + * + * \brief Register a callback with DM for scan and advertising events. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRegister(dmCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn DmFindAdType + * + * \brief Find an advertising data element in the given advertising or scan response data. + * + * \param adType Advertising data element type to find. + * \param dataLen Data length. + * \param pData Pointer to advertising or scan response data. + * + * \return Pointer to the advertising data element byte array or NULL if not found. + */ +/*************************************************************************************************/ +uint8_t *DmFindAdType(uint8_t adType, uint16_t dataLen, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn DmAdvInit + * + * \brief Initialize DM legacy advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtAdvInit + * + * \brief Initialize DM extended advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtAdvInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvModeLeg + * + * \brief Whether DM advertising is in legacy mode. + * + * \return TRUE if DM advertising is in legacy mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvModeLeg(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvModeExt + * + * \brief Whether DM advertising is in extended mode. + * + * \return TRUE if DM advertising is in extended mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvModeExt(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvConfig + * + * \brief Set the advertising parameters using the given advertising type, and peer address. + * + * \param advHandle Advertising handle. + * \param advType Advertising type. + * \param peerAddrType Peer address type. + * \param pPeerAddr Peer address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvConfig(uint8_t advHandle, uint8_t advType, uint8_t peerAddrType, uint8_t *pPeerAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetData + * + * \brief Set the advertising or scan response data to the given data. + * + * \param advHandle Advertising handle. + * \param op Data operation. + * \param location Data location. + * \param len Length of the data. Maximum length is 236 bytes. + * \param pData Pointer to the data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetData(uint8_t advHandle, uint8_t op, uint8_t location, uint8_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn DmAdvStart + * + * \brief Start advertising using the given advertising set and duration. + * + * \param numSets Number of advertising sets to enable. + * \param advHandle Advertising handle array. + * \param duration Advertising duration (in milliseconds) array. + * \param maxEaEvents Maximum number of extended advertising events array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvStart(uint8_t numSets, uint8_t *pAdvHandles, uint16_t *pDuration, uint8_t *pMaxEaEvents); + +/*************************************************************************************************/ +/*! + * \fn DmAdvStop + * + * \brief Stop advertising for the given advertising set. If the number of sets is set to 0 + * then all advertising sets are disabled. + * + * \param numSets Number of advertising sets to disable. + * \param pAdvHandles Advertising handles array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvStop(uint8_t numSets, uint8_t *pAdvHandles); + +/*************************************************************************************************/ +/*! + * \fn DmAdvRemoveAdvSet + * + * \brief Remove an advertising set. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvRemoveAdvSet(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmAdvClearAdvSets + * + * \brief Clear advertising sets. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvClearAdvSets(void); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvConfig + * + * \brief Set the advertising parameters for periodic advertising. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvConfig(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvSetData + * + * \brief Set the advertising data to the given data for periodic advertising. + * + * \param advHandle Advertising handle. + * \param op Data operation. + * \param len Length of the data. Maximum length is 236 bytes. + * \param pData Pointer to the data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvSetData(uint8_t advHandle, uint8_t op, uint8_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! +* \fn DmPerAdvStart + * + * \brief Start periodic advertising for the advertising set specified by the advertising handle. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvStart(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvStop + * + * \brief Stop periodic advertising for the advertising set specified by the advertising handle. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvStop(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetInterval + * + * \brief Set the minimum and maximum advertising intervals. + * + * \param advHandle Advertising handle. + * \param intervalMin Minimum advertising interval. + * \param intervalMax Maximum advertising interval. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetInterval(uint8_t advHandle, uint16_t intervalMin, uint16_t intervalMax); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetChannelMap + * + * \brief Include or exclude certain channels from the advertising channel map. + * + * \param advHandle Advertising handle. + * \param channelMap Advertising channel map. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetChannelMap(uint8_t advHandle, uint8_t channelMap); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetAddrType + * + * \brief Set the local address type used while advertising. This function can be used to + * configure advertising to use a random address. + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetAdValue + * + * \brief Set the value of an advertising data element in the given advertising or + * scan response data. If the element already exists in the data then it is replaced + * with the new value. If the element does not exist in the data it is appended + * to it, space permitting. + * + * \param adType Advertising data element type. + * \param len Length of the value. Maximum length is 29 bytes. + * \param pValue Pointer to the value. + * \param pAdvDataLen Advertising or scan response data length. The new length is returned + * in this parameter. + * \param pAdvData Pointer to advertising or scan response data. + * \param advDataBufLen Length of the advertising or scan response data buffer maintained by + * Application. + * + * \return TRUE if the element was successfully added to the data, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvSetAdValue(uint8_t adType, uint8_t len, uint8_t *pValue, uint16_t *pAdvDataLen, + uint8_t *pAdvData, uint16_t advDataBufLen); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetName + * + * \brief Set the device name in the given advertising or scan response data. If the + * name can only fit in the data if it is shortened, the name is shortened + * and the AD type is changed to DM_ADV_TYPE_SHORT_NAME. + * + * \param len Length of the name. Maximum length is 29 bytes. + * \param pValue Pointer to the name in UTF-8 format. + * \param pAdvDataLen Advertising or scan response data length. The new length is returned + * in this parameter. + * \param pAdvData Pointer to advertising or scan response data. + * \param advDataBufLen Length of the advertising or scan response data buffer maintained by + * Application. + * + * \return TRUE if the element was successfully added to the data, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvSetName(uint8_t len, uint8_t *pValue, uint16_t *pAdvDataLen, uint8_t *pAdvData, + uint16_t advDataBufLen); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetRandAddr + * + * \brief Set the random device address for a given advertising set. + * + * \param advHandle Advertising handle. + * \param pAddr Random device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetRandAddr(uint8_t advHandle, const uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvUseLegacyPdu + * + * \brief Set whether or not to use legacy advertising PDUs with extended advertising. + * + * \param advHandle Advertising handle. + * \param useLegacyPdu Whether to use legacy advertising PDUs (default value is TRUE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvUseLegacyPdu(uint8_t advHandle, bool_t useLegacyPdu); + +/*************************************************************************************************/ +/*! + * \fn DmAdvOmitAdvAddr + * + * \brief Set whether or not to omit advertiser�s address from all PDUs (anonymous advertising). + * + * \param advHandle Advertising handle. + * \param omitAdvAddr Whether to omit advertiser�s address from all PDUs (default value is FALSE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvOmitAdvAddr(uint8_t advHandle, bool_t omitAdvAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvIncTxPwr + * + * \brief Set whether or not to include TxPower in extended header of advertising PDU. + * + * \param advHandle Advertising handle. + * \param incTxPwr Whether to include TxPower in extended header of advertising PDU (default + * value is FALSE). + * \param advTxPwr Advertising tx power (127 = no preference). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvIncTxPwr(uint8_t advHandle, bool_t incTxPwr, int8_t advTxPwr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetPhyParam + * + * \brief Set extended advertising PHY parameters. + * + * \param advHandle Advertising handle. + * \param priAdvPhy Primary advertising Phy. + * \param secAdvMaxSkip Maximum advertising events Controller can skip before sending AUX_ADV_IND + * on secondary advertising channel (0 = AUX_ADV_IND will be sent prior to + * next advertising event). + * \param secAdvPhy Secondary advertising Phy. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetPhyParam(uint8_t advHandle, uint8_t priAdvPhy, uint8_t secAdvMaxSkip, uint8_t secAdvPhy); + +/*************************************************************************************************/ +/*! + * \fn DmAdvScanReqNotifEnable + * + * \brief Set scan request notification enable. + * + * \param advHandle Advertising handle. + * \param scanReqNotifEna Scan request notification enable. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvScanReqNotifEnable(uint8_t advHandle, bool_t scanReqNotifEna); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetfragPref + * + * \brief Set fragment preference for advertising data. + * + * \param advHandle Advertising handle. + * \param fragPref Fragment preference. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetFragPref(uint8_t advHandle, uint8_t fragPref); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvSetInterval + * + * \brief Set the minimum and maximum advertising intervals for periodic advertising. + * + * \param advHandle Advertising handle. + * \param intervalMin Minimum advertising interval. + * \param intervalMax Maximum advertising interval. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvSetInterval(uint8_t advHandle, uint16_t intervalMin, uint16_t intervalMax); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvIncTxPwr + * + * \brief Set whether or not to include TxPower in extended header of advertising PDU for + * periodic advertising. + * + * \param advHandle Advertising handle. + * \param incTxPwr Whether to include TxPower in extended header of advertising PDU (default + * value is FALSE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvIncTxPwr(uint8_t advHandle, bool_t incTxPwr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivInit + * + * \brief Initialize private advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivStart + * + * \brief Start using a private resolvable address. + * + * \param changeInterval Interval between automatic address changes, in seconds. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivStart(uint16_t changeInterval); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivStop + * + * \brief Stop using a private resolvable address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivStop(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanInit + * + * \brief Initialize DM legacy scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtScanInit + * + * \brief Initialize DM extended scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtScanInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanModeLeg + * + * \brief Whether DM scanning is in legacy mode. + * + * \return TRUE if DM scanning is in legacy mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmScanModeLeg(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanModeExt + * + * \brief Whether DM scanning is in extended mode. + * + * \return TRUE if DM scanning is in extended mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmScanModeExt(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanStart + * + * \brief Start scanning on the given PHYs. + * + * \param scanPhys Scanner PHYs. + * \param mode Discoverability mode. + * \param pScanType Scan type array. + * \param filterDup Filter duplicates. Set to TRUE to filter duplicate responses received + * from the same device. Set to FALSE to receive all responses. + * \param duration The scan duration, in milliseconds. If set to zero or both duration and + * period set to non-zero, scanning will continue until DmScanStop() is called. + * \param period The scan period, in 1.28 sec units (only applicable to AE). If set to zero, + * periodic scanning is disabled. + * + * \return None. + */ + /*************************************************************************************************/ +void DmScanStart(uint8_t scanPhys, uint8_t mode, const uint8_t *pScanType, bool_t filterDup, + uint16_t duration, uint16_t period); + +/*************************************************************************************************/ +/*! + * \fn DmScanStop + * + * \brief Stop scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanStop(void); + +/*************************************************************************************************/ +/*! + * \fn DmSyncStart + * + * \brief Synchronize with periodic advertising from the given advertisier, and start receiving + * periodic advertising packets. + * + * \param filterPolicy Filter policy. + * \param advSid Advertising SID. + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param skip Number of periodic advertising packets that can be skipped after + * successful receive. + * \param syncTimeout Synchronization timeout. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncStart(uint8_t filterPolicy, uint8_t advSid, uint8_t advAddrType, const uint8_t *pAdvAddr, + uint16_t skip, uint16_t syncTimeout); + +/*************************************************************************************************/ +/*! + * \fn DmSyncStop + * + * \brief Stop reception of the periodic advertising identified by the given sync handle. + * + * \param syncHandle Sync handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncStop(uint16_t syncHandle); + +/*************************************************************************************************/ +/*! + * \fn DmSyncCancel + * + * \brief Cancel creation of a sync while it's pending. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncCancel(void); + +/*************************************************************************************************/ +/*! + * \fn DmAddDeviceToPerAdvList + * + * \brief Add device to periodic advertiser list. + * + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param advSid Advertising SID. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAddDeviceToPerAdvList(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); + +/*************************************************************************************************/ +/*! + * \fn DmRemoveDeviceFromPerAdvList + * + * \brief DM remove device from periodic advertiser list. + * + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param advSid Advertising SID. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoveDeviceFromPerAdvList(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); + +/*************************************************************************************************/ +/*! + * \fn DmClearPerAdvList + * + * \brief DM clear periodic advertiser list. + * + * \return None. + */ +/*************************************************************************************************/ +void DmClearPerAdvList(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanSetInterval + * + * \brief Set the scan interval and window for the specified PHYs. + * + * \param scanPhys Scanning PHYs. + * \param pScanInterval Scan interval array. + * \param pScanWindow Scan window array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanSetInterval(uint8_t scanPhys, uint16_t *pScanInterval, uint16_t *pScanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmScanSetAddrType + * + * \brief Set the local address type used while scanning. This function can be used to + * configure scanning to use a random address. + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmConnInit + * + * \brief Initialize DM connection manager. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnMasterInit + * + * \brief Initialize DM connection manager for operation as legacy master. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnMasterInit + * + * \brief Initialize DM connection manager for operation as extended master. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnSlaveInit + * + * \brief Initialize DM connection manager for operation as legacy slave. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnSlaveInit + * + * \brief Initialize DM connection manager for operation as extended slave. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnRegister + * + * \brief Register with the DM connection manager. + * + * \param clientId The client identifier. + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnRegister(uint8_t clientId, dmCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn DmConnOpen + * + * \brief Open a connection to a peer device with the given address. + * + * \param clientId The client identifier. + * \param initPhys Initiator PHYs. + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return Connection identifier. + */ +/*************************************************************************************************/ +dmConnId_t DmConnOpen(uint8_t clientId, uint8_t initPhys, uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmConnClose + * + * \brief Close the connection with the give connection identifier. + * + * \param clientId The client identifier. + * \param connId Connection identifier. + * \param reason Reason connection is being closed. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnClose(uint8_t clientId, dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmConnAccept + * + * \brief Accept a connection from the given peer device by initiating directed advertising. + * + * \param clientId The client identifier. + * \param advHandle Advertising handle. + * \param advType Advertising type. + * \param duration Advertising duration (in ms). + * \param maxEaEvents Maximum number of extended advertising events. + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return Connection identifier. + */ +/*************************************************************************************************/ +dmConnId_t DmConnAccept(uint8_t clientId, uint8_t advHandle, uint8_t advType, uint16_t duration, + uint8_t maxEaEvents, uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmConnUpdate + * + * \brief Update the connection parameters of an open connection + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnUpdate(dmConnId_t connId, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetScanInterval + * + * \brief Set the scan interval and window for connections to be created with DmConnOpen(). + * + * \param scanInterval The scan interval. + * \param scanWindow The scan window. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetScanInterval(uint16_t scanInterval, uint16_t scanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnSetScanInterval + * + * \brief Set the scan interval and window for extended connections to be created with + * DmConnOpen(). + * + * \param initPhy Initiator PHYs. + * \param pScanInterval Scan interval array. + * \param pScanWindow Scan window array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSetScanInterval(uint8_t initPhys, uint16_t *pScanInterval, uint16_t *pScanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetConnSpec + * + * \brief Set the connection spec parameters for connections to be created with DmConnOpen(). + * + * \param pConnSpec Connection spec parameters. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetConnSpec(hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetExtConnSpec + * + * \brief Set the extended connection spec parameters for extended connections to be created + * with DmConnOpen(). + * + * \param initPhys The initiator PHYs. + * \param pConnSpec Connection spec parameters array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSetConnSpec(uint8_t initPhys, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetAddrType + * + * \brief Set the local address type used for connections created with DmConnOpen(). + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetIdle + * + * \brief Configure a bit in the connection idle state mask as busy or idle. + * + * \param connId Connection identifier. + * \param idleMask Bit in the idle state mask to configure. + * \param idle DM_CONN_BUSY or DM_CONN_IDLE. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetIdle(dmConnId_t connId, uint16_t idleMask, uint8_t idle); + +/*************************************************************************************************/ +/*! + * \fn DmConnCheckIdle + * + * \brief Check if a connection is idle. + * + * \param connId Connection identifier. + * + * \return Zero if connection is idle, nonzero if busy. + */ +/*************************************************************************************************/ +uint16_t DmConnCheckIdle(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnReadRssi + * + * \brief Read RSSI of a given connection. + * + * \param connId Connection identifier. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnReadRssi(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmRemoteConnParamReqReply + * + * \brief Reply to the HCI remote connection parameter request event. This command is used to + * indicate that the Host has accepted the remote device�s request to change connection + * parameters. + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoteConnParamReqReply(dmConnId_t connId, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmRemoteConnParamReqNegReply + * + * \brief Negative reply to the HCI remote connection parameter request event. This command + * is used to indicate that the Host has rejected the remote device�s request to change + * connection parameters. + * + * \param connId Connection identifier. + * \param reason Reason for rejection. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoteConnParamReqNegReply(dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetDataLen + * + * \brief Set data length for a given connection. + * + * \param connId Connection identifier. + * \param txOctets Maximum number of payload octets for a Data PDU. + * \param txTime Maximum number of microseconds for a Data PDU. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetDataLen(dmConnId_t connId, uint16_t txOctets, uint16_t txTime); + +/*************************************************************************************************/ +/*! + * \fn DmWriteAuthPayloadTimeout + * + * \brief Set authenticated payload timeout for a given connection. + * + * \param connId Connection identifier. + * \param timeout Timeout period in units of 10ms + * + * \return None. + */ +/*************************************************************************************************/ +void DmWriteAuthPayloadTimeout(dmConnId_t connId, uint16_t timeout); + +/*************************************************************************************************/ +/*! + * \fn DmReadPhy + * + * \brief Read the current transmitter PHY and receiver PHY for a given connection. + * + * \param connId Connection identifier. + * + * \return None. + */ +/*************************************************************************************************/ +void DmReadPhy(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSetDefaultPhy + * + * \brief Set the preferred values for the transmitter PHY and receiver PHY for all subsequent + * connections. + * + * \param allPhys All PHYs preferences. + * \param txPhys Preferred transmitter PHYs. + * \param rxPhys Preferred receiver PHYs. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSetDefaultPhy(uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys); + +/*************************************************************************************************/ +/*! + * \fn DmSetPhy + * + * \brief Set the PHY preferences for a given connection. + * + * \param connId Connection identifier. + * \param allPhys All PHYs preferences. + * \param txPhys Preferred transmitter PHYs. + * \param rxPhys Preferred receiver PHYs. + * \param phyOptions PHY options. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSetPhy(dmConnId_t connId, uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys, uint16_t phyOptions); + +/*************************************************************************************************/ +/*! + * \fn DmDevReset + * + * \brief Reset the device. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevReset(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevRole + * + * \brief Return the device role indicating master or slave. + * + * \return Device role. + */ +/*************************************************************************************************/ +uint8_t DmDevRole(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetRandAddr + * + * \brief Set the random address to be used by the local device. + * + * \param pAddr Random address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevSetRandAddr(uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListAdd + * + * \brief Add a peer device to the white list. Note that this function cannot be called + * while advertising, scanning, or connecting with white list filtering active. + * + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListAdd(uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListRemove + * + * \brief Remove a peer device from the white list. Note that this function cannot be called + * while advertising, scanning, or connecting with white list filtering active. + * + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListRemove(uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListClear + * + * \brief Clear the white list. Note that this function cannot be called while + * advertising, scanning, or connecting with white list filtering active. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListClear(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetFilterPolicy + * + * \brief Set the Advertising, Scanning or Initiator filter policy. + * + * \param mode Policy mode. + * \param policy Filter policy. + * + * \return TRUE if the filter policy was successfully set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmDevSetFilterPolicy(uint8_t mode, uint8_t policy); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetExtFilterPolicy + * + * \brief Set the Advertising filter policy for the given advertising, Scanning or Initiator + * filter policy. + * + * \param advHandle Advertising handle. + * \param mode Policy mode. + * \param policy Filter policy. + * + * \return TRUE if the filter policy was successfully set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmDevSetExtFilterPolicy(uint8_t advHandle, uint8_t mode, uint8_t policy); + +/*************************************************************************************************/ +/*! + * \fn DmDevVsInit + * + * \brief Vendor-specific controller initialization function. + * + * \param param Vendor-specific parameter. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevVsInit(uint8_t param); + +/*************************************************************************************************/ +/*! + * \fn DmSecInit + * + * \brief Initialize DM security. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecLescInit + * + * \brief Initialize DM LE Secure Connections security. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecLescInit(void); + +/*************************************************************************************************/ +/*! +* \fn DmPhyInit +* +* \brief Initialize DM PHY. +* +* \return None. +*/ +/*************************************************************************************************/ +void DmPhyInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecPairReq + * + * \brief This function is called by a master device to initiate pairing. + * + * \param connId DM connection ID. + * \param oob Out-of-band pairing data present or not present. + * \param auth Authentication and bonding flags. + * \param iKeyDist Initiator key distribution flags. + * \param rKeyDist Responder key distribution flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecPairReq(dmConnId_t connId, bool_t oob, uint8_t auth, uint8_t iKeyDist, uint8_t rKeyDist); + +/*************************************************************************************************/ +/*! + * \fn DmSecPairRsp + * + * \brief This function is called by a slave device to proceed with pairing after a + * DM_SEC_PAIR_IND event is received. + * + * \param connId DM connection ID. + * \param oob Out-of-band pairing data present or not present. + * \param auth Authentication and bonding flags. + * \param iKeyDist Initiator key distribution flags. + * \param rKeyDist Responder key distribution flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecPairRsp(dmConnId_t connId, bool_t oob, uint8_t auth, uint8_t iKeyDist, uint8_t rKeyDist); + +/*************************************************************************************************/ +/*! + * \fn DmSecCancelReq + * + * \brief This function is called to cancel the pairing process. + * + * \param connId DM connection ID. + * \param reason Failure reason. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecCancelReq(dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmSecAuthRsp + * + * \brief This function is called in response to a DM_SEC_AUTH_REQ_IND event to provide + * PIN or OOB data during pairing. + * + * \param connId DM connection ID. + * \param authDataLen Length of PIN or OOB data. + * \param pAuthData pointer to PIN or OOB data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecAuthRsp(dmConnId_t connId, uint8_t authDataLen, uint8_t *pAuthData); + +/*************************************************************************************************/ +/*! + * \fn DmSecSlaveReq + * + * \brief This function is called by a slave device to request that the master initiates + * pairing or link encryption. + * + * \param connId DM connection ID. + * \param auth Authentication flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSlaveReq(dmConnId_t connId, uint8_t auth); + +/*************************************************************************************************/ +/*! + * \fn DmSecEncryptReq + * + * \brief This function is called by a master device to initiate link encryption. + * + * \param connId DM connection ID. + * \param secLevel Security level of pairing when LTK was exchanged. + * \param pLtk Pointer to LTK parameter structure. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecEncryptReq(dmConnId_t connId, uint8_t secLevel, dmSecLtk_t *pLtk); + +/*************************************************************************************************/ +/*! + * \fn DmSecLtkRsp + * + * \brief This function is called by a slave in response to a DM_SEC_LTK_REQ_IND event + * to provide the long term key used for encryption. + * + * \param connId DM connection ID. + * \param keyFound TRUE if key found. + * \param secLevel Security level of pairing when key was exchanged. + * \param pKey Pointer to the key, if found. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecLtkRsp(dmConnId_t connId, bool_t keyFound, uint8_t secLevel, uint8_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetLocalCsrk + * + * \brief This function sets the local CSRK used by the device. + * + * \param pCsrk Pointer to CSRK. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalCsrk(uint8_t *pCsrk); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetLocalIrk + * + * \brief This function sets the local IRK used by the device. + * + * \param pCsrk Pointer to IRK. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalIrk(uint8_t *pIrk); + +/*************************************************************************************************/ +/*! + * \fn DmPrivInit + * + * \brief Initialize DM privacy module. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmPrivResolveAddr + * + * \brief Resolve a private resolvable address. When complete the client's callback function + * is called with a DM_PRIV_RESOLVED_ADDR_IND event. The client must wait to receive + * this event before executing this function again. + * + * \param pAddr Peer device address. + * \param pIrk The peer's identity resolving key. + * \param param Client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivResolveAddr(uint8_t *pAddr, uint8_t *pIrk, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivAddDevToResList + * + * \brief Add device to resolving list. When complete the client's callback function + * is called with a DM_PRIV_ADD_DEV_TO_RES_LIST_IND event. The client must wait + * to receive this event before executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * Note: If the local or peer IRK associated with the peer Identity Address is all + * zeros then the LL will use or accept the local or peer Identity Address. + * + * Note: 'enableLlPriv' should be set to TRUE when the last device is being added + * to resolving list to enable address resolution in LL. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param pPeerIrk The peer's identity resolving key. + * \param pLocalIrk The local identity resolving key. + * \param enableLlPriv Set to TRUE to enable address resolution in LL. + * \param param client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivAddDevToResList(uint8_t addrType, const uint8_t *pIdentityAddr, uint8_t *pPeerIrk, + uint8_t *pLocalIrk, bool_t enableLlPriv, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivRemDevFromResList + * + * \brief Remove device from resolving list. When complete the client's callback function + * is called with a DM_PRIV_REM_DEV_FROM_RES_LIST_IND event. The client must wait to + * receive this event before executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param param client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivRemDevFromResList(uint8_t addrType, const uint8_t *pIdentityAddr, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivClearResList + * + * \brief Clear resolving list. When complete the client's callback function is called with a + * DM_PRIV_CLEAR_RES_LIST_IND event. The client must wait to receive this event before + * executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * Note: Address resolution in LL will be disabled when resolving list's cleared + * successfully. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivClearResList(void); + +/*************************************************************************************************/ +/*! + * \fn DmPrivReadPeerResolvableAddr + * + * \brief HCI read peer resolvable address command. When complete the client's callback + * function is called with a DM_PRIV_READ_PEER_RES_ADDR_IND event. The client must + * wait to receive this event before executing this function again. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivReadPeerResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); + +/*************************************************************************************************/ +/*! + * \fn DmPrivReadLocalResolvableAddr + * + * \brief Read local resolvable address command. When complete the client's callback + * function is called with a DM_PRIV_READ_LOCAL_RES_ADDR_IND event. The client must + * wait to receive this event before executing this function again. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivReadLocalResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetAddrResEnable + * + * \brief Enable or disable address resolution in LL. When complete the client's callback + * function is called with a DM_PRIV_SET_ADDR_RES_ENABLE_IND event. The client must + * wait to receive this event before executing this function again. + * + * Note: This command can be used at any time except when: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * \param enable Set to TRUE to enable address resolution or FALSE to disable it. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetAddrResEnable(bool_t enable); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetResolvablePrivateAddrTimeout + * + * \brief Set resolvable private address timeout command. + * + * \param rpaTimeout Timeout measured in seconds. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetResolvablePrivateAddrTimeout(uint16_t rpaTimeout); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetPrivacyMode + * + * \brief Set privacy mode for a given entry in the resolving list. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param mode Privacy mode (by default, network privacy mode is used). + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetPrivacyMode(uint8_t addrType, const uint8_t *pIdentityAddr, uint8_t mode); + +/*************************************************************************************************/ +/*! + * \fn DmLlPrivEnabled + * + * \brief Whether LL Privacy is enabled. + * + * \return TRUE if LL Privacy is enabled. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmLlPrivEnabled(void); + +/*************************************************************************************************/ +/*! + * \fn DmLlAddrType + * + * \brief Map an address type to a type used by LL. + * + * \param addrType Address type used by Host. + * + * \return Address type used by LL. + */ +/*************************************************************************************************/ +uint8_t DmLlAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmHostAddrType + * + * \brief Map an address type to a type used by Host. + * + * \param addrType Address type used by LL. + * + * \return Address type used by Host. + */ +/*************************************************************************************************/ +uint8_t DmHostAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmSizeOfEvt + * + * \brief Return size of a DM callback event. + * + * \param pDmEvt DM callback event. + * + * \return Size of DM callback event. + */ +/*************************************************************************************************/ +uint16_t DmSizeOfEvt(dmEvt_t *pDmEvt); + +/*************************************************************************************************/ +/*! + * \fn DmL2cConnUpdateCnf + * + * \brief For internal use only. L2C calls this function to send the result of an L2CAP + * connection update response to DM. + * + * \param handle Connection handle. + * \param reason Connection update response reason code. + * \return None. + */ +/*************************************************************************************************/ +void DmL2cConnUpdateCnf(uint16_t handle, uint16_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmL2cConnUpdateInd + * + * \brief For internal use only. L2C calls this function when it receives a connection update + * request from a peer device. + * + * \param identifier Identifier value. + * \param handle Connection handle. + * \param pConnSpec Connection spec parameters. + * \return None. + */ +/*************************************************************************************************/ +void DmL2cConnUpdateInd(uint8_t identifier, uint16_t handle, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnIdByHandle + * + * \brief For internal use only. Find the connection ID with matching handle. + * + * \param handle Handle to find. + * + * \return Connection ID or DM_CONN_ID_NONE if error. + */ +/*************************************************************************************************/ +dmConnId_t DmConnIdByHandle(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \fn DmConnInUse + * + * \brief For internal use only. Return TRUE if the connection is in use. + * + * \param connId Connection ID. + * + * \return TRUE if the connection is in use, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmConnInUse(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnPeerAddrType + * + * \brief For internal use only. Return the peer address type. + * + * \param connId Connection ID. + * + * \return Peer address type. + */ +/*************************************************************************************************/ +uint8_t DmConnPeerAddrType(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnPeerAddr + * + * \brief For internal use only. Return the peer device address. + * + * \param connId Connection ID. + * + * \return Pointer to peer device address. + */ +/*************************************************************************************************/ +uint8_t *DmConnPeerAddr(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnLocalAddrType + * + * \brief For internal use only. Return the local address type. + * + * \param connId Connection ID. + * + * \return Local address type. + */ +/*************************************************************************************************/ +uint8_t DmConnLocalAddrType(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnLocalAddr + * + * \brief For internal use only. Return the local address. + * + * \param connId Connection ID. + * + * \return Pointer to local address. + */ +/*************************************************************************************************/ +uint8_t *DmConnLocalAddr(dmConnId_t connId); + +/*************************************************************************************************/ +/*! +* \fn DmConnPeerRpa +* +* \brief For internal use only. Return the peer resolvable private address (RPA). +* +* \param connId Connection ID. +* +* \return Pointer to peer RPA. +*/ +/*************************************************************************************************/ +uint8_t *DmConnPeerRpa(dmConnId_t connId); + +/*************************************************************************************************/ +/*! +* \fn DmConnLocalRpa +* +* \brief For internal use only. Return the local resolvable private address (RPA). +* +* \param connId Connection ID. +* +* \return Pointer to local RPA. +*/ +/*************************************************************************************************/ +uint8_t *DmConnLocalRpa(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnSecLevel + * + * \brief For internal use only. Return the security level of the connection. + * + * \param connId Connection ID. + * + * \return Security level of the connection. + */ +/*************************************************************************************************/ +uint8_t DmConnSecLevel(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSmpEncryptReq + * + * \brief For internal use only. This function is called by SMP to request encryption. + * + * \param connId DM connection ID. + * \param secLevel Security level of pairing when key was exchanged. + * \param pKey Pointer to key. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSmpEncryptReq(dmConnId_t connId, uint8_t secLevel, uint8_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSmpCbackExec + * + * \brief For internal use only. Execute DM callback from SMP procedures. + * + * \param pDmEvt Pointer to callback event data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSmpCbackExec(dmEvt_t *pDmEvt); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetLocalCsrk + * + * \brief For internal use only. This function gets the local CSRK used by the device. + * + * \return Pointer to CSRK. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalCsrk(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetLocalIrk + * + * \brief For internal use only. This function gets the local IRK used by the device. + * + * \return Pointer to IRK. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalIrk(void); + +/*************************************************************************************************/ +/*! + * \fn DmReadRemoteFeatures + * + * \brief For internal use only. Read the features of the remote device. + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmReadRemoteFeatures(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSecGenerateEccKeyReq + * + * \brief This function generates an ECC key for use with LESC security. + * + * \return none. + */ +/*************************************************************************************************/ +void DmSecGenerateEccKeyReq(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetEccKey + * + * \brief This function sets the ECC key for use with LESC security. + * + * \param pKey Pointer to key. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetEccKey(secEccKey_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetEccKey + * + * \brief This function gets the local ECC key for use with LESC security. + * + * \return Pointer to local ECC key. + */ +/*************************************************************************************************/ +secEccKey_t *DmSecGetEccKey(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetDebugEccKey + * + * \brief This function sets the ECC key for use with LESC security to standard debug keys values. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetDebugEccKey(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetOob + * + * \brief This function configures the DM to use OOB pairing for the given connection. + * The pRand and pConfirm contain the Random and Confirm values exchanged via + * out of band methods. + * + * \param connId ID of the connection + * \param pConfig Pointer to OOB configuration. + * + * \return Pointer to IRK. + */ +/*************************************************************************************************/ +void DmSecSetOob(dmConnId_t connId, dmSecLescOobCfg_t *pConfig); + +/*************************************************************************************************/ +/*! + * \fn DmSecCalcOobReq + * + * \brief This function calculates the local random and confirm values used in LESC OOB pairing. + * The operation's result is posted as a DM_SEC_CALC_OOB_IND event to the application's DM + * callback handler. The local rand and confirm values are exchanged with the peer via + * out-of-band (OOB) methods and passed into the DmSecSetOob after DM_CONN_OPEN_IND. + * + * \param pRand Random value used in calculation. + * \param pPubKeyX X component of the local public key. + * + * \return none. + */ +/*************************************************************************************************/ +void DmSecCalcOobReq(uint8_t *pRand, uint8_t *pPubKeyX); + +/*************************************************************************************************/ +/*! + * \fn DmSecCompareRsp + * + * \brief This function is called by the application in response to a DM_SEC_COMPARE_IND event. + * The valid parameter indicates if the compare value of the DM_SEC_COMPARE_IND was valid. + * + * \param connId ID of the connection + * \param valid TRUE if compare value was valid + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecCompareRsp(dmConnId_t connId, bool_t valid); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetCompareValue + * + * \brief This function returns the 6-digit compare value for the specified 128-bit confirm value. + * + * \param pConfirm Pointer to 128-bit comfirm value. + * + * \return Six-digit compare value. + */ +/*************************************************************************************************/ +uint32_t DmSecGetCompareValue(uint8_t *pConfirm); + +#ifdef __cplusplus +}; +#endif + +#endif /* DM_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h new file mode 100644 index 00000000000..650ecb06461 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file dm_handler.h + * + * \brief Interface to DM event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef DM_HANDLER_H +#define DM_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn DmHandlerInit + * + * \brief DM handler init function called during system initialization. + * + * \param handlerID WSF handler ID for DM. + * + * \return None. + */ +/*************************************************************************************************/ +void DmHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn DmHandler + * + * \brief WSF event handler for DM. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void DmHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* DM_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h new file mode 100644 index 00000000000..30ea3c099bd --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h @@ -0,0 +1,837 @@ +/*************************************************************************************************/ +/*! + * \file hci_api.h + * + * \brief HCI subsystem API. + * + * $Date: 2017-02-09 11:58:21 -0600 (Thu, 09 Feb 2017) $ + * $Revision: 11135 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_API_H +#define HCI_API_H + +#include "wsf_types.h" +#include "hci_defs.h" +#include "wsf_os.h" +#include "bda.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Internal event values for the HCI event and sec callbacks */ +#define HCI_RESET_SEQ_CMPL_CBACK_EVT 0 /*! Reset sequence complete */ +#define HCI_LE_CONN_CMPL_CBACK_EVT 1 /*! LE connection complete */ +#define HCI_LE_ENHANCED_CONN_CMPL_CBACK_EVT 2 /*! LE enhanced connection complete */ +#define HCI_DISCONNECT_CMPL_CBACK_EVT 3 /*! LE disconnect complete */ +#define HCI_LE_CONN_UPDATE_CMPL_CBACK_EVT 4 /*! LE connection update complete */ +#define HCI_LE_CREATE_CONN_CANCEL_CMD_CMPL_CBACK_EVT 5 /*! LE create connection cancel command complete */ +#define HCI_LE_ADV_REPORT_CBACK_EVT 6 /*! LE advertising report */ +#define HCI_READ_RSSI_CMD_CMPL_CBACK_EVT 7 /*! Read RSSI command complete */ +#define HCI_LE_READ_CHAN_MAP_CMD_CMPL_CBACK_EVT 8 /*! LE Read channel map command complete */ +#define HCI_READ_TX_PWR_LVL_CMD_CMPL_CBACK_EVT 9 /*! Read transmit power level command complete */ +#define HCI_READ_REMOTE_VER_INFO_CMPL_CBACK_EVT 10 /*! Read remote version information complete */ +#define HCI_LE_READ_REMOTE_FEAT_CMPL_CBACK_EVT 11 /*! LE read remote features complete */ +#define HCI_LE_LTK_REQ_REPL_CMD_CMPL_CBACK_EVT 12 /*! LE LTK request reply command complete */ +#define HCI_LE_LTK_REQ_NEG_REPL_CMD_CMPL_CBACK_EVT 13 /*! LE LTK request negative reply command complete */ +#define HCI_ENC_KEY_REFRESH_CMPL_CBACK_EVT 14 /*! Encryption key refresh complete */ +#define HCI_ENC_CHANGE_CBACK_EVT 15 /*! Encryption change */ +#define HCI_LE_LTK_REQ_CBACK_EVT 16 /*! LE LTK request */ +#define HCI_VENDOR_SPEC_CMD_STATUS_CBACK_EVT 17 /*! Vendor specific command status */ +#define HCI_VENDOR_SPEC_CMD_CMPL_CBACK_EVT 18 /*! Vendor specific command complete */ +#define HCI_VENDOR_SPEC_CBACK_EVT 19 /*! Vendor specific */ +#define HCI_HW_ERROR_CBACK_EVT 20 /*! Hardware error */ +#define HCI_LE_ADD_DEV_TO_RES_LIST_CMD_CMPL_CBACK_EVT 21 /*! LE add device to resolving list command complete */ +#define HCI_LE_REM_DEV_FROM_RES_LIST_CMD_CMPL_CBACK_EVT 22 /*! LE remove device from resolving command complete */ +#define HCI_LE_CLEAR_RES_LIST_CMD_CMPL_CBACK_EVT 23 /*! LE clear resolving list command complete */ +#define HCI_LE_READ_PEER_RES_ADDR_CMD_CMPL_CBACK_EVT 24 /*! LE read peer resolving address command complete */ +#define HCI_LE_READ_LOCAL_RES_ADDR_CMD_CMPL_CBACK_EVT 25 /*! LE read local resolving address command complete */ +#define HCI_LE_SET_ADDR_RES_ENABLE_CMD_CMPL_CBACK_EVT 26 /*! LE set address resolving enable command complete */ +#define HCI_LE_ENCRYPT_CMD_CMPL_CBACK_EVT 27 /*! LE encrypt command complete */ +#define HCI_LE_RAND_CMD_CMPL_CBACK_EVT 28 /*! LE rand command complete */ +#define HCI_LE_REM_CONN_PARAM_REP_CMD_CMPL_CBACK_EVT 29 /*! LE remote connection parameter request reply complete */ +#define HCI_LE_REM_CONN_PARAM_NEG_REP_CMD_CMPL_CBACK_EVT 30 /*! LE remote connection parameter request negative reply complete */ +#define HCI_LE_READ_DEF_DATA_LEN_CMD_CMPL_CBACK_EVT 31 /*! LE read suggested default data length command complete */ +#define HCI_LE_WRITE_DEF_DATA_LEN_CMD_CMPL_CBACK_EVT 32 /*! LE write suggested default data length command complete */ +#define HCI_LE_SET_DATA_LEN_CMD_CMPL_CBACK_EVT 33 /*! LE set data length command complete */ +#define HCI_LE_READ_MAX_DATA_LEN_CMD_CMPL_CBACK_EVT 34 /*! LE read maximum data length command complete */ +#define HCI_LE_REM_CONN_PARAM_REQ_CBACK_EVT 35 /*! LE remote connection parameter request */ +#define HCI_LE_DATA_LEN_CHANGE_CBACK_EVT 36 /*! LE data length change */ +#define HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_CBACK_EVT 37 /*! LE read local P-256 public key */ +#define HCI_LE_GENERATE_DHKEY_CMPL_CBACK_EVT 38 /*! LE generate DHKey complete */ +#define HCI_WRITE_AUTH_PAYLOAD_TO_CMD_CMPL_CBACK_EVT 39 /*! Write authenticated payload timeout command complete */ +#define HCI_AUTH_PAYLOAD_TO_EXPIRED_CBACK_EVT 40 /*! Authenticated payload timeout expired event */ +#define HCI_LE_READ_PHY_CMD_CMPL_CBACK_EVT 41 /*! LE read phy command complete */ +#define HCI_LE_SET_DEF_PHY_CMD_CMPL_CBACK_EVT 42 /*! LE set default phy command complete */ +#define HCI_LE_PHY_UPDATE_CMPL_CBACK_EVT 43 /*! LE phy update complete */ +#define HCI_LE_EXT_ADV_REPORT_CBACK_EVT 44 /*! LE extended advertising report */ +#define HCI_LE_SCAN_TIMEOUT_CBACK_EVT 45 /*! LE scan timeout event */ +#define HCI_LE_ADV_SET_TERM_CBACK_EVT 46 /*! LE advertising set terminated event */ +#define HCI_LE_SCAN_REQ_RCVD_CBACK_EVT 47 /*! LE scan request received event */ +#define HCI_LE_PER_ADV_SYNC_EST_CBACK_EVT 48 /*! LE periodic advertising sync established event */ +#define HCI_LE_PER_ADV_REPORT_CBACK_EVT 49 /*! LE periodic advertising report event */ +#define HCI_LE_PER_ADV_SYNC_LOST_CBACK_EVT 50 /*! LE periodic advertising synch lost event */ +#define HCI_LE_CH_SEL_ALGO_CBACK_EVT 51 /*! LE channel selection algorithm event */ +#define HCI_LE_SCAN_ENABLE_CMPL_CBACK_EVT 52 /*! LE scan enable complete event */ +#define HCI_LE_ADV_ENABLE_CMPL_CBACK_EVT 53 /*! LE advertise enable complete event */ +#define HCI_LE_EXT_SCAN_ENABLE_CMPL_CBACK_EVT 54 /*! LE extended scan enable complete event */ +#define HCI_LE_EXT_ADV_ENABLE_CMPL_CBACK_EVT 55 /*! LE extended advertise enable complete event */ +#define HCI_LE_PER_ADV_ENABLE_CMPL_CBACK_EVT 56 /*! LE periodic advertise enable complete event */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection specification type */ +typedef struct +{ + uint16_t connIntervalMin; /*!< Minimum connection interval. */ + uint16_t connIntervalMax; /*!< Maximum connection interval. */ + uint16_t connLatency; /*!< Connection latency. */ + uint16_t supTimeout; /*!< Supervision timeout. */ + uint16_t minCeLen; /*!< Minimum CE length. */ + uint16_t maxCeLen; /*!< Maximum CE length. */ +} hciConnSpec_t; + +/*! Initiating parameters */ +typedef struct +{ + uint8_t filterPolicy; /*!< Scan filter policy. */ + uint8_t ownAddrType; /*!< Address type used by this device. */ + uint8_t peerAddrType; /*!< Address type used for peer device. */ + const uint8_t *pPeerAddr; /*!< Address of peer device. */ + uint8_t initPhys; /*!< Initiating PHYs. */ +} hciExtInitParam_t; + +/*! Initiating scan parameters */ +typedef struct +{ + uint16_t scanInterval; /*! Scan interval. */ + uint16_t scanWindow; /*! Scan window. */ +} hciExtInitScanParam_t; + +/*! Extended advertising parameters */ +typedef struct +{ + uint16_t advEventProp; /*! Advertising Event Properties. */ + uint32_t priAdvInterMin; /*! Primary Advertising Interval Minimum. */ + uint32_t priAdvInterMax; /*! Primary Advertising Interval Maximum. */ + uint8_t priAdvChanMap; /*! Primary Advertising Channel Map. */ + uint8_t ownAddrType; /*! Own Address Type. */ + uint8_t peerAddrType; /*! Peer Address Type. */ + uint8_t *pPeerAddr; /*! Peer Address. */ + uint8_t advFiltPolicy; /*! Advertising Filter Policy. */ + int8_t advTxPwr; /*! Advertising Tx Power. */ + uint8_t priAdvPhy; /*! Primary Advertising PHY. */ + uint8_t secAdvMaxSkip; /*! Secondary Advertising Maximum Skip. */ + uint8_t secAdvPhy; /*! Secondary Advertising PHY. */ + uint8_t advSetId; /*! Advertising set ID. */ + uint8_t scanReqNotifEna; /*! Scan Request Notification Enable. */ +} hciExtAdvParam_t; + +/*! Extended advertising enable parameters */ +typedef struct +{ + uint8_t advHandle; /*! Advertising handle. */ + uint16_t duration; /*! Advertising duration in 10 ms units. */ + uint8_t maxEaEvents; /*! Maximum number of extended advertising events. */ +} hciExtAdvEnableParam_t; + +/*! Extended scanning parameters */ +typedef struct +{ + uint16_t scanInterval; /*! Scan interval. */ + uint16_t scanWindow; /*! Scan window. */ + uint8_t scanType; /*! Scan type. */ +} hciExtScanParam_t; + +/*! LE connection complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t role; + uint8_t addrType; + bdAddr_t peerAddr; + uint16_t connInterval; + uint16_t connLatency; + uint16_t supTimeout; + uint8_t clockAccuracy; + + /* enhanced fields */ + bdAddr_t localRpa; + bdAddr_t peerRpa; +} hciLeConnCmplEvt_t; + +/*! Disconnect complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t reason; +} hciDisconnectCmplEvt_t; + +/*! LE connection update complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint16_t connInterval; + uint16_t connLatency; + uint16_t supTimeout; +} hciLeConnUpdateCmplEvt_t; + +/*! LE create connection cancel command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeCreateConnCancelCmdCmplEvt_t; + +/*! LE advertising report event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t *pData; + uint8_t len; + int8_t rssi; + uint8_t eventType; + uint8_t addrType; + bdAddr_t addr; + + /* direct fields */ + uint8_t directAddrType; + bdAddr_t directAddr; +} hciLeAdvReportEvt_t; + +/*! LE extended advertising report */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t eventType; /*!< Event type. */ + uint8_t addrType; /*!< Address type. */ + bdAddr_t addr; /*!< Address. */ + uint8_t priPhy; /*!< Primary PHY. */ + uint8_t secPhy; /*!< Secondary PHY. */ + uint8_t advSid; /*!< Advertising SID. */ + int8_t txPower; /*!< Tx Power. */ + int8_t rssi; /*!< RSSI. */ + int16_t perAdvInter; /*!< Periodic advertising interval. */ + uint8_t directAddrType; /*!< Directed address type. */ + bdAddr_t directAddr; /*!< Directed address. */ + uint8_t len; /*!< Data buffer length. */ + uint8_t *pData; /*!< Data buffer. */ +} hciLeExtAdvReportEvt_t; + +/*! LE scan timeout */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ +} hciLeScanTimeoutEvt_t; + +/*! LE advertising set terminated */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint8_t advHandle; /*!< Advertising handle. */ + uint16_t handle; /*!< Connection handle. */ + uint8_t numComplEvts; /*!< Number of completed extended advertising events. */ +} hciLeAdvSetTermEvt_t; + +/*! LE scan request received */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t advHandle; /*!< Advertising handle. */ + uint8_t scanAddrType; /*!< Scanner address type. */ + bdAddr_t scanAddr; /*!< Scanner address. */ +} hciLeScanReqRcvdEvt_t; + +/*! LE periodic advertising sync established */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint16_t syncHandle; /*!< Sync handle. */ + uint8_t advSid; /*!< Advertising SID. */ + uint8_t advAddrType; /*!< Advertiser address type. */ + bdAddr_t advAddr; /*!< Advertiser address. */ + uint8_t advPhy; /*!< Advertiser PHY. */ + uint16_t perAdvInterval; /*!< Periodic advertising interval. */ + uint8_t clockAccuracy; /*!< Advertiser clock accuracy. */ +} hciLePerAdvSyncEstEvt_t; + +/*! LE periodic advertising report */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t syncHandle; /*!< Sync handle. */ + uint8_t txPower; /*!< Tx power. */ + uint8_t rssi; /*!< RSSI. */ + uint8_t unused; /*!< Intended to be used in a future feature. */ + uint8_t status; /*!< Data status. */ + uint8_t len; /*!< Data buffer length. */ + uint8_t *pData; /*!< Data buffer. */ +} hciLePerAdvReportEvt_t; + +/*! LE periodic advertising synch lost */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t syncHandle; /*!< Sync handle. */ +} hciLePerAdvSyncLostEvt_t; + +/*! LE channel selection algorithm */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t handle; /*!< Connection handle. */ + uint8_t chSelAlgo; /*!< Channel selection algorithm */ +} hciLeChSelAlgoEvt_t; + +/*! Read RSSI command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + int8_t rssi; +} hciReadRssiCmdCmplEvt_t; + +/*! LE Read channel map command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t chanMap[HCI_CHAN_MAP_LEN]; +} hciReadChanMapCmdCmplEvt_t; + +/*! Read transmit power level command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t handle; + int8_t pwrLvl; +} hciReadTxPwrLvlCmdCmplEvt_t; + +/*! Read remote version information complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t version; + uint16_t mfrName; + uint16_t subversion; +} hciReadRemoteVerInfoCmplEvt_t; + +/*! LE read remote features complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t features[HCI_FEAT_LEN]; +} hciLeReadRemoteFeatCmplEvt_t; + +/*! LE LTK request reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeLtkReqReplCmdCmplEvt_t; + +/*! LE LTK request negative reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeLtkReqNegReplCmdCmplEvt_t; + +/*! Encryption key refresh complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciEncKeyRefreshCmpl_t; + +/*! Encryption change event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t enabled; +} hciEncChangeEvt_t; + +/*! LE LTK request event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint8_t randNum[HCI_RAND_LEN]; + uint16_t encDiversifier; +} hciLeLtkReqEvt_t; + +/*! Vendor specific command status event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t opcode; +} hciVendorSpecCmdStatusEvt_t; + +/*! Vendor specific command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t opcode; + uint8_t param[1]; +} hciVendorSpecCmdCmplEvt_t; + +/*! Vendor specific event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t param[1]; +} hciVendorSpecEvt_t; + +/*! Hardware error event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t code; +} hciHwErrorEvt_t; + +/*! LE encrypt command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t data[HCI_ENCRYPT_DATA_LEN]; +} hciLeEncryptCmdCmplEvt_t; + +/*! LE rand command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t randNum[HCI_RAND_LEN]; +} hciLeRandCmdCmplEvt_t; + +/*! LE remote connection parameter request reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeRemConnParamRepEvt_t; + +/*! LE remote connection parameter request negative reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeRemConnParamNegRepEvt_t; + +/*! LE read suggested default data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t suggestedMaxTxOctets; + uint16_t suggestedMaxTxTime; +} hciLeReadDefDataLenEvt_t; + +/*! LE write suggested default data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeWriteDefDataLenEvt_t; + +/*! LE set data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeSetDataLenEvt_t; + +/*! LE read maximum data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t supportedMaxTxOctets; + uint16_t supportedMaxTxTime; + uint16_t supportedMaxRxOctets; + uint16_t supportedMaxRxTime; +} hciLeReadMaxDataLenEvt_t; + +/*! LE remote connetion parameter request event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint16_t intervalMin; + uint16_t intervalMax; + uint16_t latency; + uint16_t timeout; +} hciLeRemConnParamReqEvt_t; + +/*! LE data length change event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint16_t maxTxOctets; + uint16_t maxTxTime; + uint16_t maxRxOctets; + uint16_t maxRxTime; +} hciLeDataLenChangeEvt_t; + +/*! LE local p256 ecc key command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t key[HCI_P256_KEY_LEN]; +} hciLeP256CmplEvt_t; + +/*! LE generate DH key command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t key[HCI_DH_KEY_LEN]; +} hciLeGenDhKeyEvt_t; + +/*! LE read peer resolving address command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t peerRpa[BDA_ADDR_LEN]; +} hciLeReadPeerResAddrCmdCmplEvt_t; + +/*! LE read local resolving address command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t localRpa[BDA_ADDR_LEN]; +} hciLeReadLocalResAddrCmdCmplEvt_t; + +/*! LE set address resolving enable command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeSetAddrResEnableCmdCmplEvt_t; + +/*! LE add device to resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeAddDevToResListCmdCmplEvt_t; + +/*! LE remove device from resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeRemDevFromResListCmdCmplEvt_t; + +/*! LE clear resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeClearResListCmdCmplEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciWriteAuthPayloadToCmdCmplEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; +} hciAuthPayloadToExpiredEvt_t; + +/*! LE read PHY command complete event */ + typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t txPhy; + uint8_t rxPhy; +} hciLeReadPhyCmdCmplEvt_t; + +/*! LE set default PHY command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeSetDefPhyCmdCmplEvt_t; + +/*! LE PHY update complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t txPhy; + uint8_t rxPhy; +} hciLePhyUpdateEvt_t; + +/*! Union of all event types */ +typedef union +{ + wsfMsgHdr_t hdr; + wsfMsgHdr_t resetSeqCmpl; + hciLeConnCmplEvt_t leConnCmpl; + hciDisconnectCmplEvt_t disconnectCmpl; + hciLeConnUpdateCmplEvt_t leConnUpdateCmpl; + hciLeCreateConnCancelCmdCmplEvt_t leCreateConnCancelCmdCmpl; + hciLeAdvReportEvt_t leAdvReport; + hciReadRssiCmdCmplEvt_t readRssiCmdCmpl; + hciReadChanMapCmdCmplEvt_t readChanMapCmdCmpl; + hciReadTxPwrLvlCmdCmplEvt_t readTxPwrLvlCmdCmpl; + hciReadRemoteVerInfoCmplEvt_t readRemoteVerInfoCmpl; + hciLeReadRemoteFeatCmplEvt_t leReadRemoteFeatCmpl; + hciLeLtkReqReplCmdCmplEvt_t leLtkReqReplCmdCmpl; + hciLeLtkReqNegReplCmdCmplEvt_t leLtkReqNegReplCmdCmpl; + hciEncKeyRefreshCmpl_t encKeyRefreshCmpl; + hciEncChangeEvt_t encChange; + hciLeLtkReqEvt_t leLtkReq; + hciVendorSpecCmdStatusEvt_t vendorSpecCmdStatus; + hciVendorSpecCmdCmplEvt_t vendorSpecCmdCmpl; + hciVendorSpecEvt_t vendorSpec; + hciHwErrorEvt_t hwError; + hciLeEncryptCmdCmplEvt_t leEncryptCmdCmpl; + hciLeRandCmdCmplEvt_t leRandCmdCmpl; + hciLeReadPeerResAddrCmdCmplEvt_t leReadPeerResAddrCmdCmpl; + hciLeReadLocalResAddrCmdCmplEvt_t leReadLocalResAddrCmdCmpl; + hciLeSetAddrResEnableCmdCmplEvt_t leSetAddrResEnableCmdCmpl; + hciLeAddDevToResListCmdCmplEvt_t leAddDevToResListCmdCmpl; + hciLeRemDevFromResListCmdCmplEvt_t leRemDevFromResListCmdCmpl; + hciLeClearResListCmdCmplEvt_t leClearResListCmdCmpl; + hciLeRemConnParamRepEvt_t leRemConnParamRepCmdCmpl; + hciLeRemConnParamNegRepEvt_t leRemConnParamNegRepCmdCmpl; + hciLeReadDefDataLenEvt_t leReadDefDataLenCmdCmpl; + hciLeWriteDefDataLenEvt_t leWriteDefDataLenCmdCmpl; + hciLeSetDataLenEvt_t leSetDataLenCmdCmpl; + hciLeReadMaxDataLenEvt_t leReadMaxDataLenCmdCmpl; + hciLeRemConnParamReqEvt_t leRemConnParamReq; + hciLeDataLenChangeEvt_t leDataLenChange; + hciLeP256CmplEvt_t leP256; + hciLeGenDhKeyEvt_t leGenDHKey; + hciWriteAuthPayloadToCmdCmplEvt_t writeAuthPayloadToCmdCmpl; + hciAuthPayloadToExpiredEvt_t authPayloadToExpired; + hciLeReadPhyCmdCmplEvt_t leReadPhyCmdCmpl; + hciLeSetDefPhyCmdCmplEvt_t leSetDefPhyCmdCmpl; + hciLePhyUpdateEvt_t lePhyUpdate; + hciLeExtAdvReportEvt_t leExtAdvReport; + hciLeScanTimeoutEvt_t leScanTimeout; + hciLeAdvSetTermEvt_t leAdvSetTerm; + hciLeScanReqRcvdEvt_t leScanReqRcvd; + hciLePerAdvSyncEstEvt_t lePerAdvSyncEst; + hciLePerAdvReportEvt_t lePerAdvReport; + hciLePerAdvSyncLostEvt_t lePerAdvSyncLost; + hciLeChSelAlgoEvt_t leChSelAlgo; +} hciEvt_t; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +typedef void (*hciEvtCback_t)(hciEvt_t *pEvent); +typedef void (*hciSecCback_t)(hciEvt_t *pEvent); +typedef void (*hciAclCback_t)(uint8_t *pData); +typedef void (*hciFlowCback_t)(uint16_t handle, bool_t flowDisabled); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*! Initialization, registration, and reset */ +void HciEvtRegister(hciEvtCback_t evtCback); +void HciSecRegister(hciSecCback_t secCback); +void HciAclRegister(hciAclCback_t aclCback, hciFlowCback_t flowCback); +void HciResetSequence(void); +void HciVsInit(uint8_t param); +void HciCoreInit(void); +void HciCoreHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); +void HciSetMaxRxAclLen(uint16_t len); +void HciSetAclQueueWatermarks(uint8_t queueHi, uint8_t queueLo); +void HciSetLeSupFeat(uint16_t feat, bool_t flag); + +/*! Optimization interface */ +uint8_t *HciGetBdAddr(void); +uint8_t HciGetWhiteListSize(void); +int8_t HciGetAdvTxPwr(void); +uint16_t HciGetBufSize(void); +uint8_t HciGetNumBufs(void); +uint8_t *HciGetSupStates(void); +uint16_t HciGetLeSupFeat(void); +uint16_t HciGetMaxRxAclLen(void); +uint8_t HciGetResolvingListSize(void); +bool_t HciLlPrivacySupported(void); +uint16_t HciGetMaxAdvDataLen(void); +uint8_t HciGetNumSupAdvSets(void); +bool_t HciLeAdvExtSupported(void); +uint8_t HciGetPerAdvListSize(void); + +/*! ACL data interface */ +void HciSendAclData(uint8_t *pAclData); + +/*! Command interface */ +void HciDisconnectCmd(uint16_t handle, uint8_t reason); +void HciLeAddDevWhiteListCmd(uint8_t addrType, uint8_t *pAddr); +void HciLeClearWhiteListCmd(void); +void HciLeConnUpdateCmd(uint16_t handle, hciConnSpec_t *pConnSpec); +void HciLeCreateConnCmd(uint16_t scanInterval, uint16_t scanWindow, uint8_t filterPolicy, + uint8_t peerAddrType, uint8_t *pPeerAddr, uint8_t ownAddrType, + hciConnSpec_t *pConnSpec); +void HciLeCreateConnCancelCmd(void); +void HciLeEncryptCmd(uint8_t *pKey, uint8_t *pData); +void HciLeLtkReqNegReplCmd(uint16_t handle); +void HciLeLtkReqReplCmd(uint16_t handle, uint8_t *pKey); +void HciLeRandCmd(void); +void HciLeReadAdvTXPowerCmd(void); +void HciLeReadBufSizeCmd(void); +void HciLeReadChanMapCmd(uint16_t handle); +void HciLeReadLocalSupFeatCmd(void); +void HciLeReadRemoteFeatCmd(uint16_t handle); +void HciLeReadSupStatesCmd(void); +void HciLeReadWhiteListSizeCmd(void); +void HciLeRemoveDevWhiteListCmd(uint8_t addrType, uint8_t *pAddr); +void HciLeSetAdvEnableCmd(uint8_t enable); +void HciLeSetAdvDataCmd(uint8_t len, uint8_t *pData); +void HciLeSetAdvParamCmd(uint16_t advIntervalMin, uint16_t advIntervalMax, uint8_t advType, + uint8_t ownAddrType, uint8_t peerAddrType, uint8_t *pPeerAddr, + uint8_t advChanMap, uint8_t advFiltPolicy); +void HciLeSetEventMaskCmd(uint8_t *pLeEventMask); +void HciLeSetHostChanClassCmd(uint8_t *pChanMap); +void HciLeSetRandAddrCmd(uint8_t *pAddr); +void HciLeSetScanEnableCmd(uint8_t enable, uint8_t filterDup); +void HciLeSetScanParamCmd(uint8_t scanType, uint16_t scanInterval, uint16_t scanWindow, + uint8_t ownAddrType, uint8_t scanFiltPolicy); +void HciLeSetScanRespDataCmd(uint8_t len, uint8_t *pData); +void HciLeStartEncryptionCmd(uint16_t handle, uint8_t *pRand, uint16_t diversifier, uint8_t *pKey); +void HciReadBdAddrCmd(void); +void HciReadBufSizeCmd(void); +void HciReadLocalSupFeatCmd(void); +void HciReadLocalVerInfoCmd(void); +void HciReadRemoteVerInfoCmd(uint16_t handle); +void HciReadRssiCmd(uint16_t handle); +void HciReadTxPwrLvlCmd(uint16_t handle, uint8_t type); +void HciResetCmd(void); +void HciSetEventMaskCmd(uint8_t *pEventMask); +void HciSetEventMaskPage2Cmd(uint8_t *pEventMask); +void HciReadAuthPayloadTimeout(uint16_t handle); +void HciWriteAuthPayloadTimeout(uint16_t handle, uint16_t timeout); +void HciLeAddDeviceToResolvingListCmd(uint8_t peerAddrType, const uint8_t *pPeerIdentityAddr, + const uint8_t *pPeerIrk, const uint8_t *pLocalIrk); +void HciLeRemoveDeviceFromResolvingList(uint8_t peerAddrType, const uint8_t *pPeerIdentityAddr); +void HciLeClearResolvingList(void); +void HciLeReadResolvingListSize(void); +void HciLeReadPeerResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); +void HciLeReadLocalResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); +void HciLeSetAddrResolutionEnable(uint8_t enable); +void HciLeSetResolvablePrivateAddrTimeout(uint16_t rpaTimeout); +void HciLeSetPrivacyModeCmd(uint8_t addrType, uint8_t *pAddr, uint8_t mode); +void HciLeReadPhyCmd(uint16_t handle); +void HciLeSetDefaultPhyCmd(uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys); +void HciLeSetPhyCmd(uint16_t handle, uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys, uint16_t phyOptions); +void HciVendorSpecificCmd(uint16_t opcode, uint8_t len, uint8_t *pData); + +void HciLeRemoteConnParamReqReply(uint16_t handle, uint16_t intervalMin, uint16_t intervalMax, uint16_t latency, + uint16_t timeout, uint16_t minCeLen, uint16_t maxCeLen); +void HciLeRemoteConnParamReqNegReply(uint16_t handle, uint8_t reason); +void HciLeSetDataLen(uint16_t handle, uint16_t txOctets, uint16_t txTime); +void HciLeReadDefDataLen(void); +void HciLeWriteDefDataLen(uint16_t suggestedMaxTxOctets, uint16_t suggestedMaxTxTime); +void HciLeReadLocalP256PubKey(void); +void HciLeGenerateDHKey(uint8_t *pPubKeyX, uint8_t *pPubKeyY); +void HciLeReadMaxDataLen(void); +void HciWriteAuthPayloadTimeout(uint16_t handle, uint16_t timeout); + +/* AE slave interface */ +void HciLeSetAdvSetRandAddrCmd(uint8_t advHandle, const uint8_t *pAddr); +void HciLeSetExtAdvParamCmd(uint8_t advHandle, hciExtAdvParam_t *pExtAdvParam); +void HciLeSetExtAdvDataCmd(uint8_t advHandle, uint8_t op, uint8_t fragPref, uint8_t len, + const uint8_t *pData); +void HciLeSetExtScanRespDataCmd(uint8_t advHandle, uint8_t op, uint8_t fragPref, uint8_t len, + const uint8_t *pData); +void HciLeSetExtAdvEnableCmd(uint8_t enable, uint8_t numSets, hciExtAdvEnableParam_t *pEnableParam); +void HciLeReadMaxAdvDataLen(void); +void HciLeReadNumSupAdvSets(void); +void HciLeRemoveAdvSet(uint8_t advHandle); +void HciLeClearAdvSets(void); +void HciLeSetPerAdvParamCmd(uint8_t advHandle, uint16_t advIntervalMin, uint16_t advIntervalMax, + uint16_t advProps); +void HciLeSetPerAdvDataCmd(uint8_t advHandle, uint8_t op, uint8_t len, const uint8_t *pData); +void HciLeSetPerAdvEnableCmd(uint8_t enable, uint8_t advHandle); + +/* AE master interface */ +void HciLeSetExtScanParamCmd(uint8_t ownAddrType, uint8_t scanFiltPolicy, uint8_t scanPhys, + hciExtScanParam_t *pScanParam); +void HciLeExtScanEnableCmd(uint8_t enable, uint8_t filterDup, uint16_t duration, uint16_t period); +void HciLeExtCreateConnCmd(hciExtInitParam_t *pInitParam, hciExtInitScanParam_t *pScanParam, + hciConnSpec_t *pConnSpec); +void HciLePerAdvCreateSyncCmd(uint8_t filterPolicy, uint8_t advSid, uint8_t advAddrType, + const uint8_t *pAdvAddr, uint16_t skip, uint16_t syncTimeout, uint8_t unused); +void HciLePerAdvCreateSyncCancelCmd(void); +void HciLePerAdvTerminateSyncCmd(uint16_t syncHandle); +void HciLeAddDeviceToPerAdvListCmd(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); +void HciLeRemoveDeviceFromPerAdvListCmd(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); +void HciLeClearPerAdvListCmd(void); +void HciLeReadPerAdvListSizeCmd(void); + +/* AE common interface */ +void HciVsAeInit(uint8_t param); +void HciLeReadTxPower(void); +void HciLeReadRfPathComp(void); +void HciLeWriteRfPathComp(int16_t txPathComp, int16_t rxPathComp); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h new file mode 100644 index 00000000000..4b7f6bad624 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file hci_handler.h + * + * \brief Interface to HCI event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_HANDLER_H +#define HCI_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn HciHandlerInit + * + * \brief HCI handler init function called during system initialization. + * + * \param handlerID WSF handler ID for HCI. + * + * \return None. + */ +/*************************************************************************************************/ +void HciHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn HciHandler + * + * \brief WSF event handler for HCI. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void HciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h new file mode 100644 index 00000000000..006791edfae --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h @@ -0,0 +1,431 @@ +/*************************************************************************************************/ +/*! + * \file l2c_api.h + * + * \brief L2CAP subsystem API. + * + * $Date: 2017-03-21 16:36:53 -0500 (Tue, 21 Mar 2017) $ + * $Revision: 11626 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_API_H +#define L2C_API_H + +#include "dm_api.h" +#include "l2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Control callback message events */ +#define L2C_CTRL_FLOW_ENABLE_IND 0 /*! Data flow enabled */ +#define L2C_CTRL_FLOW_DISABLE_IND 1 /*! Data flow disabled */ + +/*! Invalid channel registration ID for connection oriented channels */ +#define L2C_COC_REG_ID_NONE 0 + +/*! Invalid channel ID for connection oriented channels */ +#define L2C_COC_CID_NONE 0 + +/*! Connection oriented channel initiator/acceptor role */ +#define L2C_COC_ROLE_NONE 0x00 /*! No role (unallocated) */ +#define L2C_COC_ROLE_INITIATOR 0x01 /*! Channel initiator */ +#define L2C_COC_ROLE_ACCEPTOR 0x02 /*! Channel acceptor */ + +/*! Connection oriented channel data confirm status values */ +#define L2C_COC_DATA_SUCCESS 0 /*! Data request successful */ +#define L2C_COC_DATA_ERR_MEMORY 1 /*! Out of memory */ +#define L2C_COC_DATA_ERR_OVERFLOW 2 /*! Transaction overflow */ + +/*! Connection oriented channel callback events */ +#define L2C_COC_CBACK_START 0x70 /*! L2C callback event starting value */ +enum +{ + L2C_COC_CONNECT_IND = L2C_COC_CBACK_START, /*! Channel connect indication */ + L2C_COC_DISCONNECT_IND, /*! Channel disconnect indication */ + L2C_COC_DATA_IND, /*! Received data indication */ + L2C_COC_DATA_CNF /*! Transmit data confirm */ +}; + +#define L2C_COC_CBACK_CBACK_END L2C_COC_DATA_CNF /*! L2C callback event ending value */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection oriented channel registration ID */ +typedef uint16_t l2cCocRegId_t; + +/*! Connection oriented channel registration structure */ +typedef struct +{ + uint16_t psm; /*! Protocol service multiplexer */ + uint16_t mps; /*! Maximum receive PDU fragment size */ + uint16_t mtu; /*! Maximum receive data packet size */ + uint16_t credits; /*! Data packet receive credits for this channel */ + bool_t authoriz; /*! TRUE if authorization is required */ + uint8_t secLevel; /*! Channel minimum security level requirements */ + uint8_t role; /*! Channel initiator/acceptor role */ +} l2cCocReg_t; + +/* Connection oriented channel connect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint16_t peerMtu; /*! Data packet MTU peer can receive */ + uint16_t psm; /*! Connected PSM */ +} l2cCocConnectInd_t; + +/* Connection oriented channel disconnect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint16_t result; /*! Connection failure result code */ +} l2cCocDisconnectInd_t; + +/* Connection oriented channel data indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint8_t *pData; /*! Pointer to packet data */ + uint16_t dataLen; /*! packet data length */ +} l2cCocDataInd_t; + +/* Connection oriented channel disconnect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ +} l2cCocDataCnf_t; + +/*! + * Connection oriented channel event structure + * + * Connection oriented channel callback header parameters: + * + * \param hdr.event Callback event + * \param hdr.param DM connection ID + * \param hdr.status Event status (L2C_COC_DATA_CNF only) + */ +typedef union +{ + wsfMsgHdr_t hdr; /*! Header structure */ + l2cCocConnectInd_t connectInd; /*! Channel connect indication */ + l2cCocDisconnectInd_t disconnectInd; /*! Channel disconnect indication */ + l2cCocDataInd_t dataInd; /*! Received data indication */ + l2cCocDataCnf_t dataCnf; /*! Transmit data confirm */ +} l2cCocEvt_t; + +/*! Configurable parameters */ +typedef struct +{ + uint16_t reqTimeout; /*! Request timeout in seconds */ +} l2cCfg_t; + +/************************************************************************************************** + Global Variables; +**************************************************************************************************/ + +/*! Configuration pointer */ +extern l2cCfg_t *pL2cCfg; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn l2cDataCback_t + * + * \brief This callback function sends a received L2CAP packet to the client. + * + * \param handle The connection handle. + * \param len The length of the L2CAP payload data in pPacket. + * \param pPacket A buffer containing the packet. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cDataCback_t)(uint16_t handle, uint16_t len, uint8_t *pPacket); + +/*************************************************************************************************/ +/*! + * \fn l2cCtrlCback_t + * + * \brief This callback function sends control messages to the client. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cCtrlCback_t)(wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn l2cCocCback_t + * + * \brief This callback function sends data and other events to connection oriented + * channels clients. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cCocCback_t)(l2cCocEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn l2cCocAuthorCback_t + * + * \brief This callback function is used for authoriztion of connection oriented channels. + * + * \param connId DM connection ID. + * \param regId The registration instance requiring authorization. + * \param psm The PSM of the registration instance. + * + * \return L2C_CONN_SUCCESS if authorization is successful, any other value for failure. + */ +/*************************************************************************************************/ +typedef uint16_t (*l2cCocAuthorCback_t)(dmConnId_t connId, l2cCocRegId_t regId, uint16_t psm); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn L2cInit + * + * \brief Initialize L2C subsystem. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cMasterInit + * + * \brief Initialize L2C for operation as a Bluetooth LE master. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveInit + * + * \brief Initialize L2C for operation as a Bluetooth LE slave. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cRegister + * + * \brief called by the L2C client, such as ATT or SMP, to register for the given CID. + * + * \param cid channel identifier. + * \param dataCback Callback function for L2CAP data received for this CID. + * \param ctrlCback Callback function for control events for this CID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cRegister(uint16_t cid, l2cDataCback_t dataCback, l2cCtrlCback_t ctrlCback); + +/*************************************************************************************************/ +/*! + * \fn L2cDataReq + * + * \brief Send an L2CAP data packet on the given CID. + * + * \param cid The channel identifier. + * \param handle The connection handle. The client receives this handle from DM. + * \param len The length of the payload data in pPacket. + * \param pPacket A buffer containing the packet. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDataReq(uint16_t cid, uint16_t handle, uint16_t len, uint8_t *pL2cPacket); + +/*************************************************************************************************/ +/*! + * \fn L2cCocInit + * + * \brief Initialize L2C connection oriented channel subsystem. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cCocRegister + * + * \brief Register to use a connection oriented channel, as either a channel acceptor, + * initiator, or both. If registering as channel acceptor then the PSM is specified. + * After registering a connection can be established by the client using this + * registration instance. + * + * \param cback Client callback function. + * \param pReg Registration parameter structure. + * + * \return Registration instance ID or L2C_COC_REG_ID_NONE if registration failed. + */ +/*************************************************************************************************/ +l2cCocRegId_t L2cCocRegister(l2cCocCback_t cback, l2cCocReg_t *pReg); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDeregister + * + * \brief Deregister and deallocate a connection oriented channel registration instance. + * This function should only be called if there are no active channels using this + * registration instance. + * + * \param regId Registration instance ID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDeregister(l2cCocRegId_t regId); + +/*************************************************************************************************/ +/*! + * \fn L2cCocConnectReq + * + * \brief Initiate a connection to the given peer PSM. + * + * \param connId DM connection ID. + * \param regId The associated registration instance. + * \param psm Peer PSM. + * + * \return Local CID or L2C_COC_CID_NONE none if failure. + */ +/*************************************************************************************************/ +uint16_t L2cCocConnectReq(dmConnId_t connId, l2cCocRegId_t regId, uint16_t psm); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDisconnectReq + * + * \brief Disconnect the channel for the given CID. + * + * \param cid Channel ID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDisconnectReq(uint16_t cid); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDataReq + * + * \brief Send an L2CAP data packet on the given connection oriented CID. + * + * \param cid The local channel identifier. + * \param len The length of the payload data in pPacket. + * \param pPacket Packet payload data. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDataReq(uint16_t cid, uint16_t len, uint8_t *pPayload); + +/*************************************************************************************************/ +/*! + * \fn L2cCocErrorTest + * + * \brief For testing purposes only. + * + * \param result Result code + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocErrorTest(uint16_t result); + +/*************************************************************************************************/ +/*! + * \fn L2cCocCreditSendTest + * + * \brief For testing purposes only. + * + * \param cid The local channel identifier. + * \param credits Credits to send. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocCreditSendTest(uint16_t cid, uint16_t credits); + +/*************************************************************************************************/ +/*! + * \fn L2cDmConnUpdateReq + * + * \brief For internal use only. This function is called by DM to send an L2CAP + * connection update request. + * + * \param handle The connection handle. + * \param pConnSpec Pointer to the connection specification structure. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDmConnUpdateReq(uint16_t handle, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn L2cDmConnUpdateRsp + * + * \brief For internal use only. This function is called by DM to send an L2CAP + * connection update response. + * + * \param identifier Identifier value previously passed from L2C to DM. + * \param handle The connection handle. + * \param result Connection update response result. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDmConnUpdateRsp(uint8_t identifier, uint16_t handle, uint16_t result); + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h new file mode 100644 index 00000000000..7754abb7f67 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h @@ -0,0 +1,118 @@ +/*************************************************************************************************/ +/*! + * \file l2c_defs.h + * + * \brief L2CAP constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_DEFS_H +#define L2C_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Packet definitions */ +#define L2C_HDR_LEN 4 /*! L2CAP packet header length */ +#define L2C_MIN_MTU 23 /*! Minimum packet payload MTU for LE */ +#define L2C_SIG_HDR_LEN 4 /*! L2CAP signaling command header length */ +#define L2C_LE_SDU_HDR_LEN 2 /*! L2CAP LE SDU data header length */ + +/*! Start of L2CAP payload in an HCI ACL packet buffer */ +#define L2C_PAYLOAD_START (HCI_ACL_HDR_LEN + L2C_HDR_LEN) + +/*! L2CAP signaling packet base length, including HCI header */ +#define L2C_SIG_PKT_BASE_LEN (HCI_ACL_HDR_LEN + L2C_HDR_LEN + L2C_SIG_HDR_LEN) + +/*! L2CAP LE SDU packet base length, including HCI header */ +#define L2C_LE_SDU_PKT_BASE_LEN (HCI_ACL_HDR_LEN + L2C_HDR_LEN + L2C_LE_SDU_HDR_LEN) + +/*! Signaling packet parameter lengths */ +#define L2C_SIG_CONN_UPDATE_REQ_LEN 8 +#define L2C_SIG_CONN_UPDATE_RSP_LEN 2 +#define L2C_SIG_CMD_REJ_LEN 2 +#define L2C_SIG_DISCONN_REQ_LEN 4 +#define L2C_SIG_DISCONN_RSP_LEN 4 +#define L2C_SIG_LE_CONN_REQ_LEN 10 +#define L2C_SIG_LE_CONN_RSP_LEN 10 +#define L2C_SIG_FLOW_CTRL_CREDIT_LEN 4 + +/*! Connection identifiers */ +#define L2C_CID_ATT 0x0004 /*! CID for attribute protocol */ +#define L2C_CID_LE_SIGNALING 0x0005 /*! CID for LE signaling */ +#define L2C_CID_SMP 0x0006 /*! CID for security manager protocol */ + +/*! Signaling codes */ +#define L2C_SIG_CMD_REJ 0x01 /*! Comand reject */ +#define L2C_SIG_DISCONNECT_REQ 0x06 /*! Disconnect request */ +#define L2C_SIG_DISCONNECT_RSP 0x07 /*! Disconnect response */ +#define L2C_SIG_CONN_UPDATE_REQ 0x12 /*! Connection parameter update request */ +#define L2C_SIG_CONN_UPDATE_RSP 0x13 /*! Connection parameter update response */ +#define L2C_SIG_LE_CONNECT_REQ 0x14 /*! LE credit based connection request */ +#define L2C_SIG_LE_CONNECT_RSP 0x15 /*! LE credit based connection response */ +#define L2C_SIG_FLOW_CTRL_CREDIT 0x16 /*! LE flow control credit */ + +/*! Signaling response code flag */ +#define L2C_SIG_RSP_FLAG 0x01 + +/*! Command reject reason codes */ +#define L2C_REJ_NOT_UNDERSTOOD 0x0000 /*! Command not understood */ +#define L2C_REJ_MTU_EXCEEDED 0x0001 /*! Signaling MTU exceeded */ +#define L2C_REJ_INVALID_CID 0x0002 /*! Invalid CID in request */ + +/*! Connection parameter update result */ +#define L2C_CONN_PARAM_ACCEPTED 0x0000 /*! Connection parameters accepted */ +#define L2C_CONN_PARAM_REJECTED 0x0001 /*! Connection parameters rejected */ + +/*! LE connection result */ +#define L2C_CONN_SUCCESS 0x0000 /*! Connection successful */ +#define L2C_CONN_NONE 0x0001 /*! No connection result value available */ +#define L2C_CONN_FAIL_PSM 0x0002 /*! Connection refused LE_PSM not supported */ +#define L2C_CONN_FAIL_RES 0x0004 /*! Connection refused no resources available */ +#define L2C_CONN_FAIL_AUTH 0x0005 /*! Connection refused insufficient authentication */ +#define L2C_CONN_FAIL_AUTHORIZ 0x0006 /*! Connection refused insufficient authorization */ +#define L2C_CONN_FAIL_KEY_SIZE 0x0007 /*! Connection refused insufficient encryption key size */ +#define L2C_CONN_FAIL_ENC 0x0008 /*! Connection Refused insufficient encryption */ +#define L2C_CONN_FAIL_INVALID_SCID 0x0009 /*! Connection refused invalid source CID */ +#define L2C_CONN_FAIL_ALLOCATED_SCID 0x000A /*! Connection refused source CID already allocated */ +#define L2C_CONN_FAIL_UNACCEPT_PARAM 0x000B /*! Connection refused unacceptable parameters */ + +/*! LE connection result proprietary codes */ +#define L2C_CONN_FAIL_TIMEOUT 0xF000 /*! Request timeout */ + +/*! Signaling parameter value ranges */ +#define L2C_PSM_MIN 0x0001 +#define L2C_PSM_MAX 0x00FF +#define L2C_CID_DYN_MIN 0x0040 +#define L2C_CID_DYN_MAX 0x007F +#define L2C_MTU_MIN 0x0017 +#define L2C_MPS_MIN 0x0017 +#define L2C_MPS_MAX 0xFFFD +#define L2C_CREDITS_MAX 0xFFFF + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h new file mode 100644 index 00000000000..5b8fde42eee --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h @@ -0,0 +1,96 @@ +/*************************************************************************************************/ +/*! + * \file l2c_handler.h + * + * \brief L2CAP handler interface. + * + * $Date $ + * $Revision $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_HANDLER_H +#define L2C_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveHandlerInit + * + * \brief Event handler initialization function for L2C when operating as a slave. + * + * \param handlerId ID for this event handler. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveHandlerInit(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveHandler + * + * \brief The WSF event handler for L2C when operating as a slave. + * + * \param event Event mask. + * \param pMsg Pointer to message. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn L2cCocHandlerInit + * + * \brief Event handler initialization function for L2C with connection oriented channels. + * + * \param handlerId ID for this event handler. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocHandlerInit(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn L2cCocHandler + * + * \brief The WSF event handler for L2C with connection oriented channels. + * + * \param event Event mask. + * \param pMsg Pointer to message. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h new file mode 100644 index 00000000000..f1624f1c4df --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h @@ -0,0 +1,242 @@ +/*************************************************************************************************/ +/*! + * \file smp_api.h + * + * \brief SMP subsystem API. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_API_H +#define SMP_API_H + +#include "wsf_os.h" +#include "smp_defs.h" +#include "dm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Event handler messages for SMP state machines */ +enum +{ + SMP_MSG_API_PAIR_REQ = 1, /*! API pairing request */ + SMP_MSG_API_PAIR_RSP, /*! API pairing response */ + SMP_MSG_API_CANCEL_REQ, /*! API cancel request */ + SMP_MSG_API_AUTH_RSP, /*! API pin response */ + SMP_MSG_API_SECURITY_REQ, /*! API security request */ + SMP_MSG_CMD_PKT, /*! SMP command packet received */ + SMP_MSG_CMD_PAIRING_FAILED, /*! SMP pairing failed packet received */ + SMP_MSG_DM_ENCRYPT_CMPL, /*! Link encrypted */ + SMP_MSG_DM_ENCRYPT_FAILED, /*! Link encryption failed */ + SMP_MSG_DM_CONN_CLOSE, /*! Connection closed */ + SMP_MSG_WSF_AES_CMPL, /*! AES calculation complete */ + SMP_MSG_INT_SEND_NEXT_KEY, /*! Send next key to be distributed */ + SMP_MSG_INT_MAX_ATTEMPTS, /*! Maximum pairing attempts reached */ + SMP_MSG_INT_PAIRING_CMPL, /*! Pairing complete */ + SMP_MSG_INT_TIMEOUT, /*! Pairing protocol timeout */ + SMP_MSG_INT_LESC, /*! Pair with Secure Connections */ + SMP_MSG_INT_LEGACY, /*! Pair with Legacy Security */ + SMP_MSG_INT_JW_NC, /*! LESC Just-Works/Numeric Comparison pairing */ + SMP_MSG_INT_PASSKEY, /*! LESC Passkey pairing */ + SMP_MSG_INT_OOB, /*! LESC Out-of-Band Pairing */ + SMP_MSG_API_USER_CONFIRM, /*! User confirms valid numeric comparison */ + SMP_MSG_API_USER_KEYPRESS, /*! User keypress in passkey pairing */ + SMP_MSG_API_KEYPRESS_CMPL, /*! User keypress complete in passkey pairing */ + SMP_MSG_WSF_ECC_CMPL, /*! WSF ECC operation complete */ + SMP_MSG_INT_PK_NEXT, /*! Continue to next passkey bit */ + SMP_MSG_INT_PK_CMPL, /*! Passkey operation complete */ + SMP_MSG_WSF_CMAC_CMPL, /*! WSF CMAC operation complete */ + SMP_MSG_DH_CHECK_FAILURE, /*! WSF CMAC operation complete */ + SMP_MSG_EARLY_CNF, /*! An early Confirm from the initiator in passkey pairing */ + SMP_NUM_MSGS +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Configurable parameters */ +typedef struct +{ + uint16_t attemptTimeout; /*! 'Repeated attempts' timeout in msec */ + uint8_t ioCap; /*! I/O Capability */ + uint8_t minKeyLen; /*! Minimum encryption key length */ + uint8_t maxKeyLen; /*! Maximum encryption key length */ + uint8_t maxAttempts; /*! Attempts to trigger 'repeated attempts' timeout */ + uint8_t auth; /*! Device authentication requirements */ +} smpCfg_t; + +/*! Data type for SMP_MSG_API_PAIR_REQ and SMP_MSG_API_PAIR_RSP */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t oob; + uint8_t auth; + uint8_t iKeyDist; + uint8_t rKeyDist; +} smpDmPair_t; + +/*! Data type for SMP_MSG_API_AUTH_RSP */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t authData[SMP_OOB_LEN]; + uint8_t authDataLen; +} smpDmAuthRsp_t; + +/*! Data type for SMP_MSG_API_USER_KEYPRESS */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t keypress; +} smpDmKeypress_t; + +/*! Data type for SMP_MSG_API_SECURITY_REQ */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t auth; +} smpDmSecurityReq_t; + +/*! Union SMP DM message data types */ +typedef union +{ + wsfMsgHdr_t hdr; + smpDmPair_t pair; + smpDmAuthRsp_t authRsp; + smpDmSecurityReq_t securityReq; + smpDmKeypress_t keypress; +} smpDmMsg_t; + +/************************************************************************************************** + Global Variables; +**************************************************************************************************/ + +/*! Configuration pointer */ +extern smpCfg_t *pSmpCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SmpiInit + * + * \brief Initialize SMP initiator role. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpiInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmprInit + * + * \brief Initialize SMP responder role. + * + * \return None. + */ +/*************************************************************************************************/ +void SmprInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpiScInit + * + * \brief Initialize SMP initiator role utilizing BTLE Secure Connections. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpiScInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmprScInit + * + * \brief Initialize SMP responder role utilizing BTLE Secure Connections. + * + * \return None. + */ +/*************************************************************************************************/ +void SmprScInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpNonInit + * + * \brief Use this SMP init function when SMP is not supported. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpNonInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpDmMsgSend + * + * \brief This function is called by DM to send a message to SMP. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpDmMsgSend(smpDmMsg_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn SmpDmEncryptInd + * + * \brief This function is called by DM to notify SMP of encrypted link status. + * + * \param pMsg Pointer to HCI message structure. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpDmEncryptInd(wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn SmpDmGetStk + * + * \brief Return the STK for the given connection. + * + * \param connId Connection identifier. + * \param pSecLevel Returns the security level of pairing when STK was created. + * + * \return Pointer to STK or NULL if not available. + */ +/*************************************************************************************************/ +uint8_t *SmpDmGetStk(dmConnId_t connId, uint8_t *pSecLevel); + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h new file mode 100644 index 00000000000..317b84802cb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h @@ -0,0 +1,155 @@ +/*************************************************************************************************/ +/*! + * \file smp_defs.h + * + * \brief Security manager constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_DEFS_H +#define SMP_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! PDU format */ +#define SMP_HDR_LEN 1 /*! Attribute PDU header length */ + +/*! Protocol timeout */ +#define SMP_TIMEOUT 30 /*! Protocol timeout in seconds */ + +/*! Encryption key size */ +#define SMP_KEY_SIZE_MAX 16 /*! Maximum encryption key size */ +#define SMP_KEY_SIZE_MIN 7 /*! Minimum encryption key size */ + +/*! OOB and PIN data lengths in bytes */ +#define SMP_OOB_LEN 16 +#define SMP_PIN_LEN 3 + +/*! Error codes */ +#define SMP_ERR_PASSKEY_ENTRY 0x01 /*! User input of passkey failed */ +#define SMP_ERR_OOB 0x02 /*! OOB data is not available */ +#define SMP_ERR_AUTH_REQ 0x03 /*! Authentication requirements cannot be met */ +#define SMP_ERR_CONFIRM_VALUE 0x04 /*! Confirm value does not match */ +#define SMP_ERR_PAIRING_NOT_SUP 0x05 /*! Pairing is not supported by the device */ +#define SMP_ERR_ENC_KEY_SIZE 0x06 /*! Insufficient encryption key size */ +#define SMP_ERR_COMMAND_NOT_SUP 0x07 /*! Command not supported */ +#define SMP_ERR_UNSPECIFIED 0x08 /*! Unspecified reason */ +#define SMP_ERR_ATTEMPTS 0x09 /*! Repeated attempts */ +#define SMP_ERR_INVALID_PARAM 0x0A /*! Invalid parameter or command length */ +#define SMP_ERR_DH_KEY_CHECK 0x0B /*! DH Key check did not match */ +#define SMP_ERR_NUMERIC_COMPARISON 0x0C /*! Numeric comparison did not match */ +#define SMP_ERR_BR_EDR_IN_PROGRESS 0x0D /*! BR/EDR in progress */ +#define SMP_ERR_CROSS_TRANSPORT 0x0E /*! BR/EDR Cross transport key generation not allowed */ + +/*! Proprietary internal error codes */ +#define SMP_ERR_MEMORY 0xE0 /*! Out of memory */ +#define SMP_ERR_TIMEOUT 0xE1 /*! Transaction timeout */ + +/*! Command codes */ +#define SMP_CMD_PAIR_REQ 0x01 /*! Pairing Request */ +#define SMP_CMD_PAIR_RSP 0x02 /*! Pairing Response */ +#define SMP_CMD_PAIR_CNF 0x03 /*! Pairing Confirm */ +#define SMP_CMD_PAIR_RAND 0x04 /*! Pairing Random */ +#define SMP_CMD_PAIR_FAIL 0x05 /*! Pairing Failed */ +#define SMP_CMD_ENC_INFO 0x06 /*! Encryption Information */ +#define SMP_CMD_MASTER_ID 0x07 /*! Master Identification */ +#define SMP_CMD_ID_INFO 0x08 /*! Identity Information */ +#define SMP_CMD_ID_ADDR_INFO 0x09 /*! Identity Address Information */ +#define SMP_CMD_SIGN_INFO 0x0A /*! Signing Information */ +#define SMP_CMD_SECURITY_REQ 0x0B /*! Security Request */ +#define SMP_CMD_PUBLIC_KEY 0x0C /*! Public Key */ +#define SMP_CMD_DHKEY_CHECK 0x0D /*! DH Key Check */ +#define SMP_CMD_KEYPRESS 0x0E /*! User Key Press */ +#define SMP_CMD_MAX 0x0F /*! Command code maximum */ + +/*! Command packet lengths */ +#define SMP_PAIR_REQ_LEN 7 +#define SMP_PAIR_RSP_LEN 7 +#define SMP_PAIR_CNF_LEN 17 +#define SMP_PAIR_RAND_LEN 17 +#define SMP_PAIR_FAIL_LEN 2 +#define SMP_ENC_INFO_LEN 17 +#define SMP_MASTER_ID_LEN 11 +#define SMP_ID_INFO_LEN 17 +#define SMP_ID_ADDR_INFO_LEN 8 +#define SMP_SIGN_INFO_LEN 17 +#define SMP_SECURITY_REQ_LEN 2 +#define SMP_PUB_KEY_MSG_LEN (1 + 2*SMP_PUB_KEY_LEN) +#define SMP_DHKEY_CHECK_MSG_LEN (1 + SMP_DHKEY_CHECK_LEN) +#define SMP_KEYPRESS_MSG_LEN 2 + +/*! I/O capabilities */ +#define SMP_IO_DISP_ONLY 0x00 /*! DisplayOnly */ +#define SMP_IO_DISP_YES_NO 0x01 /*! DisplayYesNo */ +#define SMP_IO_KEY_ONLY 0x02 /*! KeyboardOnly */ +#define SMP_IO_NO_IN_NO_OUT 0x03 /*! NoInputNoOutput */ +#define SMP_IO_KEY_DISP 0x04 /*! KeyboardDisplay */ + +/*! OOB data present */ +#define SMP_OOB_DATA_NONE 0x00 +#define SMP_OOB_DATA_PRESENT 0x01 + +/*! Authentication/security properties bit mask */ +#define SMP_AUTH_BOND_MASK 0x03 /*! Mask for bonding bits */ +#define SMP_AUTH_BOND_FLAG 0x01 /*! Bonding requested */ +#define SMP_AUTH_MITM_FLAG 0x04 /*! MITM (authenticated pairing) requested */ +#define SMP_AUTH_SC_FLAG 0x08 /*! LE Secure Connections requested */ +#define SMP_AUTH_KP_FLAG 0x10 /*! Keypress notifications requested */ + +/*! Key distribution bit mask */ +#define SMP_KEY_DIST_ENC 0x01 /*! Distribute LTK */ +#define SMP_KEY_DIST_ID 0x02 /*! Distribute IRK */ +#define SMP_KEY_DIST_SIGN 0x04 /*! Distribute CSRK */ +#define SMP_KEY_DIST_MASK (SMP_KEY_DIST_ENC | SMP_KEY_DIST_ID | SMP_KEY_DIST_SIGN) + +/*! LESC Passkey keypress types */ +#define SMP_PASSKEY_ENTRY_STARTED 0x00 /*! Passkey entry started keypress type */ +#define SMP_PASSKEY_DIGIT_ENTERED 0x01 /*! Passkey digit entered keypress type */ +#define SMP_PASSKEY_DIGIT_ERASED 0x02 /*! Passkey digit erased keypress type */ +#define SMP_PASSKEY_CLEARED 0x03 /*! Passkey cleared keypress type */ +#define SMP_PASSKEY_ENTRY_COMPLETED 0x04 /*! Passkey entry complete keypress type */ + +/*! Various parameter lengths */ +#define SMP_RAND_LEN 16 +#define SMP_CONFIRM_LEN 16 +#define SMP_KEY_LEN 16 +#define SMP_RAND8_LEN 8 +#define SMP_PRIVATE_KEY_LEN 32 +#define SMP_PUB_KEY_LEN 32 +#define SMP_DHKEY_LEN 32 +#define SMP_DHKEY_CHECK_LEN 16 + +/* CMAC Input Lengths */ +#define SMP_F4_TEXT_LEN (SMP_PUB_KEY_LEN * 2 + 1) +#define SMP_G2_TEXT_LEN (SMP_PUB_KEY_LEN * 2 + SMP_RAND_LEN) +#define SMP_F5_TKEY_TEXT_LEN (SMP_DHKEY_LEN) +#define SMP_F5_TEXT_LEN (9 + 2*BDA_ADDR_LEN + 2*SMP_RAND_LEN) +#define SMP_F6_TEXT_LEN (2*BDA_ADDR_LEN + 3*SMP_RAND_LEN + 5) + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h new file mode 100644 index 00000000000..b324afba3f4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file smp_handler.h + * + * \brief Interface to SMP event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_HANDLER_H +#define SMP_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SmpHandlerInit + * + * \brief SMP handler init function called during system initialization. + * + * \param handlerID WSF handler ID for SMP. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn SmpHandler + * + * \brief WSF event handler for SMP. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h new file mode 100644 index 00000000000..4acda1153e6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h @@ -0,0 +1,891 @@ +/*************************************************************************************************/ +/*! + * \file hci_defs.h + * + * \brief HCI constants and definitions from the Bluetooth specification. + * + * $Date: 2017-03-09 12:18:38 -0600 (Thu, 09 Mar 2017) $ + * $Revision: 11460 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_DEFS_H +#define HCI_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Packet definitions */ +#define HCI_CMD_HDR_LEN 3 /*!< Command packet header length */ +#define HCI_ACL_HDR_LEN 4 /*!< ACL packet header length */ +#define HCI_EVT_HDR_LEN 2 /*!< Event packet header length */ +#define HCI_EVT_PARAM_MAX_LEN 255 /*!< Maximum length of event packet parameters */ +#define HCI_ACL_DEFAULT_LEN 27 /*!< Default maximum ACL packet length */ +#define HCI_PB_FLAG_MASK 0x3000 /*!< ACL packet boundary flag mask */ +#define HCI_PB_START_H2C 0x0000 /*!< Packet boundary flag, start, host-to-controller */ +#define HCI_PB_CONTINUE 0x1000 /*!< Packet boundary flag, continue */ +#define HCI_PB_START_C2H 0x2000 /*!< Packet boundary flag, start, controller-to-host */ +#define HCI_HANDLE_MASK 0x0FFF /*!< Mask for handle bits in ACL packet */ +#define HCI_HANDLE_NONE 0xFFFF /*!< Value for invalid handle */ + +/* Packet types */ +#define HCI_CMD_TYPE 1 /*!< HCI command packet */ +#define HCI_ACL_TYPE 2 /*!< HCI ACL data packet */ +#define HCI_EVT_TYPE 4 /*!< HCI event packet */ + +/* Error codes */ +#define HCI_SUCCESS 0x00 /*!< Success */ +#define HCI_ERR_UNKNOWN_CMD 0x01 /*!< Unknown HCI command */ +#define HCI_ERR_UNKNOWN_HANDLE 0x02 /*!< Unknown connection identifier */ +#define HCI_ERR_HARDWARE_FAILURE 0x03 /*!< Hardware failure */ +#define HCI_ERR_PAGE_TIMEOUT 0x04 /*!< Page timeout */ +#define HCI_ERR_AUTH_FAILURE 0x05 /*!< Authentication failure */ +#define HCI_ERR_KEY_MISSING 0x06 /*!< PIN or key missing */ +#define HCI_ERR_MEMORY_EXCEEDED 0x07 /*!< Memory capacity exceeded */ +#define HCI_ERR_CONN_TIMEOUT 0x08 /*!< Connection timeout */ +#define HCI_ERR_CONN_LIMIT 0x09 /*!< Connection limit exceeded */ +#define HCI_ERR_SYNCH_CONN_LIMIT 0x0A /*!< Synchronous connection limit exceeded */ +#define HCI_ERR_ACL_CONN_EXISTS 0x0B /*!< ACL connection already exists */ +#define HCI_ERR_CMD_DISALLOWED 0x0C /*!< Command disallowed */ +#define HCI_ERR_REJ_RESOURCES 0x0D /*!< Connection rejected limited resources */ +#define HCI_ERR_REJ_SECURITY 0x0E /*!< Connection rejected security reasons */ +#define HCI_ERR_REJ_BD_ADDR 0x0F /*!< Connection rejected unacceptable BD_ADDR */ +#define HCI_ERR_ACCEPT_TIMEOUT 0x10 /*!< Connection accept timeout exceeded */ +#define HCI_ERR_UNSUP_FEAT 0x11 /*!< Unsupported feature or parameter value */ +#define HCI_ERR_INVALID_PARAM 0x12 /*!< Invalid HCI command parameters */ +#define HCI_ERR_REMOTE_TERMINATED 0x13 /*!< Remote user terminated connection */ +#define HCI_ERR_REMOTE_RESOURCES 0x14 /*!< Remote device low resources */ +#define HCI_ERR_REMOTE_POWER_OFF 0x15 /*!< Remote device power off */ +#define HCI_ERR_LOCAL_TERMINATED 0x16 /*!< Connection terminated by local host */ +#define HCI_ERR_REPEATED_ATTEMPTS 0x17 /*!< Repeated attempts */ +#define HCI_ERR_PAIRING_NOT_ALLOWED 0x18 /*!< Pairing not allowed */ +#define HCI_ERR_UNKNOWN_LMP_PDU 0x19 /*!< Unknown LMP PDU */ +#define HCI_ERR_UNSUP_REMOTE_FEAT 0x1A /*!< Unsupported remote feature */ +#define HCI_ERR_SCO_OFFSET 0x1B /*!< SCO offset rejected */ +#define HCI_ERR_SCO_INTERVAL 0x1C /*!< SCO interval rejected */ +#define HCI_ERR_SCO_MODE 0x1D /*!< SCO air mode rejected */ +#define HCI_ERR_LMP_PARAM 0x1E /*!< Invalid LMP parameters */ +#define HCI_ERR_UNSPECIFIED 0x1F /*!< Unspecified error */ +#define HCI_ERR_UNSUP_LMP_PARAM 0x20 /*!< Unsupported LMP parameter value */ +#define HCI_ERR_ROLE_CHANGE 0x21 /*!< Role change not allowed */ +#define HCI_ERR_LL_RESP_TIMEOUT 0x22 /*!< LL response timeout */ +#define HCI_ERR_LMP_COLLISION 0x23 /*!< LMP error transaction collision */ +#define HCI_ERR_LMP_PDU 0x24 /*!< LMP pdu not allowed */ +#define HCI_ERR_ENCRYPT_MODE 0x25 /*!< Encryption mode not acceptable */ +#define HCI_ERR_LINK_KEY 0x26 /*!< Link key can not be changed */ +#define HCI_ERR_UNSUP_QOS 0x27 /*!< Requested qos not supported */ +#define HCI_ERR_INSTANT_PASSED 0x28 /*!< Instant passed */ +#define HCI_ERR_UNSUP_UNIT_KEY 0x29 /*!< Pairing with unit key not supported */ +#define HCI_ERR_TRANSACT_COLLISION 0x2A /*!< Different transaction collision */ +#define HCI_ERR_CHANNEL_CLASS 0x2E /*!< Channel classification not supported */ +#define HCI_ERR_MEMORY 0x2F /*!< Insufficient security */ +#define HCI_ERR_PARAMETER_RANGE 0x30 /*!< Parameter out of mandatory range */ +#define HCI_ERR_ROLE_SWITCH_PEND 0x32 /*!< Role switch pending */ +#define HCI_ERR_RESERVED_SLOT 0x34 /*!< Reserved slot violation */ +#define HCI_ERR_ROLE_SWITCH 0x35 /*!< Role switch failed */ +#define HCI_ERR_INQ_TOO_LARGE 0x36 /*!< Extended inquiry response too large */ +#define HCI_ERR_UNSUP_SSP 0x37 /*!< Secure simple pairing not supported by host */ +#define HCI_ERR_HOST_BUSY_PAIRING 0x38 /*!< Host busy - pairing */ +#define HCI_ERR_NO_CHANNEL 0x39 /*!< Connection rejected no suitable channel */ +#define HCI_ERR_CONTROLLER_BUSY 0x3A /*!< Controller busy */ +#define HCI_ERR_CONN_INTERVAL 0x3B /*!< Unacceptable connection interval */ +#define HCI_ERR_ADV_TIMEOUT 0x3C /*!< Advertising timeout */ +#define HCI_ERR_MIC_FAILURE 0x3D /*!< Connection terminated due to MIC failure */ +#define HCI_ERR_CONN_FAIL 0x3E /*!< Connection failed to be established */ +#define HCI_ERR_MAC_CONN_FAIL 0x3F /*!< MAC connection failed */ +#define HCI_ERR_COARSE_CLK_ADJ_REJ 0x40 /*!< Coarse clock adjustment rejected */ +#define HCI_ERR_TYPE0_SUBMAP_NOT_DEF 0x41 /*!< Type0 submap not defined */ +#define HCI_ERR_UNKNOWN_ADV_ID 0x42 /*!< Unknown advertising identifier */ +#define HCI_ERR_LIMIT_REACHED 0x43 /*!< Limit reached */ +#define HCI_ERR_OP_CANCELLED_BY_HOST 0x44 /*!< Operation cancelled by host */ + +/* Command groups */ +#define HCI_OGF_NOP 0x00 /*!< No operation */ +#define HCI_OGF_LINK_CONTROL 0x01 /*!< Link control */ +#define HCI_OGF_LINK_POLICY 0x02 /*!< Link policy */ +#define HCI_OGF_CONTROLLER 0x03 /*!< Controller and baseband */ +#define HCI_OGF_INFORMATIONAL 0x04 /*!< Informational parameters */ +#define HCI_OGF_STATUS 0x05 /*!< Status parameters */ +#define HCI_OGF_TESTING 0x06 /*!< Testing */ +#define HCI_OGF_LE_CONTROLLER 0x08 /*!< LE controller */ +#define HCI_OGF_VENDOR_SPEC 0x3F /*!< Vendor specific */ + +/* NOP command */ +#define HCI_OCF_NOP 0x00 + +/* Link control commands */ +#define HCI_OCF_DISCONNECT 0x06 +#define HCI_OCF_READ_REMOTE_VER_INFO 0x1D + +/* Link policy commands (none used for LE) */ + +/* Controller and baseband commands */ +#define HCI_OCF_SET_EVENT_MASK 0x01 +#define HCI_OCF_RESET 0x03 +#define HCI_OCF_READ_TX_PWR_LVL 0x2D +#define HCI_OCF_SET_CONTROLLER_TO_HOST_FC 0x31 +#define HCI_OCF_HOST_BUFFER_SIZE 0x33 +#define HCI_OCF_HOST_NUM_CMPL_PKTS 0x35 +#define HCI_OCF_SET_EVENT_MASK_PAGE2 0x63 +#define HCI_OCF_READ_AUTH_PAYLOAD_TO 0x7B +#define HCI_OCF_WRITE_AUTH_PAYLOAD_TO 0x7C + +/* Informational commands */ +#define HCI_OCF_READ_LOCAL_VER_INFO 0x01 +#define HCI_OCF_READ_LOCAL_SUP_CMDS 0x02 +#define HCI_OCF_READ_LOCAL_SUP_FEAT 0x03 +#define HCI_OCF_READ_BUF_SIZE 0x05 +#define HCI_OCF_READ_BD_ADDR 0x09 + +/* Status commands */ +#define HCI_OCF_READ_RSSI 0x05 + +/* LE controller commands */ +#define HCI_OCF_LE_SET_EVENT_MASK 0x01 +#define HCI_OCF_LE_READ_BUF_SIZE 0x02 +#define HCI_OCF_LE_READ_LOCAL_SUP_FEAT 0x03 +#define HCI_OCF_LE_SET_RAND_ADDR 0x05 +#define HCI_OCF_LE_SET_ADV_PARAM 0x06 +#define HCI_OCF_LE_READ_ADV_TX_POWER 0x07 +#define HCI_OCF_LE_SET_ADV_DATA 0x08 +#define HCI_OCF_LE_SET_SCAN_RESP_DATA 0x09 +#define HCI_OCF_LE_SET_ADV_ENABLE 0x0A +#define HCI_OCF_LE_SET_SCAN_PARAM 0x0B +#define HCI_OCF_LE_SET_SCAN_ENABLE 0x0C +#define HCI_OCF_LE_CREATE_CONN 0x0D +#define HCI_OCF_LE_CREATE_CONN_CANCEL 0x0E +#define HCI_OCF_LE_READ_WHITE_LIST_SIZE 0x0F +#define HCI_OCF_LE_CLEAR_WHITE_LIST 0x10 +#define HCI_OCF_LE_ADD_DEV_WHITE_LIST 0x11 +#define HCI_OCF_LE_REMOVE_DEV_WHITE_LIST 0x12 +#define HCI_OCF_LE_CONN_UPDATE 0x13 +#define HCI_OCF_LE_SET_HOST_CHAN_CLASS 0x14 +#define HCI_OCF_LE_READ_CHAN_MAP 0x15 +#define HCI_OCF_LE_READ_REMOTE_FEAT 0x16 +#define HCI_OCF_LE_ENCRYPT 0x17 +#define HCI_OCF_LE_RAND 0x18 +#define HCI_OCF_LE_START_ENCRYPTION 0x19 +#define HCI_OCF_LE_LTK_REQ_REPL 0x1A +#define HCI_OCF_LE_LTK_REQ_NEG_REPL 0x1B +#define HCI_OCF_LE_READ_SUP_STATES 0x1C +#define HCI_OCF_LE_RECEIVER_TEST 0x1D +#define HCI_OCF_LE_TRANSMITTER_TEST 0x1E +#define HCI_OCF_LE_TEST_END 0x1F +/* New in version 4.1 */ +#define HCI_OCF_LE_REM_CONN_PARAM_REP 0x20 +#define HCI_OCF_LE_REM_CONN_PARAM_NEG_REP 0x21 +/* New in version 4.2 */ +#define HCI_OCF_LE_SET_DATA_LEN 0x22 +#define HCI_OCF_LE_READ_DEF_DATA_LEN 0x23 +#define HCI_OCF_LE_WRITE_DEF_DATA_LEN 0x24 +#define HCI_OCF_LE_READ_LOCAL_P256_PUB_KEY 0x25 +#define HCI_OCF_LE_GENERATE_DHKEY 0x26 +#define HCI_OCF_LE_ADD_DEV_RES_LIST 0x27 +#define HCI_OCF_LE_REMOVE_DEV_RES_LIST 0x28 +#define HCI_OCF_LE_CLEAR_RES_LIST 0x29 +#define HCI_OCF_LE_READ_RES_LIST_SIZE 0x2A +#define HCI_OCF_LE_READ_PEER_RES_ADDR 0x2B +#define HCI_OCF_LE_READ_LOCAL_RES_ADDR 0x2C +#define HCI_OCF_LE_SET_ADDR_RES_ENABLE 0x2D +#define HCI_OCF_LE_SET_RES_PRIV_ADDR_TO 0x2E +#define HCI_OCF_LE_READ_MAX_DATA_LEN 0x2F +/* New in version 5.0 */ +#define HCI_OCF_LE_READ_PHY 0x30 +#define HCI_OCF_LE_SET_DEF_PHY 0x31 +#define HCI_OCF_LE_SET_PHY 0x32 +#define HCI_OCF_LE_ENHANCED_RECEIVER_TEST 0x33 +#define HCI_OCF_LE_ENHANCED_TRANSMITTER_TEST 0x34 +#define HCI_OCF_LE_SET_ADV_SET_RAND_ADDR 0x35 +#define HCI_OCF_LE_SET_EXT_ADV_PARAM 0x36 +#define HCI_OCF_LE_SET_EXT_ADV_DATA 0x37 +#define HCI_OCF_LE_SET_EXT_SCAN_RESP_DATA 0x38 +#define HCI_OCF_LE_SET_EXT_ADV_ENABLE 0x39 +#define HCI_OCF_LE_READ_MAX_ADV_DATA_LEN 0x3A +#define HCI_OCF_LE_READ_NUM_SUP_ADV_SETS 0x3B +#define HCI_OCF_LE_REMOVE_ADV_SET 0x3C +#define HCI_OCF_LE_CLEAR_ADV_SETS 0x3D +#define HCI_OCF_LE_SET_PER_ADV_PARAM 0x3E +#define HCI_OCF_LE_SET_PER_ADV_DATA 0x3F +#define HCI_OCF_LE_SET_PER_ADV_ENABLE 0x40 +#define HCI_OCF_LE_SET_EXT_SCAN_PARAM 0x41 +#define HCI_OCF_LE_SET_EXT_SCAN_ENABLE 0x42 +#define HCI_OCF_LE_EXT_CREATE_CONN 0x43 +#define HCI_OCF_LE_PER_ADV_CREATE_SYNC 0x44 +#define HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL 0x45 +#define HCI_OCF_LE_PER_ADV_TERM_SYNC 0x46 +#define HCI_OCF_LE_ADD_DEV_PER_ADV_LIST 0x47 +#define HCI_OCF_LE_REMOVE_DEV_PER_ADV_LIST 0x48 +#define HCI_OCF_LE_CLEAR_PER_ADV_LIST 0x49 +#define HCI_OCF_LE_READ_PER_ADV_LIST_SIZE 0x4A +#define HCI_OCF_LE_READ_TX_POWER 0x4B +#define HCI_OCF_LE_READ_RF_PATH_COMP 0x4C +#define HCI_OCF_LE_WRITE_RF_PATH_COMP 0x4D +#define HCI_OCF_LE_SET_PRIVACY_MODE 0x4E + +/* Opcode manipulation macros */ +#define HCI_OPCODE(ogf, ocf) (((ogf) << 10) + (ocf)) +#define HCI_OGF(opcode) ((opcode) >> 10) +#define HCI_OCF(opcode) ((opcode) & 0x03FF) + +/* Command opcodes */ +#define HCI_OPCODE_NOP HCI_OPCODE(HCI_OGF_NOP, HCI_OCF_NOP) + +#define HCI_OPCODE_DISCONNECT HCI_OPCODE(HCI_OGF_LINK_CONTROL, HCI_OCF_DISCONNECT) +#define HCI_OPCODE_READ_REMOTE_VER_INFO HCI_OPCODE(HCI_OGF_LINK_CONTROL, HCI_OCF_READ_REMOTE_VER_INFO) + +#define HCI_OPCODE_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK) +#define HCI_OPCODE_RESET HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_RESET) +#define HCI_OPCODE_READ_TX_PWR_LVL HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_TX_PWR_LVL) +#define HCI_OPCODE_SET_EVENT_MASK_PAGE2 HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK_PAGE2) +#define HCI_OPCODE_READ_AUTH_PAYLOAD_TO HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_AUTH_PAYLOAD_TO) +#define HCI_OPCODE_WRITE_AUTH_PAYLOAD_TO HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_WRITE_AUTH_PAYLOAD_TO) + +#define HCI_OPCODE_READ_LOCAL_VER_INFO HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_VER_INFO) +#define HCI_OPCODE_READ_LOCAL_SUP_CMDS HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_SUP_CMDS) +#define HCI_OPCODE_READ_LOCAL_SUP_FEAT HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_SUP_FEAT) +#define HCI_OPCODE_READ_BUF_SIZE HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_BUF_SIZE) +#define HCI_OPCODE_READ_BD_ADDR HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_BD_ADDR) + +#define HCI_OPCODE_READ_RSSI HCI_OPCODE(HCI_OGF_STATUS, HCI_OCF_READ_RSSI) + +#define HCI_OPCODE_LE_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EVENT_MASK) +#define HCI_OPCODE_LE_READ_BUF_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_BUF_SIZE) +#define HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_SUP_FEAT) +#define HCI_OPCODE_LE_SET_RAND_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_RAND_ADDR) +#define HCI_OPCODE_LE_SET_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_PARAM) +#define HCI_OPCODE_LE_READ_ADV_TX_POWER HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_ADV_TX_POWER) +#define HCI_OPCODE_LE_SET_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_DATA) +#define HCI_OPCODE_LE_SET_SCAN_RESP_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_RESP_DATA) +#define HCI_OPCODE_LE_SET_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_ENABLE) +#define HCI_OPCODE_LE_SET_SCAN_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_PARAM) +#define HCI_OPCODE_LE_SET_SCAN_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_ENABLE) +#define HCI_OPCODE_LE_CREATE_CONN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CREATE_CONN) +#define HCI_OPCODE_LE_CREATE_CONN_CANCEL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CREATE_CONN_CANCEL) +#define HCI_OPCODE_LE_READ_WHITE_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_WHITE_LIST_SIZE) +#define HCI_OPCODE_LE_CLEAR_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_WHITE_LIST) +#define HCI_OPCODE_LE_ADD_DEV_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_WHITE_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_WHITE_LIST) +#define HCI_OPCODE_LE_CONN_UPDATE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CONN_UPDATE) +#define HCI_OPCODE_LE_SET_HOST_CHAN_CLASS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_HOST_CHAN_CLASS) +#define HCI_OPCODE_LE_READ_CHAN_MAP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_CHAN_MAP) +#define HCI_OPCODE_LE_READ_REMOTE_FEAT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_REMOTE_FEAT) +#define HCI_OPCODE_LE_ENCRYPT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENCRYPT) +#define HCI_OPCODE_LE_RAND HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_RAND) +#define HCI_OPCODE_LE_START_ENCRYPTION HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_START_ENCRYPTION) +#define HCI_OPCODE_LE_LTK_REQ_REPL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_LTK_REQ_REPL) +#define HCI_OPCODE_LE_LTK_REQ_NEG_REPL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_LTK_REQ_NEG_REPL) +#define HCI_OPCODE_LE_READ_SUP_STATES HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_SUP_STATES) +#define HCI_OPCODE_LE_RECEIVER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_RECEIVER_TEST) +#define HCI_OPCODE_LE_TRANSMITTER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_TRANSMITTER_TEST) +#define HCI_OPCODE_LE_TEST_END HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_TEST_END) +/* New in version 4.1 */ +#define HCI_OPCODE_LE_REM_CONN_PARAM_REP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REM_CONN_PARAM_REP) +#define HCI_OPCODE_LE_REM_CONN_PARAM_NEG_REP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REM_CONN_PARAM_NEG_REP) +/* New in version 4.2 */ +#define HCI_OPCODE_LE_SET_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_DATA_LEN) +#define HCI_OPCODE_LE_READ_DEF_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_DEF_DATA_LEN) +#define HCI_OPCODE_LE_WRITE_DEF_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_WRITE_DEF_DATA_LEN) +#define HCI_OPCODE_LE_READ_LOCAL_P256_PUB_KEY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_P256_PUB_KEY) +#define HCI_OPCODE_LE_GENERATE_DHKEY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_GENERATE_DHKEY) +#define HCI_OPCODE_LE_ADD_DEV_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_RES_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_RES_LIST) +#define HCI_OPCODE_LE_CLEAR_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_RES_LIST) +#define HCI_OPCODE_LE_READ_RES_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_RES_LIST_SIZE) +#define HCI_OPCODE_LE_READ_PEER_RES_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PEER_RES_ADDR) +#define HCI_OPCODE_LE_READ_LOCAL_RES_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_RES_ADDR) +#define HCI_OPCODE_LE_SET_ADDR_RES_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADDR_RES_ENABLE) +#define HCI_OPCODE_LE_SET_RES_PRIV_ADDR_TO HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_RES_PRIV_ADDR_TO) +#define HCI_OPCODE_LE_READ_MAX_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_MAX_DATA_LEN) +/* New in version 5.0 */ +#define HCI_OPCODE_LE_READ_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PHY) +#define HCI_OPCODE_LE_SET_DEF_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_DEF_PHY) +#define HCI_OPCODE_LE_SET_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PHY) +#define HCI_OPCODE_LE_ENHANCED_RECEIVER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENHANCED_RECEIVER_TEST) +#define HCI_OPCODE_LE_ENHANCED_TRANSMITTER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENHANCED_TRANSMITTER_TEST) +#define HCI_OPCODE_LE_SET_ADV_SET_RAND_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_SET_RAND_ADDR) +#define HCI_OPCODE_LE_SET_EXT_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_PARAM) +#define HCI_OPCODE_LE_SET_EXT_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_DATA) +#define HCI_OPCODE_LE_SET_EXT_SCAN_RESP_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_RESP_DATA) +#define HCI_OPCODE_LE_SET_EXT_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_ENABLE) +#define HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_MAX_ADV_DATA_LEN) +#define HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_NUM_SUP_ADV_SETS) +#define HCI_OPCODE_LE_REMOVE_ADV_SET HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_ADV_SET) +#define HCI_OPCODE_LE_CLEAR_ADV_SETS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_ADV_SETS) +#define HCI_OPCODE_LE_SET_PER_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_PARAM) +#define HCI_OPCODE_LE_SET_PER_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_DATA) +#define HCI_OPCODE_LE_SET_PER_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_ENABLE) +#define HCI_OPCODE_LE_SET_EXT_SCAN_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_PARAM) +#define HCI_OPCODE_LE_SET_EXT_SCAN_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_ENABLE) +#define HCI_OPCODE_LE_EXT_CREATE_CONN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_EXT_CREATE_CONN) +#define HCI_OPCODE_LE_PER_ADV_CREATE_SYNC HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_CREATE_SYNC) +#define HCI_OPCODE_LE_PER_ADV_CREATE_SYNC_CANCEL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL) +#define HCI_OPCODE_LE_PER_ADV_TERMINATE_SYNC HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_TERM_SYNC) +#define HCI_OPCODE_LE_ADD_DEV_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_PER_ADV_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_PER_ADV_LIST) +#define HCI_OPCODE_LE_CLEAR_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_PER_ADV_LIST) +#define HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PER_ADV_LIST_SIZE) +#define HCI_OPCODE_LE_READ_TX_POWER HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_TX_POWER) +#define HCI_OPCODE_LE_WRITE_RF_PATH_COMP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_WRITE_RF_PATH_COMP) +#define HCI_OPCODE_LE_READ_RF_PATH_COMP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_RF_PATH_COMP) +#define HCI_OPCODE_LE_SET_PRIVACY_MODE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PRIVACY_MODE) + +/* ARM Vendor Specific */ +#define HCI_OPCODE_LE_VS_ENABLE_READ_FEAT_ON_CONN ((uint16_t)(0xfff3)) + +/* Command parameter lengths */ +#define HCI_LEN_NOP 0 + +#define HCI_LEN_DISCONNECT 3 +#define HCI_LEN_READ_REMOTE_VER_INFO 2 + +#define HCI_LEN_SET_EVENT_MASK 8 +#define HCI_LEN_SET_EVENT_MASK_PAGE2 8 +#define HCI_LEN_RESET 0 +#define HCI_LEN_READ_TX_PWR_LVL 3 +#define HCI_LEN_SET_CONTROLLER_TO_HOST_FC 1 +#define HCI_LEN_HOST_BUFFER_SIZE 8 +#define HCI_LEN_HOST_NUM_CMPL_PKTS 1 + +#define HCI_LEN_READ_LOCAL_VER_INFO 0 +#define HCI_LEN_READ_LOCAL_SUP_CMDS 0 +#define HCI_LEN_READ_LOCAL_SUP_FEAT 0 +#define HCI_LEN_READ_BUF_SIZE 0 +#define HCI_LEN_READ_BD_ADDR 0 + +#define HCI_LEN_READ_RSSI 2 +#define HCI_LEN_READ_AUTH_PAYLOAD_TO 2 +#define HCI_LEN_WRITE_AUTH_PAYLOAD_TO 4 + +#define HCI_LEN_LE_SET_EVENT_MASK 8 +#define HCI_LEN_LE_READ_BUF_SIZE 0 +#define HCI_LEN_LE_READ_LOCAL_SUP_FEAT 0 +#define HCI_LEN_LE_SET_RAND_ADDR 6 +#define HCI_LEN_LE_SET_ADV_PARAM 15 +#define HCI_LEN_LE_READ_ADV_TX_POWER 0 +#define HCI_LEN_LE_SET_ADV_DATA 32 +#define HCI_LEN_LE_SET_SCAN_RESP_DATA 32 +#define HCI_LEN_LE_SET_ADV_ENABLE 1 +#define HCI_LEN_LE_SET_SCAN_PARAM 7 +#define HCI_LEN_LE_SET_SCAN_ENABLE 2 +#define HCI_LEN_LE_CREATE_CONN 25 +#define HCI_LEN_LE_CREATE_CONN_CANCEL 0 +#define HCI_LEN_LE_READ_WHITE_LIST_SIZE 0 +#define HCI_LEN_LE_CLEAR_WHITE_LIST 0 +#define HCI_LEN_LE_ADD_DEV_WHITE_LIST 7 +#define HCI_LEN_LE_REMOVE_DEV_WHITE_LIST 7 +#define HCI_LEN_LE_CONN_UPDATE 14 +#define HCI_LEN_LE_SET_HOST_CHAN_CLASS 5 +#define HCI_LEN_LE_READ_CHAN_MAP 2 +#define HCI_LEN_LE_READ_REMOTE_FEAT 2 +#define HCI_LEN_LE_ENCRYPT 32 +#define HCI_LEN_LE_RAND 0 +#define HCI_LEN_LE_START_ENCRYPTION 28 +#define HCI_LEN_LE_LTK_REQ_REPL 18 +#define HCI_LEN_LE_LTK_REQ_NEG_REPL 2 +#define HCI_LEN_LE_READ_SUP_STATES 0 +#define HCI_LEN_LE_RECEIVER_TEST 1 +#define HCI_LEN_LE_TRANSMITTER_TEST 3 +#define HCI_LEN_LE_TEST_END 0 +/* New in version 4.1 */ +#define HCI_LEN_LE_REM_CONN_PARAM_REP 14 +#define HCI_LEN_LE_REM_CONN_PARAM_NEG_REP 3 +/* New in version 4.2 */ +#define HCI_LEN_LE_SET_DATA_LEN 6 +#define HCI_LEN_LE_READ_DEF_DATA_LEN 0 +#define HCI_LEN_LE_WRITE_DEF_DATA_LEN 4 +#define HCI_LEN_LE_READ_LOCAL_P256_PUB_KEY 0 +#define HCI_LEN_LE_GENERATE_DHKEY 64 +#define HCI_LEN_LE_ADD_DEV_RES_LIST 39 +#define HCI_LEN_LE_REMOVE_DEV_RES_LIST 7 +#define HCI_LEN_LE_CLEAR_RES_LIST 0 +#define HCI_LEN_LE_READ_RES_LIST_SIZE 0 +#define HCI_LEN_LE_READ_PEER_RES_ADDR 7 +#define HCI_LEN_LE_READ_LOCAL_RES_ADDR 7 +#define HCI_LEN_LE_SET_ADDR_RES_ENABLE 1 +#define HCI_LEN_LE_SET_RES_PRIV_ADDR_TO 2 +#define HCI_LEN_LE_READ_MAX_DATA_LEN 0 +/* New in version 5.0 */ +#define HCI_LEN_LE_READ_PHY 2 +#define HCI_LEN_LE_SET_DEF_PHY 3 +#define HCI_LEN_LE_SET_PHY 7 +#define HCI_LEN_LE_ENHANCED_RECEIVER_TEST 3 +#define HCI_LEN_LE_ENHANCED_TRANSMITTER_TEST 4 +#define HCI_LEN_LE_SET_ADV_SET_RAND_ADDR 7 +#define HCI_LEN_LE_SET_EXT_ADV_PARAM 25 +#define HCI_LEN_LE_SET_EXT_ADV_DATA(len) (4 + (len)) +#define HCI_LEN_LE_SET_EXT_SCAN_RESP_DATA(len) (4 + (len)) +#define HCI_LEN_LE_EXT_ADV_ENABLE(numSets) (2 + (4 * (numSets))) +#define HCI_LEN_LE_READ_MAX_ADV_DATA_LEN 0 +#define HCI_LEN_LE_READ_NUM_OF_SUP_ADV_SETS 0 +#define HCI_LEN_LE_REMOVE_ADV_SET 1 +#define HCI_LEN_LE_CLEAR_ADV_SETS 0 +#define HCI_LEN_LE_SET_PER_ADV_PARAM 7 +#define HCI_LEN_LE_SET_PER_ADV_DATA(len) (3 + (len)) +#define HCI_LEN_LE_SET_PER_ADV_ENABLE 2 +#define HCI_LEN_LE_SET_EXT_SCAN_PARAM(numPhys) (3 + (5 * (numPhys))) +#define HCI_LEN_LE_SET_EXT_SCAN_ENABLE 6 +#define HCI_LEN_LE_EXT_CREATE_CONN(numPhys) (10 + (16 * (numPhys))) +#define HCI_LEN_LE_PER_ADV_CREATE_SYNC 14 +#define HCI_LEN_LE_PER_ADV_CREATE_SYNC_CANCEL 0 +#define HCI_LEN_LE_PER_ADV_TERMINATE_SYNC 2 +#define HCI_LEN_LE_ADD_DEV_PER_ADV_LIST 8 +#define HCI_LEN_LE_REMOVE_DEV_PER_ADV_LIST 8 +#define HCI_LEN_LE_CLEAR_PER_ADV_LIST 0 +#define HCI_LEN_LE_READ_PER_ADV_LIST_SIZE 0 +#define HCI_LEN_LE_READ_TX_POWER 0 +#define HCI_LEN_LE_READ_RF_PATH_COMP 0 +#define HCI_LEN_LE_WRITE_RF_PATH_COMP 4 +#define HCI_LEN_LE_SET_PRIVACY_MODE 8 + +/* Events */ +#define HCI_DISCONNECT_CMPL_EVT 0x05 +#define HCI_ENC_CHANGE_EVT 0x08 +#define HCI_READ_REMOTE_VER_INFO_CMPL_EVT 0x0C +#define HCI_CMD_CMPL_EVT 0x0E +#define HCI_CMD_STATUS_EVT 0x0F +#define HCI_HW_ERROR_EVT 0x10 +#define HCI_NUM_CMPL_PKTS_EVT 0x13 +#define HCI_DATA_BUF_OVERFLOW_EVT 0x1A +#define HCI_ENC_KEY_REFRESH_CMPL_EVT 0x30 +#define HCI_LE_META_EVT 0x3E +#define HCI_AUTH_PAYLOAD_TIMEOUT_EVT 0x57 +#define HCI_VENDOR_SPEC_EVT 0xFF + +/* LE Subevents */ +#define HCI_LE_CONN_CMPL_EVT 0x01 +#define HCI_LE_ADV_REPORT_EVT 0x02 +#define HCI_LE_CONN_UPDATE_CMPL_EVT 0x03 +#define HCI_LE_READ_REMOTE_FEAT_CMPL_EVT 0x04 +#define HCI_LE_LTK_REQ_EVT 0x05 +/* New in version 4.1 */ +#define HCI_LE_REM_CONN_PARAM_REQ_EVT 0x06 +/* New in version 4.2 */ +#define HCI_LE_DATA_LEN_CHANGE_EVT 0x07 +#define HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_EVT 0x08 +#define HCI_LE_GENERATE_DHKEY_CMPL_EVT 0x09 +#define HCI_LE_ENHANCED_CONN_CMPL_EVT 0x0A +#define HCI_LE_DIRECT_ADV_REPORT_EVT 0x0B +/* New in version 5.0 */ +#define HCI_LE_PHY_UPDATE_CMPL_EVT 0x0C +#define HCI_LE_EXT_ADV_REPORT_EVT 0x0D +#define HCI_LE_PER_ADV_SYNC_EST_EVT 0x0E +#define HCI_LE_PER_ADV_REPORT_EVT 0x0F +#define HCI_LE_PER_ADV_SYNC_LOST_EVT 0x10 +#define HCI_LE_SCAN_TIMEOUT_EVT 0x11 +#define HCI_LE_ADV_SET_TERM_EVT 0x12 +#define HCI_LE_SCAN_REQ_RCVD_EVT 0x13 +#define HCI_LE_CH_SEL_ALGO_EVT 0x14 + +/* Event parameter lengths */ +#define HCI_LEN_DISCONNECT_CMPL 4 /*!< Disconnect event length. */ +#define HCI_LEN_READ_REMOTE_VER_INFO_CMPL 8 /*!< Read remove version info complete event length. */ +#define HCI_LEN_CMD_CMPL 3 /*!< Command complete event length. */ +#define HCI_LEN_CMD_STATUS 4 /*!< Command status event length. */ +#define HCI_LEN_HW_ERR 1 /*!< Hardware error event length. */ +#define HCI_LEN_NUM_CMPL_PKTS 5 /*!< Number of completed packets event length. */ +#define HCI_LEN_ENC_CHANGE 4 /*!< Encryption change event length. */ +#define HCI_LEN_ENC_KEY_REFRESH_CMPL 3 /*!< Encryption key refresh complete event length. */ +#define HCI_LEN_LE_CONN_CMPL 19 /*!< Connection complete event length. */ +#define HCI_LEN_LE_ADV_RPT_MIN 12 /*!< Advertising report event minimum length. */ +#define HCI_LEN_LE_CONN_UPDATE_CMPL 10 /*!< Connection update complete event length. */ +#define HCI_LEN_LE_READ_REMOTE_FEAT_CMPL 12 /*!< Read remote feature event length. */ +#define HCI_LEN_LE_LTK_REQ 13 /*!< LTK request event length. */ +/* New in version 4.1 */ +#define HCI_LEN_LE_REM_CONN_PARAM_REQ 11 /*!< Remote connection parameter event length. */ +#define HCI_LEN_LE_DATA_LEN_CHANGE 11 /*!< Data length change event length. */ +#define HCI_LEN_LE_READ_PUB_KEY_CMPL 66 /*!< Read local P256 public key compete event length. */ +#define HCI_LEN_LE_GEN_DHKEY_CMPL 34 /*!< Generate DH key complete event length. */ +#define HCI_LEN_LE_ENHANCED_CONN_CMPL 31 /*!< Enhanced connection complete event length. */ +#define HCI_LEN_LE_DIRECT_ADV_REPORT 18 /*!< Direct advertising report event length. */ +#define HCI_LEN_AUTH_PAYLOAD_TIMEOUT 2 /*!< Authenticated payload timeout event length. */ +/* New in version 5.0 */ +#define HCI_LEN_LE_PHY_UPDATE_CMPL 6 /*!< PHY update complete event length. */ +#define HCI_LEN_LE_CH_SEL_ALGO 4 /*!< Channel selection algorithm event length. */ +#define HCI_LEN_LE_PHY_UPDATE_CMPL 6 /*!< PHY update complete event length. */ +#define HCI_LEN_LE_EXT_ADV_REPORT_MIN 26 /*!< Extended advertising report minimum length. */ +#define HCI_LEN_LE_PER_ADV_SYNC_EST 16 /*!< Periodic advertising sync established event length. */ +#define HCI_LEN_LE_PER_ADV_REPORT 8 /*!< Periodic advertising report event length. */ +#define HCI_LEN_LE_PER_ADV_SYNC_LOST 3 /*!< Periodic advertising sync lost event length. */ +#define HCI_LEN_LE_SCAN_TIMEOUT 1 /*!< Scan timeout event length. */ +#define HCI_LEN_LE_ADV_SET_TERM 6 /*!< Advertising set terminated event length. */ +#define HCI_LEN_LE_SCAN_REQ_RCVD 9 /*!< Scan request received event length. */ + +/* Supported commands */ +#define HCI_SUP_DISCONNECT 0x20 /* Byte 0 */ +#define HCI_SUP_READ_REMOTE_VER_INFO 0x80 /* Byte 2 */ +#define HCI_SUP_SET_EVENT_MASK 0x40 /* Byte 5 */ +#define HCI_SUP_RESET 0x80 /* Byte 5 */ +#define HCI_SUP_READ_TX_PWR_LVL 0x04 /* Byte 10 */ +#define HCI_SUP_READ_LOCAL_VER_INFO 0x08 /* Byte 14 */ +#define HCI_SUP_READ_LOCAL_SUP_FEAT 0x20 /* Byte 14 */ +#define HCI_SUP_READ_BD_ADDR 0x02 /* Byte 15 */ +#define HCI_SUP_READ_RSSI 0x20 /* Byte 15 */ +#define HCI_SUP_SET_EVENT_MASK_PAGE2 0x04 /* Byte 22 */ +#define HCI_SUP_LE_SET_EVENT_MASK 0x01 /* Byte 25 */ +#define HCI_SUP_LE_READ_BUF_SIZE 0x02 /* Byte 25 */ +#define HCI_SUP_LE_READ_LOCAL_SUP_FEAT 0x04 /* Byte 25 */ +#define HCI_SUP_LE_SET_RAND_ADDR 0x10 /* Byte 25 */ +#define HCI_SUP_LE_SET_ADV_PARAM 0x20 /* Byte 25 */ +#define HCI_SUP_LE_READ_ADV_TX_POWER 0x40 /* Byte 25 */ +#define HCI_SUP_LE_SET_ADV_DATA 0x80 /* Byte 25 */ +#define HCI_SUP_LE_SET_SCAN_RESP_DATA 0x01 /* Byte 26 */ +#define HCI_SUP_LE_SET_ADV_ENABLE 0x02 /* Byte 26 */ +#define HCI_SUP_LE_SET_SCAN_PARAM 0x04 /* Byte 26 */ +#define HCI_SUP_LE_SET_SCAN_ENABLE 0x08 /* Byte 26 */ +#define HCI_SUP_LE_CREATE_CONN 0x10 /* Byte 26 */ +#define HCI_SUP_LE_CREATE_CONN_CANCEL 0x20 /* Byte 26 */ +#define HCI_SUP_LE_READ_WHITE_LIST_SIZE 0x40 /* Byte 26 */ +#define HCI_SUP_LE_CLEAR_WHITE_LIST 0x80 /* Byte 26 */ +#define HCI_SUP_LE_ADD_DEV_WHITE_LIST 0x01 /* Byte 27 */ +#define HCI_SUP_LE_REMOVE_DEV_WHITE_LIST 0x02 /* Byte 27 */ +#define HCI_SUP_LE_CONN_UPDATE 0x04 /* Byte 27 */ +#define HCI_SUP_LE_SET_HOST_CHAN_CLASS 0x08 /* Byte 27 */ +#define HCI_SUP_LE_READ_CHAN_MAP 0x10 /* Byte 27 */ +#define HCI_SUP_LE_READ_REMOTE_FEAT 0x20 /* Byte 27 */ +#define HCI_SUP_LE_ENCRYPT 0x40 /* Byte 27 */ +#define HCI_SUP_LE_RAND 0x80 /* Byte 27 */ +#define HCI_SUP_LE_START_ENCRYPTION 0x01 /* Byte 28 */ +#define HCI_SUP_LE_LTK_REQ_REPL 0x02 /* Byte 28 */ +#define HCI_SUP_LE_LTK_REQ_NEG_REPL 0x04 /* Byte 28 */ +#define HCI_SUP_LE_READ_SUP_STATES 0x08 /* Byte 28 */ +#define HCI_SUP_LE_RECEIVER_TEST 0x10 /* Byte 28 */ +#define HCI_SUP_LE_TRANSMITTER_TEST 0x20 /* Byte 28 */ +#define HCI_SUP_LE_TEST_END 0x40 /* Byte 28 */ +#define HCI_SUP_READ_AUTH_PAYLOAD_TO 0x10 /* Byte 32 */ +#define HCI_SUP_WRITE_AUTH_PAYLOAD_TO 0x20 /* Byte 32 */ +/* New in version 4.1 */ +#define HCI_SUP_LE_REM_CONN_PARAM_REQ_REPL 0x10 /* Byte 33 */ +#define HCI_SUP_LE_REM_CONN_PARAM_REQ_NEG_REPL 0x20 /* Byte 33 */ +/* New in version 4.2 */ +#define HCI_SUP_LE_SET_DATA_LEN 0x40 /* Byte 33 */ +#define HCI_SUP_LE_READ_DEF_DATA_LEN 0x80 /* Byte 33 */ +#define HCI_SUP_LE_WRITE_DEF_DATA_LEN 0x01 /* Byte 34 */ +#define HCI_SUP_LE_READ_LOCAL_P256_PUB_KEY 0x02 /* Byte 34 */ +#define HCI_SUP_LE_GENERATE_DHKEY 0x04 /* Byte 34 */ +#define HCI_SUP_LE_ADD_DEV_RES_LIST_EVT 0x08 /* Byte 34 */ +#define HCI_SUP_LE_REMOVE_DEV_RES_LIST 0x10 /* Byte 34 */ +#define HCI_SUP_LE_CLEAR_RES_LIST 0x20 /* Byte 34 */ +#define HCI_SUP_LE_READ_RES_LIST_SIZE 0x40 /* Byte 34 */ +#define HCI_SUP_LE_READ_PEER_RES_ADDR 0x80 /* Byte 34 */ +#define HCI_SUP_LE_READ_LOCAL_RES_ADDR 0x01 /* Byte 35 */ +#define HCI_SUP_LE_SET_ADDR_RES_ENABLE 0x02 /* Byte 35 */ +#define HCI_SUP_LE_SET_RES_PRIV_ADDR_TO 0x04 /* Byte 35 */ +#define HCI_SUP_LE_READ_MAX_DATA_LEN 0x08 /* Byte 35 */ +/* New in version 5.0 */ +#define HCI_SUP_LE_READ_PHY 0x10 /* Byte 35 */ +#define HCI_SUP_LE_SET_DEF_PHY 0x20 /* Byte 35 */ +#define HCI_SUP_LE_SET_PHY 0x40 /* Byte 35 */ +#define HCI_SUP_LE_ENHANCED_RECEIVER_TEST 0x80 /* Byte 35 */ +#define HCI_SUP_LE_ENHANCED_TRANSMITTER_TEST 0x01 /* Byte 36 */ +#define HCI_SUP_LE_SET_ADV_SET_RAND_ADDR 0x02 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_PARAM 0x04 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_DATA 0x08 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_SCAN_RESP_DATA 0x10 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_ENABLE 0x20 /* Byte 36 */ +#define HCI_SUP_LE_READ_MAX_ADV_DATA_LEN 0x40 /* Byte 36 */ +#define HCI_SUP_LE_READ_NUM_OF_SUP_ADV_SETS 0x80 /* Byte 36 */ +#define HCI_SUP_LE_REMOVE_ADV_SET 0x01 /* Byte 37 */ +#define HCI_SUP_LE_CLEAR_ADV_SETS 0x02 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_PARAM 0x04 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_DATA 0x08 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_ENABLE 0x10 /* Byte 37 */ +#define HCI_SUP_LE_SET_EXT_SCAN_PARAM 0x20 /* Byte 37 */ +#define HCI_SUP_LE_SET_EXT_SCAN_ENABLE 0x40 /* Byte 37 */ +#define HCI_SUP_LE_EXT_CREATE_CONN 0x80 /* Byte 37 */ +#define HCI_SUP_LE_PER_ADV_CREATE_SYNC 0x01 /* Byte 38 */ +#define HCI_SUP_LE_PER_ADV_CREATE_SYNC_CANCEL 0x02 /* Byte 38 */ +#define HCI_SUP_LE_PER_ADV_TERMINATE_SYNC 0x04 /* Byte 38 */ +#define HCI_SUP_LE_ADD_DEV_PER_ADV_LIST 0x08 /* Byte 38 */ +#define HCI_SUP_LE_REMOVE_DEV_PER_ADV_LIST 0x10 /* Byte 38 */ +#define HCI_SUP_LE_CLEAR_PER_ADV_LIST 0x20 /* Byte 38 */ +#define HCI_SUP_LE_READ_PER_ADV_LIST_SIZE 0x40 /* Byte 38 */ +#define HCI_SUP_LE_READ_TX_POWER 0x80 /* Byte 38 */ +#define HCI_SUP_LE_READ_RF_PATH_COMP 0x01 /* Byte 39 */ +#define HCI_SUP_LE_WRITE_RF_PATH_COMP 0x02 /* Byte 39 */ +#define HCI_SUP_LE_SET_PRIVACY_MODE 0x04 /* Byte 39 */ +#define HCI_SUP_LE_SET_MIN_NUM_OF_USED_CH 0x08 /* Byte 39 */ + +/* Event mask */ +#define HCI_EVT_MASK_DISCONNECT_CMPL 0x10 /* Byte 0 */ +#define HCI_EVT_MASK_ENC_CHANGE 0x80 /* Byte 0 */ +#define HCI_EVT_MASK_READ_REMOTE_VER_INFO_CMPL 0x08 /* Byte 1 */ +#define HCI_EVT_MASK_HW_ERROR 0x80 /* Byte 1 */ +#define HCI_EVT_MASK_DATA_BUF_OVERFLOW 0x02 /* Byte 3 */ +#define HCI_EVT_MASK_ENC_KEY_REFRESH_CMPL 0x80 /* Byte 5 */ +#define HCI_EVT_MASK_LE_META 0x20 /* Byte 7 */ + +/* Event mask page 2 */ +#define HCI_EVT_MASK_AUTH_PAYLOAD_TIMEOUT 0x80 /* Byte 2 */ + +/* LE event mask */ +#define HCI_EVT_MASK_LE_CONN_CMPL_EVT 0x01 /* Byte 0 */ +#define HCI_EVT_MASK_LE_ADV_REPORT_EVT 0x02 /* Byte 0 */ +#define HCI_EVT_MASK_LE_CONN_UPDATE_CMPL_EVT 0x04 /* Byte 0 */ +#define HCI_EVT_MASK_LE_READ_REMOTE_FEAT_CMPL_EVT 0x08 /* Byte 0 */ +#define HCI_EVT_MASK_LE_LTK_REQ_EVT 0x10 /* Byte 0 */ +/* New in version 4.1 */ +#define HCI_EVT_MASK_LE_REMOTE_CONN_PARAM_REQ_EVT 0x20 /* Byte 0 */ +/* New in version 4.2 */ +#define HCI_EVT_MASK_LE_DATA_LEN_CHANGE_EVT 0x40 /* Byte 0 */ +#define HCI_EVT_MASK_LE_READ_LOCAL_P256_PUB_KEY_CMPL 0x80 /* Byte 0 */ +#define HCI_EVT_MASK_LE_GENERATE_DHKEY_CMPL 0x01 /* Byte 1 */ +#define HCI_EVT_MASK_LE_ENHANCED_CONN_CMPL_EVT 0x02 /* Byte 1 */ +#define HCI_EVT_MASK_LE_DIRECT_ADV_REPORT_EVT 0x04 /* Byte 1 */ +/* New in version 5.0 */ +#define HCI_EVT_MASK_LE_PHY_UPDATE_CMPL_EVT 0x08 /* Byte 1 */ +#define HCI_EVT_MASK_LE_EXT_ADV_REPORT_EVT 0x10 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_SYNC_EST_EVT 0x20 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_REPORT_EVT 0x40 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_SYNC_LOST_EVT 0x80 /* Byte 1 */ +#define HCI_EVT_MASK_LE_SCAN_TIMEOUT_EVT 0x01 /* Byte 2 */ +#define HCI_EVT_MASK_LE_ADV_SET_TERM_EVT 0x02 /* Byte 2 */ +#define HCI_EVT_MASK_LE_SCAN_REQ_RCVD_EVT 0x04 /* Byte 2 */ +#define HCI_EVT_MASK_LE_CH_SEL_ALGO_EVT 0x08 /* Byte 2 */ + +/* LE supported features */ +/* New in version 4.0 */ +#define HCI_LE_SUP_FEAT_ENCRYPTION 0x0001 /*!< Encryption supported */ +/* New in version 4.1 */ +#define HCI_LE_SUP_FEAT_CONN_PARAM_REQ_PROC 0x0002 /*!< Connection Parameters Request Procedure supported */ +#define HCI_LE_SUP_FEAT_EXT_REJECT_IND 0x0004 /*!< Extended Reject Indication supported */ +#define HCI_LE_SUP_FEAT_SLV_INIT_FEAT_EXCH 0x0008 /*!< Slave-Initiated Features Exchange supported */ +#define HCI_LE_SUP_FEAT_LE_PING 0x0010 /*!< LE Ping supported */ +/* New in version 4.2 */ +#define HCI_LE_SUP_FEAT_DATA_LEN_EXT 0x0020 /*!< Data Length Extension supported */ +#define HCI_LE_SUP_FEAT_PRIVACY 0x0040 /*!< LL Privacy supported */ +#define HCI_LE_SUP_FEAT_EXT_SCAN_FILT_POLICY 0x0080 /*!< Extended Scan Filter Policy supported */ +/* New in version 5.0 */ +#define HCI_LE_SUP_FEAT_LE_2M_PHY 0x0100 /*!< LE 2M PHY supported */ +#define HCI_LE_SUP_FEAT_STABLE_MOD_IDX_TRANSMITTER 0x0200 /*!< Stable Modulation Index - Transmitter supported */ +#define HCI_LE_SUP_FEAT_STABLE_MOD_IDX_RECEIVER 0x0400 /*!< Stable Modulation Index - Receiver supported */ +#define HCI_LE_SUP_FEAT_LE_CODED_PHY 0x0800 /*!< LE Coded PHY supported */ +#define HCI_LE_SUP_FEAT_LE_EXT_ADV 0x1000 /*!< LE Extended Advertising supported */ +#define HCI_LE_SUP_FEAT_LE_PER_ADV 0x2000 /*!< LE Periodic Advertising supported */ +#define HCI_LE_SUP_FEAT_CH_SEL_2 0x4000 /*!< Channel Selection Algorithm #2 supported */ +#define HCI_LE_SUP_FEAT_LE_POWER_CLASS_1 0x8000 /*!< LE Power Class 1 supported */ + +/* Advertising command parameters */ +#define HCI_ADV_MIN_INTERVAL 0x0020 /*!< Minimum advertising interval */ +#define HCI_ADV_MAX_INTERVAL 0x4000 /*!< Maximum advertising interval */ +#define HCI_ADV_DIRECTED_MAX_DURATION 0x0500 /*!< Maximum high duty cycle connectable directed advertising duration */ +#define HCI_ADV_TYPE_CONN_UNDIRECT 0x00 /*!< Connectable undirected advertising */ +#define HCI_ADV_TYPE_CONN_DIRECT 0x01 /*!< Connectable directed high duty cycle advertising */ +#define HCI_ADV_TYPE_DISC_UNDIRECT 0x02 /*!< Discoverable undirected advertising */ +#define HCI_ADV_TYPE_NONCONN_UNDIRECT 0x03 /*!< Nonconnectable undirected advertising */ +#define HCI_ADV_TYPE_CONN_DIRECT_LO_DUTY 0x04 /*!< Connectable directed low duty cycle advertising */ +#define HCI_ADV_CHAN_37 0x01 /*!< Advertising channel 37 */ +#define HCI_ADV_CHAN_38 0x02 /*!< Advertising channel 38 */ +#define HCI_ADV_CHAN_39 0x04 /*!< Advertising channel 39 */ +#define HCI_ADV_FILT_NONE 0x00 /*!< No scan request or connection filtering */ +#define HCI_ADV_FILT_SCAN 0x01 /*!< White list filters scan requests */ +#define HCI_ADV_FILT_CONN 0x02 /*!< White list filters connections */ +#define HCI_ADV_FILT_ALL 0x03 /*!< White list filters scan req. and conn. */ + +/* Scan command parameters */ +#define HCI_SCAN_TYPE_PASSIVE 0 /*!< Passive scan */ +#define HCI_SCAN_TYPE_ACTIVE 1 /*!< Active scan */ +#define HCI_SCAN_INTERVAL_MIN 0x0004 /*!< Minimum scan interval */ +#define HCI_SCAN_INTERVAL_MAX 0x4000 /*!< Maximum scan interval */ +#define HCI_SCAN_INTERVAL_DEFAULT 0x0010 /*!< Default scan interval */ +#define HCI_SCAN_WINDOW_MIN 0x0004 /*!< Minimum scan window */ +#define HCI_SCAN_WINDOW_MAX 0x4000 /*!< Maximum scan window */ +#define HCI_SCAN_WINDOW_DEFAULT 0x0010 /*!< Default scan window */ + +/* Connection command parameters */ +#define HCI_CONN_INTERVAL_MIN 0x0006 /*!< Minimum connection interval */ +#define HCI_CONN_INTERVAL_MAX 0x0C80 /*!< Maximum connection interval */ +#define HCI_CONN_LATENCY_MAX 0x01F3 /*!< Maximum connection latency */ +#define HCI_SUP_TIMEOUT_MIN 0x000A /*!< Minimum supervision timeout */ +#define HCI_SUP_TIMEOUT_MAX 0x0C80 /*!< Maximum supervision timeout */ + +/* Connection event parameters */ +#define HCI_ROLE_MASTER 0 /*!< Role is master */ +#define HCI_ROLE_SLAVE 1 /*!< Role is slave */ +#define HCI_CLOCK_500PPM 0x00 /*!< 500 ppm clock accuracy */ +#define HCI_CLOCK_250PPM 0x01 /*!< 250 ppm clock accuracy */ +#define HCI_CLOCK_150PPM 0x02 /*!< 150 ppm clock accuracy */ +#define HCI_CLOCK_100PPM 0x03 /*!< 100 ppm clock accuracy */ +#define HCI_CLOCK_75PPM 0x04 /*!< 75 ppm clock accuracy */ +#define HCI_CLOCK_50PPM 0x05 /*!< 50 ppm clock accuracy */ +#define HCI_CLOCK_30PPM 0x06 /*!< 30 ppm clock accuracy */ +#define HCI_CLOCK_20PPM 0x07 /*!< 20 ppm clock accuracy */ + +/* Advertising report event parameters */ +#define HCI_ADV_CONN_UNDIRECT 0x00 /*!< Connectable undirected advertising */ +#define HCI_ADV_CONN_DIRECT 0x01 /*!< Connectable directed advertising */ +#define HCI_ADV_DISC_UNDIRECT 0x02 /*!< Discoverable undirected advertising */ +#define HCI_ADV_NONCONN_UNDIRECT 0x03 /*!< Non-connectable undirected advertising */ +#define HCI_ADV_SCAN_RESPONSE 0x04 /*!< Scan response */ + +/*! Extended advertising data operations */ +#define HCI_ADV_DATA_OP_FRAG_INTER 0x00 /*!< Intermediate fragment */ +#define HCI_ADV_DATA_OP_FRAG_FIRST 0x01 /*!< First fragment */ +#define HCI_ADV_DATA_OP_FRAG_LAST 0x02 /*!< Last fragment */ +#define HCI_ADV_DATA_OP_COMP_FRAG 0x03 /*!< Complete extended advertising data */ +#define HCI_ADV_DATA_OP_UNCHANGED_DATA 0x04 /*!< Unchanged data (just update Advertising DID) */ + +/*! Advertising data fragment preference */ +#define HCI_ADV_DATA_FRAG_PREF_FRAG 0x00 /*!< Controller may fragment all Host advertising data */ +#define HCI_ADV_DATA_FRAG_PREF_NO_FRAG 0x01 /*!< Controller should not fragment nor minimize fragmentation of Host advertising data */ + +/*! Number of advertising sets */ +#define HCI_ADV_NUM_SETS_ALL_DISABLE 0x00 /*!< Disable all advertising sets */ + +/*! Maximum number of scanning or initiating PHYs */ +#define HCI_MAX_NUM_PHYS 3 /*! Maximum number of scanning or initiating PHYs */ + +/*! Advertising PHY values */ +#define HCI_ADV_PHY_LE_1M 0x01 /*!< LE 1M PHY */ +#define HCI_ADV_PHY_LE_2M 0x02 /*!< LE 2M PHY */ +#define HCI_ADV_PHY_LE_CODED 0x03 /*!< LE Coded PHY */ + +/*! Scanner PHY value bits */ +#define HCI_SCAN_PHY_LE_1M_BIT (1<<0) /*!< LE 1M PHY */ +#define HCI_SCAN_PHY_LE_2M_BIT (1<<1) /*!< LE 2M PHY */ +#define HCI_SCAN_PHY_LE_CODED_BIT (1<<2) /*!< LE Coded PHY */ + +/*! Initiator PHY value bits */ +#define HCI_INIT_PHY_LE_1M_BIT (1<<0) /*!< LE 1M PHY */ +#define HCI_INIT_PHY_LE_2M_BIT (1<<1) /*!< LE 2M PHY */ +#define HCI_INIT_PHY_LE_CODED_BIT (1<<2) /*!< LE Coded PHY */ + +/*! Advertising event properties type bits */ +#define HCI_ADV_PROP_CONN_ADV_BIT (1<<0) /*!< Connectable advertising bit */ +#define HCI_ADV_PROP_SCAN_ADV_BIT (1<<1) /*!< Scannable advertising bit */ +#define HCI_ADV_PROP_DIRECT_ADV_BIT (1<<2) /*!< Directed advertising bit */ +#define HCI_ADV_PROP_CONN_DIRECT_ADV_BIT (1<<3) /*!< High duty cycle connectable directed advertising bit */ +#define HCI_ADV_PROP_USE_LEG_PDU_BIT (1<<4) /*!< Use legacy advertising PDUs bit */ +#define HCI_ADV_PROP_OMIT_ADV_ADDR_BIT (1<<5) /*!< Omit advertiser's address from all PDUs (anonymous advertising) bit */ +#define HCI_ADV_PROP_INC_TX_PWR_BIT (1<<6) /*!< Include TxPower in extended header of advertising PDU bit */ + +/*! Advertising event properties for legacy PDUs */ +#define HCI_ADV_PROP_LEG_CONN_UNDIRECT 0x13 /*!< Connectable and scannable undirected advertising (00010011b) */ +#define HCI_ADV_PROP_LEG_CONN_DIRECT 0x1D /*!< Connectable directed high duty cycle advertising (00011101b) */ +#define HCI_ADV_PROP_LEG_SCAN_UNDIRECT 0x12 /*!< Scannable undirected advertising (00010010b) */ +#define HCI_ADV_PROP_LEG_NONCONN_UNDIRECT 0x10 /*!< Non-connectable and non-scannable undirected advertising (00010000b) */ +#define HCI_ADV_PROP_LEG_CONN_DIRECT_LO_DUTY 0x15 /*!< Connectable directed low duty cycle advertising (00010101b) */ + +/*! Extended advertising report event type bits */ +#define HCI_ADV_RPT_CONN_ADV_BIT (1<<0) /*!< Connectable advertising event bit */ +#define HCI_ADV_RPT_SCAN_ADV_BIT (1<<1) /*!< Scannable advertising event bit */ +#define HCI_ADV_RPT_DIRECT_ADV_BIT (1<<2) /*!< Directed advertising event bit */ +#define HCI_ADV_RPT_SCAN_RSP_BIT (1<<3) /*!< Scan response event bit */ +#define HCI_ADV_RPT_LEG_ADV_BIT (1<<4) /*!< Legacy advertising PDU event bit */ +#define HCI_ADV_RPT_DATA_STATUS_BITS (3<<5) /*!< Data status bits */ + +/*! Advertising report event types for legacy PDUs */ +#define HCI_ADV_RPT_LEG_CONN_UNDIRECT 0x13 /*! Connectable and scannable undirected advertising (0010011b) */ +#define HCI_ADV_RPT_LEG_CONN_DIRECT 0x15 /*! Connectable directed advertising (0010101b) */ +#define HCI_ADV_RPT_LEG_SCAN_UNDIRECT 0x12 /*! Scannable undirected advertising (0010010b) */ +#define HCI_ADV_RPT_LEG_NONCONN_UNDIRECT 0x10 /*! Non-connectable and non-scannable undirected advertising (0010000b) */ +#define HCI_ADV_RPT_LEG_CONN_UNDIRECT_SCAN_RSP 0x1B /*! Scan response to connectable and scannable undirected advertising (0011011b) */ +#define HCI_ADV_RPT_LEG_SCAN_UNDIRECT_SCAN_RSP 0x1A /*! Scan response to scannable undirected advertising (0011010b) */ + +/*! Advertising report data status */ +#define HCI_ADV_RPT_DATA_CMPL 0x00 /*!< Data complete */ +#define HCI_ADV_RPT_DATA_INCMPL_MORE 0x01 /*!< Data incomplete, more date to come */ +#define HCI_ADV_RPT_DATA_INCMPL_TRUNC 0x02 /*!< Data incomplete, data truncated, no more date to come */ + +/*! Extended advertising report event primary PHY values */ +#define HCI_ADV_RPT_PHY_PRIM_LE_1M 0x01 /*!< Advertiser PHY is LE 1M */ +#define HCI_ADV_RPT_PHY_PRIM_LE_CODED 0x03 /*!< Advertiser PHY is LE Coded */ + +/*! Extended advertising report event seconday PHY values */ +#define HCI_ADV_RPT_PHY_SEC_NONE 0x00 /*!< No packets on seconday advertising channel */ +#define HCI_ADV_RPT_PHY_SEC_LE_1M 0x01 /*!< Advertiser PHY is LE 1M */ +#define HCI_ADV_RPT_PHY_SEC_LE_2M 0x02 /*!< Advertiser PHY is LE 2M */ +#define HCI_ADV_RPT_PHY_SEC_LE_CODED 0x03 /*!< Advertiser PHY is LE Coded */ + +/*! Channel selection algorithm used */ +#define HCI_CH_SEL_ALGO_1 0x00 /*!< LE channel selection algorithm #1 used */ +#define HCI_CH_SEL_ALGO_2 0x01 /*!< LE channel selection algorithm #2 used */ + +/*! Minimum number of used channels */ +#define HCI_MIN_NUM_OF_USED_CHAN 8 /*!< Minimum number of used channels */ + +/* Misc command parameters */ +#define HCI_READ_TX_PWR_CURRENT 0 /*!< Read current tx power */ +#define HCI_READ_TX_PWR_MAX 1 /*!< Read maximum tx power */ +#define HCI_TX_PWR_MIN -30 /*!< Minimum tx power dBm */ +#define HCI_TX_PWR_MAX 20 /*!< Maximum tx power dBm */ +#define HCI_TX_PWR_NO_PREFERENCE 127 /*!< Tx power no preference */ +#define HCI_VERSION 6 /*!< HCI specification version */ +#define HCI_RSSI_MIN -127 /*!< Minimum RSSI dBm */ +#define HCI_RSSI_MAX 20 /*!< Maximum RSSI dBm */ +#define HCI_ADDR_TYPE_PUBLIC 0 /*!< Public device address */ +#define HCI_ADDR_TYPE_RANDOM 1 /*!< Random device address */ +#define HCI_ADDR_TYPE_PUBLIC_IDENTITY 2 /*!< Public identity address */ +#define HCI_ADDR_TYPE_RANDOM_IDENTITY 3 /*!< Random identity address */ +#define HCI_ADDR_TYPE_ANONYMOUS 0xFF /*!< Anonymous device address */ +#define HCI_FILT_NONE 0 /*!< Accept all advertising packets */ +#define HCI_FILT_WHITE_LIST 1 /*!< Accept from While List only */ +#define HCI_FILT_RES_INIT 2 /*!< Accept directed advertisements with RPAs */ +#define HCI_FILT_WHITE_LIST_RES_INIT 3 /*!< Accept from White List or directed advertisements with RPAs */ +#define HCI_FILT_PER_ADV_PARAM 0 /*!< Listen to advertiser specified by create sync command parameters */ +#define HCI_FILT_PER_ADV_LIST 1 /*!< Listen to advertiser from Periodic Advertiser List only */ +#define HCI_ROLE_MASTER 0 /*!< Role is master */ +#define HCI_ROLE_SLAVE 1 /*!< Role is slave */ +#define HCI_PRIV_MODE_NETWORK 0x00 /*!< Network privacy mode (default) */ +#define HCI_PRIV_MODE_DEVICE 0x01 /*!< Device privacy mode */ + +/*! PHY types */ +#define HCI_PHY_NONE 0x00 /*! No selected PHY */ +#define HCI_PHY_LE_1M_BIT (1<<0) /*! LE 1M PHY */ +#define HCI_PHY_LE_2M_BIT (1<<1) /*! LE 2M PHY */ +#define HCI_PHY_LE_CODED_BIT (1<<2) /*! LE Coded PHY */ + +/*! All PHYs preference */ +#define HCI_ALL_PHY_ALL_PREFERENCES 0x00 /*! All PHY preferences */ +#define HCI_ALL_PHY_TX_PREFERENCE_BIT (1<<0) /*! Tx PHY preference */ +#define HCI_ALL_PHY_RX_PREFERENCE_BIT (1<<1) /*! Rx PHY preference */ + +/*! PHY options */ +#define HCI_PHY_OPTIONS_NONE 0x00 /*! No preferences */ + +/* Parameter lengths */ +#define HCI_EVT_MASK_LEN 8 /*!< Length of event mask byte array */ +#define HCI_EVT_MASK_PAGE_2_LEN 8 /*!< Length of event mask page 2 byte array */ +#define HCI_LE_EVT_MASK_LEN 8 /*!< Length of LE event mask byte array */ +#define HCI_FEAT_LEN 8 /*!< Length of features byte array */ +#define HCI_ADV_DATA_LEN 31 /*!< Length of advertising data */ +#define HCI_SCAN_DATA_LEN 31 /*!< Length of scan response data */ +#define HCI_EXT_ADV_DATA_LEN 251 /*!< Length of extended advertising data */ +#define HCI_PER_ADV_DATA_LEN 252 /*!< Length of periodic advertising data */ +#define HCI_EXT_ADV_RPT_DATA_LEN 229 /*!< Length of extended advertising report data */ +#define HCI_PER_ADV_RPT_DATA_LEN 248 /*!< Length of periodic advertising report data */ +#define HCI_CHAN_MAP_LEN 5 /*!< Length of channel map byte array */ +#define HCI_KEY_LEN 16 /*!< Length of encryption key */ +#define HCI_ENCRYPT_DATA_LEN 16 /*!< Length of data used in encryption */ +#define HCI_RAND_LEN 8 /*!< Length of random number */ +#define HCI_LE_STATES_LEN 8 /*!< Length of LE states byte array */ +#define HCI_P256_KEY_LEN 64 /*!< Length of P256 key */ +#define HCI_DH_KEY_LEN 32 /*!< Length of DH Key */ + +#define HCI_EXT_ADV_RPT_DATA_LEN_OFFSET 23 /*!< Length field offset of extended advertising report data */ +#define HCI_PER_ADV_RPT_DATA_LEN_OFFSET 5 /*!< Length field offset of periodic advertising report data */ + +/* Company ID */ +#define HCI_ID_ARM 0x005F /*! ARM Ltd. company ID */ + +/* Manufacturer location in Local version */ +#define HCI_LOCAL_VER_MANUFACTURER_POS 4 + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h new file mode 100644 index 00000000000..8c00ef377c2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h @@ -0,0 +1,341 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer constant definitions. + * + * $Date: 2017-03-10 20:10:06 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11511 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ + +#ifndef LL_DEFS_H +#define LL_DEFS_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*** Version ***/ + +#define LL_VER_BT_CORE_SPEC_4_0 0x06 /*!< Bluetooth core specification 4.0 */ +#define LL_VER_BT_CORE_SPEC_4_1 0x07 /*!< Bluetooth core specification 4.1 */ +#define LL_VER_BT_CORE_SPEC_4_2 0x08 /*!< Bluetooth core specification 4.2 */ +#define LL_VER_BT_CORE_SPEC_5_0 0x09 /*!< Bluetooth core specification 5.0 */ + +#define LL_COMP_ID_ARM 0x005F /*!< ARM Ltd. company ID. */ + +/*** Common ***/ + +#define LL_RSSI_MIN -127 /*!< Minimum RSSI value. */ +#define LL_RSSI_MAX 20 /*!< Maximum RSSI value. */ +#define LL_RSSI_NOT_AVAIL 127 /*!< RSSI is not available. */ + +#define LL_CRC_LEN 3 /*!< CRC length. */ +#define LL_AA_LEN 4 /*!< Access address length. */ +#define LL_PREAMBLE_LEN_1M 1 /*!< Preamble length (LE 1M PHY). */ +#define LL_PREAMBLE_LEN_2M 2 /*!< Preamble length (LE 2M PHY). */ +#define LL_PREAMBLE_LEN_CODED_BITS 10 /*!< Preamble length (LE Coded PHY). */ +#define LL_CI_LEN_BITS 2 /*!< Coding indicator length (LE Coded PHY). */ +#define LL_TERM1_LEN_BITS 3 /*!< TERM1 length (LE Coded PHY). */ +#define LL_TERM2_LEN_BITS 3 /*!< TERM2 length (LE Coded PHY). */ + +#define LL_RAND_ADDR_MSBS_MASK 0x03 /*!< Mask of 2 most significant bits of BD Random Address */ +#define LL_RAND_ADDR_MSBS_POS 46 /*!< Position of 2 MSBs of BD Random Address */ +#define LL_RAND_ADDR_MSBS_STATIC 0x03 /*!< 2 most significant bits of BD Random Address are '0b11', static random address */ +#define LL_RAND_ADDR_MSBS_RPA 0x01 /*!< 2 most significant bits of BD Random Address are '0b01', resolvable private address */ +#define LL_RAND_ADDR_MSBS_NRPA 0x00 /*!< 2 most significant bits of BD Random Address are '0b00', non-resolvable private address */ +#define LL_RAND_ADDR_MSBS_IVLD 0x02 /*!< 2 most significant bits of BD Random Address are '0b10', invalid random address */ + +/*** Advertising PDU ***/ + +/*! \brief Advertising channel PDU types. */ +enum +{ + /* --- Core Spec 4.0 --- */ + LL_PDU_ADV_IND = 0, /*!< Connectable undirected advertising PDU. */ + LL_PDU_ADV_DIRECT_IND = 1, /*!< Connectable directed advertising PDU. */ + LL_PDU_ADV_NONCONN_IND = 2, /*!< Non-connectable undirected advertising PDU. */ + LL_PDU_SCAN_REQ = 3, /*!< Scan request PDU. */ + LL_PDU_SCAN_RSP = 4, /*!< Scan response PDU. */ + LL_PDU_CONNECT_IND = 5, /*!< Connect indication PDU. */ + LL_PDU_ADV_SCAN_IND = 6, /*!< Scannable undirected advertising PDU. */ + /* --- Core Spec 5.0 --- */ + LL_PDU_AUX_SCAN_REQ = 3, /*!< Auxiliary scan request PDU. */ + LL_PDU_AUX_CONNECT_REQ = 5, /*!< Auxiliary connect request PDU. */ + LL_PDU_ADV_EXT_IND = 7, /*!< Extended advertising PDU. */ + LL_PDU_AUX_ADV_IND = 7, /*!< Auxiliary advertising PDU. */ + LL_PDU_AUX_SCAN_RSP = 7, /*!< Auxiliary scan response PDU. */ + LL_PDU_AUX_SYNC_IND = 7, /*!< Auxiliary synchronize PDU. */ + LL_PDU_AUX_CHAIN_IND = 7, /*!< Auxiliary chain PDU. */ + LL_PDU_AUX_CONNECT_RSP = 8, /*!< Auxiliary connect response PDU. */ +}; + +#define LL_SCAN_REQ_PDU_LEN 12 /*!< Size of a scan request PDU. */ +#define LL_CONN_IND_PDU_LEN 34 /*!< Size of a connect indication PDU. */ + +#define LL_CHAN_ADV_MIN_IDX 37 /*!< Minimum advertising channel index. */ +#define LL_CHAN_ADV_MAX_IDX 39 /*!< Maximum advertising channel index. */ +#define LL_NUM_CHAN_ADV 3 /*!< Total number of advertising channels. */ + +#define LL_ADVBU_MAX_LEN 31 /*!< Maximum advertising channel host data length. */ +#define LL_ADVB_MAX_LEN 39 /*!< Maximum advertising channel PDU length. */ +#define LL_ADVB_MIN_LEN (LL_ADVB_MAX_LEN - LL_ADVBU_MAX_LEN) /*!< Minimum advertising channel packet length. */ +#define LL_ADVB_MAX_TIME_1M ((LL_BLE_US_PER_BYTE_1M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Maximum time for a 1M advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_2M ((LL_BLE_US_PER_BYTE_2M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_2M) + /*!< Maximum time for a 2M advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_S2 ((LL_BLE_US_PER_BYTE_CODED_S2 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) + /*!< Maximum time for a Coded S2 advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_S8 ((LL_BLE_US_PER_BYTE_CODED_S8 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) + /*!< Maximum time for a Coded S8 advertising channel PDU. */ + +#define LL_ADV_PKT_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for an advertising packet. */ +#define LL_SCAN_REQ_MAX_USEC ((8 * (LL_ADV_PREFIX_LEN + LL_SCAN_PREFIX_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Maximum time in microseconds for a scan request packet. */ +#define LL_SCAN_RSP_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for a scan response packet. */ + +#define LL_ADV_HDR_LEN 2 /*!< Advertising channel header length. */ +#define LL_ADV_HDR_TYPE_OFFS 0 /*!< Advertising header type offset. */ +#define LL_ADV_HDR_TYPE_MSK 0x0F /*!< Advertising header type mask. */ +#define LL_ADV_HDR_LEN_OFFS 1 /*!< Advertising header length offset. */ +#define LL_ADV_HDR_LEN_MSK 0x3F /*!< Advertising header length mask for 4.2. */ +#define LL_ADV_EXT_HDR_LEN_MSK 0xFF /*!< Advertising extension header length mask for 5.0. */ +#define LL_ADV_PREFIX_LEN 6 /*!< Advertising PDU payload prefix length (AdvA). */ +#define LL_SCAN_PREFIX_LEN 6 /*!< Scan request/response PDU payload prefix length (AdvA). */ + +#define LL_ADV_ACCESS_ADDR UINT32_C(0x8E89BED6) /*!< Advertising channel access address. */ +#define LL_ADV_CRC_INIT UINT32_C(0x555555) /*!< Advertising CRC initial value. */ + +#define LL_DIR_ADV_INTER_TICKS 6 /*!< Advertising interval between directed advertising events (3.75 ms). */ +#define LL_DIR_ADV_DUR_TICKS 2048 /*!< Maximum high duty cycle directed advertising duration (1.28 seconds). */ + +enum +{ + LL_EXT_HDR_ADV_ADDR_BIT = (1 << 0), /*!< Extended header AdvA bit. */ + LL_EXT_HDR_TGT_ADDR_BIT = (1 << 1), /*!< Extended header TargetA bit. */ + LL_EXT_HDR_SUPP_INFO_BIT = (1 << 2), /*!< Extended header SuppInfo bit. */ + LL_EXT_HDR_ADI_BIT = (1 << 3), /*!< Extended header AdvDataInfo bit. */ + LL_EXT_HDR_AUX_PTR_BIT = (1 << 4), /*!< Extended header AuxPtr bit. */ + LL_EXT_HDR_SYNC_INFO_BIT = (1 << 5), /*!< Extended header SyncInfo bit. */ + LL_EXT_HDR_TX_PWR_BIT = (1 << 6), /*!< Extended header TxPower bit. */ +}; + +#define LL_MAX_ADV_HANDEL 0xEF /*!< Maximum advertising handle. */ +#define LL_MAX_ADV_SID 0x0F /*!< Maximum advertising SID */ + + +#define LL_EXT_ADV_HDR_MIN_LEN 1 /*!< Minimum extended advertising header length (+1 for ExtHdrLen and AdvMode fields). */ +#define LL_EXT_ADV_HDR_MAX_LEN 64 /*!< Maximum extended advertising header length (+1 for ExtHdrLen and AdvMode fields). */ +#define LL_EXT_ADVBU_MAX_LEN 251 /*!< Maximum extended advertising channel PDU host data length. */ +#define LL_EXT_ADVB_MAX_LEN 257 /*!< Maximum extended advertising channel PDU length. */ + +#define LL_AUX_PTR_MAX_USEC 2457600 /*!< Maximum AuxPtr offset value in microseconds. */ + +#define LL_SYNC_MIN_TIMEOUT 0x000A /*!< Minimum synchronization timeout. */ +#define LL_SYNC_MAX_TIMEOUT 0x4000 /*!< Maximum synchronization timeout. */ +#define LL_SYNC_MAX_SKIP 0x01F3 /*!< Maximum synchronization skip. */ +#define LL_SYNC_MAX_HANDLE 0x0EFF /*!< Maximum synchronization handle. */ + +#define LL_PER_ADV_INT_MIN 0x0006 /*!< Minimum periodic advertising interval. */ + + +/*** Data PDU ***/ + +/*! \brief Data channel LL Control PDU types. */ +enum +{ + /* --- Core Spec 4.0 --- */ + LL_PDU_CONN_UPDATE_IND = 0x00, /*!< Connection update indication PDU. */ + LL_PDU_CHANNEL_MAP_IND = 0x01, /*!< Channel map indication PDU. */ + LL_PDU_TERMINATE_IND = 0x02, /*!< Terminate indication PDU. */ + LL_PDU_ENC_REQ = 0x03, /*!< Encryption request PDU. */ + LL_PDU_ENC_RSP = 0x04, /*!< Encryption response PDU. */ + LL_PDU_START_ENC_REQ = 0x05, /*!< Start encryption request PDU. */ + LL_PDU_START_ENC_RSP = 0x06, /*!< Start encryption response PDU. */ + LL_PDU_UNKNOWN_RSP = 0x07, /*!< Unknown response PDU. */ + LL_PDU_FEATURE_REQ = 0x08, /*!< Feature request PDU. */ + LL_PDU_FEATURE_RSP = 0x09, /*!< Feature response PDU. */ + LL_PDU_PAUSE_ENC_REQ = 0x0A, /*!< Pause encryption request PDU. */ + LL_PDU_PAUSE_ENC_RSP = 0x0B, /*!< Pause encryption response PDU. */ + LL_PDU_VERSION_IND = 0x0C, /*!< Version indication PDU. */ + LL_PDU_REJECT_IND = 0x0D, /*!< Reject indication PDU. */ + /* --- Core Spec 4.2 --- */ + LL_PDU_SLV_FEATURE_REQ = 0x0E, /*!< Slave feature request PDU. */ + LL_PDU_CONN_PARAM_REQ = 0x0F, /*!< Connection parameter request PDU. */ + LL_PDU_CONN_PARAM_RSP = 0x10, /*!< Connection parameter response PDU. */ + LL_PDU_REJECT_EXT_IND = 0x11, /*!< Reject extended indication PDU. */ + LL_PDU_PING_REQ = 0x12, /*!< Ping request PDU. */ + LL_PDU_PING_RSP = 0x13, /*!< Ping response PDU. */ + LL_PDU_LENGTH_REQ = 0x14, /*!< Data length request PDU. */ + LL_PDU_LENGTH_RSP = 0x15, /*!< Data length response PDU. */ + /* --- Core Spec 5.0 --- */ + LL_PDU_PHY_REQ = 0x16, /*!< PHY request PDU. */ + LL_PDU_PHY_RSP = 0x17, /*!< PHY response PDU. */ + LL_PDU_PHY_UPDATE_IND = 0x18, /*!< PHY update indication PDU. */ + LL_PDU_MIN_USED_CHAN_IND = 0x19, /*!< Minimum used channels indication PDU. */ + LL_PDU_UNSPECIFIED = 0xFF /*!< Unspecified PDU. */ +}; + +/* Data PDU length */ +/* --- Core Spec 4.0 --- */ +#define LL_CONN_UPD_IND_PDU_LEN 12 /*!< Connection update indication PDU length. */ +#define LL_CHAN_MAP_IND_PDU_LEN 8 /*!< Channel map indication PDU length. */ +#define LL_TERMINATE_IND_PDU_LEN 2 /*!< Terminate indication PDU length. */ +#define LL_ENC_REQ_LEN 23 /*!< Encryption request PDU length. */ +#define LL_ENC_RSP_LEN 13 /*!< Encryption response PDU length. */ +#define LL_START_ENC_LEN 1 /*!< Start encryption request/response PDU length. */ +#define LL_UNKNOWN_RSP_LEN 2 /*!< Unknown response PDU length. */ +#define LL_FEATURE_PDU_LEN 9 /*!< Feature request/response PDU length. */ +#define LL_PAUSE_ENC_LEN 1 /*!< Pause encryption request/response PDU length. */ +#define LL_VERSION_IND_PDU_LEN 6 /*!< Version indication PDU length. */ +#define LL_REJECT_IND_PDU_LEN 2 /*!< Reject indication PDU length. */ +/* --- Core Spec 4.2 --- */ +#define LL_CONN_PARAM_PDU_LEN 24 /*!< Connection parameter request or response PDU length. */ +#define LL_REJECT_EXT_IND_PDU_LEN 3 /*!< Reject extended indication PDU length. */ +#define LL_PING_PDU_LEN 1 /*!< Ping request/response PDU length. */ +#define LL_DATA_LEN_PDU_LEN 9 /*!< Data length request or response PDU length. */ +/* --- Core Spec 5.0 --- */ +#define LL_PHY_PDU_LEN 3 /*!< PHY request/response PDU length. */ +#define LL_PHY_UPD_IND_PDU_LEN 5 /*!< PHY update indication PDU length. */ +#define LL_MIN_USED_CHAN_PDU_LEN 3 /*!< Minimum used channels indication PDU length. */ + +#define LL_EMPTY_PDU_LEN 2 /*!< Length of an empty data PDU. */ + +#define LL_DATA_HDR_LEN 2 /*!< Data channel header length. */ +#define LL_DATA_MIC_LEN 4 /*!< Data channel PDU MIC length. */ + +#define LL_DATA_HDR_LLID_MSK 0x03 /*!< Data PDU LLID mask. */ +#define LL_DATA_HDR_LEN_MSK 0xFF /*!< Data header length mask. BLE 4.2 data len extension allows 8 bits. */ + +#define LL_MAX_NUM_CHAN_DATA 37 /*!< Maximum number of used data channels. */ +#define LL_MIN_NUM_CHAN_DATA 2 /*!< Minimum number of used data channels. */ + +/*! \brief Data PDU LLID types. */ +enum +{ + LL_LLID_VS_PDU = 0x00, /*!< Vendor specific PDU. */ + /* N.B. next two enumerations intentionally use identical values. */ + LL_LLID_EMPTY_PDU = 0x01, /*!< Empty PDU. */ + LL_LLID_CONT_PDU = 0x01, /*!< Data PDU: continuation fragment of an L2CAP message. */ + LL_LLID_START_PDU = 0x02, /*!< Data PDU: start of an L2CAP message or a complete L2CAP message with no fragmentation. */ + LL_LLID_CTRL_PDU = 0x03, /*!< Control PDU. */ +}; + +/*** Encryption ***/ + +#define LL_ECC_KEY_LEN 32 /*!< ECC key length. */ + +#define LL_DEF_RES_ADDR_TO_SEC 900 /*!< Default resolvable address timeout in seconds. */ + +#define LL_RAND_LEN 8 /*!< Length of random number */ +#define LL_KEY_LEN 16 /*!< Encryption key length. */ +#define LL_SKD_LEN LL_KEY_LEN /*!< Session key diversifier length. */ +#define LL_IV_LEN 8 /*!< Initialization vector length. */ + +#define LL_DEF_AUTH_TO_MS 30000 /*!< Default authentication timeout in milliseconds. */ + +/*** LLCP ***/ + +#define LL_DATA_LEN_TO_TIME_1M(len) ((LL_BLE_US_PER_BYTE_1M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_2M(len) ((LL_BLE_US_PER_BYTE_2M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_2M) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_CODED_S8(len) ((LL_BLE_US_PER_BYTE_CODED_S8 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_CODED_S2(len) ((LL_BLE_US_PER_BYTE_CODED_S2 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) + /*!< Convert data length to time. */ + +#define LL_MIN_INSTANT 6 /*!< Minimum number of CE to apply a CONN_UPD or CHAN_MAP. */ + +#define LL_MAX_DATA_LEN_MIN 27 /*!< Minimum value for maximum Data PDU length */ +#define LL_MAX_DATA_LEN_ABS_MAX 251 /*!< Absolute maximum limit for maximum Data PDU length */ + +#define LL_MAX_DATA_TIME_MIN 328 /*!< Minimum value for maximum Data PDU time */ +#define LL_MAX_DATA_TIME_ABS_MAX 17040 /*!< Absolute maximum limit for maximum Data PDU time */ +#define LL_MAX_DATA_TIME_ABS_MAX_1M 2120 /*!< Absolute maximum limit for maximum Data PDU time (LE 1M PHY) */ + +#define LL_T_PRT_SEC 40 /*!< LLCP procedure response timeout in seconds. */ + +#define LL_MAX_ADV_DLY_MS 10 /*!< Maximum advertising delay in milliseconds. */ + +#define LL_MIN_CONN_INTERVAL 6 /*!< Minimum value for connection interval. */ +#define LL_MAX_CONN_INTERVAL 3200 /*!< Maximum value for connection interval. */ + +#define LL_MIN_TX_WIN_SIZE 1 /*!< Minimum value for transmit window size. */ +#define LL_MAX_TX_WIN_SIZE 8 /*!< Maximum value for transmit window size. */ + +#define LL_MAX_CONN_LATENCY 499 /*!< Maximum value for connection slave latency. */ + +#define LL_MIN_SUP_TIMEOUT 10 /*!< Minimum value for connection supervision timeout. */ +#define LL_MAX_SUP_TIMEOUT 3200 /*!< Maximum value for connection supervision timeout. */ + +#define LL_MIN_POWER_THRESHOLD -128 /*!< Minimum value for power threshold. */ +#define LL_MAX_POWER_THRESHOLD 127 /*!< Maximum value for power threshold. */ + +#define LL_ALL_PHYS_MSK 0x7 /*!< All supported LE PHYs mask. */ + +/*** DTM ***/ + +#define LL_DTM_HDR_LEN 2 /*!< Direct Test Mode PDU header length. */ +#define LL_DTM_SYNC_WORD UINT32_C(0x71764129) /*!< Direct Test Mode sync word. */ +#define LL_DTM_CRC_INIT UINT32_C(0x555555) /*!< Direct Test Mode CRC initial value. */ +#define LL_DTM_MAX_INT_US 12500 /*!< Maximum time interval between packets in microseconds. */ +#define LL_DTM_PDU_ABS_MAX_LEN 255 /*!< Absolute maximum DTM PDU length. */ +#define LL_DTM_MAX_CHAN_IDX 39 /*!< Maximum channel index. */ + +/*** Baseband ***/ + +#define LL_CHAN_DATA_MIN_IDX 0 /*!< Minimum data channel index. */ +#define LL_CHAN_DATA_MAX_IDX 36 /*!< Maximum data channel index. */ +#define LL_CHAN_DATA_ALL UINT64_C(0x0000001FFFFFFFFF) /*!< Maximum data channel index. */ + +#define LL_BLE_BIT_PER_US 1 /*!< BLE PHY rate. */ +#define LL_BLE_US_PER_BYTE_1M 8 /*!< BLE PHY speed (LE 1M PHY). */ +#define LL_BLE_US_PER_BYTE_2M 4 /*!< BLE PHY speed (LE 2M PHY). */ +#define LL_BLE_US_PER_BYTE_CODED_S8 64 /*!< BLE PHY speed (LE Coded PHY, S=8). */ +#define LL_BLE_US_PER_BIT_CODED_S8 8 /*!< BLE PHY speed (LE Coded PHY, S=8). */ +#define LL_BLE_US_PER_BYTE_CODED_S2 16 /*!< BLE PHY speed (LE Coded PHY, S=2). */ +#define LL_BLE_US_PER_BIT_CODED_S2 2 /*!< BLE PHY speed (LE Coded PHY, S=2). */ +#define LL_BLE_TIFS_US 150 /*!< BLE inter-frame space. */ +#define LL_BLE_MAFS_US 300 /*!< BLE minimum AUX frame space. */ +#define LL_BLE_US_PER_TICK 625 /*!< Microseconds per BLE tick. */ + +#define LL_MIN_PKT_TIME_US_1M 80 /*!< Minimum packet time (i.e. empty PDU) on LE 1M PHY. */ +#define LL_MIN_PKT_TIME_US_2M 44 /*!< Minimum packet time (i.e. empty PDU) on LE 2M PHY. */ +#define LL_MIN_PKT_TIME_US_CODED_S8 720 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=8. */ +#define LL_MIN_PKT_TIME_US_CODED_S2 462 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=2. */ + +#define LL_MIN_ADV_TX_PWR_LVL -20 /*!< Minimum Tx power level for advertising. */ +#define LL_MAX_ADV_TX_PWR_LVL 10 /*!< Maximum Tx power level for advertising. */ + +#define LL_MIN_TX_PWR_LVL -30 /*!< Minimum Tx power level for connections. */ +#define LL_MAX_TX_PWR_LVL 20 /*!< Maximum Tx power level for connections. */ + +#define LL_MAX_TIFS_DEVIATION 2 /*!< Maximum TIFS deviation in microseconds. */ + +#ifdef __cplusplus +}; +#endif + +#endif /* LL_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h new file mode 100644 index 00000000000..7948f672ed8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h @@ -0,0 +1,143 @@ +/*************************************************************************************************/ +/*! + * \file bda.h + * + * \brief Bluetooth device address utilities. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef BDA_H +#define BDA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief BD address length */ +#define BDA_ADDR_LEN 6 + +/*! \brief BD address string length */ +#define BDA_ADDR_STR_LEN (BDA_ADDR_LEN * 2) + +/*! \brief BDA RPA check */ +#define BDA_ADDR_IS_RPA(bda) (((bda)[5] & 0xC0) == 0x40) + +/*! \brief BDA NRPA check */ +#define BDA_ADDR_IS_NRPA(bda) (((bda)[5] & 0xC0) == 0x00) + +/*! \brief BDA static random check */ +#define BDA_ADDR_IS_STATIC(bda) (((bda)[5] & 0xC0) == 0xC0) + +/*! \brief BDA64 RPA check */ +#define BDA64_ADDR_IS_RPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x40) + +/*! \brief BDA64 NRPA check */ +#define BDA64_ADDR_IS_NRPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x00) + +/*! \brief BDA64 static random check */ +#define BDA64_ADDR_IS_STATIC(bda64) ((((bda64) >> 40) & 0xC0) == 0xC0) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief BD address data type */ +typedef uint8_t bdAddr_t[BDA_ADDR_LEN]; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn BdaCpy + * + * \brief Copy a BD address from source to destination. + * + * \param pDst Pointer to destination. + * \param pSrc Pointer to source. + * + * \return None. + */ +/*************************************************************************************************/ +void BdaCpy(uint8_t *pDst, const uint8_t *pSrc); + + +/*************************************************************************************************/ +/*! + * \fn BdaCmp + * + * \brief Compare two BD addresses. + * + * \param pAddr1 First address. + * \param pAddr2 Second address. + * + * \return TRUE if addresses match, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t BdaCmp(const uint8_t *pAddr1, const uint8_t *pAddr2); + +/*************************************************************************************************/ +/*! + * \fn BdaClr + * + * \brief Set a BD address to all zeros. + * + * \param pDst Pointer to destination. + * + * \return pDst + BDA_ADDR_LEN + */ +/*************************************************************************************************/ +uint8_t *BdaClr(uint8_t *pDst); + +/*************************************************************************************************/ +/*! +* \fn BdaIsZeros +* +* \brief Check if a BD address is all zeros. +* +* \param pAddr Pointer to address. +* +* \return TRUE if address is all zeros, FALSE otherwise. +*/ +/*************************************************************************************************/ +bool_t BdaIsZeros(const uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn Bda2Str + * + * \brief Convert a BD address to a string. + * + * \param pAddr Pointer to BD address. + * + * \return Pointer to string. + */ +/*************************************************************************************************/ +char *Bda2Str(const uint8_t *pAddr); + +#ifdef __cplusplus +}; +#endif + +#endif /* BDA_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h new file mode 100644 index 00000000000..a8749b340fe --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h @@ -0,0 +1,152 @@ +/*************************************************************************************************/ +/*! + * \file bstream.h + * + * \brief Byte stream to integer conversion macros. + * + * $Date: 2017-02-06 19:25:09 -0600 (Mon, 06 Feb 2017) $ + * $Revision: 11104 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef BSTREAM_H +#define BSTREAM_H + +#include "bda.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! + * Macros for converting a little endian byte buffer to integers. + */ +#define BYTES_TO_UINT16(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8));} + +#define BYTES_TO_UINT24(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8) + \ + ((uint16_t)(p)[2] << 16));} + +#define BYTES_TO_UINT32(n, p) {n = ((uint32_t)(p)[0] + ((uint32_t)(p)[1] << 8) + \ + ((uint32_t)(p)[2] << 16) + ((uint32_t)(p)[3] << 24));} + +#define BYTES_TO_UINT40(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \ + ((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \ + ((uint64_t)(p)[4] << 32));} + +#define BYTES_TO_UINT64(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \ + ((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \ + ((uint64_t)(p)[4] << 32) + ((uint64_t)(p)[5] << 40) + \ + ((uint64_t)(p)[6] << 48) + ((uint64_t)(p)[7] << 56));} + +/*! + * Macros for converting little endian integers to array of bytes + */ +#define UINT16_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)) +#define UINT32_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)), ((uint8_t)((n) >> 16)), ((uint8_t)((n) >> 24)) + +/*! + * Macros for converting little endian integers to single bytes + */ +#define UINT16_TO_BYTE0(n) ((uint8_t) (n)) +#define UINT16_TO_BYTE1(n) ((uint8_t) ((n) >> 8)) + +#define UINT32_TO_BYTE0(n) ((uint8_t) (n)) +#define UINT32_TO_BYTE1(n) ((uint8_t) ((n) >> 8)) +#define UINT32_TO_BYTE2(n) ((uint8_t) ((n) >> 16)) +#define UINT32_TO_BYTE3(n) ((uint8_t) ((n) >> 24)) + +/*! + * Macros for converting a little endian byte stream to integers, with increment. + */ +#define BSTREAM_TO_INT8(n, p) {n = (int8_t)(*(p)++);} +#define BSTREAM_TO_UINT8(n, p) {n = (uint8_t)(*(p)++);} +#define BSTREAM_TO_UINT16(n, p) {BYTES_TO_UINT16(n, p); p += 2;} +#define BSTREAM_TO_UINT24(n, p) {BYTES_TO_UINT24(n, p); p += 3;} +#define BSTREAM_TO_UINT32(n, p) {BYTES_TO_UINT32(n, p); p += 4;} +#define BSTREAM_TO_UINT40(n, p) {BYTES_TO_UINT40(n, p); p += 5;} +#define BSTREAM_TO_UINT64(n, p) {n = BstreamToUint64(p); p += 8;} +#define BSTREAM_TO_BDA(bda, p) {BdaCpy(bda, p); p += BDA_ADDR_LEN;} +#define BSTREAM_TO_BDA64(bda, p) {bda = BstreamToBda64(p); p += BDA_ADDR_LEN;} + +/*! + * Macros for converting integers to a little endian byte stream, with increment. + */ +#define UINT8_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n);} +#define UINT16_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8);} +#define UINT24_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16);} +#define UINT32_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);} +#define UINT40_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24); \ + *(p)++ = (uint8_t)((n) >> 32);} +#define UINT64_TO_BSTREAM(p, n) {Uint64ToBstream(p, n); p += sizeof(uint64_t);} +#define BDA_TO_BSTREAM(p, bda) {BdaCpy(p, bda); p += BDA_ADDR_LEN;} +#define BDA64_TO_BSTREAM(p, bda) {Bda64ToBstream(p, bda); p += BDA_ADDR_LEN;} + +/*! + * Macros for converting integers to a little endian byte stream, without increment. + */ +#define UINT16_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8);} +#define UINT24_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16);} +#define UINT32_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);} +#define UINT40_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);\ + (p)[4] = (uint8_t)((n) >> 32);} + +/*! + * Macros for comparing a little endian byte buffer to integers. + */ +#define BYTES_UINT16_CMP(p, n) ((p)[1] == UINT16_TO_BYTE1(n) && (p)[0] == UINT16_TO_BYTE0(n)) + +/*! + * Macros for IEEE FLOAT type: exponent = byte 3, mantissa = bytes 2-0 + */ +#define FLT_TO_UINT32(m, e) ((m) | ((int32_t)(e) << 24)) +#define UINT32_TO_FLT(m, e, n) {m = UINT32_TO_FLT_M(n); e = UINT32_TO_FLT_E(n);} +#define UINT32_TO_FLT_M(n) ((((n) & 0x00FFFFFF) >= 0x00800000) ? \ + ((int32_t)(((n) | 0xFF000000))) : ((int32_t)((n) & 0x00FFFFFF))) +#define UINT32_TO_FLT_E(n) ((int8_t)(n >> 24)) +/*! + * Macros for IEEE SFLOAT type: exponent = bits 15-12, mantissa = bits 11-0 + */ +#define SFLT_TO_UINT16(m, e) ((m) | ((int16_t)(e) << 12)) +#define UINT16_TO_SFLT(m, e, n) {m = UINT16_TO_SFLT_M(n); e = UINT16_TO_SFLT_E(n);} +#define UINT16_TO_SFLT_M(n) ((((n) & 0x0FFF) >= 0x0800) ? \ + ((int16_t)(((n) | 0xF000))) : ((int16_t)((n) & 0x0FFF))) +#define UINT16_TO_SFLT_E(n) (((n >> 12) >= 0x0008) ? \ + ((int8_t)(((n >> 12) | 0xF0))) : ((int8_t)(n >> 12))) + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +uint64_t BstreamToBda64(const uint8_t *p); +uint64_t BstreamToUint64(const uint8_t *p); +void Bda64ToBstream(uint8_t *p, uint64_t bda); +void Uint64ToBstream(uint8_t *p, uint64_t n); + +#ifdef __cplusplus +}; +#endif + +#endif /* BSTREAM_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h new file mode 100644 index 00000000000..69b40254f5f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h @@ -0,0 +1,108 @@ +/*************************************************************************************************/ +/*! + * \file wsf_os_int.h + * + * \brief Software foundation OS platform-specific interface file. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_OS_INT_H +#define WSF_OS_INT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/* Task events */ +#define WSF_MSG_QUEUE_EVENT 0x01 /* Message queued for event handler */ +#define WSF_TIMER_EVENT 0x02 /* Timer expired for event handler */ +#define WSF_HANDLER_EVENT 0x04 /* Event set for event handler */ + +/* Derive task from handler ID */ +#define WSF_TASK_FROM_ID(handlerID) (((handlerID) >> 4) & 0x0F) + +/* Derive handler from handler ID */ +#define WSF_HANDLER_FROM_ID(handlerID) ((handlerID) & 0x0F) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Event handler ID data type */ +typedef uint8_t wsfHandlerId_t; + +/* Event handler event mask data type */ +typedef uint8_t wsfEventMask_t; + +/* Task ID data type */ +typedef wsfHandlerId_t wsfTaskId_t; + +/* Task event mask data type */ +typedef uint8_t wsfTaskEvent_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfOsReadyToSleep + * + * \brief Check if WSF is ready to sleep. + * + * \param None. + * + * \return Return TRUE if there are no pending WSF task events set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t wsfOsReadyToSleep(void); + +/*************************************************************************************************/ +/*! + * \fn wsfOsDispatcher + * + * \brief Event dispatched. Designed to be called repeatedly from infinite loop. + * + * \param None. + * + * \return None. + */ +/*************************************************************************************************/ +void wsfOsDispatcher(void); + +/*************************************************************************************************/ +/*! + * \fn WsfOsShutdown + * + * \brief Shutdown OS. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfOsShutdown(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_OS_INT_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h new file mode 100644 index 00000000000..0347086c06f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h @@ -0,0 +1,66 @@ +/*************************************************************************************************/ +/*! + * \file wsf_types.h + * + * \brief Platform-independent data types. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_TYPES_H +#define WSF_TYPES_H + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Integer data types */ +#if ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \ + (!defined(__ICC8051__) || (__ICC8051__ == 0))) || \ + defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) +#include +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed long int32_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; +#endif + +/* Boolean data type */ +typedef uint8_t bool_t; + +#endif /* WSF_TYPES_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h new file mode 100644 index 00000000000..e15476ed4ba --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h @@ -0,0 +1,199 @@ +/*************************************************************************************************/ +/*! + * \file wsf_buf.h + * + * \brief Buffer pool service. + * + * $Date: 2017-03-04 13:45:34 -0600 (Sat, 04 Mar 2017) $ + * $Revision: 11379 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_BUF_H +#define WSF_BUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Length of the buffer statistics array */ +#define WSF_BUF_STATS_MAX_LEN 128 + +/*! Failure Codes */ +#define WSF_BUF_ALLOC_FAILED 0x01 + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Buffer pool descriptor structure */ +typedef struct +{ + uint16_t len; /*! length of buffers in pool */ + uint8_t num; /*! number of buffers in pool */ +} wsfBufPoolDesc_t; + +/*! Pool statistics */ +typedef struct +{ + uint16_t bufSize; /*!< Pool buffer size. */ + uint8_t numBuf; /*!< Total number of buffers. */ + uint8_t numAlloc; /*!< Number of outstanding allocations. */ + uint8_t maxAlloc; /*!< High allocation watermark. */ + uint16_t maxReqLen; /*!< Maximum requested buffer length. */ +} WsfBufPoolStat_t; + +/*! WSF buffer diagnostics - buffer allocation failure */ +typedef struct +{ + uint8_t taskId; /*! Task handler ID where failure occured */ + uint16_t len; /*! Length of buffer being allocated */ +} wsfBufDiagAllocFail_t; + +/*! WSF buffer diagnostics message */ +typedef struct +{ + union + { + wsfBufDiagAllocFail_t alloc; /*! Buffer allocation failure */ + } param; + + uint8_t type; /*! Type of error */ +} WsfBufDiag_t; + +/************************************************************************************************** + Callback Function Datatypes +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfBufDiagCback_t + * + * \brief Callback providing WSF buffer diagnostic messages. + * + * \param pInfo Diagnostics message + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*wsfBufDiagCback_t)(WsfBufDiag_t *pInfo); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfBufInit + * + * \brief Initialize the buffer pool service. This function should only be called once + * upon system initialization. + * + * \param bufMemLen Length in bytes of memory pointed to by pBufMem. + * \param pBufMem Memory in which to store the pools used by the buffer pool service. + * \param numPools Number of buffer pools. + * \param pDesc Array of buffer pool descriptors, one for each pool. + * + * \return Amount of pBufMem used or 0 for failures. + */ +/*************************************************************************************************/ +uint16_t WsfBufInit(uint16_t bufMemLen, uint8_t *pBufMem, uint8_t numPools, const wsfBufPoolDesc_t *pDesc); + +/*************************************************************************************************/ +/*! + * \fn WsfBufAlloc + * + * \brief Allocate a buffer. + * + * \param len Length of buffer to allocate. + * + * \return Pointer to allocated buffer or NULL if allocation fails. + */ +/*************************************************************************************************/ +void *WsfBufAlloc(uint16_t len); + +/*************************************************************************************************/ +/*! + * \fn WsfBufFree + * + * \brief Free a buffer. + * + * \param pBuf Buffer to free. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfBufFree(void *pBuf); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetAllocStats + * + * \brief Diagnostic function to get the buffer allocation statistics. + * + * \return Buffer allocation statistics array. + */ +/*************************************************************************************************/ +uint8_t *WsfBufGetAllocStats(void); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetNumPool + * + * \brief Get number of pools. + * + * \return Number of pools. + */ +/*************************************************************************************************/ +uint8_t WsfBufGetNumPool(void); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetPoolStats + * + * \brief Get statistics for each pool. + * + * \param pStat Buffer to store the statistics. + * \param numPool Number of pool elements. + * + * \return Pool statistics. + */ +/*************************************************************************************************/ +void WsfBufGetPoolStats(WsfBufPoolStat_t *pStat, uint8_t numPool); + +/*************************************************************************************************/ +/*! + * \fn WsfBufDiagRegister + * + * \brief Called to register the buffer diagnostics callback function. + * + * \param pCallback Pointer to the callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfBufDiagRegister(wsfBufDiagCback_t callback); + + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_BUF_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h new file mode 100644 index 00000000000..abc7c112adc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h @@ -0,0 +1,48 @@ +/*************************************************************************************************/ +/*! + * \file wsf_math.h + * + * \brief Common math utilities. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_MATH_H +#define WSF_MATH_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Returns the minimum of two values. */ +#define WSF_MIN(a,b) ((a) < (b) ? (a) : (b)) + +/*! \brief Returns the maximum of two values. */ +#define WSF_MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MATH_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h new file mode 100644 index 00000000000..7235130f4fa --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h @@ -0,0 +1,140 @@ +/*************************************************************************************************/ +/*! + * \file wsf_msg.h + * + * \brief Message passing service. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_MSG_H +#define WSF_MSG_H + +#include "wsf_queue.h" +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfMsgDataAlloc + * + * \brief Allocate a data message buffer to be sent with WsfMsgSend(). + * + * \param len Message length in bytes. + * \param tailroom Tailroom length in bytes. + * + * \return Pointer to data message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *WsfMsgDataAlloc(uint16_t len, uint8_t tailroom); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgAlloc + * + * \brief Allocate a message buffer to be sent with WsfMsgSend(). + * + * \param len Message length in bytes. + * + * \return Pointer to message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *WsfMsgAlloc(uint16_t len); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgFree + * + * \brief Free a message buffer allocated with WsfMsgAlloc(). + * + * \param pMsg Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgFree(void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgSend + * + * \brief Send a message to an event handler. + * + * \param handlerId Event handler ID. + * \param pMsg Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgSend(wsfHandlerId_t handlerId, void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgEnq + * + * \brief Enqueue a message. + * + * \param pQueue Pointer to queue. + * \param handerId Set message handler ID to this value. + * \param pElem Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgEnq(wsfQueue_t *pQueue, wsfHandlerId_t handlerId, void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgDeq + * + * \brief Dequeue a message. + * + * \param pQueue Pointer to queue. + * \param pHandlerId Handler ID of returned message; this is a return parameter. + * + * \return Pointer to message that has been dequeued or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfMsgDeq(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgPeek + * + * \brief Get the next message without removing it from the queue. + * + * \param pQueue Pointer to queue. + * \param pHandlerId Handler ID of returned message; this is a return parameter. + * + * \return Pointer to the next message on the queue or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfMsgPeek(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MSG_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h new file mode 100644 index 00000000000..0ad337556d5 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h @@ -0,0 +1,179 @@ +/*************************************************************************************************/ +/*! + * \file wsf_os.h + * + * \brief Software foundation OS API. + * + * $Date: 2017-03-02 16:50:43 -0600 (Thu, 02 Mar 2017) $ + * $Revision: 11350 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_OS_H +#define WSF_OS_H + +#include "wsf_os_int.h" +#include "wsf_queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Configuration +**************************************************************************************************/ + +/* OS Diagnistics */ +#ifndef WSF_OS_DIAG +#define WSF_OS_DIAG FALSE +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/* Invalid Task Identifier */ +#define WSF_INVALID_TASK_ID 0xFF + +#if WSF_OS_DIAG == TRUE +#define WSF_OS_GET_ACTIVE_HANDLER_ID() WsfActiveHandler +#else +#define WSF_OS_GET_ACTIVE_HANDLER_ID() WSF_INVALID_TASK_ID +#endif /* WSF_OS_DIAG */ + +/************************************************************************************************** + External Variables +**************************************************************************************************/ + +/* Diagnistic Task Identifier */ +extern wsfHandlerId_t WsfActiveHandler; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Common message structure passed to event handler */ +typedef struct +{ + uint16_t param; /*! General purpose parameter passed to event handler */ + uint8_t event; /*! General purpose event value passed to event handler */ + uint8_t status; /*! General purpose status value passed to event handler */ +} wsfMsgHdr_t; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfEventHandler_t + * + * \brief Event handler callback function. + * + * \param event Mask of events set for the event handler. + * \param pMsg Pointer to message for the event handler. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*wsfEventHandler_t)(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfSetEvent + * + * \brief Set an event for an event handler. + * + * \param handlerId Handler ID. + * \param event Event or events to set. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfSetEvent(wsfHandlerId_t handlerId, wsfEventMask_t event); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskLock + * + * \brief Lock task scheduling. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskLock(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskUnlock + * + * \brief Unlock task scheduling. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskUnlock(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskSetReady + * + * \brief Set the task used by the given handler as ready to run. + * + * \param handlerId Event handler ID. + * \param event Task event mask. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskSetReady(wsfHandlerId_t handlerId, wsfTaskEvent_t event); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskMsgQueue + * + * \brief Return the task message queue used by the given handler. + * + * \param handlerId Event handler ID. + * + * \return Task message queue. + */ +/*************************************************************************************************/ +wsfQueue_t *WsfTaskMsgQueue(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn WsfOsSetNextHandler + * + * \brief Set the next WSF handler function in the WSF OS handler array. This function + * should only be called as part of the OS initialization procedure. + * + * \param handler WSF handler function. + * + * \return WSF handler ID for this handler. + */ +/*************************************************************************************************/ +wsfHandlerId_t WsfOsSetNextHandler(wsfEventHandler_t handler); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_OS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h new file mode 100644 index 00000000000..14d0cf19f75 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h @@ -0,0 +1,158 @@ +/*************************************************************************************************/ +/*! + * \file wsf_queue.h + * + * \brief General purpose queue service. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_QUEUE_H +#define WSF_QUEUE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Initialize a queue */ +#define WSF_QUEUE_INIT(pQueue) {(pQueue)->pHead = NULL; (pQueue)->pTail = NULL;} + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Queue structure */ +typedef struct +{ + void *pHead; /*! head of queue */ + void *pTail; /*! tail of queue */ +} wsfQueue_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfQueueEnq + * + * \brief Enqueue an element to the tail of a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueDeq + * + * \brief Dequeue an element from the head of a queue. + * + * \param pQueue Pointer to queue. + * + * \return Pointer to element that has been dequeued or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfQueueDeq(wsfQueue_t *pQueue); + +/*************************************************************************************************/ +/*! + * \fn WsfQueuePush + * + * \brief Push an element to the head of a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueuePush(wsfQueue_t *pQueue, void *pElem); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueInsert + * + * \brief Insert an element into a queue. This function is typically used when iterating + * over a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element to be inserted. + * \param pPrev Pointer to previous element in the queue before element to be inserted. + * Note: set pPrev to NULL if pElem is first element in queue. + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueRemove + * + * \brief Remove an element from a queue. This function is typically used when iterating + * over a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element to be removed. + * \param pPrev Pointer to previous element in the queue before element to be removed. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueCount + * + * \brief Count the number of elements in a queue. + * + * \param pQueue Pointer to queue. + * + * \return Number of elements in queue. + */ +/*************************************************************************************************/ +uint16_t WsfQueueCount(wsfQueue_t *pQueue); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueEmpty + * + * \brief Return TRUE if queue is empty. + * + * \param pQueue Pointer to queue. + * + * \return TRUE if queue is empty, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t WsfQueueEmpty(wsfQueue_t *pQueue); + + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_QUEUE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h new file mode 100644 index 00000000000..7d75e254638 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h @@ -0,0 +1,167 @@ +/*************************************************************************************************/ +/*! + * \file wsf_timer.h + * + * \brief Timer service. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_TIMER_H +#define WSF_TIMER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#ifndef WSF_MS_PER_TICK +/*! Default milliseconds per tick rate */ +#define WSF_MS_PER_TICK 1 +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Timer ticks data type */ +typedef uint32_t wsfTimerTicks_t; + +/*! Timer structure */ +typedef struct wsfTimer_tag +{ + struct wsfTimer_tag *pNext; /*! pointer to next timer in queue */ + wsfTimerTicks_t ticks; /*! number of ticks until expiration */ + wsfHandlerId_t handlerId; /*! event handler for this timer */ + bool_t isStarted; /*! TRUE if timer has been started */ + wsfMsgHdr_t msg; /*! application-defined timer event parameters */ +} wsfTimer_t; + + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfTimerInit + * + * \brief Initialize the timer service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerInit(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStartSec + * + * \brief Start a timer in units of seconds. Before this function is called parameter + * pTimer->handlerId must be set to the event handler for this timer and parameter + * pTimer->msg must be set to any application-defined timer event parameters. + * + * \param pTimer Pointer to timer. + * \param sec Seconds until expiration. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStartSec(wsfTimer_t *pTimer, wsfTimerTicks_t sec); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStartMs + * + * \brief Start a timer in units of milliseconds. + * + * \param pTimer Pointer to timer. + * \param ms Milliseconds until expiration. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStartMs(wsfTimer_t *pTimer, wsfTimerTicks_t ms); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStop + * + * \brief Stop a timer. + * + * \param pTimer Pointer to timer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStop(wsfTimer_t *pTimer); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerUpdate + * + * \brief Update the timer service with the number of elapsed ticks. This function is + * typically called only from timer porting code. + * + * \param ticks Number of ticks since last update. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerUpdate(wsfTimerTicks_t ticks); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerNextExpiration + * + * \brief Return the number of ticks until the next timer expiration. Note that this + * function can return zero even if a timer is running, indicating the timer + * has expired but has not yet been serviced. + * + * \param pTimerRunning Returns TRUE if a timer is running, FALSE if no timers running. + * + * \return The number of ticks until the next timer expiration. + */ +/*************************************************************************************************/ +wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerServiceExpired + * + * \brief Service expired timers for the given task. This function is typically called only + * WSF OS porting code. + * + * \param taskId OS Task ID of task servicing timers. + * + * \return Pointer to next expired timer or NULL if there are no expired timers. + */ +/*************************************************************************************************/ +wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_TIMER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar new file mode 100644 index 00000000000..3384be486f3 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar new file mode 100644 index 00000000000..abd590ab593 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 00000000000..a5fb4ab0ce7 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar new file mode 100644 index 00000000000..31f299594c8 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 00000000000..c5f20081e85 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 00000000000..85cd5e02ceb Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a new file mode 100644 index 00000000000..1c38f95eeef Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 00000000000..fa947cc2ea1 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a new file mode 100644 index 00000000000..b97f1656dcf Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 00000000000..49243d1927c Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a new file mode 100644 index 00000000000..fe97d4d83fd Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a new file mode 100644 index 00000000000..3efbdd64025 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar new file mode 100644 index 00000000000..94c6a13f811 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar new file mode 100644 index 00000000000..4416909af37 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 00000000000..a8ba7678d45 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar new file mode 100644 index 00000000000..cdaedc932fb Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 00000000000..315783eb749 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 00000000000..95fbae95fe1 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a new file mode 100644 index 00000000000..ded76db7c34 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 00000000000..750ca8fec90 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a new file mode 100644 index 00000000000..72d535b26a7 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 00000000000..444a46fa9b0 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a new file mode 100644 index 00000000000..bb4be319bec Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a new file mode 100644 index 00000000000..084e7453839 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar new file mode 100644 index 00000000000..33ec662464a Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar new file mode 100644 index 00000000000..c7ee6fa277a Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 00000000000..be4fc74df19 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar new file mode 100644 index 00000000000..c11e06b141d Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 00000000000..136a7ad1cc4 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 00000000000..f4ddab2ae05 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a new file mode 100644 index 00000000000..140192865e3 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 00000000000..a3d7380c34c Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a new file mode 100644 index 00000000000..ac246b29c05 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 00000000000..bfc21b106d7 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a new file mode 100644 index 00000000000..cbd3dc6d89e Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a new file mode 100644 index 00000000000..e6938ca404c Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar new file mode 100644 index 00000000000..796744a5b1a Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar new file mode 100644 index 00000000000..70429b7acd6 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 00000000000..5f4cbb09a35 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar new file mode 100644 index 00000000000..6086a112c33 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 00000000000..d607932aee1 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 00000000000..084248d9050 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a new file mode 100644 index 00000000000..84e168ea2e3 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 00000000000..eaeda2da13d Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a new file mode 100644 index 00000000000..4eb2a563e1e Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 00000000000..97b9b3b1e58 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a new file mode 100644 index 00000000000..9e6790f9ef4 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a new file mode 100644 index 00000000000..1488a250db4 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/hci_mbed_os_adaptation.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/hci_mbed_os_adaptation.h new file mode 100644 index 00000000000..7423e8cecc4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/hci_mbed_os_adaptation.h @@ -0,0 +1,65 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HCI_MBED_OS_ADAPTATION_H_ +#define HCI_MBED_OS_ADAPTATION_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Write data to the driver. + * + * @param type HCI packet type. + * @param len Number of bytes to write + * @param pData Pointer to the data to write. + * @return the actual number of data bytes written, + * + * @note type parameter allows the driver layer to prepend the data with a + * header on the same write transaction. + * @note mbed os wrapper of hciDrvWrite + */ +uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData); + +/** + * Start the hci reset sequence. + * @note stable wrapper around hciCoreResetStart. + * @note definition provided in mbed OS. + */ +void hci_mbed_os_start_reset_sequence(void); + +/** + * Handle hci messages during the reset sequence. + * @param msg: The HCI message to handle. + * @note stable wrapper of hciCoreResetSequence. + * @note definition provided in mbed os. + */ +void hci_mbed_os_handle_reset_sequence(uint8_t* msg); + +/** + * Signal to the stack that the reset sequence is done. + * @note shall be called from mbed OS when the reset sequence has been done. + */ +void hci_mbed_os_signal_reset_sequence_done(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_MBED_OS_ADAPTATION_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h new file mode 100644 index 00000000000..45c601c81f8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h @@ -0,0 +1,44 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WSF_MBED_OS_ADAPTATION_H_ +#define WSF_MBED_OS_ADAPTATION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrap core_util_critical_section_enter + */ +void wsf_mbed_os_critical_section_enter(void); + +/** + * Wrap core_util_critical_section_exit + */ +void wsf_mbed_os_critical_section_exit(void); + +/** + * Signal an event insertion in the Cordio stack to ble API. + */ +void wsf_mbed_ble_signal_event(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MBED_OS_ADAPTATION_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp index c381e733f55..f303c23d068 100644 --- a/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp @@ -383,11 +383,11 @@ void MaximGattServer::attCback(attEvt_t *pEvt) uint8_t MaximGattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) { GattReadCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .offset = offset, - .len = *pAttr->pLen, - .data = pAttr->pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .offset = */ offset, + /* .len = */ *pAttr->pLen, + /* .data = */ pAttr->pValue }; getInstance().handleDataReadEvent(&cbParams); @@ -426,12 +426,12 @@ uint8_t MaximGattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint } GattWriteCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .writeOp = writeOp, - .offset = offset, - .len = len, - .data = pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .writeOp = */ writeOp, + /* .offset = */ offset, + /* .len = */ len, + /* .data = */ pValue }; getInstance().handleDataWrittenEvent(&cbParams); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp index d6f815d64ec..fdf0ec76ca5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp @@ -63,11 +63,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_READ_RSP: { GattReadCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle, - .offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.read_rsp.handle, + /* .offset = */ p_ble_evt->evt.gattc_evt.params.read_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.read_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; gattClient.processReadResponse(&response); } @@ -75,12 +75,12 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_WRITE_RSP: { GattWriteCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.write_rsp.handle, - .writeOp = (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), - .offset = p_ble_evt->evt.gattc_evt.params.write_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.write_rsp.handle, + /* .writeOp = */ (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), + /* .offset = */ p_ble_evt->evt.gattc_evt.params.write_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.write_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; gattClient.processWriteResponse(&response); } @@ -88,11 +88,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_HVX: { GattHVXCallbackParams params; - params.connHandle = p_ble_evt->evt.gattc_evt.conn_handle; - params.handle = p_ble_evt->evt.gattc_evt.params.hvx.handle; - params.type = static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); - params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; - params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; + /* params.connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle; + /* params.handle = */ p_ble_evt->evt.gattc_evt.params.hvx.handle; + /* params.type = */ static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); + /* params.len = */ p_ble_evt->evt.gattc_evt.params.hvx.len; + /* params.data = */ p_ble_evt->evt.gattc_evt.params.hvx.data; gattClient.processHVXEvent(¶ms); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp index 4c5365f1b70..26f53848f8d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp @@ -440,12 +440,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) switch (eventType) { case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.write.op), - .offset = gattsEventP->params.write.offset, - .len = gattsEventP->params.write.len, - .data = gattsEventP->params.write.data + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.write.op), + /* .offset = */ gattsEventP->params.write.offset, + /* .len = */ gattsEventP->params.write.len, + /* .data = */ gattsEventP->params.write.data }; handleDataWrittenEvent(&cbParams); break; @@ -480,12 +480,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) */ if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.authorize_request.request.write.op), - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.authorize_request.request.write.op), + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, }; handleDataWrittenEvent(&cbParams); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp index 4f11a9d8ae9..c81d632434e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp @@ -24,8 +24,8 @@ nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHan characteristicDiscoveryStarted(connectionHandle); ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); ble_error_t err = BLE_ERROR_NONE; @@ -170,8 +170,8 @@ nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) if (startHandle < endHandle) { ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp index 99059f6623a..8090e8498b0 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp @@ -63,11 +63,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_READ_RSP: { GattReadCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle, - .offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.read_rsp.handle, + /* .offset = */ p_ble_evt->evt.gattc_evt.params.read_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.read_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; gattClient.processReadResponse(&response); } @@ -75,12 +75,12 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_WRITE_RSP: { GattWriteCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.write_rsp.handle, - .writeOp = (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), - .offset = p_ble_evt->evt.gattc_evt.params.write_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.write_rsp.handle, + /* .writeOp = */ (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), + /* .offset = */ p_ble_evt->evt.gattc_evt.params.write_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.write_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; gattClient.processWriteResponse(&response); } @@ -88,11 +88,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_HVX: { GattHVXCallbackParams params; - params.connHandle = p_ble_evt->evt.gattc_evt.conn_handle; - params.handle = p_ble_evt->evt.gattc_evt.params.hvx.handle; - params.type = static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); - params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; - params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; + /* params.connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle; + /* params.handle = */ p_ble_evt->evt.gattc_evt.params.hvx.handle; + /* params.type = */ static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); + /* params.len = */ p_ble_evt->evt.gattc_evt.params.hvx.len; + /* params.data = */ p_ble_evt->evt.gattc_evt.params.hvx.data; gattClient.processHVXEvent(¶ms); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp index 4a520305246..2a1c0af1a68 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp @@ -503,12 +503,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) switch (eventType) { case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.write.op), - .offset = gattsEventP->params.write.offset, - .len = gattsEventP->params.write.len, - .data = gattsEventP->params.write.data + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.write.op), + /* .offset = */ gattsEventP->params.write.offset, + /* .len = */ gattsEventP->params.write.len, + /* .data = */ gattsEventP->params.write.data }; handleDataWrittenEvent(&cbParams); break; @@ -539,7 +539,7 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) if (req->length == 0) { req->attr_handle = input_req.handle; req->offset = input_req.offset; - } else { + } else { // it should be the subsequent write if ((req->offset + req->length) != input_req.offset) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply); @@ -627,12 +627,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply); GattWriteCallbackParams writeParams = { - .connHandle = conn_handle, - .handle = req->attr_handle, - .writeOp = static_cast(input_req.op), - .offset = req->offset, - .len = req->length, - .data = req->data, + /* .connHandle = */ conn_handle, + /* .handle = */ req->attr_handle, + /* .writeOp = */ static_cast(input_req.op), + /* .offset = */ req->offset, + /* .len = */ req->length, + /* .data = */ req->data, }; handleDataWrittenEvent(&writeParams); releaseLongWriteRequest(conn_handle); @@ -649,7 +649,7 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; - + ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, .params = { @@ -662,12 +662,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } } }; - + if (reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) { reply.params.write.update = 0; } - + sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); /* @@ -679,12 +679,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) */ if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.authorize_request.request.write.op), - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.authorize_request.request.write.op), + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, }; handleDataWrittenEvent(&cbParams); } @@ -789,4 +789,4 @@ void nRF5xGattServer::releaseAllWriteRequests() { req.data = NULL; } } -} \ No newline at end of file +} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp index 87ac20c8ff0..79f691bfcf6 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp @@ -24,8 +24,8 @@ nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHan characteristicDiscoveryStarted(connectionHandle); ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); ble_error_t err = BLE_ERROR_NONE; @@ -170,8 +170,8 @@ nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) if (startHandle < endHandle) { ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED); @@ -288,8 +288,8 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt if (state == DISCOVER_SERVICE_UUIDS) { if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) { UUID::LongUUIDBytes_t uuid; - -#if (NRF_SD_BLE_API_VERSION >= 3) + +#if (NRF_SD_BLE_API_VERSION >= 3) ble_gattc_handle_value_t iter; memset(&iter, 0, sizeof(ble_gattc_handle_value_t)); (void) sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(const_cast(p_gattc_evt), &iter); @@ -308,7 +308,7 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) { if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) { UUID::LongUUIDBytes_t uuid; - + #if (NRF_SD_BLE_API_VERSION >= 3) ble_gattc_handle_value_t iter; memset(&iter, 0, sizeof(ble_gattc_handle_value_t)); @@ -317,7 +317,7 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt #else memcpy(uuid, &(response->handle_value[0].p_value[3]), UUID::LENGTH_OF_LONG_UUID); #endif - + unsigned charIndex = charUUIDDiscoveryQueue.dequeue(); characteristics[charIndex].setupLongUUID(uuid, UUID::LSB); diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK64F12.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K64F/hardware_init_MK64F12.c similarity index 100% rename from features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK64F12.c rename to features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K64F/hardware_init_MK64F12.c diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK66F18.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K66F/hardware_init_MK66F18.c similarity index 98% rename from features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK66F18.c rename to features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K66F/hardware_init_MK66F18.c index 6ff6dc2614a..222a3173ee3 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK66F18.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K66F/hardware_init_MK66F18.c @@ -39,7 +39,7 @@ void k66f_init_eth_hardware(void) #ifndef FEATURE_UVISOR /* Disable MPU only when uVisor is not around. */ - MPU->CESR &= ~MPU_CESR_VLD_MASK; + SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK; #endif/*FEATURE_UVISOR*/ /* Ungate the port clock */ diff --git a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp index f87864626fa..22d9a193205 100644 --- a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp +++ b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp @@ -558,18 +558,12 @@ nsapi_error_t PPPCellularInterface::connect() nsapi_error_t retcode; bool success; bool did_init = false; + const char *apn_config = NULL; if (dev_info.ppp_connection_up) { return NSAPI_ERROR_IS_CONNECTED; } - const char *apn_config = NULL; -#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP - if (!set_credentials_api_used) { - apn_config = apnconfig(dev_info.imsi); - } -#endif - do { retry_init: @@ -604,6 +598,12 @@ nsapi_error_t PPPCellularInterface::connect() return NSAPI_ERROR_NO_CONNECTION; } +#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP + if (!apn_config) { + apn_config = apnconfig(dev_info.imsi); + } +#endif + /* Check if user want skip SIM pin checking on boot up */ if (set_sim_pin_check_request) { retcode = do_sim_pin_check(_at, _pin); @@ -629,6 +629,7 @@ nsapi_error_t PPPCellularInterface::connect() _apn = _APN_GET(apn_config); _uname = _APN_GET(apn_config); _pwd = _APN_GET(apn_config); + tr_info("Looked up APN %s.", _apn); } #endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F103RB.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h similarity index 53% rename from features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F103RB.h rename to features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h index 271610b217b..d7cfc5b35c1 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F103RB.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 mbed.org, MIT License +/* Copyright (c) 2017 mbed.org, MIT License * * 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 @@ -15,16 +15,29 @@ * 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. */ -#ifndef USBHAL_STM32F103RB -#define USBHAL_STM32F103RB +#ifndef USBHAL_IP_DEVICE_H +#define USBHAL_IP_DEVICE_H +#if defined(TARGET_NUCLEO_F303ZE) +#define USBHAL_IRQn USB_LP_CAN_RX0_IRQn + +#elif defined(TARGET_NUCLEO_F103RB) #define USBHAL_IRQn USB_LP_CAN1_RX0_IRQn +#elif defined(TARGET_DISCO_L072CZ_LRWAN1) || \ + defined(TARGET_DISCO_L053C8) +#define USBHAL_IRQn USB_IRQn + +#else +#error "USB IRQ is not configured !" +#endif + +#define NB_ENDPOINT 8 // Must be a multiple of 4 bytes -#define NB_ENDPOINT 8 -/* must be multiple of 4 bytes */ #define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) + +#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE + MAX_PACKET_SIZE_EP0 + MAX_PACKET_SIZE_EP1 + MAX_PACKET_SIZE_EP2 + MAX_PACKET_SIZE_EP3) + #if (FIFO_USB_RAM_SIZE > 0x500) #error "FIFO dimensioning incorrect" #endif @@ -32,34 +45,33 @@ typedef struct { USBHAL *inst; + void (USBHAL::*bus_reset)(void); void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); + void (USBHAL::*connect_change)(unsigned int connected); void (USBHAL::*suspend_change)(unsigned int suspended); void (USBHAL::*ep0_setup)(void); void (USBHAL::*ep0_in)(void); void (USBHAL::*ep0_out)(void); void (USBHAL::*ep0_read)(void); bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - uint8_t epComplete[8]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; + bool (USBHAL::*epCallback[(2 * NB_ENDPOINT) - 2])(void); -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),!state); -} + uint8_t epComplete[2 * NB_ENDPOINT]; + + /* Memorize dummy buffer used for reception */ + uint32_t pBufRx[MAXTRANSFER_SIZE >> 2]; + uint32_t pBufRx0[MAX_PACKET_SIZE_EP0 >> 2]; + + gpio_t usb_switch; +} USBHAL_Private_t; uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) { return 1024; } -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) + +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; @@ -68,24 +80,31 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) (obj->*func)(sofnum); } -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) { - /* init parameter */ + USBHAL_Private_t *priv = ((USBHAL_Private_t *)(hpcd->pData)); +#if defined(TARGET_NUCLEO_F103RB) + gpio_write(&(priv->usb_switch), !state); +#else + gpio_write(&(priv->usb_switch), state); +#endif +} + +USBHAL *USBHAL::instance; + +USBHAL::USBHAL(void) { USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ + hpcd.Instance = USB; - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ + memset(&hpcd.Init, 0, sizeof(hpcd.Init)); hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; + hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; hpcd.Init.Sof_enable = 1; hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ + + // Pass instance for usage inside call back HALPriv->inst = this; HALPriv->bus_reset = &USBHAL::busReset; HALPriv->suspend_change = &USBHAL::suspendStateChanged; @@ -96,7 +115,6 @@ USBHAL::USBHAL(void) HALPriv->ep0_in = &USBHAL::EP0in; HALPriv->ep0_out = &USBHAL::EP0out; HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; @@ -105,43 +123,56 @@ USBHAL::USBHAL(void) HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; instance = this; + // Configure USB pins and other clocks +#if defined(TARGET_NUCLEO_F303ZE) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); // DP + __HAL_RCC_GPIOG_CLK_ENABLE(); + gpio_init_out(&HALPriv->usb_switch, PG_6); + +#elif defined(TARGET_NUCLEO_F103RB) + // Make sure to connect a 1.5K resistor between USB-DP PA12 pin and +3.3V + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DP + +#elif defined(TARGET_DISCO_L072CZ_LRWAN1) || \ + defined(TARGET_DISCO_L053C8) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); // DP - /* Configure USB VBUS GPIO */ - gpio_init_out(&HALPriv->usb_switch,PB_14); - gpio_mode(&HALPriv->usb_switch,OpenDrain); - /* Configure USB FS GPIOs */ - - /* Configure DM DP Pins - * - USB-DP (D+ of the USB connector) <======> PA12 (Nucleo board) - * Make sure to connect a 1.5KOhm pull up to USB-DP PA12 pin - * (permanent pull-up) - - USB-DM (D- of the USB connector) <======> PA11 (Nucleo board) - */ - - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); +#else +#error "USB pins are not configured !" +#endif __HAL_RCC_USB_CLK_ENABLE(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + // Configure PCD and FIFOs + hpcd.pData = (void*)HALPriv; hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); - HAL_PCDEx_PMAConfig(&hpcd , 0x01 , PCD_SNG_BUF, 0x90); - HAL_PCDEx_PMAConfig(&hpcd , 0x81 , PCD_SNG_BUF, 0xb0); -#if 0 - HAL_PCDEx_PMAConfig(&hpcd , 0x2, PCD_DBL_BUF, 0x018000b0); -#else - HAL_PCDEx_PMAConfig(&hpcd , 0x2, PCD_SNG_BUF, 0x100); -#endif - HAL_PCDEx_PMAConfig(&hpcd , 0x82, PCD_SNG_BUF, 0x120); - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority( USBHAL_IRQn, 1); + // EP0 + HAL_PCDEx_PMAConfig(&hpcd, 0x00, PCD_SNG_BUF, 0x30); + HAL_PCDEx_PMAConfig(&hpcd, 0x80, PCD_SNG_BUF, 0x70); + // EP1 + HAL_PCDEx_PMAConfig(&hpcd, 0x01, PCD_SNG_BUF, 0x90); + HAL_PCDEx_PMAConfig(&hpcd, 0x81, PCD_SNG_BUF, 0xb0); + // EP2 + HAL_PCDEx_PMAConfig(&hpcd, 0x02, PCD_SNG_BUF, 0x100); + HAL_PCDEx_PMAConfig(&hpcd, 0x82, PCD_SNG_BUF, 0x120); + // EP3 + HAL_PCDEx_PMAConfig(&hpcd, 0x03, PCD_DBL_BUF, 0x018000b0); + HAL_PCDEx_PMAConfig(&hpcd, 0x83, PCD_SNG_BUF, 0xb0); + + // Configure interrupt vector + NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); + NVIC_SetPriority(USBHAL_IRQn, 1); HAL_PCD_Start(&hpcd); } -#endif +#endif // USBHAL_IP_DEVICE_H diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F769NI.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h similarity index 55% rename from features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F769NI.h rename to features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h index f2bfa7a1025..e79e01be476 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F769NI.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 mbed.org, MIT License +/* Copyright (c) 2017 mbed.org, MIT License * * 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 @@ -15,13 +15,31 @@ * 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. */ -#ifndef USBHAL_STM32F769NI_H -#define USBHAL_STM32F769NI_H +#ifndef USBHAL_IP_OTGFSHS_H +#define USBHAL_IP_OTGFSHS_H + +//================================================================== +// This board has both USB OTG FS and HS connectors. +// Select one line only. +//================================================================== +#if defined(TARGET_DISCO_F746NG) +//#define TARGET_DISCO_F746NG_OTG_FS +#define TARGET_DISCO_F746NG_OTG_HS +#endif + +#if defined(TARGET_DISCO_F769NI) || \ + defined(TARGET_DISCO_F746NG_OTG_HS) #define USBHAL_IRQn OTG_HS_IRQn -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 4 +#else +#define USBHAL_IRQn OTG_FS_IRQn +#endif + +#define NB_ENDPOINT 4 // Must be a multiple of 4 bytes + #define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) + +#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE + MAX_PACKET_SIZE_EP0 + MAX_PACKET_SIZE_EP1 + MAX_PACKET_SIZE_EP2 + MAX_PACKET_SIZE_EP3) + #if (FIFO_USB_RAM_SIZE > 0x500) #error "FIFO dimensioning incorrect" #endif @@ -29,30 +47,37 @@ typedef struct { USBHAL *inst; + void (USBHAL::*bus_reset)(void); void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); + void (USBHAL::*connect_change)(unsigned int connected); void (USBHAL::*suspend_change)(unsigned int suspended); void (USBHAL::*ep0_setup)(void); void (USBHAL::*ep0_in)(void); void (USBHAL::*ep0_out)(void); void (USBHAL::*ep0_read)(void); bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - uint8_t epComplete[2*NB_ENDPOINT]; -}USBHAL_Private_t; + bool (USBHAL::*epCallback[(2 * NB_ENDPOINT) - 2])(void); + + uint8_t epComplete[2 * NB_ENDPOINT]; + + /* Memorize dummy buffer used for reception */ + uint32_t pBufRx[MAXTRANSFER_SIZE >> 2]; + uint32_t pBufRx0[MAX_PACKET_SIZE_EP0 >> 2]; +} USBHAL_Private_t; uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) { uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else + if (fifo == 0) { + len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ >> 16; + } + else { len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; + } + return len * 4; } + void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); @@ -60,27 +85,32 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; void (USBHAL::*func)(int frame) = priv->sof; - /* fix me call with same frame number */ (obj->*func)(sofnum); } - -USBHAL * USBHAL::instance; +USBHAL *USBHAL::instance; USBHAL::USBHAL(void) { - /* init parameter */ USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB_OTG_HS; + memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; + +#if defined(TARGET_DISCO_F769NI) || \ + defined(TARGET_DISCO_F746NG_OTG_HS) + hpcd.Instance = USB_OTG_HS; hpcd.Init.phy_itface = PCD_PHY_ULPI; hpcd.Init.Sof_enable = 0; - hpcd.Init.speed = PCD_SPEED_HIGH; - //hpcd.Init.vbus_sensing_enable = 0; - //hpcd.Init.lpm_enable = 0; - /* pass instance for usage inside call back */ +#else + hpcd.Instance = USB_OTG_FS; + hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd.Init.Sof_enable = 1; + hpcd.Init.speed = PCD_SPEED_FULL; +#endif + hpcd.Init.dev_endpoints = NB_ENDPOINT; + hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; + + // Pass instance for usage inside call back HALPriv->inst = this; HALPriv->bus_reset = &USBHAL::busReset; HALPriv->suspend_change = &USBHAL::suspendStateChanged; @@ -91,7 +121,6 @@ USBHAL::USBHAL(void) { HALPriv->ep0_in = &USBHAL::EP0in; HALPriv->ep0_out = &USBHAL::EP0out; HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; @@ -99,16 +128,49 @@ USBHAL::USBHAL(void) { HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; instance = this; - /* Enable power and clocking */ + + // Configure USB pins and other clocks + +#if defined(TARGET_NUCLEO_F207ZG) || \ + defined(TARGET_NUCLEO_F401RE) || \ + defined(TARGET_NUCLEO_F411RE) || \ + defined(TARGET_NUCLEO_F412ZG) || \ + defined(TARGET_NUCLEO_F429ZI) || \ + defined(TARGET_NUCLEO_F446RE) || \ + defined(TARGET_NUCLEO_F446ZE) || \ + defined(TARGET_NUCLEO_F767ZI) || \ + defined(TARGET_NUCLEO_F746ZG) || \ + defined(TARGET_DISCO_F407VG) || \ + defined(TARGET_DISCO_F469NI) || \ + defined(TARGET_DISCO_F746NG_OTG_FS) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DP + pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // VBUS + pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); // ID + pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // SOF + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + +#elif defined(TARGET_DISCO_L475VG_IOT01A) || \ + defined(TARGET_DISCO_L476VG) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DP + __HAL_RCC_GPIOC_CLK_ENABLE(); + pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // VBUS + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddUSB(); + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + +#elif defined(TARGET_DISCO_F769NI) || \ + defined(TARGET_DISCO_F746NG_OTG_HS) __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); - pin_function(PA_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // CLK pin_function(PA_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D0 - pin_function(PB_0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D1 pin_function(PB_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D2 pin_function(PB_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D3 @@ -116,32 +178,46 @@ USBHAL::USBHAL(void) { pin_function(PB_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D5 pin_function(PB_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D6 pin_function(PB_13, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D7 - pin_function(PC_0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // STP pin_function(PH_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // NXT +#if defined(TARGET_DISCO_F769NI) pin_function(PI_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // DIR - +#else // TARGET_DISCO_F746NG + pin_function(PC_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // DIR +#endif __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); +#else +#error "USB pins are not configured !" +#endif + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + // Configure PCD and FIFOs + hpcd.pData = (void*)HALPriv; hpcd.State = HAL_PCD_STATE_RESET; HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ + + /* 1.25 kbytes */ /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); + /* max value 256 (= 1K bytes ) */ + /* maximum sum is 0x140 */ + HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE / 4)); + // EP0 = Bulk/Int 64 bytes in FS + HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0 / 4) + 1); + // EP1 = Bulk/Int bytes in FS + HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1 / 4) + 1); + // EP2 + HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2 / 4)); + // EP3 = ISOchronous + HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3 / 4)); + + // Configure interrupt vector NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); NVIC_SetPriority(USBHAL_IRQn, 1); + HAL_PCD_Start(&hpcd); } -#endif +#endif // USBHAL_IP_OTGFSHS_H diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp index 36c0caf3590..6953f4a0783 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License +/* Copyright (c) 2017 mbed.org, MIT License * * 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 @@ -15,11 +15,13 @@ * 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. */ + /* TARGET NOT STM does not support this HAL */ #ifndef TARGET_STM #define USBSTM_HAL_UNSUPPORTED #endif -/* F4 famlily wihtout USB_STM_HAL use another HAL*/ + +/* STM32F4 family without USB_STM_HAL use another HAL */ #if defined(TARGET_STM) && defined(TARGET_STM32F4) && !defined(USB_STM_HAL) #define USBSTM_HAL_UNSUPPORTED #endif @@ -27,15 +29,15 @@ #ifndef USBSTM_HAL_UNSUPPORTED #include "USBHAL.h" #include "pinmap.h" -/* mbed endpoint definition to hal definition */ + +#include "USBHAL_STM32.h" + +/* mbed endpoint definition to hal definition */ #define EP_ADDR(ep) (((ep) >> 1)|((ep) & 1) << 7) + /* from hal definition to mbed definition */ #define ADDR_EPIN(ep) (((ep) << 1) | 1) #define ADDR_EPOUT(ep) (((ep) << 1)) -/* id to detect if rx buffer is used or not */ - -#include "USBHAL_STM_TARGET.h" - /* this call at device reception completion on a Out Enpoint */ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) @@ -318,15 +320,12 @@ bool USBHAL::getEndpointStallState(uint8_t endpoint) { void USBHAL::remoteWakeup(void) { } - void USBHAL::_usbisr(void) { instance->usbisr(); } - void USBHAL::usbisr(void) { - HAL_PCD_IRQHandler(&instance->hpcd); } -#endif +#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_TARGET.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h similarity index 54% rename from features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_TARGET.h rename to features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h index b380ba85945..1ed92bad54d 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_TARGET.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h @@ -15,29 +15,35 @@ * 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. */ +#ifndef USBHAL_STM32_H +#define USBHAL_STM32_H + +#if defined(TARGET_NUCLEO_F207ZG) || \ + defined(TARGET_NUCLEO_F401RE) || \ + defined(TARGET_NUCLEO_F411RE) || \ + defined(TARGET_NUCLEO_F412ZG) || \ + defined(TARGET_NUCLEO_F429ZI) || \ + defined(TARGET_NUCLEO_F446RE) || \ + defined(TARGET_NUCLEO_F446ZE) || \ + defined(TARGET_NUCLEO_F767ZI) || \ + defined(TARGET_NUCLEO_F746ZG) || \ + defined(TARGET_DISCO_F407VG) || \ + defined(TARGET_DISCO_F469NI) || \ + defined(TARGET_DISCO_F746NG) || \ + defined(TARGET_DISCO_F769NI) || \ + defined(TARGET_DISCO_L475VG_IOT01A) || \ + defined(TARGET_DISCO_L476VG) +#include "USBHAL_IP_OTGFSHS.h" + +#elif defined(TARGET_NUCLEO_F103RB) || \ + defined(TARGET_NUCLEO_F303ZE) || \ + defined(TARGET_DISCO_L053C8) || \ + defined(TARGET_DISCO_L072CZ_LRWAN1) +#include "USBHAL_IP_DEVICE.h" + +#else +#error "Target not supported !" -#if defined(TARGET_DISCO_L476VG) -#include "USBHAL_STM32L476VG.h" - -#elif defined(TARGET_DISCO_L475VG_IOT01A) -#include "USBHAL_STM32L475VG.h" - -#elif defined(TARGET_DISCO_L072CZ_LRWAN1) -#include "USBHAL_STM32L072CZ.h" - -#elif defined(TARGET_NUCLEO_F303ZE) -#include "USBHAL_STM32F303ZE.h" - -#elif defined(TARGET_NUCLEO_F103RB) -#include "USBHAL_STM32F103RB.h" - -#elif defined(TARGET_DISCO_F769NI) -#include "USBHAL_STM32F769NI.h" - -#elif defined(TARGET_DISCO_L053C8) -#include "USBHAL_STM32L053C8.h" - -#else /* default configuration */ -#include "USBHAL_STM_144_64pins.h" - #endif + +#endif // USBHAL_STM32_H diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F303ZE.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F303ZE.h deleted file mode 100644 index fa49ba280a7..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F303ZE.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* 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. -*/ -#ifndef USBHAL_STM32F303ZE_H -#define USBHAL_STM32F303ZE_H -#define USBHAL_IRQn USB_LP_CAN_RX0_IRQn -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 8 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[6])(void); - uint8_t epComplete[2*NB_ENDPOINT]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - return 1024; -} - -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state){ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),state); -} - -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - uint32_t sofnum = (hpcd->Instance->FNR) & USB_FNR_FN; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB; - /* initialized Init to zero (constructor does not zero initialized the - * area */ - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - __HAL_RCC_GPIOA_CLK_ENABLE(); - /* Configure USB DM pin. This is optional, and maintained only for user guidance. */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); - __HAL_RCC_GPIOG_CLK_ENABLE(); - gpio_init_out(&HALPriv->usb_switch,PG_6); - /* Enable USB Clock */ - __HAL_RCC_USB_CLK_ENABLE(); - /* Enable SYSCFG Clock */ - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); -#if 1 - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_DBL_BUF, 0x018000b0); -#else - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_SNG_BUF, 0x180); -#endif - HAL_PCDEx_PMAConfig(&hpcd , 0x83, PCD_SNG_BUF, 0xb0); - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L053C8.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L053C8.h deleted file mode 100644 index 69b6b8196cb..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L053C8.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* 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. -*/ -#ifndef USBHAL_STM32L053C8_H -#define USBHAL_STM32L053C8_H - -#define USBHAL_IRQn USB_IRQn - -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 8 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[6])(void); - uint8_t epComplete[2*NB_ENDPOINT]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - return 1024; -} - -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),state); -} - -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - uint32_t sofnum = (hpcd->Instance->FNR) & USB_FNR_FN; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) -{ - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB; - /* initialized Init to zero (constructor does not zero initialized the - * area */ - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - /* Configure USB DM pin. This is optional, and maintained only for user guidance. */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - - /* Enable USB Clock */ - __HAL_RCC_USB_CLK_ENABLE(); - - /* Enable SYSCFG Clock */ - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); -#if 1 - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_DBL_BUF, 0x018000b0); -#else - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_SNG_BUF, 0x180); -#endif - HAL_PCDEx_PMAConfig(&hpcd , 0x83, PCD_SNG_BUF, 0xb0); - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L072CZ.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L072CZ.h deleted file mode 100644 index 628701af4bb..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L072CZ.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* 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. -*/ -#ifndef USBHAL_STM32L072CZ_H -#define USBHAL_STM32L072CZ_H - -#define USBHAL_IRQn USB_IRQn - -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 8 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[6])(void); - uint8_t epComplete[2*NB_ENDPOINT]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - return 1024; -} - -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),state); -} - -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - uint32_t sofnum = (hpcd->Instance->FNR) & USB_FNR_FN; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) -{ - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB; - /* initialized Init to zero (constructor does not zero initialized the - * area */ - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - /* Configure USB DM pin. This is optional, and maintained only for user guidance. */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - - /* Enable USB Clock */ - __HAL_RCC_USB_CLK_ENABLE(); - - /* Enable SYSCFG Clock */ - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_DBL_BUF, 0x018000b0); - HAL_PCDEx_PMAConfig(&hpcd , 0x83, PCD_SNG_BUF, 0xb0); - - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L475VG.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L475VG.h deleted file mode 100644 index 39a9df449c1..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L475VG.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* 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. -*/ -#ifndef USBHAL_STM32L475VG -#define USBHAL_STM32L475VG - -#define USBHAL_IRQn OTG_FS_IRQn - - -#define NB_ENDPOINT 4 -/* must be multiple of 4 bytes */ -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - uint8_t epComplete[8]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else - len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; -} -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; - void (USBHAL::*func)(int frame) = priv->sof; - /* fix me call with same frame number */ - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - hpcd.Instance = USB_OTG_FS; - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - __HAL_RCC_PWR_CLK_ENABLE(); - - HAL_PWREx_EnableVddUSB(); - /* Configure USB VBUS GPIO */ - __HAL_RCC_GPIOC_CLK_ENABLE(); - - /* Configure USB FS GPIOs */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - - /* Configure DM DP Pins */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - /* Configure VBUS Pin */ - pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - - hpcd.State = HAL_PCD_STATE_RESET; - - HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ - /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); - - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority( USBHAL_IRQn, 1); - - HAL_PCD_Start(&hpcd); -} - -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L476VG.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L476VG.h deleted file mode 100644 index b08bce8b40a..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L476VG.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* 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. -*/ -#ifndef USBHAL_STM32L476VG -#define USBHAL_STM32L476VG - -#define USBHAL_IRQn OTG_FS_IRQn - - -#define NB_ENDPOINT 4 -/* must be multiple of 4 bytes */ -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - uint8_t epComplete[8]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else - len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; -} -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; - void (USBHAL::*func)(int frame) = priv->sof; - /* fix me call with same frame number */ - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - hpcd.Instance = USB_OTG_FS; - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - __HAL_RCC_PWR_CLK_ENABLE(); - - HAL_PWREx_EnableVddUSB(); - /* Configure USB VBUS GPIO */ - __HAL_RCC_GPIOC_CLK_ENABLE(); - - /* Configure USB FS GPIOs */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - - /* Configure DM DP Pins */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - /* Configure VBUS Pin */ - pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - - hpcd.State = HAL_PCD_STATE_RESET; - - HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ - /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); - - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority( USBHAL_IRQn, 1); - - HAL_PCD_Start(&hpcd); -} - -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h deleted file mode 100644 index 200369d8dc2..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* 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. -*/ -#ifndef USBHAL_STM32_144_64 -#define USBHAL_STM32_144_64 - -#define USBHAL_IRQn OTG_FS_IRQn -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 4 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - uint8_t epComplete[2*NB_ENDPOINT]; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else - len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; -} -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB_OTG_FS; - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - - hpcd.Init.speed = PCD_SPEED_FULL; - //hpcd.Init.vbus_sensing_enable = 0; - //hpcd.Init.lpm_enable = 0; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - // Enable power and clocking - /* board 144 pin all similar */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_SOF */ - pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_VBUS */ - pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); /* OTG_FS_ID */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DM */ - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DP */ - - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ - /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); - NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif - diff --git a/platform/ATCmdParser.cpp b/platform/ATCmdParser.cpp index 6200f1fa4b6..3e5ee2cde2a 100644 --- a/platform/ATCmdParser.cpp +++ b/platform/ATCmdParser.cpp @@ -380,3 +380,44 @@ void ATCmdParser::abort() { _aborted = true; } + +bool ATCmdParser::process_oob() +{ + if (!_fh->readable()) { + return false; + } + + int i = 0; + while (true) { + // Receive next character + int c = getc(); + if (c < 0) { + return false; + } + _buffer[i++] = c; + _buffer[i] = 0; + + // Check for oob data + struct oob *oob = _oobs; + while ( oob ) { + if (i == (int)oob->len && memcmp( + oob->prefix, _buffer, oob->len) == 0) { + debug_if(_dbg_on, "AT! %s\r\n", oob->prefix); + oob->cb(); + return true; + } + oob = oob->next; + } + + // Clear the buffer when we hit a newline or ran out of space + // running out of space usually means we ran into binary data + if (i+1 >= _buffer_size || + strcmp(&_buffer[i-_output_delim_size], _output_delimiter) == 0) { + + debug_if(_dbg_on, "AT< %s", _buffer); + i = 0; + } + } +} + + diff --git a/platform/ATCmdParser.h b/platform/ATCmdParser.h index 03b1ef6b2ac..1201a6055f5 100644 --- a/platform/ATCmdParser.h +++ b/platform/ATCmdParser.h @@ -288,6 +288,16 @@ class ATCmdParser : private NonCopyable * recv operation. */ void abort(); + + /** + * Process out-of-band data + * + * Process out-of-band data in the receive buffer. This function + * returns immediately if there is no data to process. + * + * @return true if oob data processed, false otherwise + */ + bool process_oob(void); }; } //namespace mbed diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c old mode 100644 new mode 100755 index 93d47c7f502..d053db788a1 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -28,154 +28,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "fsl_common.h" -#include "fsl_smc.h" -#include "fsl_clock_config.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ -/*! @brief Clock configuration structure. */ -typedef struct _clock_config -{ - mcg_config_t mcgConfig; /*!< MCG configuration. */ - sim_clock_config_t simConfig; /*!< SIM configuration. */ - osc_config_t oscConfig; /*!< OSC configuration. */ - uint32_t coreClock; /*!< core clock frequency. */ -} clock_config_t; - -/******************************************************************************* - * Variables - ******************************************************************************/ -/* System clock frequency. */ -extern uint32_t SystemCoreClock; - -/* Configuration for enter VLPR mode. Core clock = 4MHz. */ -const clock_config_t g_defaultClockConfigVlpr = { - .mcgConfig = - { - .mcgMode = kMCG_ModeBLPI, /* Work in BLPI mode. */ - .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enable. */ - .ircs = kMCG_IrcFast, /* Select IRC4M. */ - .fcrdiv = 0U, /* FCRDIV is 0.*/ - - .frdiv = 0U, - .drs = kMCG_DrsLow, /* Low frequency range */ - .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ - .oscsel = kMCG_OscselOsc, /* Select OSC */ - - .pll0Config = - { - .enableMode = 0U, /* Don't enable PLL. */ - .prdiv = 0U, - .vdiv = 0U, - }, - .pllcs = kMCG_PllClkSelPll0, - }, - .simConfig = - { - .pllFllSel = 3U, /* PLLFLLSEL select IRC48MCLK. */ - .pllFllDiv = 0U, - .pllFllFrac = 0U, - .er32kSrc = 2U, /* ERCLK32K selection, use RTC. */ - .clkdiv1 = 0x00040000U, /* SIM_CLKDIV1. */ - }, - .oscConfig = {.freq = BOARD_XTAL0_CLK_HZ, - .capLoad = 0U, - .workMode = kOSC_ModeOscLowPower, - .oscerConfig = - { - .enableMode = kOSC_ErClkEnable, -#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) - .erclkDiv = 0U, -#endif - }}, - .coreClock = 4000000U, /* Core clock frequency */ -}; - -/* Configuration for enter RUN mode. Core clock = 120MHz. */ -const clock_config_t g_defaultClockConfigRun = { - .mcgConfig = - { - .mcgMode = kMCG_ModePEE, /* Work in PEE mode. */ - .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enable. */ - .ircs = kMCG_IrcSlow, /* Select IRC32k. */ - .fcrdiv = 0U, /* FCRDIV is 0. */ - - .frdiv = 4U, - .drs = kMCG_DrsLow, /* Low frequency range */ - .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ - .oscsel = kMCG_OscselOsc, /* Select OSC */ - - .pll0Config = - { - .enableMode = 0U, .prdiv = 0x00U, .vdiv = 0x04U, - }, - .pllcs = kMCG_PllClkSelPll0, - }, - .simConfig = - { - .pllFllSel = 1U, /* PLLFLLSEL select PLL. */ - .pllFllDiv = 0U, - .pllFllFrac = 0U, - .er32kSrc = 2U, /* ERCLK32K selection, use RTC. */ - .clkdiv1 = 0x01140000U, /* SIM_CLKDIV1. */ - }, - .oscConfig = {.freq = BOARD_XTAL0_CLK_HZ, - .capLoad = 0, - .workMode = kOSC_ModeOscLowPower, - .oscerConfig = - { - .enableMode = kOSC_ErClkEnable, -#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) - .erclkDiv = 0U, -#endif - }}, - .coreClock = 120000000U, /* Core clock frequency */ -}; - -/* Configuration for HSRUN mode. Core clock = 180MHz. */ -const clock_config_t g_defaultClockConfigHsrun = { - .mcgConfig = - { - .mcgMode = kMCG_ModePEE, /* Work in PEE mode. */ - .irclkEnableMode = kMCG_IrclkEnableInStop, /* MCGIRCLK enable. */ - .ircs = kMCG_IrcSlow, /* Select IRC32k.*/ - .fcrdiv = 0U, /* FCRDIV is 0. */ - - .frdiv = 4U, - .drs = kMCG_DrsLow, /* Low frequency range. */ - .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25%. */ - .oscsel = kMCG_OscselOsc, /* Select OSC. */ - - .pll0Config = - { - .enableMode = 0U, .prdiv = 0x00U, .vdiv = 0x0EU, - }, - .pllcs = kMCG_PllClkSelPll0, - }, - .simConfig = - { - .pllFllSel = 1U, /* PLLFLLSEL select PLL. */ - .er32kSrc = 2U, /* ERCLK32K selection, use RTC. */ - .clkdiv1 = 0x02260000U, /* SIM_CLKDIV1. */ - }, - .oscConfig = {.freq = BOARD_XTAL0_CLK_HZ, - .capLoad = 0, - .workMode = kOSC_ModeOscLowPower, - .oscerConfig = - { - .enableMode = kOSC_ErClkEnable, -#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) - .erclkDiv = 0U, -#endif - }}, - .coreClock = 180000000U, /* Core clock frequency */ -}; - -/******************************************************************************* - * Code - ******************************************************************************/ /* * How to setup clock using clock driver functions: * @@ -204,62 +56,389 @@ const clock_config_t g_defaultClockConfigHsrun = { * 4. Call CLOCK_SetSimConfig to set the clock configuration in SIM. */ -void BOARD_BootClockVLPR(void) -{ - CLOCK_SetSimSafeDivs(); - - CLOCK_BootToBlpiMode(g_defaultClockConfigVlpr.mcgConfig.fcrdiv, g_defaultClockConfigVlpr.mcgConfig.ircs, - g_defaultClockConfigVlpr.mcgConfig.irclkEnableMode); +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!ClocksProfile +product: Clocks v1.0 +processor: MK66FN2M0xxx18 +package_id: MK66FN2M0VMD18 +mcu_data: ksdk2_0 +processor_version: 1.0.1 +board: FRDM-K66F + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ - CLOCK_SetSimConfig(&g_defaultClockConfigVlpr.simConfig); +#include "fsl_smc.h" +#include "fsl_clock_config.h" - SystemCoreClock = g_defaultClockConfigVlpr.coreClock; +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define MCG_PLL_DISABLE 0U /*!< MCGPLLCLK disabled */ +#define OSC_CAP0P 0U /*!< Oscillator 0pF capacitor load */ +#define OSC_ER_CLK_DISABLE 0U /*!< Disable external reference clock */ +#define SIM_OSC32KSEL_RTC32KCLK_CLK 2U /*!< OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ +#define SIM_PLLFLLSEL_IRC48MCLK_CLK 3U /*!< PLLFLL select: IRC48MCLK clock */ +#define SIM_PLLFLLSEL_MCGPLLCLK_CLK 1U /*!< PLLFLL select: MCGPLLCLK clock */ - SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); - SMC_SetPowerModeVlpr(SMC); - while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr) - { - } -} +/******************************************************************************* + * Variables + ******************************************************************************/ +/* System clock frequency. */ +extern uint32_t SystemCoreClock; -void BOARD_BootClockRUN(void) +/******************************************************************************* + * Code + ******************************************************************************/ +/*FUNCTION********************************************************************** + * + * Function Name : CLOCK_CONFIG_SetFllExtRefDiv + * Description : Configure FLL external reference divider (FRDIV). + * Param frdiv : The value to set FRDIV. + * + *END**************************************************************************/ +static void CLOCK_CONFIG_SetFllExtRefDiv(uint8_t frdiv) { - CLOCK_SetSimSafeDivs(); - - CLOCK_InitOsc0(&g_defaultClockConfigRun.oscConfig); - CLOCK_SetXtal0Freq(BOARD_XTAL0_CLK_HZ); - - CLOCK_BootToPeeMode(g_defaultClockConfigRun.mcgConfig.oscsel, kMCG_PllClkSelPll0, - &g_defaultClockConfigRun.mcgConfig.pll0Config); - - CLOCK_SetInternalRefClkConfig(g_defaultClockConfigRun.mcgConfig.irclkEnableMode, - g_defaultClockConfigRun.mcgConfig.ircs, g_defaultClockConfigRun.mcgConfig.fcrdiv); + MCG->C1 = ((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); +} - CLOCK_SetSimConfig(&g_defaultClockConfigRun.simConfig); +/******************************************************************************* + ********************* Configuration BOARD_BootClockHSRUN ********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!Configuration +name: BOARD_BootClockHSRUN +outputs: +- {id: Bus_clock.outFreq, value: 60 MHz} +- {id: Core_clock.outFreq, value: 180 MHz, locked: true, accuracy: '0.001'} +- {id: Flash_clock.outFreq, value: 180/7 MHz} +- {id: FlexBus_clock.outFreq, value: 60 MHz} +- {id: LPO_clock.outFreq, value: 1 kHz} +- {id: MCGFFCLK.outFreq, value: 375 kHz} +- {id: MCGIRCLK.outFreq, value: 32.768 kHz} +- {id: OSCERCLK.outFreq, value: 12 MHz} +- {id: OSCERCLK_UNDIV.outFreq, value: 12 MHz} +- {id: PLLFLLCLK.outFreq, value: 180 MHz} +- {id: System_clock.outFreq, value: 180 MHz} +settings: +- {id: MCGMode, value: PEE} +- {id: powerMode, value: HSRUN} +- {id: MCG.FCRDIV.scale, value: '1', locked: true} +- {id: MCG.FRDIV.scale, value: '32'} +- {id: MCG.IREFS.sel, value: MCG.FRDIV} +- {id: MCG.PLLS.sel, value: MCG.PLLCS} +- {id: MCG.VDIV.scale, value: '30'} +- {id: MCG_C1_IRCLKEN_CFG, value: Enabled} +- {id: MCG_C1_IREFSTEN_CFG, value: Enabled} +- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} +- {id: MCG_C2_RANGE0_CFG, value: Very_high} +- {id: MCG_C2_RANGE0_FRDIV_CFG, value: Very_high} +- {id: OSC_CR_ERCLKEN_CFG, value: Enabled} +- {id: OSC_CR_ERCLKEN_UNDIV_CFG, value: Enabled} +- {id: RTC_CR_CLKO_CFG, value: Disabled} +- {id: SIM.LPUARTSRCSEL.sel, value: OSC.OSCERCLK} +- {id: SIM.OSC32KSEL.sel, value: RTC.RTC32KCLK} +- {id: SIM.OUTDIV2.scale, value: '3', locked: true} +- {id: SIM.OUTDIV3.scale, value: '3', locked: true} +- {id: SIM.OUTDIV4.scale, value: '7', locked: true} +- {id: SIM.PLLFLLSEL.sel, value: MCG.MCGPLLCLK} +- {id: SIM.RMIICLKSEL.sel, value: SIM.ENET_1588_CLK_EXT} +- {id: SIM.SDHCSRCSEL.sel, value: OSC.OSCERCLK} +- {id: SIM.TPMSRCSEL.sel, value: SIM.PLLFLLDIV} +- {id: SIM.TRACECLKSEL.sel, value: SIM.TRACEDIV} +- {id: SIM.TRACEDIV.scale, value: '2'} +- {id: SIM.USBSRCSEL.sel, value: SIM.USBDIV} +- {id: USBPHY.DIV.scale, value: '40'} +- {id: USBPHY.PFD_CLK_SEL.sel, value: USBPHY.PFD_CLK_DIV2} +- {id: USBPHY.PFD_FRAC_DIV.scale, value: '24', locked: true} +sources: +- {id: OSC.OSC.outFreq, value: 12 MHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ - SystemCoreClock = g_defaultClockConfigRun.coreClock; -} +/******************************************************************************* + * Variables for BOARD_BootClockHSRUN configuration + ******************************************************************************/ +const mcg_config_t mcgConfig_BOARD_BootClockHSRUN = + { + .mcgMode = kMCG_ModePEE, /* PEE - PLL Engaged External */ + .irclkEnableMode = kMCG_IrclkEnable | kMCG_IrclkEnableInStop,/* MCGIRCLK enabled as well as in STOP mode */ + .ircs = kMCG_IrcSlow, /* Slow internal reference clock selected */ + .fcrdiv = 0x0U, /* Fast IRC divider: divided by 1 */ + .frdiv = 0x0U, /* FLL reference clock divider: divided by 32 */ + .drs = kMCG_DrsLow, /* Low frequency range */ + .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ + .oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */ + .pll0Config = + { + .enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */ + .prdiv = 0x0U, /* PLL Reference divider: divided by 1 */ + .vdiv = 0xeU, /* VCO divider: multiplied by 30 */ + }, + .pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */ + }; +const sim_clock_config_t simConfig_BOARD_BootClockHSRUN = + { + .pllFllSel = SIM_PLLFLLSEL_MCGPLLCLK_CLK, /* PLLFLL select: MCGPLLCLK clock */ + .pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */ + .pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */ + .er32kSrc = SIM_OSC32KSEL_RTC32KCLK_CLK, /* OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ + .clkdiv1 = 0x2260000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /3, OUTDIV3: /3, OUTDIV4: /7 */ + }; +const osc_config_t oscConfig_BOARD_BootClockHSRUN = + { + .freq = 12000000U, /* Oscillator frequency: 12000000Hz */ + .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ + .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ + .oscerConfig = + { + .enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */ + .erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */ + } + }; +/******************************************************************************* + * Code for BOARD_BootClockHSRUN configuration + ******************************************************************************/ void BOARD_BootClockHSRUN(void) { + /* Set HSRUN power mode */ SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); SMC_SetPowerModeHsrun(SMC); while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateHsrun) { } - + /* Set the system clock dividers in SIM to safe value. */ CLOCK_SetSimSafeDivs(); + /* Initializes OSC0 according to board configuration. */ + CLOCK_InitOsc0(&oscConfig_BOARD_BootClockHSRUN); + CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockHSRUN.freq); + /* Configure the Internal Reference clock (MCGIRCLK). */ + CLOCK_SetInternalRefClkConfig(mcgConfig_BOARD_BootClockHSRUN.irclkEnableMode, + mcgConfig_BOARD_BootClockHSRUN.ircs, + mcgConfig_BOARD_BootClockHSRUN.fcrdiv); + /* Configure FLL external reference divider (FRDIV). */ + CLOCK_CONFIG_SetFllExtRefDiv(mcgConfig_BOARD_BootClockHSRUN.frdiv); + /* Set MCG to PEE mode. */ + CLOCK_BootToPeeMode(mcgConfig_BOARD_BootClockHSRUN.oscsel, + mcgConfig_BOARD_BootClockHSRUN.pllcs, + &mcgConfig_BOARD_BootClockHSRUN.pll0Config); + /* Set the clock configuration in SIM module. */ + CLOCK_SetSimConfig(&simConfig_BOARD_BootClockHSRUN); + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKHSRUN_CORE_CLOCK; +} - CLOCK_InitOsc0(&g_defaultClockConfigHsrun.oscConfig); - CLOCK_SetXtal0Freq(BOARD_XTAL0_CLK_HZ); +/******************************************************************************* + ********************* Configuration BOARD_BootClockVLPR *********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!Configuration +name: BOARD_BootClockVLPR +outputs: +- {id: Bus_clock.outFreq, value: 4 MHz} +- {id: Core_clock.outFreq, value: 4 MHz} +- {id: Flash_clock.outFreq, value: 800 kHz} +- {id: FlexBus_clock.outFreq, value: 4 MHz} +- {id: LPO_clock.outFreq, value: 1 kHz} +- {id: MCGIRCLK.outFreq, value: 4 MHz} +- {id: System_clock.outFreq, value: 4 MHz} +settings: +- {id: MCGMode, value: BLPI} +- {id: powerMode, value: VLPR} +- {id: MCG.CLKS.sel, value: MCG.IRCS} +- {id: MCG.FCRDIV.scale, value: '1', locked: true} +- {id: MCG.FRDIV.scale, value: '32'} +- {id: MCG.IRCS.sel, value: MCG.FCRDIV} +- {id: MCG_C1_IRCLKEN_CFG, value: Enabled} +- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} +- {id: MCG_C2_RANGE0_CFG, value: Very_high} +- {id: MCG_C2_RANGE0_FRDIV_CFG, value: Very_high} +- {id: RTC_CR_CLKO_CFG, value: Disabled} +- {id: SIM.OSC32KSEL.sel, value: RTC.RTC32KCLK} +- {id: SIM.OUTDIV3.scale, value: '1'} +- {id: SIM.OUTDIV4.scale, value: '5'} +- {id: SIM.PLLFLLSEL.sel, value: IRC48M.IRC48MCLK} +sources: +- {id: OSC.OSC.outFreq, value: 12 MHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ + +/******************************************************************************* + * Variables for BOARD_BootClockVLPR configuration + ******************************************************************************/ +const mcg_config_t mcgConfig_BOARD_BootClockVLPR = + { + .mcgMode = kMCG_ModeBLPI, /* BLPI - Bypassed Low Power Internal */ + .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */ + .ircs = kMCG_IrcFast, /* Fast internal reference clock selected */ + .fcrdiv = 0x0U, /* Fast IRC divider: divided by 1 */ + .frdiv = 0x0U, /* FLL reference clock divider: divided by 32 */ + .drs = kMCG_DrsLow, /* Low frequency range */ + .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ + .oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */ + .pll0Config = + { + .enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */ + .prdiv = 0x0U, /* PLL Reference divider: divided by 1 */ + .vdiv = 0x0U, /* VCO divider: multiplied by 16 */ + }, + .pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */ + }; +const sim_clock_config_t simConfig_BOARD_BootClockVLPR = + { + .pllFllSel = SIM_PLLFLLSEL_IRC48MCLK_CLK, /* PLLFLL select: IRC48MCLK clock */ + .pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */ + .pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */ + .er32kSrc = SIM_OSC32KSEL_RTC32KCLK_CLK, /* OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ + .clkdiv1 = 0x40000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /1, OUTDIV3: /1, OUTDIV4: /5 */ + }; +const osc_config_t oscConfig_BOARD_BootClockVLPR = + { + .freq = 12000000U, /* Oscillator frequency: 12000000Hz */ + .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ + .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ + .oscerConfig = + { + .enableMode = OSC_ER_CLK_DISABLE, /* Disable external reference clock */ + .erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */ + } + }; - CLOCK_BootToPeeMode(g_defaultClockConfigHsrun.mcgConfig.oscsel, kMCG_PllClkSelPll0, - &g_defaultClockConfigHsrun.mcgConfig.pll0Config); +/******************************************************************************* + * Code for BOARD_BootClockVLPR configuration + ******************************************************************************/ +void BOARD_BootClockVLPR(void) +{ + /* Set the system clock dividers in SIM to safe value. */ + CLOCK_SetSimSafeDivs(); + /* Initializes OSC0 according to board configuration. */ + CLOCK_InitOsc0(&oscConfig_BOARD_BootClockVLPR); + CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockVLPR.freq); + /* Set MCG to BLPI mode. */ + CLOCK_BootToBlpiMode(mcgConfig_BOARD_BootClockVLPR.fcrdiv, + mcgConfig_BOARD_BootClockVLPR.ircs, + mcgConfig_BOARD_BootClockVLPR.irclkEnableMode); + /* Select the MCG external reference clock. */ + CLOCK_SetExternalRefClkConfig(mcgConfig_BOARD_BootClockVLPR.oscsel); + /* Set the clock configuration in SIM module. */ + CLOCK_SetSimConfig(&simConfig_BOARD_BootClockVLPR); + /* Set VLPR power mode. */ + SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); +#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) + SMC_SetPowerModeVlpr(SMC, false); +#else + SMC_SetPowerModeVlpr(SMC); +#endif + while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr) + { + } + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKVLPR_CORE_CLOCK; +} - CLOCK_SetInternalRefClkConfig(g_defaultClockConfigHsrun.mcgConfig.irclkEnableMode, - g_defaultClockConfigHsrun.mcgConfig.ircs, g_defaultClockConfigHsrun.mcgConfig.fcrdiv); +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!Configuration +name: BOARD_BootClockRUN +outputs: +- {id: Bus_clock.outFreq, value: 60 MHz} +- {id: Core_clock.outFreq, value: 120 MHz} +- {id: Flash_clock.outFreq, value: 24 MHz} +- {id: FlexBus_clock.outFreq, value: 60 MHz} +- {id: LPO_clock.outFreq, value: 1 kHz} +- {id: MCGFFCLK.outFreq, value: 375 kHz} +- {id: MCGIRCLK.outFreq, value: 32.768 kHz} +- {id: OSCERCLK.outFreq, value: 12 MHz} +- {id: OSCERCLK_UNDIV.outFreq, value: 12 MHz} +- {id: PLLFLLCLK.outFreq, value: 120 MHz} +- {id: System_clock.outFreq, value: 120 MHz} +settings: +- {id: MCGMode, value: PEE} +- {id: MCG.FCRDIV.scale, value: '1', locked: true} +- {id: MCG.FRDIV.scale, value: '32'} +- {id: MCG.IREFS.sel, value: MCG.FRDIV} +- {id: MCG.PLLS.sel, value: MCG.PLLCS} +- {id: MCG.PRDIV.scale, value: '1', locked: true} +- {id: MCG.VDIV.scale, value: '20', locked: true} +- {id: MCG_C1_IRCLKEN_CFG, value: Enabled} +- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} +- {id: MCG_C2_RANGE0_CFG, value: Very_high} +- {id: MCG_C2_RANGE0_FRDIV_CFG, value: Very_high} +- {id: OSC_CR_ERCLKEN_CFG, value: Enabled} +- {id: OSC_CR_ERCLKEN_UNDIV_CFG, value: Enabled} +- {id: RTC_CR_CLKO_CFG, value: Disabled} +- {id: SIM.OSC32KSEL.sel, value: RTC.RTC32KCLK} +- {id: SIM.OUTDIV1.scale, value: '1', locked: true} +- {id: SIM.OUTDIV2.scale, value: '2'} +- {id: SIM.OUTDIV4.scale, value: '5'} +- {id: SIM.PLLFLLSEL.sel, value: MCG.MCGPLLCLK} +sources: +- {id: OSC.OSC.outFreq, value: 12 MHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ - CLOCK_SetSimConfig(&g_defaultClockConfigHsrun.simConfig); +/******************************************************************************* + * Variables for BOARD_BootClockRUN configuration + ******************************************************************************/ +const mcg_config_t mcgConfig_BOARD_BootClockRUN = + { + .mcgMode = kMCG_ModePEE, /* PEE - PLL Engaged External */ + .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */ + .ircs = kMCG_IrcSlow, /* Slow internal reference clock selected */ + .fcrdiv = 0x0U, /* Fast IRC divider: divided by 1 */ + .frdiv = 0x0U, /* FLL reference clock divider: divided by 32 */ + .drs = kMCG_DrsLow, /* Low frequency range */ + .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ + .oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */ + .pll0Config = + { + .enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */ + .prdiv = 0x0U, /* PLL Reference divider: divided by 1 */ + .vdiv = 0x4U, /* VCO divider: multiplied by 20 */ + }, + .pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */ + }; +const sim_clock_config_t simConfig_BOARD_BootClockRUN = + { + .pllFllSel = SIM_PLLFLLSEL_MCGPLLCLK_CLK, /* PLLFLL select: MCGPLLCLK clock */ + .pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */ + .pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */ + .er32kSrc = SIM_OSC32KSEL_RTC32KCLK_CLK, /* OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ + .clkdiv1 = 0x1140000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /2, OUTDIV3: /2, OUTDIV4: /5 */ + }; +const osc_config_t oscConfig_BOARD_BootClockRUN = + { + .freq = 12000000U, /* Oscillator frequency: 12000000Hz */ + .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ + .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ + .oscerConfig = + { + .enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */ + .erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */ + } + }; - SystemCoreClock = g_defaultClockConfigHsrun.coreClock; +/******************************************************************************* + * Code for BOARD_BootClockRUN configuration + ******************************************************************************/ +void BOARD_BootClockRUN(void) +{ + /* Set the system clock dividers in SIM to safe value. */ + CLOCK_SetSimSafeDivs(); + /* Initializes OSC0 according to board configuration. */ + CLOCK_InitOsc0(&oscConfig_BOARD_BootClockRUN); + CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockRUN.freq); + /* Configure the Internal Reference clock (MCGIRCLK). */ + CLOCK_SetInternalRefClkConfig(mcgConfig_BOARD_BootClockRUN.irclkEnableMode, + mcgConfig_BOARD_BootClockRUN.ircs, + mcgConfig_BOARD_BootClockRUN.fcrdiv); + /* Configure FLL external reference divider (FRDIV). */ + CLOCK_CONFIG_SetFllExtRefDiv(mcgConfig_BOARD_BootClockRUN.frdiv); + /* Set MCG to PEE mode. */ + CLOCK_BootToPeeMode(mcgConfig_BOARD_BootClockRUN.oscsel, + mcgConfig_BOARD_BootClockRUN.pllcs, + &mcgConfig_BOARD_BootClockRUN.pll0Config); + /* Set the clock configuration in SIM module. */ + CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN); + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; } + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h old mode 100644 new mode 100755 index 0a23dd9917f..1086faaa83b --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -27,28 +27,121 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef _CLOCK_CONFIG_H_ #define _CLOCK_CONFIG_H_ +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define BOARD_XTAL0_CLK_HZ 12000000U /*!< Board xtal0 frequency in Hz */ + +/******************************************************************************* + ********************* Configuration BOARD_BootClockHSRUN ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockHSRUN configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKHSRUN_CORE_CLOCK 180000000U /*!< Core clock frequency: 180000000Hz */ + +/*! @brief MCG set for BOARD_BootClockHSRUN configuration. + */ +extern const mcg_config_t mcgConfig_BOARD_BootClockHSRUN; +/*! @brief SIM module set for BOARD_BootClockHSRUN configuration. + */ +extern const sim_clock_config_t simConfig_BOARD_BootClockHSRUN; +/*! @brief OSC set for BOARD_BootClockHSRUN configuration. + */ +extern const osc_config_t oscConfig_BOARD_BootClockHSRUN; + +/******************************************************************************* + * API for BOARD_BootClockHSRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockHSRUN(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************* Configuration BOARD_BootClockVLPR *********************** + ******************************************************************************/ /******************************************************************************* - * DEFINITION + * Definitions for BOARD_BootClockVLPR configuration ******************************************************************************/ -#define BOARD_XTAL0_CLK_HZ 12000000U -#define BOARD_XTAL32K_CLK_HZ 32768U +#define BOARD_BOOTCLOCKVLPR_CORE_CLOCK 4000000U /*!< Core clock frequency: 4000000Hz */ + +/*! @brief MCG set for BOARD_BootClockVLPR configuration. + */ +extern const mcg_config_t mcgConfig_BOARD_BootClockVLPR; +/*! @brief SIM module set for BOARD_BootClockVLPR configuration. + */ +extern const sim_clock_config_t simConfig_BOARD_BootClockVLPR; +/*! @brief OSC set for BOARD_BootClockVLPR configuration. + */ +extern const osc_config_t oscConfig_BOARD_BootClockVLPR; /******************************************************************************* - * API + * API for BOARD_BootClockVLPR configuration ******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif /* __cplusplus*/ +/*! + * @brief This function executes configuration of clocks. + * + */ void BOARD_BootClockVLPR(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockRUN configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 120000000U /*!< Core clock frequency: 120000000Hz */ + +/*! @brief MCG set for BOARD_BootClockRUN configuration. + */ +extern const mcg_config_t mcgConfig_BOARD_BootClockRUN; +/*! @brief SIM module set for BOARD_BootClockRUN configuration. + */ +extern const sim_clock_config_t simConfig_BOARD_BootClockRUN; +/*! @brief OSC set for BOARD_BootClockRUN configuration. + */ +extern const osc_config_t oscConfig_BOARD_BootClockRUN; + +/******************************************************************************* + * API for BOARD_BootClockRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ void BOARD_BootClockRUN(void); -void BOARD_BootClockHSRUN(void); #if defined(__cplusplus) } #endif /* __cplusplus*/ #endif /* _CLOCK_CONFIG_H_ */ + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c index 961a97f339f..a5bef533d5f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_phy.h" @@ -53,8 +53,10 @@ extern uint32_t ENET_GetInstance(ENET_Type *base); * Variables ******************************************************************************/ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to enet clocks for each instance. */ extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT]; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -64,14 +66,30 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz) { uint32_t bssReg; uint32_t counter = PHY_TIMEOUT_COUNT; + uint32_t idReg = 0; status_t result = kStatus_Success; uint32_t instance = ENET_GetInstance(base); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Set SMI first. */ CLOCK_EnableClock(s_enetClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ ENET_SetSMI(base, srcClock_Hz, false); + /* Initialization after PHY stars to work. */ + while ((idReg != PHY_CONTROL_ID1) && (counter != 0)) + { + PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg); + counter --; + } + + if (!counter) + { + return kStatus_Fail; + } + /* Reset PHY. */ + counter = PHY_TIMEOUT_COUNT; result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK); if (result == kStatus_Success) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h index bf3167fa69a..9353bea7989 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h index 516ce8501e3..a2d8eec3b9c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h @@ -9,17 +9,17 @@ ** Freescale C/C++ for Embedded ARM ** GNU C Compiler ** IAR ANSI C/C++ Compiler for ARM +** MCUXpresso Compiler ** ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151218 +** Build: b170112 ** ** Abstract: ** CMSIS Peripheral Access Layer for MK66F18 ** -** Copyright (c) 1997 - 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright (c) 1997 - 2016 Freescale Semiconductor, Inc. +** Copyright 2016 - 2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -30,7 +30,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -45,8 +45,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) @@ -5218,7 +5218,7 @@ typedef struct { /** Array initializer of DMA peripheral base pointers */ #define DMA_BASE_PTRS { DMA0 } /** Interrupt vectors for the DMA peripheral type */ -#define DMA_CHN_IRQS { DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn, DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn } +#define DMA_CHN_IRQS { { DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn, DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn } } #define DMA_ERROR_IRQS { DMA_Error_IRQn } /*! @@ -6182,6 +6182,9 @@ typedef struct { #define ENET_Receive_IRQS { ENET_Receive_IRQn } #define ENET_Error_IRQS { ENET_Error_IRQn } #define ENET_1588_Timer_IRQS { ENET_1588_Timer_IRQn } +/* ENET Buffer Descriptor and Buffer Address Alignment. */ +#define ENET_BUFF_ALIGNMENT (16U) + /*! * @} @@ -7731,30 +7734,30 @@ typedef struct { /* GPIO - Peripheral instance base addresses */ -/** Peripheral PTA base address */ -#define PTA_BASE (0x400FF000u) -/** Peripheral PTA base pointer */ -#define PTA ((GPIO_Type *)PTA_BASE) -/** Peripheral PTB base address */ -#define PTB_BASE (0x400FF040u) -/** Peripheral PTB base pointer */ -#define PTB ((GPIO_Type *)PTB_BASE) -/** Peripheral PTC base address */ -#define PTC_BASE (0x400FF080u) -/** Peripheral PTC base pointer */ -#define PTC ((GPIO_Type *)PTC_BASE) -/** Peripheral PTD base address */ -#define PTD_BASE (0x400FF0C0u) -/** Peripheral PTD base pointer */ -#define PTD ((GPIO_Type *)PTD_BASE) -/** Peripheral PTE base address */ -#define PTE_BASE (0x400FF100u) -/** Peripheral PTE base pointer */ -#define PTE ((GPIO_Type *)PTE_BASE) +/** Peripheral GPIOA base address */ +#define GPIOA_BASE (0x400FF000u) +/** Peripheral GPIOA base pointer */ +#define GPIOA ((GPIO_Type *)GPIOA_BASE) +/** Peripheral GPIOB base address */ +#define GPIOB_BASE (0x400FF040u) +/** Peripheral GPIOB base pointer */ +#define GPIOB ((GPIO_Type *)GPIOB_BASE) +/** Peripheral GPIOC base address */ +#define GPIOC_BASE (0x400FF080u) +/** Peripheral GPIOC base pointer */ +#define GPIOC ((GPIO_Type *)GPIOC_BASE) +/** Peripheral GPIOD base address */ +#define GPIOD_BASE (0x400FF0C0u) +/** Peripheral GPIOD base pointer */ +#define GPIOD ((GPIO_Type *)GPIOD_BASE) +/** Peripheral GPIOE base address */ +#define GPIOE_BASE (0x400FF100u) +/** Peripheral GPIOE base pointer */ +#define GPIOE ((GPIO_Type *)GPIOE_BASE) /** Array initializer of GPIO peripheral base addresses */ -#define GPIO_BASE_ADDRS { PTA_BASE, PTB_BASE, PTC_BASE, PTD_BASE, PTE_BASE } +#define GPIO_BASE_ADDRS { GPIOA_BASE, GPIOB_BASE, GPIOC_BASE, GPIOD_BASE, GPIOE_BASE } /** Array initializer of GPIO peripheral base pointers */ -#define GPIO_BASE_PTRS { PTA, PTB, PTC, PTD, PTE } +#define GPIO_BASE_PTRS { GPIOA, GPIOB, GPIOC, GPIOD, GPIOE } /*! * @} @@ -9827,252 +9830,6 @@ typedef struct { */ /* end of group MCM_Peripheral_Access_Layer */ -/* ---------------------------------------------------------------------------- - -- MPU Peripheral Access Layer - ---------------------------------------------------------------------------- */ - -/*! - * @addtogroup MPU_Peripheral_Access_Layer MPU Peripheral Access Layer - * @{ - */ - -/** MPU - Register Layout Typedef */ -typedef struct { - __IO uint32_t CESR; /**< Control/Error Status Register, offset: 0x0 */ - uint8_t RESERVED_0[12]; - struct { /* offset: 0x10, array step: 0x8 */ - __I uint32_t EAR; /**< Error Address Register, slave port n, array offset: 0x10, array step: 0x8 */ - __I uint32_t EDR; /**< Error Detail Register, slave port n, array offset: 0x14, array step: 0x8 */ - } SP[5]; - uint8_t RESERVED_1[968]; - __IO uint32_t WORD[12][4]; /**< Region Descriptor n, Word 0..Region Descriptor n, Word 3, array offset: 0x400, array step: index*0x10, index2*0x4 */ - uint8_t RESERVED_2[832]; - __IO uint32_t RGDAAC[12]; /**< Region Descriptor Alternate Access Control n, array offset: 0x800, array step: 0x4 */ -} MPU_Type; - -/* ---------------------------------------------------------------------------- - -- MPU Register Masks - ---------------------------------------------------------------------------- */ - -/*! - * @addtogroup MPU_Register_Masks MPU Register Masks - * @{ - */ - -/*! @name CESR - Control/Error Status Register */ -#define MPU_CESR_VLD_MASK (0x1U) -#define MPU_CESR_VLD_SHIFT (0U) -#define MPU_CESR_VLD(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_VLD_SHIFT)) & MPU_CESR_VLD_MASK) -#define MPU_CESR_NRGD_MASK (0xF00U) -#define MPU_CESR_NRGD_SHIFT (8U) -#define MPU_CESR_NRGD(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_NRGD_SHIFT)) & MPU_CESR_NRGD_MASK) -#define MPU_CESR_NSP_MASK (0xF000U) -#define MPU_CESR_NSP_SHIFT (12U) -#define MPU_CESR_NSP(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_NSP_SHIFT)) & MPU_CESR_NSP_MASK) -#define MPU_CESR_HRL_MASK (0xF0000U) -#define MPU_CESR_HRL_SHIFT (16U) -#define MPU_CESR_HRL(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_HRL_SHIFT)) & MPU_CESR_HRL_MASK) -#define MPU_CESR_SPERR_MASK (0xF8000000U) -#define MPU_CESR_SPERR_SHIFT (27U) -#define MPU_CESR_SPERR(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_SPERR_SHIFT)) & MPU_CESR_SPERR_MASK) - -/*! @name EAR - Error Address Register, slave port n */ -#define MPU_EAR_EADDR_MASK (0xFFFFFFFFU) -#define MPU_EAR_EADDR_SHIFT (0U) -#define MPU_EAR_EADDR(x) (((uint32_t)(((uint32_t)(x)) << MPU_EAR_EADDR_SHIFT)) & MPU_EAR_EADDR_MASK) - -/* The count of MPU_EAR */ -#define MPU_EAR_COUNT (5U) - -/*! @name EDR - Error Detail Register, slave port n */ -#define MPU_EDR_ERW_MASK (0x1U) -#define MPU_EDR_ERW_SHIFT (0U) -#define MPU_EDR_ERW(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_ERW_SHIFT)) & MPU_EDR_ERW_MASK) -#define MPU_EDR_EATTR_MASK (0xEU) -#define MPU_EDR_EATTR_SHIFT (1U) -#define MPU_EDR_EATTR(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EATTR_SHIFT)) & MPU_EDR_EATTR_MASK) -#define MPU_EDR_EMN_MASK (0xF0U) -#define MPU_EDR_EMN_SHIFT (4U) -#define MPU_EDR_EMN(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EMN_SHIFT)) & MPU_EDR_EMN_MASK) -#define MPU_EDR_EPID_MASK (0xFF00U) -#define MPU_EDR_EPID_SHIFT (8U) -#define MPU_EDR_EPID(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EPID_SHIFT)) & MPU_EDR_EPID_MASK) -#define MPU_EDR_EACD_MASK (0xFFFF0000U) -#define MPU_EDR_EACD_SHIFT (16U) -#define MPU_EDR_EACD(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EACD_SHIFT)) & MPU_EDR_EACD_MASK) - -/* The count of MPU_EDR */ -#define MPU_EDR_COUNT (5U) - -/*! @name WORD - Region Descriptor n, Word 0..Region Descriptor n, Word 3 */ -#define MPU_WORD_VLD_MASK (0x1U) -#define MPU_WORD_VLD_SHIFT (0U) -#define MPU_WORD_VLD(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_VLD_SHIFT)) & MPU_WORD_VLD_MASK) -#define MPU_WORD_M0UM_MASK (0x7U) -#define MPU_WORD_M0UM_SHIFT (0U) -#define MPU_WORD_M0UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M0UM_SHIFT)) & MPU_WORD_M0UM_MASK) -#define MPU_WORD_M0SM_MASK (0x18U) -#define MPU_WORD_M0SM_SHIFT (3U) -#define MPU_WORD_M0SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M0SM_SHIFT)) & MPU_WORD_M0SM_MASK) -#define MPU_WORD_M0PE_MASK (0x20U) -#define MPU_WORD_M0PE_SHIFT (5U) -#define MPU_WORD_M0PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M0PE_SHIFT)) & MPU_WORD_M0PE_MASK) -#define MPU_WORD_ENDADDR_MASK (0xFFFFFFE0U) -#define MPU_WORD_ENDADDR_SHIFT (5U) -#define MPU_WORD_ENDADDR(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_ENDADDR_SHIFT)) & MPU_WORD_ENDADDR_MASK) -#define MPU_WORD_SRTADDR_MASK (0xFFFFFFE0U) -#define MPU_WORD_SRTADDR_SHIFT (5U) -#define MPU_WORD_SRTADDR(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_SRTADDR_SHIFT)) & MPU_WORD_SRTADDR_MASK) -#define MPU_WORD_M1UM_MASK (0x1C0U) -#define MPU_WORD_M1UM_SHIFT (6U) -#define MPU_WORD_M1UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M1UM_SHIFT)) & MPU_WORD_M1UM_MASK) -#define MPU_WORD_M1SM_MASK (0x600U) -#define MPU_WORD_M1SM_SHIFT (9U) -#define MPU_WORD_M1SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M1SM_SHIFT)) & MPU_WORD_M1SM_MASK) -#define MPU_WORD_M1PE_MASK (0x800U) -#define MPU_WORD_M1PE_SHIFT (11U) -#define MPU_WORD_M1PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M1PE_SHIFT)) & MPU_WORD_M1PE_MASK) -#define MPU_WORD_M2UM_MASK (0x7000U) -#define MPU_WORD_M2UM_SHIFT (12U) -#define MPU_WORD_M2UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M2UM_SHIFT)) & MPU_WORD_M2UM_MASK) -#define MPU_WORD_M2SM_MASK (0x18000U) -#define MPU_WORD_M2SM_SHIFT (15U) -#define MPU_WORD_M2SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M2SM_SHIFT)) & MPU_WORD_M2SM_MASK) -#define MPU_WORD_PIDMASK_MASK (0xFF0000U) -#define MPU_WORD_PIDMASK_SHIFT (16U) -#define MPU_WORD_PIDMASK(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_PIDMASK_SHIFT)) & MPU_WORD_PIDMASK_MASK) -#define MPU_WORD_M2PE_MASK (0x20000U) -#define MPU_WORD_M2PE_SHIFT (17U) -#define MPU_WORD_M2PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M2PE_SHIFT)) & MPU_WORD_M2PE_MASK) -#define MPU_WORD_M3UM_MASK (0x1C0000U) -#define MPU_WORD_M3UM_SHIFT (18U) -#define MPU_WORD_M3UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M3UM_SHIFT)) & MPU_WORD_M3UM_MASK) -#define MPU_WORD_M3SM_MASK (0x600000U) -#define MPU_WORD_M3SM_SHIFT (21U) -#define MPU_WORD_M3SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M3SM_SHIFT)) & MPU_WORD_M3SM_MASK) -#define MPU_WORD_M3PE_MASK (0x800000U) -#define MPU_WORD_M3PE_SHIFT (23U) -#define MPU_WORD_M3PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M3PE_SHIFT)) & MPU_WORD_M3PE_MASK) -#define MPU_WORD_PID_MASK (0xFF000000U) -#define MPU_WORD_PID_SHIFT (24U) -#define MPU_WORD_PID(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_PID_SHIFT)) & MPU_WORD_PID_MASK) -#define MPU_WORD_M4WE_MASK (0x1000000U) -#define MPU_WORD_M4WE_SHIFT (24U) -#define MPU_WORD_M4WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M4WE_SHIFT)) & MPU_WORD_M4WE_MASK) -#define MPU_WORD_M4RE_MASK (0x2000000U) -#define MPU_WORD_M4RE_SHIFT (25U) -#define MPU_WORD_M4RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M4RE_SHIFT)) & MPU_WORD_M4RE_MASK) -#define MPU_WORD_M5WE_MASK (0x4000000U) -#define MPU_WORD_M5WE_SHIFT (26U) -#define MPU_WORD_M5WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M5WE_SHIFT)) & MPU_WORD_M5WE_MASK) -#define MPU_WORD_M5RE_MASK (0x8000000U) -#define MPU_WORD_M5RE_SHIFT (27U) -#define MPU_WORD_M5RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M5RE_SHIFT)) & MPU_WORD_M5RE_MASK) -#define MPU_WORD_M6WE_MASK (0x10000000U) -#define MPU_WORD_M6WE_SHIFT (28U) -#define MPU_WORD_M6WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M6WE_SHIFT)) & MPU_WORD_M6WE_MASK) -#define MPU_WORD_M6RE_MASK (0x20000000U) -#define MPU_WORD_M6RE_SHIFT (29U) -#define MPU_WORD_M6RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M6RE_SHIFT)) & MPU_WORD_M6RE_MASK) -#define MPU_WORD_M7WE_MASK (0x40000000U) -#define MPU_WORD_M7WE_SHIFT (30U) -#define MPU_WORD_M7WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M7WE_SHIFT)) & MPU_WORD_M7WE_MASK) -#define MPU_WORD_M7RE_MASK (0x80000000U) -#define MPU_WORD_M7RE_SHIFT (31U) -#define MPU_WORD_M7RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M7RE_SHIFT)) & MPU_WORD_M7RE_MASK) - -/* The count of MPU_WORD */ -#define MPU_WORD_COUNT (12U) - -/* The count of MPU_WORD */ -#define MPU_WORD_COUNT2 (4U) - -/*! @name RGDAAC - Region Descriptor Alternate Access Control n */ -#define MPU_RGDAAC_M0UM_MASK (0x7U) -#define MPU_RGDAAC_M0UM_SHIFT (0U) -#define MPU_RGDAAC_M0UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M0UM_SHIFT)) & MPU_RGDAAC_M0UM_MASK) -#define MPU_RGDAAC_M0SM_MASK (0x18U) -#define MPU_RGDAAC_M0SM_SHIFT (3U) -#define MPU_RGDAAC_M0SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M0SM_SHIFT)) & MPU_RGDAAC_M0SM_MASK) -#define MPU_RGDAAC_M0PE_MASK (0x20U) -#define MPU_RGDAAC_M0PE_SHIFT (5U) -#define MPU_RGDAAC_M0PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M0PE_SHIFT)) & MPU_RGDAAC_M0PE_MASK) -#define MPU_RGDAAC_M1UM_MASK (0x1C0U) -#define MPU_RGDAAC_M1UM_SHIFT (6U) -#define MPU_RGDAAC_M1UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M1UM_SHIFT)) & MPU_RGDAAC_M1UM_MASK) -#define MPU_RGDAAC_M1SM_MASK (0x600U) -#define MPU_RGDAAC_M1SM_SHIFT (9U) -#define MPU_RGDAAC_M1SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M1SM_SHIFT)) & MPU_RGDAAC_M1SM_MASK) -#define MPU_RGDAAC_M1PE_MASK (0x800U) -#define MPU_RGDAAC_M1PE_SHIFT (11U) -#define MPU_RGDAAC_M1PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M1PE_SHIFT)) & MPU_RGDAAC_M1PE_MASK) -#define MPU_RGDAAC_M2UM_MASK (0x7000U) -#define MPU_RGDAAC_M2UM_SHIFT (12U) -#define MPU_RGDAAC_M2UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M2UM_SHIFT)) & MPU_RGDAAC_M2UM_MASK) -#define MPU_RGDAAC_M2SM_MASK (0x18000U) -#define MPU_RGDAAC_M2SM_SHIFT (15U) -#define MPU_RGDAAC_M2SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M2SM_SHIFT)) & MPU_RGDAAC_M2SM_MASK) -#define MPU_RGDAAC_M2PE_MASK (0x20000U) -#define MPU_RGDAAC_M2PE_SHIFT (17U) -#define MPU_RGDAAC_M2PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M2PE_SHIFT)) & MPU_RGDAAC_M2PE_MASK) -#define MPU_RGDAAC_M3UM_MASK (0x1C0000U) -#define MPU_RGDAAC_M3UM_SHIFT (18U) -#define MPU_RGDAAC_M3UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M3UM_SHIFT)) & MPU_RGDAAC_M3UM_MASK) -#define MPU_RGDAAC_M3SM_MASK (0x600000U) -#define MPU_RGDAAC_M3SM_SHIFT (21U) -#define MPU_RGDAAC_M3SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M3SM_SHIFT)) & MPU_RGDAAC_M3SM_MASK) -#define MPU_RGDAAC_M3PE_MASK (0x800000U) -#define MPU_RGDAAC_M3PE_SHIFT (23U) -#define MPU_RGDAAC_M3PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M3PE_SHIFT)) & MPU_RGDAAC_M3PE_MASK) -#define MPU_RGDAAC_M4WE_MASK (0x1000000U) -#define MPU_RGDAAC_M4WE_SHIFT (24U) -#define MPU_RGDAAC_M4WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M4WE_SHIFT)) & MPU_RGDAAC_M4WE_MASK) -#define MPU_RGDAAC_M4RE_MASK (0x2000000U) -#define MPU_RGDAAC_M4RE_SHIFT (25U) -#define MPU_RGDAAC_M4RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M4RE_SHIFT)) & MPU_RGDAAC_M4RE_MASK) -#define MPU_RGDAAC_M5WE_MASK (0x4000000U) -#define MPU_RGDAAC_M5WE_SHIFT (26U) -#define MPU_RGDAAC_M5WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M5WE_SHIFT)) & MPU_RGDAAC_M5WE_MASK) -#define MPU_RGDAAC_M5RE_MASK (0x8000000U) -#define MPU_RGDAAC_M5RE_SHIFT (27U) -#define MPU_RGDAAC_M5RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M5RE_SHIFT)) & MPU_RGDAAC_M5RE_MASK) -#define MPU_RGDAAC_M6WE_MASK (0x10000000U) -#define MPU_RGDAAC_M6WE_SHIFT (28U) -#define MPU_RGDAAC_M6WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M6WE_SHIFT)) & MPU_RGDAAC_M6WE_MASK) -#define MPU_RGDAAC_M6RE_MASK (0x20000000U) -#define MPU_RGDAAC_M6RE_SHIFT (29U) -#define MPU_RGDAAC_M6RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M6RE_SHIFT)) & MPU_RGDAAC_M6RE_MASK) -#define MPU_RGDAAC_M7WE_MASK (0x40000000U) -#define MPU_RGDAAC_M7WE_SHIFT (30U) -#define MPU_RGDAAC_M7WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M7WE_SHIFT)) & MPU_RGDAAC_M7WE_MASK) -#define MPU_RGDAAC_M7RE_MASK (0x80000000U) -#define MPU_RGDAAC_M7RE_SHIFT (31U) -#define MPU_RGDAAC_M7RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M7RE_SHIFT)) & MPU_RGDAAC_M7RE_MASK) - -/* The count of MPU_RGDAAC */ -#define MPU_RGDAAC_COUNT (12U) - - -/*! - * @} - */ /* end of group MPU_Register_Masks */ - - -/* MPU - Peripheral instance base addresses */ -/** Peripheral MPU base address */ -#define MPU_BASE (0x4000D000u) -/** Peripheral MPU base pointer */ -#define MPU ((MPU_Type *)MPU_BASE) -/** Array initializer of MPU peripheral base addresses */ -#define MPU_BASE_ADDRS { MPU_BASE } -/** Array initializer of MPU peripheral base pointers */ -#define MPU_BASE_PTRS { MPU } - -/*! - * @} - */ /* end of group MPU_Peripheral_Access_Layer */ - - /* ---------------------------------------------------------------------------- -- NV Peripheral Access Layer ---------------------------------------------------------------------------- */ @@ -10590,7 +10347,7 @@ typedef struct { /** Array initializer of PIT peripheral base pointers */ #define PIT_BASE_PTRS { PIT } /** Interrupt vectors for the PIT peripheral type */ -#define PIT_IRQS { PIT0_IRQn, PIT1_IRQn, PIT2_IRQn, PIT3_IRQn } +#define PIT_IRQS { { PIT0_IRQn, PIT1_IRQn, PIT2_IRQn, PIT3_IRQn } } /*! * @} @@ -13236,6 +12993,252 @@ typedef struct { */ /* end of group SPI_Peripheral_Access_Layer */ +/* ---------------------------------------------------------------------------- + -- SYSMPU Peripheral Access Layer + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup SYSMPU_Peripheral_Access_Layer SYSMPU Peripheral Access Layer + * @{ + */ + +/** SYSMPU - Register Layout Typedef */ +typedef struct { + __IO uint32_t CESR; /**< Control/Error Status Register, offset: 0x0 */ + uint8_t RESERVED_0[12]; + struct { /* offset: 0x10, array step: 0x8 */ + __I uint32_t EAR; /**< Error Address Register, slave port n, array offset: 0x10, array step: 0x8 */ + __I uint32_t EDR; /**< Error Detail Register, slave port n, array offset: 0x14, array step: 0x8 */ + } SP[5]; + uint8_t RESERVED_1[968]; + __IO uint32_t WORD[12][4]; /**< Region Descriptor n, Word 0..Region Descriptor n, Word 3, array offset: 0x400, array step: index*0x10, index2*0x4 */ + uint8_t RESERVED_2[832]; + __IO uint32_t RGDAAC[12]; /**< Region Descriptor Alternate Access Control n, array offset: 0x800, array step: 0x4 */ +} SYSMPU_Type; + +/* ---------------------------------------------------------------------------- + -- SYSMPU Register Masks + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup SYSMPU_Register_Masks SYSMPU Register Masks + * @{ + */ + +/*! @name CESR - Control/Error Status Register */ +#define SYSMPU_CESR_VLD_MASK (0x1U) +#define SYSMPU_CESR_VLD_SHIFT (0U) +#define SYSMPU_CESR_VLD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_VLD_SHIFT)) & SYSMPU_CESR_VLD_MASK) +#define SYSMPU_CESR_NRGD_MASK (0xF00U) +#define SYSMPU_CESR_NRGD_SHIFT (8U) +#define SYSMPU_CESR_NRGD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_NRGD_SHIFT)) & SYSMPU_CESR_NRGD_MASK) +#define SYSMPU_CESR_NSP_MASK (0xF000U) +#define SYSMPU_CESR_NSP_SHIFT (12U) +#define SYSMPU_CESR_NSP(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_NSP_SHIFT)) & SYSMPU_CESR_NSP_MASK) +#define SYSMPU_CESR_HRL_MASK (0xF0000U) +#define SYSMPU_CESR_HRL_SHIFT (16U) +#define SYSMPU_CESR_HRL(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_HRL_SHIFT)) & SYSMPU_CESR_HRL_MASK) +#define SYSMPU_CESR_SPERR_MASK (0xF8000000U) +#define SYSMPU_CESR_SPERR_SHIFT (27U) +#define SYSMPU_CESR_SPERR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_SPERR_SHIFT)) & SYSMPU_CESR_SPERR_MASK) + +/*! @name EAR - Error Address Register, slave port n */ +#define SYSMPU_EAR_EADDR_MASK (0xFFFFFFFFU) +#define SYSMPU_EAR_EADDR_SHIFT (0U) +#define SYSMPU_EAR_EADDR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EAR_EADDR_SHIFT)) & SYSMPU_EAR_EADDR_MASK) + +/* The count of SYSMPU_EAR */ +#define SYSMPU_EAR_COUNT (5U) + +/*! @name EDR - Error Detail Register, slave port n */ +#define SYSMPU_EDR_ERW_MASK (0x1U) +#define SYSMPU_EDR_ERW_SHIFT (0U) +#define SYSMPU_EDR_ERW(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_ERW_SHIFT)) & SYSMPU_EDR_ERW_MASK) +#define SYSMPU_EDR_EATTR_MASK (0xEU) +#define SYSMPU_EDR_EATTR_SHIFT (1U) +#define SYSMPU_EDR_EATTR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EATTR_SHIFT)) & SYSMPU_EDR_EATTR_MASK) +#define SYSMPU_EDR_EMN_MASK (0xF0U) +#define SYSMPU_EDR_EMN_SHIFT (4U) +#define SYSMPU_EDR_EMN(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EMN_SHIFT)) & SYSMPU_EDR_EMN_MASK) +#define SYSMPU_EDR_EPID_MASK (0xFF00U) +#define SYSMPU_EDR_EPID_SHIFT (8U) +#define SYSMPU_EDR_EPID(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EPID_SHIFT)) & SYSMPU_EDR_EPID_MASK) +#define SYSMPU_EDR_EACD_MASK (0xFFFF0000U) +#define SYSMPU_EDR_EACD_SHIFT (16U) +#define SYSMPU_EDR_EACD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EACD_SHIFT)) & SYSMPU_EDR_EACD_MASK) + +/* The count of SYSMPU_EDR */ +#define SYSMPU_EDR_COUNT (5U) + +/*! @name WORD - Region Descriptor n, Word 0..Region Descriptor n, Word 3 */ +#define SYSMPU_WORD_VLD_MASK (0x1U) +#define SYSMPU_WORD_VLD_SHIFT (0U) +#define SYSMPU_WORD_VLD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_VLD_SHIFT)) & SYSMPU_WORD_VLD_MASK) +#define SYSMPU_WORD_M0UM_MASK (0x7U) +#define SYSMPU_WORD_M0UM_SHIFT (0U) +#define SYSMPU_WORD_M0UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M0UM_SHIFT)) & SYSMPU_WORD_M0UM_MASK) +#define SYSMPU_WORD_M0SM_MASK (0x18U) +#define SYSMPU_WORD_M0SM_SHIFT (3U) +#define SYSMPU_WORD_M0SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M0SM_SHIFT)) & SYSMPU_WORD_M0SM_MASK) +#define SYSMPU_WORD_M0PE_MASK (0x20U) +#define SYSMPU_WORD_M0PE_SHIFT (5U) +#define SYSMPU_WORD_M0PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M0PE_SHIFT)) & SYSMPU_WORD_M0PE_MASK) +#define SYSMPU_WORD_ENDADDR_MASK (0xFFFFFFE0U) +#define SYSMPU_WORD_ENDADDR_SHIFT (5U) +#define SYSMPU_WORD_ENDADDR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_ENDADDR_SHIFT)) & SYSMPU_WORD_ENDADDR_MASK) +#define SYSMPU_WORD_SRTADDR_MASK (0xFFFFFFE0U) +#define SYSMPU_WORD_SRTADDR_SHIFT (5U) +#define SYSMPU_WORD_SRTADDR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_SRTADDR_SHIFT)) & SYSMPU_WORD_SRTADDR_MASK) +#define SYSMPU_WORD_M1UM_MASK (0x1C0U) +#define SYSMPU_WORD_M1UM_SHIFT (6U) +#define SYSMPU_WORD_M1UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M1UM_SHIFT)) & SYSMPU_WORD_M1UM_MASK) +#define SYSMPU_WORD_M1SM_MASK (0x600U) +#define SYSMPU_WORD_M1SM_SHIFT (9U) +#define SYSMPU_WORD_M1SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M1SM_SHIFT)) & SYSMPU_WORD_M1SM_MASK) +#define SYSMPU_WORD_M1PE_MASK (0x800U) +#define SYSMPU_WORD_M1PE_SHIFT (11U) +#define SYSMPU_WORD_M1PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M1PE_SHIFT)) & SYSMPU_WORD_M1PE_MASK) +#define SYSMPU_WORD_M2UM_MASK (0x7000U) +#define SYSMPU_WORD_M2UM_SHIFT (12U) +#define SYSMPU_WORD_M2UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M2UM_SHIFT)) & SYSMPU_WORD_M2UM_MASK) +#define SYSMPU_WORD_M2SM_MASK (0x18000U) +#define SYSMPU_WORD_M2SM_SHIFT (15U) +#define SYSMPU_WORD_M2SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M2SM_SHIFT)) & SYSMPU_WORD_M2SM_MASK) +#define SYSMPU_WORD_PIDMASK_MASK (0xFF0000U) +#define SYSMPU_WORD_PIDMASK_SHIFT (16U) +#define SYSMPU_WORD_PIDMASK(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_PIDMASK_SHIFT)) & SYSMPU_WORD_PIDMASK_MASK) +#define SYSMPU_WORD_M2PE_MASK (0x20000U) +#define SYSMPU_WORD_M2PE_SHIFT (17U) +#define SYSMPU_WORD_M2PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M2PE_SHIFT)) & SYSMPU_WORD_M2PE_MASK) +#define SYSMPU_WORD_M3UM_MASK (0x1C0000U) +#define SYSMPU_WORD_M3UM_SHIFT (18U) +#define SYSMPU_WORD_M3UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M3UM_SHIFT)) & SYSMPU_WORD_M3UM_MASK) +#define SYSMPU_WORD_M3SM_MASK (0x600000U) +#define SYSMPU_WORD_M3SM_SHIFT (21U) +#define SYSMPU_WORD_M3SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M3SM_SHIFT)) & SYSMPU_WORD_M3SM_MASK) +#define SYSMPU_WORD_M3PE_MASK (0x800000U) +#define SYSMPU_WORD_M3PE_SHIFT (23U) +#define SYSMPU_WORD_M3PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M3PE_SHIFT)) & SYSMPU_WORD_M3PE_MASK) +#define SYSMPU_WORD_PID_MASK (0xFF000000U) +#define SYSMPU_WORD_PID_SHIFT (24U) +#define SYSMPU_WORD_PID(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_PID_SHIFT)) & SYSMPU_WORD_PID_MASK) +#define SYSMPU_WORD_M4WE_MASK (0x1000000U) +#define SYSMPU_WORD_M4WE_SHIFT (24U) +#define SYSMPU_WORD_M4WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M4WE_SHIFT)) & SYSMPU_WORD_M4WE_MASK) +#define SYSMPU_WORD_M4RE_MASK (0x2000000U) +#define SYSMPU_WORD_M4RE_SHIFT (25U) +#define SYSMPU_WORD_M4RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M4RE_SHIFT)) & SYSMPU_WORD_M4RE_MASK) +#define SYSMPU_WORD_M5WE_MASK (0x4000000U) +#define SYSMPU_WORD_M5WE_SHIFT (26U) +#define SYSMPU_WORD_M5WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M5WE_SHIFT)) & SYSMPU_WORD_M5WE_MASK) +#define SYSMPU_WORD_M5RE_MASK (0x8000000U) +#define SYSMPU_WORD_M5RE_SHIFT (27U) +#define SYSMPU_WORD_M5RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M5RE_SHIFT)) & SYSMPU_WORD_M5RE_MASK) +#define SYSMPU_WORD_M6WE_MASK (0x10000000U) +#define SYSMPU_WORD_M6WE_SHIFT (28U) +#define SYSMPU_WORD_M6WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M6WE_SHIFT)) & SYSMPU_WORD_M6WE_MASK) +#define SYSMPU_WORD_M6RE_MASK (0x20000000U) +#define SYSMPU_WORD_M6RE_SHIFT (29U) +#define SYSMPU_WORD_M6RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M6RE_SHIFT)) & SYSMPU_WORD_M6RE_MASK) +#define SYSMPU_WORD_M7WE_MASK (0x40000000U) +#define SYSMPU_WORD_M7WE_SHIFT (30U) +#define SYSMPU_WORD_M7WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M7WE_SHIFT)) & SYSMPU_WORD_M7WE_MASK) +#define SYSMPU_WORD_M7RE_MASK (0x80000000U) +#define SYSMPU_WORD_M7RE_SHIFT (31U) +#define SYSMPU_WORD_M7RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M7RE_SHIFT)) & SYSMPU_WORD_M7RE_MASK) + +/* The count of SYSMPU_WORD */ +#define SYSMPU_WORD_COUNT (12U) + +/* The count of SYSMPU_WORD */ +#define SYSMPU_WORD_COUNT2 (4U) + +/*! @name RGDAAC - Region Descriptor Alternate Access Control n */ +#define SYSMPU_RGDAAC_M0UM_MASK (0x7U) +#define SYSMPU_RGDAAC_M0UM_SHIFT (0U) +#define SYSMPU_RGDAAC_M0UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M0UM_SHIFT)) & SYSMPU_RGDAAC_M0UM_MASK) +#define SYSMPU_RGDAAC_M0SM_MASK (0x18U) +#define SYSMPU_RGDAAC_M0SM_SHIFT (3U) +#define SYSMPU_RGDAAC_M0SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M0SM_SHIFT)) & SYSMPU_RGDAAC_M0SM_MASK) +#define SYSMPU_RGDAAC_M0PE_MASK (0x20U) +#define SYSMPU_RGDAAC_M0PE_SHIFT (5U) +#define SYSMPU_RGDAAC_M0PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M0PE_SHIFT)) & SYSMPU_RGDAAC_M0PE_MASK) +#define SYSMPU_RGDAAC_M1UM_MASK (0x1C0U) +#define SYSMPU_RGDAAC_M1UM_SHIFT (6U) +#define SYSMPU_RGDAAC_M1UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M1UM_SHIFT)) & SYSMPU_RGDAAC_M1UM_MASK) +#define SYSMPU_RGDAAC_M1SM_MASK (0x600U) +#define SYSMPU_RGDAAC_M1SM_SHIFT (9U) +#define SYSMPU_RGDAAC_M1SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M1SM_SHIFT)) & SYSMPU_RGDAAC_M1SM_MASK) +#define SYSMPU_RGDAAC_M1PE_MASK (0x800U) +#define SYSMPU_RGDAAC_M1PE_SHIFT (11U) +#define SYSMPU_RGDAAC_M1PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M1PE_SHIFT)) & SYSMPU_RGDAAC_M1PE_MASK) +#define SYSMPU_RGDAAC_M2UM_MASK (0x7000U) +#define SYSMPU_RGDAAC_M2UM_SHIFT (12U) +#define SYSMPU_RGDAAC_M2UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M2UM_SHIFT)) & SYSMPU_RGDAAC_M2UM_MASK) +#define SYSMPU_RGDAAC_M2SM_MASK (0x18000U) +#define SYSMPU_RGDAAC_M2SM_SHIFT (15U) +#define SYSMPU_RGDAAC_M2SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M2SM_SHIFT)) & SYSMPU_RGDAAC_M2SM_MASK) +#define SYSMPU_RGDAAC_M2PE_MASK (0x20000U) +#define SYSMPU_RGDAAC_M2PE_SHIFT (17U) +#define SYSMPU_RGDAAC_M2PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M2PE_SHIFT)) & SYSMPU_RGDAAC_M2PE_MASK) +#define SYSMPU_RGDAAC_M3UM_MASK (0x1C0000U) +#define SYSMPU_RGDAAC_M3UM_SHIFT (18U) +#define SYSMPU_RGDAAC_M3UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M3UM_SHIFT)) & SYSMPU_RGDAAC_M3UM_MASK) +#define SYSMPU_RGDAAC_M3SM_MASK (0x600000U) +#define SYSMPU_RGDAAC_M3SM_SHIFT (21U) +#define SYSMPU_RGDAAC_M3SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M3SM_SHIFT)) & SYSMPU_RGDAAC_M3SM_MASK) +#define SYSMPU_RGDAAC_M3PE_MASK (0x800000U) +#define SYSMPU_RGDAAC_M3PE_SHIFT (23U) +#define SYSMPU_RGDAAC_M3PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M3PE_SHIFT)) & SYSMPU_RGDAAC_M3PE_MASK) +#define SYSMPU_RGDAAC_M4WE_MASK (0x1000000U) +#define SYSMPU_RGDAAC_M4WE_SHIFT (24U) +#define SYSMPU_RGDAAC_M4WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M4WE_SHIFT)) & SYSMPU_RGDAAC_M4WE_MASK) +#define SYSMPU_RGDAAC_M4RE_MASK (0x2000000U) +#define SYSMPU_RGDAAC_M4RE_SHIFT (25U) +#define SYSMPU_RGDAAC_M4RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M4RE_SHIFT)) & SYSMPU_RGDAAC_M4RE_MASK) +#define SYSMPU_RGDAAC_M5WE_MASK (0x4000000U) +#define SYSMPU_RGDAAC_M5WE_SHIFT (26U) +#define SYSMPU_RGDAAC_M5WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M5WE_SHIFT)) & SYSMPU_RGDAAC_M5WE_MASK) +#define SYSMPU_RGDAAC_M5RE_MASK (0x8000000U) +#define SYSMPU_RGDAAC_M5RE_SHIFT (27U) +#define SYSMPU_RGDAAC_M5RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M5RE_SHIFT)) & SYSMPU_RGDAAC_M5RE_MASK) +#define SYSMPU_RGDAAC_M6WE_MASK (0x10000000U) +#define SYSMPU_RGDAAC_M6WE_SHIFT (28U) +#define SYSMPU_RGDAAC_M6WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M6WE_SHIFT)) & SYSMPU_RGDAAC_M6WE_MASK) +#define SYSMPU_RGDAAC_M6RE_MASK (0x20000000U) +#define SYSMPU_RGDAAC_M6RE_SHIFT (29U) +#define SYSMPU_RGDAAC_M6RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M6RE_SHIFT)) & SYSMPU_RGDAAC_M6RE_MASK) +#define SYSMPU_RGDAAC_M7WE_MASK (0x40000000U) +#define SYSMPU_RGDAAC_M7WE_SHIFT (30U) +#define SYSMPU_RGDAAC_M7WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M7WE_SHIFT)) & SYSMPU_RGDAAC_M7WE_MASK) +#define SYSMPU_RGDAAC_M7RE_MASK (0x80000000U) +#define SYSMPU_RGDAAC_M7RE_SHIFT (31U) +#define SYSMPU_RGDAAC_M7RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M7RE_SHIFT)) & SYSMPU_RGDAAC_M7RE_MASK) + +/* The count of SYSMPU_RGDAAC */ +#define SYSMPU_RGDAAC_COUNT (12U) + + +/*! + * @} + */ /* end of group SYSMPU_Register_Masks */ + + +/* SYSMPU - Peripheral instance base addresses */ +/** Peripheral SYSMPU base address */ +#define SYSMPU_BASE (0x4000D000u) +/** Peripheral SYSMPU base pointer */ +#define SYSMPU ((SYSMPU_Type *)SYSMPU_BASE) +/** Array initializer of SYSMPU peripheral base addresses */ +#define SYSMPU_BASE_ADDRS { SYSMPU_BASE } +/** Array initializer of SYSMPU peripheral base pointers */ +#define SYSMPU_BASE_PTRS { SYSMPU } + +/*! + * @} + */ /* end of group SYSMPU_Peripheral_Access_Layer */ + + /* ---------------------------------------------------------------------------- -- TPM Peripheral Access Layer ---------------------------------------------------------------------------- */ @@ -17249,6 +17252,43 @@ typedef struct { */ /* end of group Peripheral_access_layer */ +/* ---------------------------------------------------------------------------- + -- Macros for use with bit field definitions (xxx_SHIFT, xxx_MASK). + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup Bit_Field_Generic_Macros Macros for use with bit field definitions (xxx_SHIFT, xxx_MASK). + * @{ + */ + +#if defined(__ARMCC_VERSION) + #if (__ARMCC_VERSION >= 6010050) + #pragma clang system_header + #endif +#elif defined(__IAR_SYSTEMS_ICC__) + #pragma system_include +#endif + +/** + * @brief Mask and left-shift a bit field value for use in a register bit range. + * @param field Name of the register bit field. + * @param value Value of the bit field. + * @return Masked and shifted value. + */ +#define NXP_VAL2FLD(field, value) (((value) << (field ## _SHIFT)) & (field ## _MASK)) +/** + * @brief Mask and right-shift a register value to extract a bit field value. + * @param field Name of the register bit field. + * @param value Value of the register. + * @return Masked and shifted bit field value. + */ +#define NXP_FLD2VAL(field, value) (((value) & (field ## _MASK)) >> (field ## _SHIFT)) + +/*! + * @} + */ /* end of group Bit_Field_Generic_Macros */ + + /* ---------------------------------------------------------------------------- -- SDK Compatibility ---------------------------------------------------------------------------- */ @@ -17498,16 +17538,16 @@ typedef struct { #define DSPI2 SPI2 #define FLEXCAN0 CAN0 #define FLEXCAN1 CAN1 -#define GPIOA_BASE PTA_BASE -#define GPIOA PTA -#define GPIOB_BASE PTB_BASE -#define GPIOB PTB -#define GPIOC_BASE PTC_BASE -#define GPIOC PTC -#define GPIOD_BASE PTD_BASE -#define GPIOD PTD -#define GPIOE_BASE PTE_BASE -#define GPIOE PTE +#define PTA_BASE GPIOA_BASE +#define PTA GPIOA +#define PTB_BASE GPIOB_BASE +#define PTB GPIOB +#define PTC_BASE GPIOC_BASE +#define PTC GPIOC +#define PTD_BASE GPIOD_BASE +#define PTD GPIOD +#define PTE_BASE GPIOE_BASE +#define PTE GPIOE #define Watchdog_IRQn WDOG_EWM_IRQn #define Watchdog_IRQHandler WDOG_EWM_IRQHandler #define LPTimer_IRQn LPTMR0_IRQn diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h index 07207f3a71c..19bfac70136 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h @@ -1,14 +1,13 @@ /* ** ################################################################### ** Version: rev. 2.9, 2015-06-08 -** Build: b151217 +** Build: b170228 ** ** Abstract: ** Chip specific module features. ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -19,7 +18,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -34,8 +33,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) @@ -212,8 +211,8 @@ #define FSL_FEATURE_SOC_MMAU_COUNT (0) /* @brief MMDVSQ availability on the SoC. */ #define FSL_FEATURE_SOC_MMDVSQ_COUNT (0) -/* @brief MPU availability on the SoC. */ -#define FSL_FEATURE_SOC_MPU_COUNT (1) +/* @brief SYSMPU availability on the SoC. */ +#define FSL_FEATURE_SOC_SYSMPU_COUNT (1) /* @brief MSCAN availability on the SoC. */ #define FSL_FEATURE_SOC_MSCAN_COUNT (0) /* @brief MSCM availability on the SoC. */ @@ -304,6 +303,8 @@ #define FSL_FEATURE_SOC_USB_COUNT (1) /* @brief USBDCD availability on the SoC. */ #define FSL_FEATURE_SOC_USBDCD_COUNT (1) +/* @brief USBHS availability on the SoC. */ +#define FSL_FEATURE_SOC_USBHS_COUNT (1) /* @brief USBHSDCD availability on the SoC. */ #define FSL_FEATURE_SOC_USBHSDCD_COUNT (1) /* @brief USBPHY availability on the SoC. */ @@ -376,6 +377,8 @@ #define FSL_FEATURE_FLEXCAN_HAS_BUF31TO0M (0) /* @brief Number of interrupt vectors. */ #define FSL_FEATURE_FLEXCAN_INTERRUPT_COUNT (6) +/* @brief Is affected by errata with ID 5641 (Module does not transmit a message that is enabled to be transmitted at a specific moment during the arbitration process). */ +#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641 (0) /* CMP module features */ @@ -437,7 +440,7 @@ #define FSL_FEATURE_DMAMUX_MODULE_CHANNEL (32) /* @brief Total number of DMA channels on all modules. */ #define FSL_FEATURE_DMAMUX_DMAMUX_CHANNELS (FSL_FEATURE_SOC_DMAMUX_COUNT * 32) -/* @brief Has the periodic trigger capability for the triggered DMA channel 0 (register bit CHCFG0[TRIG]). */ +/* @brief Has the periodic trigger capability for the triggered DMA channel (register bit CHCFG0[TRIG]). */ #define FSL_FEATURE_DMAMUX_HAS_TRIG (1) /* ENET module features */ @@ -485,6 +488,10 @@ #define FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS (1) /* @brief Has flash cache control in MCM module. */ #define FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has flash cache control in MSCM module. */ + #define FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has prefetch speculation control in flash, such as kv5x. */ + #define FSL_FEATURE_FLASH_PREFETCH_SPECULATION_CONTROL_IN_FLASH (0) /* @brief P-Flash start address. */ #define FSL_FEATURE_FLASH_PFLASH_START_ADDRESS (0x00000000) /* @brief P-Flash block count. */ @@ -499,6 +506,8 @@ #define FSL_FEATURE_FLASH_PFLASH_BLOCK_DATA_PATH_WIDTH (16) /* @brief P-Flash block swap feature. */ #define FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP (1) + /* @brief P-Flash protection region count. */ + #define FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT (32) /* @brief Has FlexNVM memory. */ #define FSL_FEATURE_FLASH_HAS_FLEX_NVM (0) /* @brief FlexNVM start address. (Valid only if FlexNVM is available.) */ @@ -551,6 +560,10 @@ #define FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD (1) /* @brief Has 0x49 Erase All Blocks Unsecure command. */ #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD (0) + /* @brief Has 0x4A Read 1s All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_READ_1S_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) + /* @brief Has 0x4B Erase All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) /* @brief Has 0x80 Program Partition command. */ #define FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD (0) /* @brief Has 0x81 Set FlexRAM Function command. */ @@ -662,6 +675,10 @@ #define FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS (1) /* @brief Has flash cache control in MCM module. */ #define FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has flash cache control in MSCM module. */ + #define FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has prefetch speculation control in flash, such as kv5x. */ + #define FSL_FEATURE_FLASH_PREFETCH_SPECULATION_CONTROL_IN_FLASH (0) /* @brief P-Flash start address. */ #define FSL_FEATURE_FLASH_PFLASH_START_ADDRESS (0x00000000) /* @brief P-Flash block count. */ @@ -676,6 +693,8 @@ #define FSL_FEATURE_FLASH_PFLASH_BLOCK_DATA_PATH_WIDTH (16) /* @brief P-Flash block swap feature. */ #define FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP (1) + /* @brief P-Flash protection region count. */ + #define FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT (16) /* @brief Has FlexNVM memory. */ #define FSL_FEATURE_FLASH_HAS_FLEX_NVM (1) /* @brief FlexNVM start address. (Valid only if FlexNVM is available.) */ @@ -728,6 +747,10 @@ #define FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD (1) /* @brief Has 0x49 Erase All Blocks Unsecure command. */ #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD (0) + /* @brief Has 0x4A Read 1s All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_READ_1S_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) + /* @brief Has 0x4B Erase All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) /* @brief Has 0x80 Program Partition command. */ #define FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD (1) /* @brief Has 0x81 Set FlexRAM Function command. */ @@ -830,6 +853,8 @@ ((x) == FTM3 ? (8) : (-1))))) /* @brief Has counter reset by the selected input capture event (register bits C0SC[ICRST], C1SC[ICRST], ...). */ #define FSL_FEATURE_FTM_HAS_COUNTER_RESET_BY_CAPTURE_EVENT (0) +/* @brief Has extended deadtime value. */ +#define FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE (0) /* @brief Enable pwm output for the module. */ #define FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT (0) /* @brief Has half-cycle reload for the module. */ @@ -839,6 +864,15 @@ /* @brief Has reload initialization trigger. */ #define FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER (0) +/* GPIO module features */ + +/* @brief Has fast (single cycle) access capability via a dedicated memory region. */ +#define FSL_FEATURE_GPIO_HAS_FAST_GPIO (0) +/* @brief Has port input disable register (PIDR). */ +#define FSL_FEATURE_GPIO_HAS_INPUT_DISABLE (0) +/* @brief Has dedicated interrupt vector. */ +#define FSL_FEATURE_GPIO_HAS_PORT_INTERRUPT_VECTOR (1) + /* I2C module features */ /* @brief Has System Management Bus support (registers SMB, A2, SLTL and SLTH). */ @@ -861,6 +895,8 @@ #define FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION (1) /* @brief Has double buffering support (register S2). */ #define FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING (0) +/* @brief Has double buffer enable. */ +#define FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE (0) /* SAI module features */ @@ -899,12 +935,14 @@ #define FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE (8) /* @brief Number of digital filters. */ #define FSL_FEATURE_LLWU_HAS_PIN_FILTER (4) -/* @brief Has MF5 register. */ +/* @brief Has MF register. */ #define FSL_FEATURE_LLWU_HAS_MF (1) /* @brief Has PF register. */ #define FSL_FEATURE_LLWU_HAS_PF (1) /* @brief Has possibility to enable reset in low leakage power mode and enable digital filter for RESET pin (register LLWU_RST). */ #define FSL_FEATURE_LLWU_HAS_RESET_ENABLE (0) +/* @brief Has no internal module wakeup flag register. */ +#define FSL_FEATURE_LLWU_HAS_NO_INTERNAL_MODULE_WAKEUP_FLAG_REG (0) /* @brief Has external pin 0 connected to LLWU device. */ #define FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN0 (1) /* @brief Index of port of external pin. */ @@ -1126,14 +1164,24 @@ /* @brief Has process identifier support. */ #define FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE (0) +/* @brief L1 ICACHE line size in byte. */ +#define FSL_FEATURE_L1ICACHE_LINESIZE_BYTE (16) +/* @brief L1 DCACHE line size in byte. */ +#define FSL_FEATURE_L1DCACHE_LINESIZE_BYTE (16) /* LPTMR module features */ /* @brief Has shared interrupt handler with another LPTMR module. */ #define FSL_FEATURE_LPTMR_HAS_SHARED_IRQ_HANDLER (0) +/* @brief Whether LPTMR counter is 32 bits width. */ +#define FSL_FEATURE_LPTMR_CNR_WIDTH_IS_32B (0) +/* @brief Has timer DMA request enable (register bit CSR[TDRE]). */ +#define FSL_FEATURE_LPTMR_HAS_CSR_TDRE (0) /* LPUART module features */ +/* @brief LPUART0 and LPUART1 has shared interrupt vector. */ +#define FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1 (0) /* @brief Has receive FIFO overflow detection (bit field CFIFO[RXOFE]). */ #define FSL_FEATURE_LPUART_HAS_IRQ_EXTENDED_FUNCTIONS (0) /* @brief Has low power features (can be enabled in wait mode via register bit C1[DOZEEN] or CTRL[DOZEEN] if the registers are 32-bit wide). */ @@ -1150,8 +1198,10 @@ #define FSL_FEATURE_LPUART_HAS_IR_SUPPORT (1) /* @brief 2 bits long stop bit is available. */ #define FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT (1) -/* @brief Maximal data width without parity bit. */ +/* @brief If 10-bit mode is supported. */ #define FSL_FEATURE_LPUART_HAS_10BIT_DATA_SUPPORT (1) +/* @brief If 7-bit mode is supported. */ +#define FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT (0) /* @brief Baud rate fine adjustment is available. */ #define FSL_FEATURE_LPUART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT (0) /* @brief Baud rate oversampling is available (has bit fields C4[OSR], C5[BOTHEDGE], C5[RESYNCDIS] or BAUD[OSR], BAUD[BOTHEDGE], BAUD[RESYNCDIS] if the registers are 32-bit wide). */ @@ -1184,12 +1234,14 @@ #define FSL_FEATURE_LPUART_HAS_LOCAL_OPERATION_NETWORK_SUPPORT (0) /* @brief Has 32-bit registers (BAUD, STAT, CTRL, DATA, MATCH, MODIR) instead of 8-bit (BDH, BDL, C1, S1, D, etc.). */ #define FSL_FEATURE_LPUART_HAS_32BIT_REGISTERS (1) -/* @brief Lin break detect available (has bit BDH[LBKDIE]). */ -#define FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT (0) +/* @brief Lin break detect available (has bit BAUD[LBKDIE]). */ +#define FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT (1) /* @brief UART stops in Wait mode available (has bit C1[UARTSWAI]). */ #define FSL_FEATURE_LPUART_HAS_WAIT_MODE_OPERATION (0) /* @brief Has separate DMA RX and TX requests. */ #define FSL_FEATURE_LPUART_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1) +/* @brief Has separate RX and TX interrupts. */ +#define FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ (0) /* @brief Has LPAURT_PARAM. */ #define FSL_FEATURE_LPUART_HAS_PARAM (0) /* @brief Has LPUART_VERID. */ @@ -1239,7 +1291,7 @@ #define FSL_FEATURE_MCG_USE_PLLREFSEL (0) /* @brief TBD */ #define FSL_FEATURE_MCG_USE_SYSTEM_CLOCK (0) -/* @brief Has phase-locked loop (PLL) (register C5 and bits C6[VDIV], C6[PLLS], C6[LOLIE0], S[PLLST], S[LOCK0], S[LOLS]). */ +/* @brief Has phase-locked loop (PLL) (register C5 and bits C6[VDIV], C6[PLLS], C6[LOLIE0], S[PLLST], S[LOCK0], S[LOLS0]). */ #define FSL_FEATURE_MCG_HAS_PLL (1) /* @brief Has phase-locked loop (PLL) PRDIV (register C5[PRDIV]. */ #define FSL_FEATURE_MCG_HAS_PLL_PRDIV (1) @@ -1270,29 +1322,6 @@ /* @brief Reset clock mode is BLPI. */ #define FSL_FEATURE_MCG_RESET_IS_BLPI (0) -/* MPU module features */ - -/* @brief Specifies number of descriptors available. */ -#define FSL_FEATURE_MPU_DESCRIPTOR_COUNT (12) -/* @brief Has process identifier support. */ -#define FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER (1) -/* @brief Has master 0. */ -#define FSL_FEATURE_MPU_HAS_MASTER0 (1) -/* @brief Has master 1. */ -#define FSL_FEATURE_MPU_HAS_MASTER1 (1) -/* @brief Has master 2. */ -#define FSL_FEATURE_MPU_HAS_MASTER2 (1) -/* @brief Has master 3. */ -#define FSL_FEATURE_MPU_HAS_MASTER3 (1) -/* @brief Has master 4. */ -#define FSL_FEATURE_MPU_HAS_MASTER4 (1) -/* @brief Has master 5. */ -#define FSL_FEATURE_MPU_HAS_MASTER5 (1) -/* @brief Has master 6. */ -#define FSL_FEATURE_MPU_HAS_MASTER6 (1) -/* @brief Has master 7. */ -#define FSL_FEATURE_MPU_HAS_MASTER7 (0) - /* interrupt module features */ /* @brief Lowest interrupt request number. */ @@ -1390,20 +1419,13 @@ #define FSL_FEATURE_PORT_PCR_MUX_WIDTH (3) /* @brief Has dedicated interrupt vector. */ #define FSL_FEATURE_PORT_HAS_INTERRUPT_VECTOR (1) +/* @brief Has multiple pin IRQ configuration (register GICLR and GICHR). */ +#define FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG (0) /* @brief Defines whether PCR[IRQC] bit-field has flag states. */ #define FSL_FEATURE_PORT_HAS_IRQC_FLAG (0) /* @brief Defines whether PCR[IRQC] bit-field has trigger states. */ #define FSL_FEATURE_PORT_HAS_IRQC_TRIGGER (0) -/* GPIO module features */ - -/* @brief Has fast (single cycle) access capability via a dedicated memory region. */ -#define FSL_FEATURE_GPIO_HAS_FAST_GPIO (0) -/* @brief Has port input disable register (PIDR). */ -#define FSL_FEATURE_GPIO_HAS_INPUT_DISABLE (0) -/* @brief Has dedicated interrupt vector. */ -#define FSL_FEATURE_GPIO_HAS_PORT_INTERRUPT_VECTOR (1) - /* RCM module features */ /* @brief Has Loss-of-Lock Reset support. */ @@ -1746,6 +1768,12 @@ #define FSL_FEATURE_SMC_HAS_PARAM (0) /* @brief Has SMC_VERID. */ #define FSL_FEATURE_SMC_HAS_VERID (0) +/* @brief Has stop abort flag (register bit PMCTRL[STOPA]). */ +#define FSL_FEATURE_SMC_HAS_PMCTRL_STOPA (1) +/* @brief Has tamper reset (register bit SRS[TAMPER]). */ +#define FSL_FEATURE_SMC_HAS_SRS_TAMPER (0) +/* @brief Has security violation reset (register bit SRS[SECVIO]). */ +#define FSL_FEATURE_SMC_HAS_SRS_SECVIO (0) /* DSPI module features */ @@ -1769,6 +1797,17 @@ /* @brief Has separate DMA RX and TX requests. */ #define FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1) +/* SYSMPU module features */ + +/* @brief Specifies number of descriptors available. */ +#define FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT (12) +/* @brief Has process identifier support. */ +#define FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER (1) +/* @brief Total number of MPU slave. */ +#define FSL_FEATURE_SYSMPU_SLAVE_COUNT (5) +/* @brief Total number of MPU master. */ +#define FSL_FEATURE_SYSMPU_MASTER_COUNT (7) + /* SysTick module features */ /* @brief Systick has external reference clock. */ @@ -1796,12 +1835,20 @@ #define FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER (1) /* @brief Has external trigger selection. */ #define FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION (1) -/* @brief Has TPM_COMBINE. */ +/* @brief Has TPM_COMBINE register. */ #define FSL_FEATURE_TPM_HAS_COMBINE (1) -/* @brief Has TPM_FILTER. */ +/* @brief Whether COMBINE register has effect. */ +#define FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(x) (1) +/* @brief Has TPM_POL. */ +#define FSL_FEATURE_TPM_HAS_POL (1) +/* @brief Has TPM_FILTER register. */ #define FSL_FEATURE_TPM_HAS_FILTER (1) -/* @brief Has TPM_QDCTRL. */ +/* @brief Whether FILTER register has effect. */ +#define FSL_FEATURE_TPM_FILTER_HAS_EFFECTn(x) (1) +/* @brief Has TPM_QDCTRL register. */ #define FSL_FEATURE_TPM_HAS_QDCTRL (1) +/* @brief Whether QDCTRL register has effect. */ +#define FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(x) (1) /* TSI module features */ @@ -1828,8 +1875,8 @@ #define FSL_FEATURE_UART_HAS_IR_SUPPORT (1) /* @brief 2 bits long stop bit is available. */ #define FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT (1) -/* @brief Maximal data width without parity bit. */ -#define FSL_FEATURE_UART_HAS_10BIT_DATA_SUPPORT (0) +/* @brief If 10-bit mode is supported. */ +#define FSL_FEATURE_UART_HAS_10BIT_DATA_SUPPORT (1) /* @brief Baud rate fine adjustment is available. */ #define FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT (1) /* @brief Baud rate oversampling is available (has bit fields C4[OSR], C5[BOTHEDGE], C5[RESYNCDIS] or BAUD[OSR], BAUD[BOTHEDGE], BAUD[RESYNCDIS] if the registers are 32-bit wide). */ @@ -1881,6 +1928,8 @@ /* USB module features */ +/* @brief KHCI module instance count */ +#define FSL_FEATURE_USB_KHCI_COUNT (1) /* @brief HOST mode enabled */ #define FSL_FEATURE_USB_KHCI_HOST_ENABLED (1) /* @brief OTG mode enabled */ @@ -1900,6 +1949,8 @@ /* USBHS module features */ +/* @brief EHCI module instance count */ +#define FSL_FEATURE_USBHS_EHCI_COUNT (1) /* @brief Number of endpoints supported */ #define FSL_FEATURE_USBHS_ENDPT_COUNT (8) @@ -1909,7 +1960,7 @@ #define FSL_FEATURE_VREF_HAS_CHOP_OSC (1) /* @brief Has second order curvature compensation (bit SC[ICOMPEN]) */ #define FSL_FEATURE_VREF_HAS_COMPENSATION (1) -/* @brief Describes the set of SC[MODE_LV] bitfield values */ +/* @brief If high/low buffer mode supported */ #define FSL_FEATURE_VREF_MODE_LV_TYPE (1) /* @brief Module has also low reference (registers VREFL/VREFH) */ #define FSL_FEATURE_VREF_HAS_LOW_REFERENCE (0) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct index c19ce975ff1..49d7a9ae4ac 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct @@ -7,14 +7,13 @@ ** Compiler: Keil ARM C/C++ Compiler ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b160406 +** Build: b170214 ** ** Abstract: ** Linker file for the Keil ARM C/C++ Compiler ** -** Copyright (c) 2016 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -25,7 +24,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -40,8 +39,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** ################################################################### */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S index c7b44f7b247..3782b2f0a71 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S @@ -4,12 +4,11 @@ ; * MK66F18 ; * @version: 3.0 ; * @date: 2015-3-25 -; * @build: b151210 +; * @build: b170112 ; * --------------------------------------------------------------------------------------- ; * -; * Copyright (c) 1997 - 2015 , Freescale Semiconductor, Inc. -; * All rights reserved. -; * +; * Copyright (c) 1997 - 2016, Freescale Semiconductor, Inc. +; * Copyright 2016 - 2017 NXP ; * Redistribution and use in source and binary forms, with or without modification, ; * are permitted provided that the following conditions are met: ; * @@ -20,7 +19,7 @@ ; * list of conditions and the following disclaimer in the documentation and/or ; * other materials provided with the distribution. ; * -; * o Neither the name of Freescale Semiconductor, Inc. nor the names of its +; * o Neither the name of the copyright holder nor the names of its ; * contributors may be used to endorse or promote products derived from this ; * software without specific prior written permission. ; * @@ -483,6 +482,8 @@ Reset_Handler PROC LDR R0, =0xE000ED08 LDR R1, =__Vectors STR R1, [R0] + LDR R2, [R1] + MSR MSP, R2 LDR R0, =SystemInit BLX R0 CPSIE i ; Unmask interrupts diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld index 4145ee2c690..0287cf769d4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld @@ -6,14 +6,13 @@ ** Compiler: GNU C Compiler ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151217 +** Build: b170214 ** ** Abstract: ** Linker file for the GNU C Compiler ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -24,7 +23,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -39,8 +38,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** ################################################################### */ @@ -212,7 +211,6 @@ SECTIONS text_end = ORIGIN(m_text) + LENGTH(m_text); ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") - USB_RAM_GAP = DEFINED(__usb_ram_size__) ? __usb_ram_size__ : 0x800; /* Uninitialized data section */ .bss : { @@ -222,9 +220,6 @@ SECTIONS __bss_start__ = .; *(.bss) *(.bss*) - . = ALIGN(512); - USB_RAM_START = .; - . += USB_RAM_GAP; *(COMMON) . = ALIGN(4); __bss_end__ = .; @@ -248,17 +243,6 @@ SECTIONS . += STACK_SIZE; } > m_data_2 - m_usb_bdt USB_RAM_START (NOLOAD) : - { - *(m_usb_bdt) - USB_RAM_BDT_END = .; - } - - m_usb_global USB_RAM_BDT_END (NOLOAD) : - { - *(m_usb_global) - } - /* Initializes stack on the end of block */ __StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2); __StackLimit = __StackTop - STACK_SIZE; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S index 5a03e0326d8..ceb9bbf6c30 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S @@ -4,12 +4,11 @@ /* MK66F18 */ /* @version: 3.0 */ /* @date: 2015-3-25 */ -/* @build: b151210 */ +/* @build: b170112 */ /* ---------------------------------------------------------------------------------------*/ /* */ -/* Copyright (c) 1997 - 2015 , Freescale Semiconductor, Inc. */ -/* All rights reserved. */ -/* */ +/* Copyright (c) 1997 - 2016, Freescale Semiconductor, Inc. */ +/* Copyright 2016 - 2017 NXP */ /* Redistribution and use in source and binary forms, with or without modification, */ /* are permitted provided that the following conditions are met: */ /* */ @@ -20,7 +19,7 @@ /* list of conditions and the following disclaimer in the documentation and/or */ /* other materials provided with the distribution. */ /* */ -/* o Neither the name of Freescale Semiconductor, Inc. nor the names of its */ +/* o Neither the name of the copyright holder nor the names of its */ /* contributors may be used to endorse or promote products derived from this */ /* software without specific prior written permission. */ /* */ @@ -328,6 +327,8 @@ Reset_Handler: ldr r0, =VTOR ldr r1, =__isr_vector str r1, [r0] + ldr r2, [r1] + msr msp, r2 #ifndef __NO_SYSTEM_INIT ldr r0,=SystemInit blx r0 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf index fe0daadc6ae..6d7fb6135ea 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf @@ -6,14 +6,13 @@ ** Compiler: IAR ANSI C/C++ Compiler for ARM ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151009 +** Build: b170214 ** ** Abstract: ** Linker file for the IAR ANSI C/C++ Compiler for ARM ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -24,7 +23,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -39,8 +38,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** ################################################################### */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S index 4a5928de9f2..47036fbd89f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S @@ -4,12 +4,11 @@ ; MK66F18 ; @version: 3.0 ; @date: 2015-3-25 -; @build: b151210 +; @build: b170112 ; --------------------------------------------------------------------------------------- ; -; Copyright (c) 1997 - 2015 , Freescale Semiconductor, Inc. -; All rights reserved. -; +; Copyright (c) 1997 - 2016, Freescale Semiconductor, Inc. +; Copyright 2016 - 2017 NXP ; Redistribution and use in source and binary forms, with or without modification, ; are permitted provided that the following conditions are met: ; @@ -20,7 +19,7 @@ ; list of conditions and the following disclaimer in the documentation and/or ; other materials provided with the distribution. ; -; o Neither the name of Freescale Semiconductor, Inc. nor the names of its +; o Neither the name of the copyright holder nor the names of its ; contributors may be used to endorse or promote products derived from this ; software without specific prior written permission. ; @@ -355,6 +354,8 @@ Reset_Handler LDR R0, =0xE000ED08 LDR R1, =__vector_table STR R1, [R0] + LDR R2, [R1] + MSR MSP, R2 LDR R0, =SystemInit BLX R0 CPSIE I ; Unmask interrupts diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h index f7a122fcdb6..9438c67fa13 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h @@ -1,7 +1,6 @@ /* - * Copyright (c) 2014 - 2015, Freescale Semiconductor, Inc. - * All rights reserved. - * + * Copyright (c) 2014 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 - 2017 NXP * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * @@ -12,7 +11,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -26,6 +25,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * */ #ifndef __FSL_DEVICE_REGISTERS_H__ @@ -36,7 +36,7 @@ * * The CPU macro should be declared in the project or makefile. */ -#if (defined(CPU_MK66FN2M0VLQ18) || defined(CPU_MK66FX1M0VLQ18) || defined(CPU_MK66FN2M0VMD18) || \ +#if (defined(CPU_MK66FN2M0VLQ18) || defined(CPU_MK66FN2M0VMD18) || defined(CPU_MK66FX1M0VLQ18) || \ defined(CPU_MK66FX1M0VMD18)) #define K66F18_SERIES diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c index 04996c713f3..a0a09bbc4d4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c @@ -9,19 +9,19 @@ ** Freescale C/C++ for Embedded ARM ** GNU C Compiler ** IAR ANSI C/C++ Compiler for ARM +** MCUXpresso Compiler ** ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151216 +** Build: b170112 ** ** Abstract: ** Provides a system configuration function and a global variable that ** contains the system frequency. It configures the device and initializes ** the oscillator (PLL) that is part of the microcontroller device. ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright (c) 2016 Freescale Semiconductor, Inc. +** Copyright 2016 - 2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -32,7 +32,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -47,8 +47,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) @@ -213,7 +213,6 @@ void SystemCoreClockUpdate (void) { Divider *= 0x04U; } else if ((USBPHY->ANACTRL & USBPHY_ANACTRL_PFD_CLK_SEL_MASK) == USBPHY_ANACTRL_PFD_CLK_SEL(2)) { Divider *= 0x02U; - } else { } MCGOUTClock = (uint32_t)(480000000 / Divider); MCGOUTClock *= 18; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h index 3e8652e09a7..3bbd4bf70d6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h @@ -9,19 +9,19 @@ ** Freescale C/C++ for Embedded ARM ** GNU C Compiler ** IAR ANSI C/C++ Compiler for ARM +** MCUXpresso Compiler ** ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151216 +** Build: b170112 ** ** Abstract: ** Provides a system configuration function and a global variable that ** contains the system frequency. It configures the device and initializes ** the oscillator (PLL) that is part of the microcontroller device. ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright (c) 2016 Freescale Semiconductor, Inc. +** Copyright 2016 - 2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -32,7 +32,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -47,8 +47,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c index 8f1aa77b2ea..0af6a4443e9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -46,8 +46,10 @@ static uint32_t ADC16_GetInstance(ADC_Type *base); /*! @brief Pointers to ADC16 bases for each instance. */ static ADC_Type *const s_adc16Bases[] = ADC_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to ADC16 clocks for each instance. */ -const clock_ip_name_t s_adc16Clocks[] = ADC16_CLOCKS; +static const clock_ip_name_t s_adc16Clocks[] = ADC16_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -57,7 +59,7 @@ static uint32_t ADC16_GetInstance(ADC_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_ADC16_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_adc16Bases); instance++) { if (s_adc16Bases[instance] == base) { @@ -65,7 +67,7 @@ static uint32_t ADC16_GetInstance(ADC_Type *base) } } - assert(instance < FSL_FEATURE_SOC_ADC16_COUNT); + assert(instance < ARRAY_SIZE(s_adc16Bases)); return instance; } @@ -76,8 +78,10 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config) uint32_t tmp32; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_adc16Clocks[ADC16_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* ADCx_CFG1. */ tmp32 = ADC_CFG1_ADICLK(config->clockSource) | ADC_CFG1_MODE(config->resolution); @@ -126,8 +130,10 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config) void ADC16_Deinit(ADC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_adc16Clocks[ADC16_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void ADC16_GetDefaultConfig(adc16_config_t *config) @@ -149,7 +155,7 @@ void ADC16_GetDefaultConfig(adc16_config_t *config) status_t ADC16_DoAutoCalibration(ADC_Type *base) { bool bHWTrigger = false; - uint32_t tmp32; + volatile uint32_t tmp32; /* 'volatile' here is for the dummy read of ADCx_R[0] register. */ status_t status = kStatus_Success; /* The calibration would be failed when in hardwar mode. @@ -171,6 +177,7 @@ status_t ADC16_DoAutoCalibration(ADC_Type *base) break; } } + tmp32 = base->R[0]; /* Dummy read to clear COCO caused by calibration. */ /* Restore the hardware trigger setting if it was enabled before. */ if (bHWTrigger) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h index c6b5bc0d1ae..ea62c55fee6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -74,7 +73,7 @@ enum _adc16_status_flags * @brief Channel multiplexer mode for each channel. * * For some ADC16 channels, there are two pin selections in channel multiplexer. For example, ADC0_SE4a and ADC0_SE4b - * are the different channels but share the same channel number. + * are the different channels that share the same channel number. */ typedef enum _adc_channel_mux_mode { @@ -104,7 +103,7 @@ typedef enum _adc16_resolution kADC16_Resolution12or13Bit = 1U, /*!< Single End 12-bit or Differential Sample 13-bit. */ kADC16_Resolution10or11Bit = 2U, /*!< Single End 10-bit or Differential Sample 11-bit. */ - /* This group of enumeration is for public user. */ + /* This group of enumeration is for a public user. */ kADC16_ResolutionSE8Bit = kADC16_Resolution8or9Bit, /*!< Single End 8-bit. */ kADC16_ResolutionSE12Bit = kADC16_Resolution12or13Bit, /*!< Single End 12-bit. */ kADC16_ResolutionSE10Bit = kADC16_Resolution10or11Bit, /*!< Single End 10-bit. */ @@ -203,7 +202,7 @@ typedef enum _adc16_pga_gain #endif /* FSL_FEATURE_ADC16_HAS_PGA */ /*! - * @brief ADC16 converter configuration . + * @brief ADC16 converter configuration. */ typedef struct _adc16_config { @@ -219,7 +218,7 @@ typedef struct _adc16_config } adc16_config_t; /*! - * @brief ADC16 Hardware compare configuration. + * @brief ADC16 Hardware comparison configuration. */ typedef struct _adc16_hardware_compare_config { @@ -237,7 +236,7 @@ typedef struct _adc16_channel_config uint32_t channelNumber; /*!< Setting the conversion channel number. The available range is 0-31. See channel connection information for each chip in Reference Manual document. */ - bool enableInterruptOnConversionCompleted; /*!< Generate a interrupt request once the conversion is completed. */ + bool enableInterruptOnConversionCompleted; /*!< Generate an interrupt request once the conversion is completed. */ #if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE bool enableDifferentialConversion; /*!< Using Differential sample mode. */ #endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */ @@ -296,9 +295,9 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config); void ADC16_Deinit(ADC_Type *base); /*! - * @brief Gets an available pre-defined settings for converter's configuration. + * @brief Gets an available pre-defined settings for the converter's configuration. * - * This function initializes the converter configuration structure with an available settings. The default values are: + * This function initializes the converter configuration structure with available settings. The default values are as follows. * @code * config->referenceVoltageSource = kADC16_ReferenceVoltageSourceVref; * config->clockSource = kADC16_ClockSourceAsynchronousClock; @@ -310,7 +309,7 @@ void ADC16_Deinit(ADC_Type *base); * config->enableLowPower = false; * config->enableContinuousConversion = false; * @endcode - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void ADC16_GetDefaultConfig(adc16_config_t *config); @@ -318,15 +317,15 @@ void ADC16_GetDefaultConfig(adc16_config_t *config); /*! * @brief Automates the hardware calibration. * - * This auto calibration helps to adjust the plus/minus side gain automatically on the converter's working situation. + * This auto calibration helps to adjust the plus/minus side gain automatically. * Execute the calibration before using the converter. Note that the hardware trigger should be used - * during calibration. + * during the calibration. * * @param base ADC16 peripheral base address. * * @return Execution status. * @retval kStatus_Success Calibration is done successfully. - * @retval kStatus_Fail Calibration is failed. + * @retval kStatus_Fail Calibration has failed. */ status_t ADC16_DoAutoCalibration(ADC_Type *base); #endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */ @@ -350,16 +349,16 @@ static inline void ADC16_SetOffsetValue(ADC_Type *base, int16_t value) /* @} */ /*! - * @name Advanced Feature + * @name Advanced Features * @{ */ #if defined(FSL_FEATURE_ADC16_HAS_DMA) && FSL_FEATURE_ADC16_HAS_DMA /*! - * @brief Enables generating the DMA trigger when conversion is completed. + * @brief Enables generating the DMA trigger when the conversion is complete. * * @param base ADC16 peripheral base address. - * @param enable Switcher of DMA feature. "true" means to enable, "false" means not. + * @param enable Switcher of the DMA feature. "true" means enabled, "false" means not enabled. */ static inline void ADC16_EnableDMA(ADC_Type *base, bool enable) { @@ -378,7 +377,7 @@ static inline void ADC16_EnableDMA(ADC_Type *base, bool enable) * @brief Enables the hardware trigger mode. * * @param base ADC16 peripheral base address. - * @param enable Switcher of hardware trigger feature. "true" means to enable, "false" means not. + * @param enable Switcher of the hardware trigger feature. "true" means enabled, "false" means not enabled. */ static inline void ADC16_EnableHardwareTrigger(ADC_Type *base, bool enable) { @@ -408,13 +407,12 @@ void ADC16_SetChannelMuxMode(ADC_Type *base, adc16_channel_mux_mode_t mode); /*! * @brief Configures the hardware compare mode. * - * The hardware compare mode provides a way to process the conversion result automatically by hardware. Only the result - * in - * compare range is available. To compare the range, see "adc16_hardware_compare_mode_t", or the reference - * manual document for more detailed information. + * The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the result + * in the compare range is available. To compare the range, see "adc16_hardware_compare_mode_t" or the appopriate reference + * manual for more information. * * @param base ADC16 peripheral base address. - * @param config Pointer to "adc16_hardware_compare_config_t" structure. Passing "NULL" is to disable the feature. + * @param config Pointer to the "adc16_hardware_compare_config_t" structure. Passing "NULL" disables the feature. */ void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare_config_t *config); @@ -422,21 +420,21 @@ void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare /*! * @brief Sets the hardware average mode. * - * Hardware average mode provides a way to process the conversion result automatically by hardware. The multiple - * conversion results are accumulated and averaged internally. This aids reading results. + * The hardware average mode provides a way to process the conversion result automatically by using hardware. The multiple + * conversion results are accumulated and averaged internally making them easier to read. * * @param base ADC16 peripheral base address. - * @param mode Setting hardware average mode. See "adc16_hardware_average_mode_t". + * @param mode Setting the hardware average mode. See "adc16_hardware_average_mode_t". */ void ADC16_SetHardwareAverage(ADC_Type *base, adc16_hardware_average_mode_t mode); #endif /* FSL_FEATURE_ADC16_HAS_HW_AVERAGE */ #if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA /*! - * @brief Configures the PGA for converter's front end. + * @brief Configures the PGA for the converter's front end. * * @param base ADC16 peripheral base address. - * @param config Pointer to "adc16_pga_config_t" structure. Passing "NULL" is to disable the feature. + * @param config Pointer to the "adc16_pga_config_t" structure. Passing "NULL" disables the feature. */ void ADC16_SetPGAConfig(ADC_Type *base, const adc16_pga_config_t *config); #endif /* FSL_FEATURE_ADC16_HAS_PGA */ @@ -468,26 +466,26 @@ void ADC16_ClearStatusFlags(ADC_Type *base, uint32_t mask); /*! * @brief Configures the conversion channel. * - * This operation triggers the conversion if in software trigger mode. When in hardware trigger mode, this API + * This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API * configures the channel while the external trigger source helps to trigger the conversion. * * Note that the "Channel Group" has a detailed description. - * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC can have more than one - * group of status and control register, one for each conversion. The channel group parameter indicates which group of - * registers are used channel group 0 is for Group A registers and channel group 1 is for Group B registers. The + * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one + * group of status and control registers, one for each conversion. The channel group parameter indicates which group of + * registers are used, for example, channel group 0 is for Group A registers and channel group 1 is for Group B registers. The * channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of - * the channel groups is actively controlling ADC conversions. Channel group 0 is used for both software and hardware - * trigger modes of operation. Channel groups 1 and greater indicate potentially multiple channel group registers for - * use only in hardware trigger mode. See the chip configuration information in the MCU reference manual about the - * number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used - * for software trigger operation and therefore writes to these channel groups do not initiate a new conversion. - * Updating channel group 0 while a different channel group is actively controlling a conversion is allowed and + * the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and hardware + * trigger modes. Channel group 1 and greater indicates multiple channel group registers for + * use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual for the + * number of SC1n registers (channel groups) specific to this device. Channel group 1 or greater are not used + * for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion. + * Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and * vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a * conversion aborts the current conversion. * * @param base ADC16 peripheral base address. * @param channelGroup Channel group index. - * @param config Pointer to "adc16_channel_config_t" structure for conversion channel. + * @param config Pointer to the "adc16_channel_config_t" structure for the conversion channel. */ void ADC16_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc16_channel_config_t *config); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c index bffbb4a3125..d75d97ff4f1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +13,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -28,7 +29,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* @@ -124,7 +124,6 @@ static uint32_t s_extPllFreq = 0U; /* External XTAL0 (OSC0) clock frequency. */ uint32_t g_xtal0Freq; - /* External XTAL32K clock frequency. */ uint32_t g_xtal32Freq; @@ -195,17 +194,36 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +/******************************************************************************* + * Code + ******************************************************************************/ + +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ -static void CLOCK_FllStableDelay(void); - -/******************************************************************************* - * Code - ******************************************************************************/ +void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (i--) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardness how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ static uint32_t CLOCK_GetMcgExtClkFreq(void) { @@ -342,19 +360,6 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -419,6 +424,9 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) case 1U: /* PLL. */ freq = CLOCK_GetPll0Freq(); break; + case 2U: /* USB1 PFD */ + freq = CLOCK_GetExtPllFreq(); + break; case 3U: /* MCG IRC48M. */ freq = MCG_INTERNAL_IRC_48M; break; @@ -572,8 +580,31 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) } bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) +{ + /* Source and freq are not used for USB HS. */ + src = src; + freq = freq; + + SIM->SCGC3 |= SIM_SCGC3_USBHS_MASK; + + SIM->USBPHYCTL = ((SIM->USBPHYCTL & ~(SIM_USBPHYCTL_USB3VOUTTRG_MASK)) | SIM_USBPHYCTL_USB3VOUTTRG(6U) /* 3.310V */ + | SIM_USBPHYCTL_USBVREGSEL_MASK); /* VREG_IN1 */ + + USBPHY->PLL_SIC |= USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* Enable USB clock output from USB PHY PLL */ + + return true; +} + +void CLOCK_DisableUsbhs0Clock(void) +{ + USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* Disable USB clock output from USB PHY PLL */ + SIM->SCGC3 &= ~SIM_SCGC3_USBHS_MASK; +} + +bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq) { volatile uint32_t i; + uint32_t phyPllDiv = 0U; /* * In order to bring up the internal 480MHz USB PLL clock, should make sure: @@ -584,12 +615,28 @@ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) assert(!(MCG->C2 & MCG_C2_IRCS_MASK)); assert(OSC0->CR & OSC_CR_ERCLKEN_MASK); + if (24000000U == freq) + { + phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U); + } + else if (16000000U == freq) + { + phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U); + } + else if (12000000U == freq) + { + phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U); + } + else + { + return false; + } + /* Source and freq are not used for USB HS. */ src = src; - freq = freq; + SIM->SCGC3 |= SIM_SCGC3_USBHSPHY_MASK; SIM->SOPT2 |= SIM_SOPT2_USBREGEN_MASK; - SIM->SCGC3 |= (SIM_SCGC3_USBHS_MASK | SIM_SCGC3_USBHSPHY_MASK); i = 500000U; while (i--) @@ -597,12 +644,66 @@ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) __NOP(); } - SIM->USBPHYCTL = ((SIM->USBPHYCTL & ~(SIM_USBPHYCTL_USB3VOUTTRG_MASK)) | SIM_USBPHYCTL_USB3VOUTTRG(6U) /* 3.310V */ - | SIM_USBPHYCTL_USBVREGSEL_MASK); /* VREG_IN1 */ + USBPHY->TRIM_OVERRIDE_EN = 0x01U; /* Override the trim. */ + USBPHY->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */ + USBPHY->PLL_SIC |= USBPHY_PLL_SIC_PLL_POWER_MASK; /* power up PLL */ + USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~USBPHY_PLL_SIC_PLL_DIV_SEL_MASK) | phyPllDiv; + USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_BYPASS_MASK; /* Clear bypass bit */ + USBPHY->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK; /* Clear to 0U to run clocks */ + + /* Wait for lock. */ + while (!(USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK)) + { + } return true; } +void CLOCK_DisableUsbhs0PhyPllClock(void) +{ + USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */ + USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK; /* Power down PLL */ + SIM->SOPT2 &= ~SIM_SOPT2_USBREGEN_MASK; + SIM->SCGC3 &= ~SIM_SCGC3_USBHSPHY_MASK; +} + +void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src) +{ + assert((frac <= 35U) && (frac >= 18U)); + uint32_t fracFreq = (480000U * 18U / frac) * 1000U; + + USBPHY->ANACTRL = (USBPHY->ANACTRL & ~(USBPHY_ANACTRL_PFD_FRAC_MASK | USBPHY_ANACTRL_PFD_CLK_SEL_MASK)) | + (USBPHY_ANACTRL_PFD_FRAC(frac) | USBPHY_ANACTRL_PFD_CLK_SEL(src)); + + USBPHY->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK; + while (!(USBPHY->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK)) + { + } + + if (kCLOCK_UsbPfdSrcExt == src) + { + s_extPllFreq = g_xtal0Freq; + } + else if (kCLOCK_UsbPfdSrcFracDivBy4 == src) + { + s_extPllFreq = fracFreq / 4U; + } + else if (kCLOCK_UsbPfdSrcFracDivBy2 == src) + { + s_extPllFreq = fracFreq / 2U; + } + else + { + s_extPllFreq = fracFreq; + } +} + +void CLOCK_DisableUsbhs0PfdClock(void) +{ + USBPHY->ANACTRL |= USBPHY_ANACTRL_PFD_CLKGATE_MASK; + s_extPllFreq = 0U; +} + uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; @@ -705,6 +806,12 @@ uint32_t CLOCK_GetPll0Freq(void) mcgpll0clk = CLOCK_GetPll0RefFreq(); + /* + * Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. + * Please call CLOCK_SetXtal1Freq base on board setting before using OSC1 clock. + */ + assert(mcgpll0clk); + mcgpll0clk /= (FSL_FEATURE_MCG_PLL_PRDIV_BASE + MCG_C5_PRDIV0_VAL); mcgpll0clk *= (FSL_FEATURE_MCG_PLL_VDIV_BASE + MCG_C6_VDIV0_VAL); @@ -746,16 +853,6 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ @@ -936,6 +1033,14 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs) +{ + MCG->C11 = ((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs); + while (pllcs != MCG_S2_PLLCST_VAL) + { + } +} + void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ @@ -1279,7 +1384,7 @@ mcg_mode_t CLOCK_GetMode(void) return mode; } -status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; bool change_drs = false; @@ -1323,7 +1428,7 @@ status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DRST_DRS(drs)); + MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); /* Check MCG_S[CLKST] */ while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) @@ -1372,6 +1477,17 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait and check status. */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1406,7 +1522,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } -status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; bool change_drs = false; @@ -1459,7 +1575,7 @@ status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DRST_DRS(drs)); + MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); /* Wait for FLL stable time. */ if (fllStableDelay) @@ -1514,6 +1630,17 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for Reference clock Status bit to clear */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1574,6 +1701,12 @@ status_t CLOCK_SetBlpeMode(void) status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { + /* If external PLL is used, then the config could be NULL. */ + if (kMCG_PllClkSelExtPll != pllcs) + { + assert(config); + } + /* This function is designed to change MCG to PBE mode from PEE/BLPE/FBE, but with this workflow, the source mode could be all modes except PEI/PBI. @@ -1601,13 +1734,15 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co CLOCK_EnablePll0(config); } + /* Change to PLL mode. */ + MCG->C6 |= MCG_C6_PLLS_MASK; + MCG->C11 = ((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs); while (pllcs != MCG_S2_PLLCST_VAL) { } - /* Change to PLL mode. */ - MCG->C6 |= MCG_C6_PLLS_MASK; + /* Wait for PLL mode changed. */ while (!(MCG->S & MCG_S_PLLST_MASK)) { } @@ -1682,9 +1817,9 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) return kStatus_Success; } -status_t CLOCK_BootToFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - return CLOCK_SetFeiMode(drs, fllStableDelay); + return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } status_t CLOCK_BootToFeeMode( @@ -1721,6 +1856,17 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt))) @@ -1735,7 +1881,11 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { - assert(config); + /* If external PLL is used, then the config could be NULL. */ + if (kMCG_PllClkSelExtPll != pllcs) + { + assert(config); + } CLOCK_SetExternalRefClkConfig(oscsel); @@ -1793,7 +1943,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) if (!(MCG->S & MCG_S_IRCST_MASK)) { CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->drs, (void (*)(void))0); + CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); } CLOCK_SetExternalRefClkConfig(config->oscsel); @@ -1805,7 +1955,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->drs, CLOCK_FllStableDelay); + CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } @@ -1821,13 +1971,13 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) switch (next_mode) { case kMCG_ModeFEI: - status = CLOCK_SetFeiMode(config->drs, CLOCK_FllStableDelay); + status = CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFEE: status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); break; case kMCG_ModeFBE: status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h index d145692508d..3f343f5cc9f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +13,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -31,45 +32,83 @@ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ +/*! @file */ + +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could contol the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ -/*! @brief Clock driver version. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @name Driver version */ +/*@{*/ +/*! @brief CLOCK driver version 2.2.2. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ /*! @brief External XTAL0 (OSC0) clock frequency. * - * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal0Freq to set the value in to clock driver. For example, - * if XTAL0 is 8MHz, + * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, + * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Setup the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver. + * CLOCK_InitOsc0(...); // Set up the OSC0 + * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. * @endcode * - * This is important for the multicore platforms, only one core needs to setup - * OSC0 using CLOCK_InitOsc0, all other cores need to call CLOCK_SetXtal0Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up the + * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq + * to get a valid clock frequency. */ extern uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * - * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal32Freq to set the value in to clock driver. + * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal32Freq to set the value in the clock driver. * - * This is important for the multicore platforms, only one core needs to setup - * the clock, all other cores need to call CLOCK_SetXtal32Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up + * the clock. All other cores need to call the CLOCK_SetXtal32Freq + * to get a valid clock frequency. */ extern uint32_t g_xtal32Freq; @@ -194,16 +233,10 @@ extern uint32_t g_xtal32Freq; kCLOCK_Sdramc0 \ } -/*! @brief Clock ip name array for MMCAU. */ -#define MMCAU_CLOCKS \ - { \ - kCLOCK_Mmcau0 \ - } - /*! @brief Clock ip name array for MPU. */ -#define MPU_CLOCKS \ - { \ - kCLOCK_Mpu0 \ +#define SYSMPU_CLOCKS \ + { \ + kCLOCK_Sysmpu0 \ } /*! @brief Clock ip name array for VREF. */ @@ -242,12 +275,6 @@ extern uint32_t g_xtal32Freq; kCLOCK_Crc0 \ } -/*! @brief Clock ip name array for LMEM. */ -#define LMEM_CLOCKS \ - { \ - kCLOCK_Lmem0 \ - } - /*! @brief Clock ip name array for I2C. */ #define I2C_CLOCKS \ { \ @@ -267,9 +294,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for CMP. */ -#define CMP_CLOCKS \ - { \ - kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2 \ +#define CMP_CLOCKS \ + { \ + kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2, kCLOCK_Cmp3 \ } /*! @@ -334,9 +361,26 @@ typedef enum _clock_usb_src kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ kCLOCK_UsbSrcUsbPfd = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(2U), /*!< Use USBPFDCLK. */ kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U), /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcUnused = 0xFFFFFFFFU, /*!< Used when the function does not + care the clock source. */ } clock_usb_src_t; +/*! @brief Source of the USB HS PHY. */ +typedef enum _clock_usb_phy_src +{ + kCLOCK_UsbPhySrcExt = 0U, /*!< Use external crystal. */ +} clock_usb_phy_src_t; + +/*! @brief Source of the USB HS PFD clock (USB1PFDCLK) */ +typedef enum _clock_usb_pfd_src +{ + kCLOCK_UsbPfdSrcExt = 0U, /*!< Use external crystal. */ + kCLOCK_UsbPfdSrcFracDivBy4 = 1U, /*!< Use PFD_FRAC output divided by 4. */ + kCLOCK_UsbPfdSrcFracDivBy2 = 2U, /*!< Use PFD_FRAC output divided by 2. */ + kCLOCK_UsbPfdSrcFrac = 3U, /*!< Use PFD_FRAC output. */ +} clock_usb_pfd_src_t; + /*------------------------------------------------------------------------------ clock_gate_t definition: @@ -402,6 +446,7 @@ typedef enum _clock_ip_name kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp3 = CLK_GATE_DEFINE(0x1034U, 19U), kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), @@ -430,7 +475,7 @@ typedef enum _clock_ip_name kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U), kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), - kCLOCK_Mpu0 = CLK_GATE_DEFINE(0x1040U, 2U), + kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), kCLOCK_Sdramc0 = CLK_GATE_DEFINE(0x1040U, 3U), } clock_ip_name_t; @@ -447,7 +492,7 @@ typedef struct _sim_clock_config /*! @brief OSC work mode. */ typedef enum _osc_mode { - kOSC_ModeExt = 0U, /*!< Use external clock. */ + kOSC_ModeExt = 0U, /*!< Use an external clock. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) kOSC_ModeOscLowPower = MCG_C2_EREFS_MASK, /*!< Oscillator low power. */ #else @@ -498,8 +543,8 @@ typedef struct _oscer_config * @brief OSC Initialization Configuration Structure * * Defines the configuration data structure to initialize the OSC. - * When porting to a new board, please set the following members - * according to board setting: + * When porting to a new board, set the following members + * according to the board setting: * 1. freq: The external frequency. * 2. workMode: The OSC module mode. */ @@ -575,7 +620,7 @@ typedef enum _mcg_oscsel typedef enum _mcg_pll_clk_select { kMCG_PllClkSelPll0, /*!< PLL0 output clock is selected */ - kMCG_PllClkSelExtPll /* External PLL clock is selected */ + kMCG_PllClkSelExtPll /* The external PLL clock is selected */ } mcg_pll_clk_select_t; /*! @brief MCG clock monitor mode. */ @@ -596,8 +641,8 @@ enum _mcg_status kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Could not change clock source because - it is used currently. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + it is in use. */ }; /*! @brief MCG status flags. */ @@ -621,11 +666,11 @@ enum _mcg_irclk_enable_mode /*! @brief MCG PLL clock enable mode definition. */ enum _mcg_pll_enable_mode { - kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable indepencent of - MCG clock mode. Generally, PLL + kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable independent of the + MCG clock mode. Generally, the PLL is disabled in FLL modes - (FEI/FBI/FEE/FBE), set PLL clock - enable independent will enable + (FEI/FBI/FEE/FBE). Setting the PLL clock + enable independent, enables the PLL in the FLL modes. */ kMCG_PllEnableInStop = MCG_C5_PLLSTEN0_MASK /*!< MCGPLLCLK enable in STOP mode. */ }; @@ -652,16 +697,16 @@ typedef struct _mcg_pll_config uint8_t vdiv; /*!< VCO divider VDIV. */ } mcg_pll_config_t; -/*! @brief MCG configure structure for mode change. +/*! @brief MCG mode change configuration structure * - * When porting to a new board, please set the following members - * according to board setting: - * 1. frdiv: If FLL uses the external reference clock, please set this - * value to make sure external reference clock divided by frdiv is - * in the range 31.25kHz to 39.0625kHz. + * When porting to a new board, set the following members + * according to the board setting: + * 1. frdiv: If the FLL uses the external reference clock, set this + * value to ensure that the external reference clock divided by frdiv is + * in the 31.25 kHz to 39.0625 kHz range. * 2. The PLL reference clock divider PRDIV: PLL reference clock frequency after - * PRDIV should be in the range of FSL_FEATURE_MCG_PLL_REF_MIN to - * FSL_FEATURE_MCG_PLL_REF_MAX. + * PRDIV should be in the FSL_FEATURE_MCG_PLL_REF_MIN to + * FSL_FEATURE_MCG_PLL_REF_MAX range. */ typedef struct _mcg_config { @@ -693,26 +738,6 @@ typedef struct _mcg_config extern "C" { #endif /* __cplusplus */ -/*! - * @brief Set the XTAL0 frequency based on board setting. - * - * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal0Freq(uint32_t freq) -{ - g_xtal0Freq = freq; -} - -/*! - * @brief Set the XTAL32/RTC_CLKIN frequency based on board setting. - * - * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal32Freq(uint32_t freq) -{ - g_xtal32Freq = freq; -} - /*! * @brief Enable the clock for specific IP. * @@ -839,8 +864,12 @@ static inline void CLOCK_SetRtcClkOutClock(uint32_t src) /*! @brief Enable USB HS clock. * - * @param src USB HS clock source. - * @param freq The frequency specified by src. + * This function only enables the access to USB HS prepheral, upper layer + * should first call the @ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY + * clock to use USB HS. + * + * @param src USB HS does not care about the clock source, here must be @ref kCLOCK_UsbSrcUnused. + * @param freq USB HS does not care about the clock source, so this parameter is ignored. * @retval true The clock is set successfully. * @retval false The clock source is invalid to get proper USB HS clock. */ @@ -848,13 +877,49 @@ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq); /*! @brief Disable USB HS clock. * - * Disable USB HS clock. + * Disable USB HS clock, this function should not be called after + * @ref CLOCK_DisableUsbhs0PhyPllClock. */ -static inline void CLOCK_DisableUsbhs0Clock(void) -{ - SIM->SOPT2 &= ~SIM_SOPT2_USBREGEN_MASK; - SIM->SCGC3 &= ~(SIM_SCGC3_USBHS_MASK | SIM_SCGC3_USBHSPHY_MASK); -} +void CLOCK_DisableUsbhs0Clock(void); + +/*! @brief Enable USB HS PHY PLL clock. + * + * This function enables the internal 480MHz USB PHY PLL clock. + * + * @param src USB HS PHY PLL clock source. + * @param freq The frequency specified by src. + * @retval true The clock is set successfully. + * @retval false The clock source is invalid to get proper USB HS clock. + */ +bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq); + +/*! @brief Disable USB HS PHY PLL clock. + * + * This function disables USB HS PHY PLL clock. + */ +void CLOCK_DisableUsbhs0PhyPllClock(void); + +/*! @brief Enable USB HS PFD clock. + * + * This function enables USB HS PFD clock. It should be called after function + * @ref CLOCK_EnableUsbhs0PhyPllClock. + * The PFD output clock is selected by the parameter @p src. When the @p src is + * @ref kCLOCK_UsbPfdSrcExt, then the PFD outout is from external crystal + * directly, in this case, the @p frac is not used. In other cases, the PFD_FRAC + * output clock frequency is 480MHz*18/frac, the PFD output frequency is based + * on the PFD_FRAC output. + * + * @param frac The value set to PFD_FRAC, it must be in the range of 18 to 35. + * @param src Source of the USB HS PFD clock (USB1PFDCLK). + */ +void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src); + +/*! @brief Disable USB HS PFD clock. + * + * This function disables USB HS PFD clock. It should be called before function + * @ref CLOCK_DisableUsbhs0PhyPllClock. + */ +void CLOCK_DisableUsbhs0PfdClock(void); /*! @brief Enable USB FS clock. * @@ -997,9 +1062,9 @@ static inline void CLOCK_SetSimSafeDivs(void) /*@{*/ /*! - * @brief Get the MCG output clock(MCGOUTCLK) frequency. + * @brief Gets the MCG output clock (MCGOUTCLK) frequency. * - * This function gets the MCG output clock frequency (Hz) based on current MCG + * This function gets the MCG output clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGOUTCLK. @@ -1007,40 +1072,40 @@ static inline void CLOCK_SetSimSafeDivs(void) uint32_t CLOCK_GetOutClkFreq(void); /*! - * @brief Get the MCG FLL clock(MCGFLLCLK) frequency. + * @brief Gets the MCG FLL clock (MCGFLLCLK) frequency. * - * This function gets the MCG FLL clock frequency (Hz) based on current MCG - * register value. The FLL is only enabled in FEI/FBI/FEE/FBE mode, in other - * modes, FLL is disabled in low power state. + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. * * @return The frequency of MCGFLLCLK. */ uint32_t CLOCK_GetFllFreq(void); /*! - * @brief Get the MCG internal reference clock(MCGIRCLK) frequency. + * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency. * - * This function gets the MCG internal reference clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGIRCLK. */ uint32_t CLOCK_GetInternalRefClkFreq(void); /*! - * @brief Get the MCG fixed frequency clock(MCGFFCLK) frequency. + * @brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. * - * This function gets the MCG fixed frequency clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGFFCLK. */ uint32_t CLOCK_GetFixedFreqClkFreq(void); /*! - * @brief Get the MCG PLL0 clock(MCGPLL0CLK) frequency. + * @brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. * - * This function gets the MCG PLL0 clock frequency (Hz) based on current MCG + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGPLL0CLK. @@ -1048,21 +1113,21 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void); uint32_t CLOCK_GetPll0Freq(void); /*! - * @brief Get the MCG external PLL frequency. + * @brief Gets the MCG external PLL frequency. * - * This function gets the MCG external PLL frequency (Hz). + * This function gets the MCG external PLL frequency in Hz. * - * @return The frequency of MCG external PLL. + * @return The frequency of the MCG external PLL. */ uint32_t CLOCK_GetExtPllFreq(void); /*! - * @brief Set the MCG external PLL frequency. + * @brief Sets the MCG external PLL frequency. * - * This function sets the MCG external PLL frequency (Hz), the MCG external PLL - * frequency is passed in to MCG driver through this function. Please call this - * function after the external PLL frequency is changed, otherwise the APIs for - * get frequency may returns wrong value. + * This function sets the MCG external PLL frequency in Hz. The MCG external PLL + * frequency is passed to the MCG driver using this function. Call this + * function after the external PLL frequency is changed. Otherwise, the APIs, which are used to get + * the frequency, may return an incorrect value. * * @param The frequency of MCG external PLL. */ @@ -1074,12 +1139,12 @@ void CLOCK_SetExtPllFreq(uint32_t freq); /*@{*/ /*! - * @brief Enable or disable MCG low power. + * @brief Enables or disables the MCG low power. * - * Enable MCG low power will disable the PLL and FLL in bypass modes. That is, - * in FBE and PBE modes, enable low power will set MCG to BLPE mode, in FBI and - * PBI mode, enable low power will set MCG to BLPI mode. - * When disable MCG low power, the PLL or FLL will be enabled based on MCG setting. + * Enabling the MCG low power disables the PLL and FLL in bypass modes. In other words, + * in FBE and PBE modes, enabling low power sets the MCG to BLPE mode. In FBI and + * PBI modes, enabling low power sets the MCG to BLPI mode. + * When disabling the MCG low power, the PLL or FLL are enabled based on MCG settings. * * @param enable True to enable MCG low power, false to disable MCG low power. */ @@ -1096,42 +1161,56 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } /*! - * @brief Configure the Internal Reference clock (MCGIRCLK) + * @brief Configures the Internal Reference clock (MCGIRCLK). * - * This function setups the \c MCGIRCLK base on parameters. It selects the IRC - * source, if fast IRC is used, this function also sets the fast IRC divider. - * This function also sets whether enable \c MCGIRCLK in stop mode. - * Calling this function in FBI/PBI/BLPI modes may change the system clock, so - * it is not allowed to use this in these modes. + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. * * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed MCGIRCLK is used as system clock, should not configure MCGIRCLK. + * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, + * the confuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); /*! - * @brief Select the MCG external reference clock. + * @brief Selects the MCG external reference clock. * - * Select the MCG external reference clock source, it changes the MCG_C7[OSCSEL] - * and wait for the clock source stable. Should not change external reference - * clock in FEE/FBE/BLPE/PBE/PEE mdes, so don't call this function in these modes. + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. - * @retval kStatus_MCG_SourceUsed External reference clock is used, should not change. + * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the confuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); +/*! + * @brief Set the FLL external reference clock divider value. + * + * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV]. + * + * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV]. + */ +static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) +{ + MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv); +} + /*! * @brief Enables the PLL0 in FLL mode. * - * This function setups the PLL0 in FLL mode, make sure the PLL reference - * clock is enabled before calling this function. This function reconfigures - * the PLL0, make sure the PLL0 is not used as a clock source while calling - * this function. The function CLOCK_CalcPllDiv can help to get the proper PLL + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL * divider values. * * @param config Pointer to the configuration structure. @@ -1141,7 +1220,7 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config); /*! * @brief Disables the PLL0 in FLL mode. * - * This function disables the PLL0 in FLL mode, it should be used together with + * This function disables the PLL0 in FLL mode. It should be used together with the * @ref CLOCK_EnablePll0. */ static inline void CLOCK_DisablePll0(void) @@ -1150,70 +1229,80 @@ static inline void CLOCK_DisablePll0(void) } /*! - * @brief Calculates the PLL divider setting for desired output frequency. + * @brief Calculates the PLL divider setting for a desired output frequency. * - * This function calculates the proper reference clock divider (\c PRDIV) and - * VCO divider (\c VDIV) to generate desired PLL output frequency. It returns the - * closest frequency PLL could generate, the corresponding \c PRDIV/VDIV are - * returned from parameters. If desired frequency is not valid, this function + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function * returns 0. * * @param refFreq PLL reference clock frequency. * @param desireFreq Desired PLL output frequency. * @param prdiv PRDIV value to generate desired PLL frequency. * @param vdiv VDIV value to generate desired PLL frequency. - * @return Closest frequency PLL could generate. + * @return Closest frequency match that the PLL was able generate. */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); +/*! + * @brief Set the PLL selection. + * + * This function sets the PLL selection between PLL0/PLL1/EXTPLL, and waits for + * change finished. + * + * @param pllcs The PLL to select. + */ +void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs); + /*@}*/ /*! @name MCG clock lock monitor functions. */ /*@{*/ /*! - * @brief Set the OSC0 clock monitor mode. + * @brief Sets the OSC0 clock monitor mode. * - * Set the OSC0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the OSC0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the RTC OSC clock monitor mode. + * @brief Sets the RTC OSC clock monitor mode. * - * Set the RTC OSC clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the RTC OSC clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the PLL0 clock monitor mode. + * @brief Sets the PLL0 clock monitor mode. * - * Set the PLL0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the PLL0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the external PLL clock monitor mode. + * @brief Sets the external PLL clock monitor mode. * - * Set the external PLL clock monitor mode, see @ref mcg_monitor_mode_t + * This function ets the external PLL clock monitor mode. See @ref mcg_monitor_mode_t * for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Get the MCG status flags. + * @brief Gets the MCG status flags. * - * This function gets the MCG clock status flags, all the status flags are + * This function gets the MCG clock status flags. All status flags are * returned as a logical OR of the enumeration @ref _mcg_status_flags_t. To - * check specific flags, compare the return value with the flags. + * check a specific flag, compare the return value with the flag. * * Example: * @code @@ -1239,8 +1328,8 @@ uint32_t CLOCK_GetStatusFlags(void); /*! * @brief Clears the MCG status flags. * - * This function clears the MCG clock lock lost status. The parameter is logical - * OR value of the flags to clear, see @ref _mcg_status_flags_t. + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See @ref _mcg_status_flags_t. * * Example: * @code @@ -1265,8 +1354,8 @@ void CLOCK_ClearStatusFlags(uint32_t mask); * @brief Configures the OSC external reference clock (OSCERCLK). * * This function configures the OSC external reference clock (OSCERCLK). - * For example, to enable the OSCERCLK in normal mode and stop mode, and also set - * the output divider to 1, as follows: + * This is an example to enable the OSCERCLK in normal and stop modes and also set + * the output divider to 1: * @code oscer_config_t config = @@ -1320,45 +1409,71 @@ static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad) } /*! - * @brief Initialize OSC0. + * @brief Initializes the OSC0. * - * This function initializes OSC0 according to board configuration. + * This function initializes the OSC0 according to the board configuration. * * @param config Pointer to the OSC0 configuration structure. */ void CLOCK_InitOsc0(osc_config_t const *config); /*! - * @brief Deinitialize OSC0. + * @brief Deinitializes the OSC0. * - * This function deinitializes OSC0. + * This function deinitializes the OSC0. */ void CLOCK_DeinitOsc0(void); /* @} */ +/*! + * @name External clock frequency + * @{ + */ + +/*! + * @brief Sets the XTAL0 frequency based on board settings. + * + * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal0Freq(uint32_t freq) +{ + g_xtal0Freq = freq; +} + +/*! + * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings. + * + * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal32Freq(uint32_t freq) +{ + g_xtal32Freq = freq; +} +/* @} */ + /*! * @name MCG auto-trim machine. * @{ */ /*! - * @brief Auto trim the internal reference clock. + * @brief Auto trims the internal reference clock. * - * This function trims the internal reference clock using external clock. If + * This function trims the internal reference clock by using the external clock. If * successful, it returns the kStatus_Success and the frequency after * trimming is received in the parameter @p actualFreq. If an error occurs, * the error code is returned. * - * @param extFreq External clock frequency, should be bus clock. - * @param desireFreq Frequency want to trim to. - * @param actualFreq Actual frequency after trim. + * @param extFreq External clock frequency, which should be a bus clock. + * @param desireFreq Frequency to trim to. + * @param actualFreq Actual frequency after trimming. * @param atms Trim fast or slow internal reference clock. * @retval kStatus_Success ATM success. - * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for ATM. + * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. * @retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. - * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as bus clock source. - * @retval kStatus_MCG_AtmHardwareFail Hardware fails during trim. + * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * @retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms); /* @} */ @@ -1369,260 +1484,265 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ /*! * @brief Gets the current MCG mode. * - * This function checks the MCG registers and determine current MCG mode. + * This function checks the MCG registers and determines the current MCG mode. * - * @return Current MCG mode or error code, see @ref mcg_mode_t. + * @return Current MCG mode or error code; See @ref mcg_mode_t. */ mcg_mode_t CLOCK_GetMode(void); /*! - * @brief Set MCG to FEI mode. + * @brief Sets the MCG to FEI mode. * - * This function sets MCG to FEI mode. If could not set to FEI mode directly - * from current mode, this function returns error. @ref kMCG_Dmx32Default is used in this - * mode because using kMCG_Dmx32Fine with internal reference clock source - * might damage hardware. + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. * + * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. */ -status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode. + * @brief Sets the MCG to FEE mode. * - * This function sets MCG to FEE mode. If could not set to FEE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBI mode. + * @brief Sets the MCG to FBI mode. * - * This function sets MCG to FBI mode. If could not set to FBI mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. * + * @param dmx32 DMX32 in FBI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBI mode, this parameter could be NULL. Pass in - * NULL does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. */ -status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBE mode. + * @brief Sets the MCG to FBE mode. * - * This function sets MCG to FBE mode. If could not set to FBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FBE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBE mode, this parameter could be NULL. Pass in NULL - * does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode. + * @brief Sets the MCG to BLPI mode. * - * This function sets MCG to BLPI mode. If could not set to BLPI mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpiMode(void); /*! - * @brief Set MCG to BLPE mode. + * @brief Sets the MCG to BLPE mode. * - * This function sets MCG to BLPE mode. If could not set to BLPE mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpeMode(void); /*! - * @brief Set MCG to PBE mode. + * @brief Sets the MCG to PBE mode. * - * This function sets MCG to PBE mode. If could not set to PBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. * * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * * @note - * 1. The parameter \c pllcs selects the PLL, for some platforms, there is - * only one PLL, the parameter pllcs is kept for interface compatible. - * 2. The parameter \c config is the PLL configuration structure, on some - * platforms, could choose the external PLL directly. This means that the - * configuration structure is not necessary, pass in NULL for this case. + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to PEE mode. + * @brief Sets the MCG to PEE mode. * - * This function sets MCG to PEE mode. + * This function sets the MCG to PEE mode. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * - * @note This function only change CLKS to use PLL/FLL output. If the - * PRDIV/VDIV are different from PBE mode, please setup these - * settings in PBE mode and wait for stable then switch to PEE mode. + * @note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. */ status_t CLOCK_SetPeeMode(void); /*! - * @brief Switch MCG to FBE mode quickly from external mode. + * @brief Switches the MCG to FBE mode from the external mode. * - * This function changes MCG from external modes (PEE/PBE/BLPE/FEE) to FBE mode quickly. - * It only changes to use external clock as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEE mode to FEI mode: + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock souce and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: * * @code * CLOCK_ExternalModeToFbeModeQuick(); * CLOCK_SetFeiMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not external modes, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. */ status_t CLOCK_ExternalModeToFbeModeQuick(void); /*! - * @brief Switch MCG to FBI mode quickly from internal modes. + * @brief Switches the MCG to FBI mode from internal modes. * - * This function changes MCG from internal modes (PEI/PBI/BLPI/FEI) to FBI mode quickly. - * It only changes to use MCGIRCLK as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEI mode to FEE mode: + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: * * @code * CLOCK_InternalModeToFbiModeQuick(); * CLOCK_SetFeeMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not internal mode, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. */ status_t CLOCK_InternalModeToFbiModeQuick(void); /*! - * @brief Set MCG to FEI mode during system boot up. + * @brief Sets the MCG to FEI mode during system boot up. * - * This function sets MCG to FEI mode from reset mode, it could be used to - * set up MCG during system boot up. @ref kMCG_Dmx32Default is used in this - * mode because using kMCG_Dmx32Fine with internal reference clock source - * might damage hardware. + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. * + * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. */ -status_t CLOCK_BootToFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode during system bootup. + * @brief Sets the MCG to FEE mode during system bootup. * - * This function sets MCG to FEE mode from reset mode, it could be used to - * set up MCG during system boot up. + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, OSCSEL. * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode during system boot up. + * @brief Sets the MCG to BLPI mode during system boot up. * - * This function sets MCG to BLPI mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during sytem boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. * @param ircEnableMode The MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * * @retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Set MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during sytem boot up. * - * This function sets MCG to BLPE mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during sytem boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel); /*! - * @brief Set MCG to PEE mode during system boot up. + * @brief Sets the MCG to PEE mode during system boot up. * - * This function sets MCG to PEE mode from reset mode, it could be used to - * setup MCG during system boot up. + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to some target mode. + * @brief Sets the MCG to a target mode. * - * This function sets MCG to some target mode defined by the configure - * structure, if cannot switch to target mode directly, this function will - * choose the proper path. + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. * * @param config Pointer to the target MCG mode configuration structure. - * @return Return kStatus_Success if switch successfully, otherwise return error code #_mcg_status. + * @return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. * - * @note If external clock is used in the target mode, please make sure it is - * enabled, for example, if the OSC0 is used, please setup OSC0 correctly before - * this funciton. + * @note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c index 09885e74211..6a5f15a75b1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t CMP_GetInstance(CMP_Type *base); ******************************************************************************/ /*! @brief Pointers to CMP bases for each instance. */ static CMP_Type *const s_cmpBases[] = CMP_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to CMP clocks for each instance. */ -const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS; +static const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t CMP_GetInstance(CMP_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_CMP_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_cmpBases); instance++) { if (s_cmpBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t CMP_GetInstance(CMP_Type *base) } } - assert(instance < FSL_FEATURE_SOC_CMP_COUNT); + assert(instance < ARRAY_SIZE(s_cmpBases)); return instance; } @@ -75,8 +77,10 @@ void CMP_Init(CMP_Type *base, const cmp_config_t *config) uint8_t tmp8; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_cmpClocks[CMP_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ CMP_Enable(base, false); /* Disable the CMP module during configuring. */ @@ -123,8 +127,10 @@ void CMP_Deinit(CMP_Type *base) /* Disable the CMP module. */ CMP_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_cmpClocks[CMP_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void CMP_GetDefaultConfig(cmp_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h index 53d84a0f2d2..5d16bf08de4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -64,8 +63,8 @@ enum _cmp_interrupt_enable */ enum _cmp_status_flags { - kCMP_OutputRisingEventFlag = CMP_SCR_CFR_MASK, /*!< Rising-edge on compare output has occurred. */ - kCMP_OutputFallingEventFlag = CMP_SCR_CFF_MASK, /*!< Falling-edge on compare output has occurred. */ + kCMP_OutputRisingEventFlag = CMP_SCR_CFR_MASK, /*!< Rising-edge on the comparison output has occurred. */ + kCMP_OutputFallingEventFlag = CMP_SCR_CFF_MASK, /*!< Falling-edge on the comparison output has occurred. */ kCMP_OutputAssertEventFlag = CMP_SCR_COUT_MASK, /*!< Return the current value of the analog comparator output. */ }; @@ -85,20 +84,20 @@ typedef enum _cmp_hysteresis_mode */ typedef enum _cmp_reference_voltage_source { - kCMP_VrefSourceVin1 = 0U, /*!< Vin1 is selected as resistor ladder network supply reference Vin. */ - kCMP_VrefSourceVin2 = 1U, /*!< Vin2 is selected as resistor ladder network supply reference Vin. */ + kCMP_VrefSourceVin1 = 0U, /*!< Vin1 is selected as a resistor ladder network supply reference Vin. */ + kCMP_VrefSourceVin2 = 1U, /*!< Vin2 is selected as a resistor ladder network supply reference Vin. */ } cmp_reference_voltage_source_t; /*! - * @brief Configure the comparator. + * @brief Configures the comparator. */ typedef struct _cmp_config { bool enableCmp; /*!< Enable the CMP module. */ cmp_hysteresis_mode_t hysteresisMode; /*!< CMP Hysteresis mode. */ - bool enableHighSpeed; /*!< Enable High Speed (HS) comparison mode. */ - bool enableInvertOutput; /*!< Enable inverted comparator output. */ - bool useUnfilteredOutput; /*!< Set compare output(COUT) to equal COUTA(true) or COUT(false). */ + bool enableHighSpeed; /*!< Enable High-speed (HS) comparison mode. */ + bool enableInvertOutput; /*!< Enable the inverted comparator output. */ + bool useUnfilteredOutput; /*!< Set the compare output(COUT) to equal COUTA(true) or COUT(false). */ bool enablePinOut; /*!< The comparator output is available on the associated pin. */ #if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE bool enableTriggerMode; /*!< Enable the trigger mode. */ @@ -106,24 +105,24 @@ typedef struct _cmp_config } cmp_config_t; /*! - * @brief Configure the filter. + * @brief Configures the filter. */ typedef struct _cmp_filter_config { #if defined(FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT) && FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT - bool enableSample; /*!< Using external SAMPLE as sampling clock input, or using divided bus clock. */ + bool enableSample; /*!< Using the external SAMPLE as a sampling clock input or using a divided bus clock. */ #endif /* FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT */ - uint8_t filterCount; /*!< Filter Sample Count. Available range is 1-7, 0 would cause the filter disabled.*/ - uint8_t filterPeriod; /*!< Filter Sample Period. The divider to bus clock. Available range is 0-255. */ + uint8_t filterCount; /*!< Filter Sample Count. Available range is 1-7; 0 disables the filter.*/ + uint8_t filterPeriod; /*!< Filter Sample Period. The divider to the bus clock. Available range is 0-255. */ } cmp_filter_config_t; /*! - * @brief Configure the internal DAC. + * @brief Configures the internal DAC. */ typedef struct _cmp_dac_config { cmp_reference_voltage_source_t referenceVoltageSource; /*!< Supply voltage reference source. */ - uint8_t DACValue; /*!< Value for DAC Output Voltage. Available range is 0-63.*/ + uint8_t DACValue; /*!< Value for the DAC Output Voltage. Available range is 0-63.*/ } cmp_dac_config_t; #if defined(__cplusplus) @@ -142,28 +141,28 @@ extern "C" { /*! * @brief Initializes the CMP. * - * This function initializes the CMP module. The operations included are: + * This function initializes the CMP module. The operations included are as follows. * - Enabling the clock for CMP module. * - Configuring the comparator. * - Enabling the CMP module. - * Note: For some devices, multiple CMP instance share the same clock gate. In this case, to enable the clock for - * any instance enables all the CMPs. Check the chip reference manual for the clock assignment of the CMP. + * Note that for some devices, multiple CMP instances share the same clock gate. In this case, to enable the clock for + * any instance enables all CMPs. See the appropriate MCU reference manual for the clock assignment of the CMP. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void CMP_Init(CMP_Type *base, const cmp_config_t *config); /*! * @brief De-initializes the CMP module. * - * This function de-initializes the CMP module. The operations included are: + * This function de-initializes the CMP module. The operations included are as follows. * - Disabling the CMP module. * - Disabling the clock for CMP module. * * This function disables the clock for the CMP. - * Note: For some devices, multiple CMP instance shares the same clock gate. In this case, before disabling the - * clock for the CMP, ensure that all the CMP instances are not used. + * Note that for some devices, multiple CMP instances share the same clock gate. In this case, before disabling the + * clock for the CMP, ensure that all the CMP instances are not used. * * @param base CMP peripheral base address. */ @@ -173,7 +172,7 @@ void CMP_Deinit(CMP_Type *base); * @brief Enables/disables the CMP module. * * @param base CMP peripheral base address. - * @param enable Enable the module or not. + * @param enable Enables or disables the module. */ static inline void CMP_Enable(CMP_Type *base, bool enable) { @@ -190,7 +189,7 @@ static inline void CMP_Enable(CMP_Type *base, bool enable) /*! * @brief Initializes the CMP user configuration structure. * -* This function initializes the user configure structure to these default values: +* This function initializes the user configuration structure to these default values. * @code * config->enableCmp = true; * config->hysteresisMode = kCMP_HysteresisLevel0; @@ -208,7 +207,7 @@ void CMP_GetDefaultConfig(cmp_config_t *config); * @brief Sets the input channels for the comparator. * * This function sets the input channels for the comparator. - * Note that two input channels cannot be set as same in the application. When the user selects the same input + * Note that two input channels cannot be set the same way in the application. When the user selects the same input * from the analog mux to the positive and negative port, the comparator is disabled automatically. * * @param base CMP peripheral base address. @@ -229,13 +228,11 @@ void CMP_SetInputChannels(CMP_Type *base, uint8_t positiveChannel, uint8_t negat * @brief Enables/disables the DMA request for rising/falling events. * * This function enables/disables the DMA request for rising/falling events. Either event triggers the generation of - * the DMA - * request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from the CMP - * if the - * DMA is disabled. + * the DMA request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from the CMP + * if the DMA is disabled. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ void CMP_EnableDMA(CMP_Type *base, bool enable); #endif /* FSL_FEATURE_CMP_HAS_DMA */ @@ -245,7 +242,7 @@ void CMP_EnableDMA(CMP_Type *base, bool enable); * @brief Enables/disables the window mode. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ static inline void CMP_EnableWindowMode(CMP_Type *base, bool enable) { @@ -265,7 +262,7 @@ static inline void CMP_EnableWindowMode(CMP_Type *base, bool enable) * @brief Enables/disables the pass through mode. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ static inline void CMP_EnablePassThroughMode(CMP_Type *base, bool enable) { @@ -284,7 +281,7 @@ static inline void CMP_EnablePassThroughMode(CMP_Type *base, bool enable) * @brief Configures the filter. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config); @@ -292,7 +289,7 @@ void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config); * @brief Configures the internal DAC. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. "NULL" is for disabling the feature. + * @param config Pointer to the configuration structure. "NULL" disables the feature. */ void CMP_SetDACConfig(CMP_Type *base, const cmp_dac_config_t *config); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c index 9e8831f9983..8cf72bc7e7d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -46,8 +46,6 @@ #define CMT_CMTDIV_FOUR (4) /* CMT diver 8. */ #define CMT_CMTDIV_EIGHT (8) -/* CMT mode bit mask. */ -#define CMT_MODE_BIT_MASK (CMT_MSC_MCGEN_MASK | CMT_MSC_FSK_MASK | CMT_MSC_BASE_MASK) /******************************************************************************* * Prototypes @@ -64,14 +62,16 @@ static uint32_t CMT_GetInstance(CMT_Type *base); * Variables ******************************************************************************/ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to cmt clocks for each instance. */ -const clock_ip_name_t s_cmtClock[FSL_FEATURE_SOC_CMT_COUNT] = CMT_CLOCKS; +static const clock_ip_name_t s_cmtClock[FSL_FEATURE_SOC_CMT_COUNT] = CMT_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to cmt bases for each instance. */ static CMT_Type *const s_cmtBases[] = CMT_BASE_PTRS; /*! @brief Pointers to cmt IRQ number for each instance. */ -const IRQn_Type s_cmtIrqs[] = CMT_IRQS; +static const IRQn_Type s_cmtIrqs[] = CMT_IRQS; /******************************************************************************* * Codes @@ -82,7 +82,7 @@ static uint32_t CMT_GetInstance(CMT_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_CMT_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_cmtBases); instance++) { if (s_cmtBases[instance] == base) { @@ -90,7 +90,7 @@ static uint32_t CMT_GetInstance(CMT_Type *base) } } - assert(instance < FSL_FEATURE_SOC_CMT_COUNT); + assert(instance < ARRAY_SIZE(s_cmtBases)); return instance; } @@ -113,8 +113,10 @@ void CMT_Init(CMT_Type *base, const cmt_config_t *config, uint32_t busClock_Hz) uint8_t divider; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate clock. */ CLOCK_EnableClock(s_cmtClock[CMT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Sets clock divider. The divider set in pps should be set to make sycClock_Hz/divder = 8MHz */ @@ -144,15 +146,17 @@ void CMT_Deinit(CMT_Type *base) CMT_DisableInterrupts(base, kCMT_EndOfCycleInterruptEnable); DisableIRQ(s_cmtIrqs[CMT_GetInstance(base)]); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the clock. */ CLOCK_DisableClock(s_cmtClock[CMT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulateConfig) { - uint8_t mscReg; + uint8_t mscReg = base->MSC; - /* Set the mode. */ + /* Judge the mode. */ if (mode != kCMT_DirectIROCtl) { assert(modulateConfig); @@ -166,13 +170,14 @@ void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulat /* Set carrier modulator. */ CMT_SetModulateMarkSpace(base, modulateConfig->markCount, modulateConfig->spaceCount); + mscReg &= ~ (CMT_MSC_FSK_MASK | CMT_MSC_BASE_MASK); + mscReg |= mode; + } + else + { + mscReg &= ~CMT_MSC_MCGEN_MASK; } - /* Set the CMT mode. */ - mscReg = base->MSC; - mscReg &= ~CMT_MODE_BIT_MASK; - mscReg |= mode; - base->MSC = mscReg; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h index df0b2c91066..3d81f8a9a4a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief CMT driver version 2.0.0. */ -#define FSL_CMT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief CMT driver version 2.0.1. */ +#define FSL_CMT_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ /*! @@ -128,15 +127,15 @@ enum _cmt_interrupt_enable }; /*! - * @brief CMT carrier generator and modulator configure structure + * @brief CMT carrier generator and modulator configuration structure * */ typedef struct _cmt_modulate_config { - uint8_t highCount1; /*!< The high time for carrier generator first register. */ - uint8_t lowCount1; /*!< The low time for carrier generator first register. */ - uint8_t highCount2; /*!< The high time for carrier generator second register for FSK mode. */ - uint8_t lowCount2; /*!< The low time for carrier generator second register for FSK mode. */ + uint8_t highCount1; /*!< The high-time for carrier generator first register. */ + uint8_t lowCount1; /*!< The low-time for carrier generator first register. */ + uint8_t highCount2; /*!< The high-time for carrier generator second register for FSK mode. */ + uint8_t lowCount2; /*!< The low-time for carrier generator second register for FSK mode. */ uint16_t markCount; /*!< The mark time for the modulator gate. */ uint16_t spaceCount; /*!< The space time for the modulator gate. */ } cmt_modulate_config_t; @@ -164,10 +163,10 @@ extern "C" { */ /*! - * @brief Gets the CMT default configuration structure. The purpose - * of this API is to get the default configuration structure for the CMT_Init(). - * Use the initialized structure unchanged in CMT_Init(), or modify - * some fields of the structure before calling the CMT_Init(). + * @brief Gets the CMT default configuration structure. This API + * gets the default configuration structure for the CMT_Init(). + * Use the initialized structure unchanged in CMT_Init() or modify + * fields of the structure before calling the CMT_Init(). * * @param config The CMT configuration structure pointer. */ @@ -216,7 +215,7 @@ void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulat * * @param base CMT peripheral base address. * @return The CMT mode. - * kCMT_DirectIROCtl Carrier modulator is disabled, the IRO signal is directly in software control. + * kCMT_DirectIROCtl Carrier modulator is disabled; the IRO signal is directly in software control. * kCMT_TimeMode Carrier modulator is enabled in time mode. * kCMT_FSKMode Carrier modulator is enabled in FSK mode. * kCMT_BasebandMode Carrier modulator is enabled in baseband mode. @@ -235,11 +234,11 @@ uint32_t CMT_GetCMTFrequency(CMT_Type *base, uint32_t busClock_Hz); /*! * @brief Sets the primary data set for the CMT carrier generator counter. * - * This function sets the high time and low time of the primary data set for the + * This function sets the high-time and low-time of the primary data set for the * CMT carrier generator counter to control the period and the duty cycle of the * output carrier signal. - * If the CMT clock period is Tcmt, The period of the carrier generator signal equals - * (highCount + lowCount) * Tcmt. The duty cycle equals highCount / (highCount + lowCount). + * If the CMT clock period is Tcmt, the period of the carrier generator signal equals + * (highCount + lowCount) * Tcmt. The duty cycle equals to highCount / (highCount + lowCount). * * @param base CMT peripheral base address. * @param highCount The number of CMT clocks for carrier generator signal high time, @@ -261,10 +260,10 @@ static inline void CMT_SetCarrirGenerateCountOne(CMT_Type *base, uint32_t highCo /*! * @brief Sets the secondary data set for the CMT carrier generator counter. * - * This function is used for FSK mode setting the high time and low time of the secondary + * This function is used for FSK mode setting the high-time and low-time of the secondary * data set CMT carrier generator counter to control the period and the duty cycle * of the output carrier signal. - * If the CMT clock period is Tcmt, The period of the carrier generator signal equals + * If the CMT clock period is Tcmt, the period of the carrier generator signal equals * (highCount + lowCount) * Tcmt. The duty cycle equals highCount / (highCount + lowCount). * * @param base CMT peripheral base address. @@ -325,7 +324,7 @@ static inline void CMT_EnableExtendedSpace(CMT_Type *base, bool enable) } /*! - * @brief Sets IRO - infrared output signal state. + * @brief Sets the IRO (infrared output) signal state. * * Changes the states of the IRO signal when the kCMT_DirectIROMode mode is set * and the IRO signal is enabled. @@ -338,12 +337,12 @@ void CMT_SetIroState(CMT_Type *base, cmt_infrared_output_state_t state); /*! * @brief Enables the CMT interrupt. * - * This function enables the CMT interrupts according to the provided maskIf enabled. + * This function enables the CMT interrupts according to the provided mask if enabled. * The CMT only has the end of the cycle interrupt - an interrupt occurs at the end * of the modulator cycle. This interrupt provides a means for the user * to reload the new mark/space values into the CMT modulator data registers * and verify the modulator mark and space. - * For example, to enable the end of cycle, do the following: + * For example, to enable the end of cycle, do the following. * @code * CMT_EnableInterrupts(CMT, kCMT_EndOfCycleInterruptEnable); * @endcode @@ -360,7 +359,7 @@ static inline void CMT_EnableInterrupts(CMT_Type *base, uint32_t mask) * * This function disables the CMT interrupts according to the provided maskIf enabled. * The CMT only has the end of the cycle interrupt. - * For example, to disable the end of cycle, do the following: + * For example, to disable the end of cycle, do the following. * @code * CMT_DisableInterrupts(CMT, kCMT_EndOfCycleInterruptEnable); * @endcode diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h index 7061b621391..b20ec09973b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -34,8 +34,12 @@ #include #include #include -#include #include + +#if defined(__ICCARM__) +#include +#endif + #include "fsl_device_registers.h" /*! @@ -43,8 +47,6 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -56,11 +58,13 @@ #define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) /* Debug console type definition. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console base on i.MX UART. */ /*! @brief Status group numbers. */ enum _status_groups @@ -87,6 +91,11 @@ enum _status_groups kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */ kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */ kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */ + kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */ + kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */ + kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */ + kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */ + kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */ kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */ kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */ kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */ @@ -101,6 +110,18 @@ enum _status_groups kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */ kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */ kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */ + kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */ + kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */ + kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */ + kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/ + kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */ + kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */ + kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */ + kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */ + kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */ + kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/ + kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */ + kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */ kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */ kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */ kStatusGroup_ApplicationRangeStart = 100, /*!< Starting number for application groups. */ @@ -127,6 +148,14 @@ typedef int32_t status_t; */ #include "fsl_clock.h" +/* + * Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral + */ +#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \ + (defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0))) +#include "fsl_reset.h" +#endif + /*! @name Min/max macros */ /* @{ */ #if !defined(MIN) @@ -182,11 +211,20 @@ extern "C" { */ static inline void EnableIRQ(IRQn_Type interrupt) { + if (NotAvail_IRQn == interrupt) + { + return; + } + #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0) if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX) #endif { +#if defined(__GIC_PRIO_BITS) + GIC_EnableIRQ(interrupt); +#else NVIC_EnableIRQ(interrupt); +#endif } } @@ -199,11 +237,20 @@ static inline void EnableIRQ(IRQn_Type interrupt) */ static inline void DisableIRQ(IRQn_Type interrupt) { + if (NotAvail_IRQn == interrupt) + { + return; + } + #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0) if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX) #endif { +#if defined(__GIC_PRIO_BITS) + GIC_DisableIRQ(interrupt); +#else NVIC_DisableIRQ(interrupt); +#endif } } @@ -217,11 +264,19 @@ static inline void DisableIRQ(IRQn_Type interrupt) */ static inline uint32_t DisableGlobalIRQ(void) { +#if defined(CPSR_I_Msk) + uint32_t cpsr = __get_CPSR() & CPSR_I_Msk; + + __disable_irq(); + + return cpsr; +#else uint32_t regPrimask = __get_PRIMASK(); __disable_irq(); return regPrimask; +#endif } /*! @@ -236,7 +291,11 @@ static inline uint32_t DisableGlobalIRQ(void) */ static inline void EnableGlobalIRQ(uint32_t primask) { +#if defined(CPSR_I_Msk) + __set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask); +#else __set_PRIMASK(primask); +#endif } /*! @@ -244,9 +303,42 @@ static inline void EnableGlobalIRQ(uint32_t primask) * * @param irq IRQ number * @param irqHandler IRQ handler address + * @return The old IRQ handler address */ void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler); +#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) +/*! + * @brief Enable specific interrupt for wake-up from deep-sleep mode. + * + * Enable the interrupt for wake-up from deep sleep mode. + * Some interrupts are typically used in sleep mode only and will not occur during + * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable + * those clocks (significantly increasing power consumption in the reduced power mode), + * making these wake-ups possible. + * + * @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internally). + * + * @param interrupt The IRQ number. + */ +void EnableDeepSleepIRQ(IRQn_Type interrupt); + +/*! + * @brief Disable specific interrupt for wake-up from deep-sleep mode. + * + * Disable the interrupt for wake-up from deep sleep mode. + * Some interrupts are typically used in sleep mode only and will not occur during + * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable + * those clocks (significantly increasing power consumption in the reduced power mode), + * making these wake-ups possible. + * + * @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internally). + * + * @param interrupt The IRQ number. + */ +void DisableDeepSleepIRQ(IRQn_Type interrupt); +#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */ + #if defined(__cplusplus) } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c index f73647e1c78..dba1db8c463 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -32,6 +32,11 @@ /******************************************************************************* * Definitions ******************************************************************************/ +/*! @internal @brief Has data register with name CRC. */ +#if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG +#define DATA CRC +#define DATALL CRCLL +#endif #if defined(CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT) && CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT /* @brief Default user configuration structure for CRC-16-CCITT */ @@ -87,7 +92,7 @@ typedef struct _crc_module_config * * @param enable True or false for the selected CRC protocol Reflect In (refin) parameter. */ -static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectIn(bool enable) +static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectIn(bool enable) { return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeBytes); } @@ -99,7 +104,7 @@ static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectIn(bool enable * * @param enable True or false for the selected CRC protocol Reflect Out (refout) parameter. */ -static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectOut(bool enable) +static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectOut(bool enable) { return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeNone); } @@ -113,7 +118,7 @@ static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectOut(bool enabl * @param base CRC peripheral address. * @param config Pointer to protocol configuration structure. */ -static void crc_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config) +static void CRC_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config) { uint32_t crcControl; @@ -148,18 +153,18 @@ static void crc_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *con * @param base CRC peripheral address. * @param protocolConfig Pointer to protocol configuration structure. */ -static void crc_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) +static void CRC_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) { crc_module_config_t moduleConfig; /* convert protocol to CRC peripheral module configuration, prepare for final checksum */ moduleConfig.polynomial = protocolConfig->polynomial; moduleConfig.seed = protocolConfig->seed; - moduleConfig.readTranspose = crc_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut); - moduleConfig.writeTranspose = crc_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); + moduleConfig.readTranspose = CRC_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut); + moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); moduleConfig.complementChecksum = protocolConfig->complementChecksum; moduleConfig.crcBits = protocolConfig->crcBits; - crc_ConfigureAndStart(base, &moduleConfig); + CRC_ConfigureAndStart(base, &moduleConfig); } /*! @@ -172,7 +177,7 @@ static void crc_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolCo * @param base CRC peripheral address. * @param protocolConfig Pointer to protocol configuration structure. */ -static void crc_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) +static void CRC_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) { crc_module_config_t moduleConfig; /* convert protocol to CRC peripheral module configuration, prepare for intermediate checksum */ @@ -180,25 +185,27 @@ static void crc_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protoco moduleConfig.seed = protocolConfig->seed; moduleConfig.readTranspose = kCrcTransposeNone; /* intermediate checksum does no transpose of data register read value */ - moduleConfig.writeTranspose = crc_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); + moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); moduleConfig.complementChecksum = false; /* intermediate checksum does no xor of data register read value */ moduleConfig.crcBits = protocolConfig->crcBits; - crc_ConfigureAndStart(base, &moduleConfig); + CRC_ConfigureAndStart(base, &moduleConfig); } void CRC_Init(CRC_Type *base, const crc_config_t *config) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* ungate clock */ CLOCK_EnableClock(kCLOCK_Crc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* configure CRC module and write the seed */ if (config->crcResult == kCrcFinalChecksum) { - crc_SetProtocolConfig(base, config); + CRC_SetProtocolConfig(base, config); } else { - crc_SetRawProtocolConfig(base, config); + CRC_SetRawProtocolConfig(base, config); } } @@ -246,6 +253,11 @@ void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize) } } +uint32_t CRC_Get32bitResult(CRC_Type *base) +{ + return base->DATA; +} + uint16_t CRC_Get16bitResult(CRC_Type *base) { uint32_t retval; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h index ce0b60fbaf9..247a9bac781 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -34,28 +34,27 @@ #include "fsl_common.h" /*! - * @addtogroup crc_driver + * @addtogroup crc * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief CRC driver version. Version 2.0.0. */ -#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief CRC driver version. Version 2.0.1. + * + * Current version: 2.0.1 + * + * Change log: + * - Version 2.0.1 + * - move DATA and DATALL macro definition from header file to source file + */ +#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ -/*! @internal @brief Has data register with name CRC. */ -#if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG -#define DATA CRC -#define DATALL CRCLL -#endif - #ifndef CRC_DRIVER_CUSTOM_DEFAULTS /*! @brief Default configuration structure filled by CRC_GetDefaultConfig(). Use CRC16-CCIT-FALSE as defeault. */ #define CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT 1 @@ -108,31 +107,33 @@ extern "C" { /*! * @brief Enables and configures the CRC peripheral module. * - * This functions enables the clock gate in the Kinetis SIM module for the CRC peripheral. - * It also configures the CRC module and starts checksum computation by writing the seed. + * This function enables the clock gate in the SIM module for the CRC peripheral. + * It also configures the CRC module and starts a checksum computation by writing the seed. * * @param base CRC peripheral address. - * @param config CRC module configuration structure + * @param config CRC module configuration structure. */ void CRC_Init(CRC_Type *base, const crc_config_t *config); /*! * @brief Disables the CRC peripheral module. * - * This functions disables the clock gate in the Kinetis SIM module for the CRC peripheral. + * This function disables the clock gate in the SIM module for the CRC peripheral. * * @param base CRC peripheral address. */ static inline void CRC_Deinit(CRC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* gate clock */ CLOCK_DisableClock(kCLOCK_Crc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! - * @brief Loads default values to CRC protocol configuration structure. + * @brief Loads default values to the CRC protocol configuration structure. * - * Loads default values to CRC protocol configuration structure. The default values are: + * Loads default values to the CRC protocol configuration structure. The default values are as follows. * @code * config->polynomial = 0x1021; * config->seed = 0xFFFF; @@ -143,14 +144,14 @@ static inline void CRC_Deinit(CRC_Type *base) * config->crcResult = kCrcFinalChecksum; * @endcode * - * @param config CRC protocol configuration structure + * @param config CRC protocol configuration structure. */ void CRC_GetDefaultConfig(crc_config_t *config); /*! * @brief Writes data to the CRC module. * - * Writes input data buffer bytes to CRC data register. + * Writes input data buffer bytes to the CRC data register. * The configured type of transpose is applied. * * @param base CRC peripheral address. @@ -160,27 +161,24 @@ void CRC_GetDefaultConfig(crc_config_t *config); void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize); /*! - * @brief Reads 32-bit checksum from the CRC module. + * @brief Reads the 32-bit checksum from the CRC module. * - * Reads CRC data register (intermediate or final checksum). - * The configured type of transpose and complement are applied. + * Reads the CRC data register (either an intermediate or the final checksum). + * The configured type of transpose and complement is applied. * * @param base CRC peripheral address. - * @return intermediate or final 32-bit checksum, after configured transpose and complement operations. + * @return An intermediate or the final 32-bit checksum, after configured transpose and complement operations. */ -static inline uint32_t CRC_Get32bitResult(CRC_Type *base) -{ - return base->DATA; -} +uint32_t CRC_Get32bitResult(CRC_Type *base); /*! - * @brief Reads 16-bit checksum from the CRC module. + * @brief Reads a 16-bit checksum from the CRC module. * - * Reads CRC data register (intermediate or final checksum). - * The configured type of transpose and complement are applied. + * Reads the CRC data register (either an intermediate or the final checksum). + * The configured type of transpose and complement is applied. * * @param base CRC peripheral address. - * @return intermediate or final 16-bit checksum, after configured transpose and complement operations. + * @return An intermediate or the final 16-bit checksum, after configured transpose and complement operations. */ uint16_t CRC_Get16bitResult(CRC_Type *base); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c index 2f83f5ee9e6..8d13d622835 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t DAC_GetInstance(DAC_Type *base); ******************************************************************************/ /*! @brief Pointers to DAC bases for each instance. */ static DAC_Type *const s_dacBases[] = DAC_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to DAC clocks for each instance. */ -const clock_ip_name_t s_dacClocks[] = DAC_CLOCKS; +static const clock_ip_name_t s_dacClocks[] = DAC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t DAC_GetInstance(DAC_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DAC_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dacBases); instance++) { if (s_dacBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t DAC_GetInstance(DAC_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DAC_COUNT); + assert(instance < ARRAY_SIZE(s_dacBases)); return instance; } @@ -75,8 +77,10 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config) uint8_t tmp8; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_dacClocks[DAC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ /* DACx_C0. */ @@ -91,15 +95,18 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config) } base->C0 = tmp8; - DAC_Enable(base, true); + /* DAC_Enable(base, true); */ + /* Tip: The DAC output can be enabled till then after user sets their own available data in application. */ } void DAC_Deinit(DAC_Type *base) { DAC_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_dacClocks[DAC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void DAC_GetDefaultConfig(dac_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h index 44e2d048bd9..b71febf3bc3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -46,8 +45,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DAC driver version 2.0.0. */ -#define FSL_DAC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief DAC driver version 2.0.1. */ +#define FSL_DAC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ /*! @@ -104,15 +103,15 @@ typedef enum _dac_buffer_watermark #if defined(FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD kDAC_BufferWatermark1Word = 0U, /*!< 1 word away from the upper limit. */ #endif /* FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD */ -#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD +#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_2_WORDS) && FSL_FEATURE_DAC_HAS_WATERMARK_2_WORDS kDAC_BufferWatermark2Word = 1U, /*!< 2 words away from the upper limit. */ -#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD */ -#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD +#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_2_WORDS */ +#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_3_WORDS) && FSL_FEATURE_DAC_HAS_WATERMARK_3_WORDS kDAC_BufferWatermark3Word = 2U, /*!< 3 words away from the upper limit. */ -#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD */ -#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD +#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_3_WORDS */ +#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_4_WORDS) && FSL_FEATURE_DAC_HAS_WATERMARK_4_WORDS kDAC_BufferWatermark4Word = 3U, /*!< 4 words away from the upper limit. */ -#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD */ +#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_4_WORDS */ } dac_buffer_watermark_t; #endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */ @@ -137,7 +136,7 @@ typedef enum _dac_buffer_work_mode typedef struct _dac_config { dac_reference_voltage_source_t referenceVoltageSource; /*!< Select the DAC reference voltage source. */ - bool enableLowPowerMode; /*!< Enable the low power mode. */ + bool enableLowPowerMode; /*!< Enable the low-power mode. */ } dac_config_t; /*! @@ -150,8 +149,8 @@ typedef struct _dac_buffer_config dac_buffer_watermark_t watermark; /*!< Select the buffer's watermark. */ #endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */ dac_buffer_work_mode_t workMode; /*!< Select the buffer's work mode. */ - uint8_t upperLimit; /*!< Set the upper limit for buffer index. - Normally, 0-15 is available for buffer with 16 item. */ + uint8_t upperLimit; /*!< Set the upper limit for the buffer index. + Normally, 0-15 is available for a buffer with 16 items. */ } dac_buffer_config_t; /******************************************************************************* @@ -169,7 +168,7 @@ extern "C" { /*! * @brief Initializes the DAC module. * - * This function initializes the DAC module, including: + * This function initializes the DAC module including the following operations. * - Enabling the clock for DAC module. * - Configuring the DAC converter with a user configuration. * - Enabling the DAC module. @@ -182,7 +181,7 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config); /*! * @brief De-initializes the DAC module. * - * This function de-initializes the DAC module, including: + * This function de-initializes the DAC module including the following operations. * - Disabling the DAC module. * - Disabling the clock for the DAC module. * @@ -193,7 +192,7 @@ void DAC_Deinit(DAC_Type *base); /*! * @brief Initializes the DAC user configuration structure. * - * This function initializes the user configuration structure to a default value. The default values are: + * This function initializes the user configuration structure to a default value. The default values are as follows. * @code * config->referenceVoltageSource = kDAC_ReferenceVoltageSourceVref2; * config->enableLowPowerMode = false; @@ -206,7 +205,7 @@ void DAC_GetDefaultConfig(dac_config_t *config); * @brief Enables the DAC module. * * @param base DAC peripheral base address. - * @param enable Enables the feature or not. + * @param enable Enables or disables the feature. */ static inline void DAC_Enable(DAC_Type *base, bool enable) { @@ -231,7 +230,7 @@ static inline void DAC_Enable(DAC_Type *base, bool enable) * @brief Enables the DAC buffer. * * @param base DAC peripheral base address. - * @param enable Enables the feature or not. + * @param enable Enables or disables the feature. */ static inline void DAC_EnableBuffer(DAC_Type *base, bool enable) { @@ -256,7 +255,7 @@ void DAC_SetBufferConfig(DAC_Type *base, const dac_buffer_config_t *config); /*! * @brief Initializes the DAC buffer configuration structure. * - * This function initializes the DAC buffer configuration structure to a default value. The default values are: + * This function initializes the DAC buffer configuration structure to default values. The default values are as follows. * @code * config->triggerMode = kDAC_BufferTriggerBySoftwareMode; * config->watermark = kDAC_BufferWatermark1Word; @@ -271,7 +270,7 @@ void DAC_GetDefaultBufferConfig(dac_buffer_config_t *config); * @brief Enables the DMA for DAC buffer. * * @param base DAC peripheral base address. - * @param enable Enables the feature or not. + * @param enable Enables or disables the feature. */ static inline void DAC_EnableBufferDMA(DAC_Type *base, bool enable) { @@ -289,15 +288,15 @@ static inline void DAC_EnableBufferDMA(DAC_Type *base, bool enable) * @brief Sets the value for items in the buffer. * * @param base DAC peripheral base address. - * @param index Setting index for items in the buffer. The available index should not exceed the size of the DAC buffer. - * @param value Setting value for items in the buffer. 12-bits are available. + * @param index Setting the index for items in the buffer. The available index should not exceed the size of the DAC buffer. + * @param value Setting the value for items in the buffer. 12-bits are available. */ void DAC_SetBufferValue(DAC_Type *base, uint8_t index, uint16_t value); /*! - * @brief Triggers the buffer by software and updates the read pointer of the DAC buffer. + * @brief Triggers the buffer using software and updates the read pointer of the DAC buffer. * - * This function triggers the function by software. The read pointer of the DAC buffer is updated with one step + * This function triggers the function using software. The read pointer of the DAC buffer is updated with one step * after this function is called. Changing the read pointer depends on the buffer's work mode. * * @param base DAC peripheral base address. @@ -311,12 +310,12 @@ static inline void DAC_DoSoftwareTriggerBuffer(DAC_Type *base) * @brief Gets the current read pointer of the DAC buffer. * * This function gets the current read pointer of the DAC buffer. - * The current output value depends on the item indexed by the read pointer. It is updated - * by software trigger or hardware trigger. + * The current output value depends on the item indexed by the read pointer. It is updated either + * by a software trigger or a hardware trigger. * * @param base DAC peripheral base address. * - * @return Current read pointer of DAC buffer. + * @return The current read pointer of the DAC buffer. */ static inline uint8_t DAC_GetBufferReadPointer(DAC_Type *base) { @@ -327,11 +326,11 @@ static inline uint8_t DAC_GetBufferReadPointer(DAC_Type *base) * @brief Sets the current read pointer of the DAC buffer. * * This function sets the current read pointer of the DAC buffer. - * The current output value depends on the item indexed by the read pointer. It is updated by - * software trigger or hardware trigger. After the read pointer changes, the DAC output value also changes. + * The current output value depends on the item indexed by the read pointer. It is updated either by a + * software trigger or a hardware trigger. After the read pointer changes, the DAC output value also changes. * * @param base DAC peripheral base address. - * @param index Setting index value for the pointer. + * @param index Setting an index value for the pointer. */ void DAC_SetBufferReadPointer(DAC_Type *base, uint8_t index); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c index a288b9f22fc..39ce9cfbead 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -52,8 +52,10 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base); /*! @brief Array to map DMAMUX instance number to base pointer. */ static DMAMUX_Type *const s_dmamuxBases[] = DMAMUX_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Array to map DMAMUX instance number to clock name. */ static const clock_ip_name_t s_dmamuxClockName[] = DMAMUX_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -63,7 +65,7 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DMAMUX_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dmamuxBases); instance++) { if (s_dmamuxBases[instance] == base) { @@ -71,17 +73,21 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DMAMUX_COUNT); + assert(instance < ARRAY_SIZE(s_dmamuxBases)); return instance; } void DMAMUX_Init(DMAMUX_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void DMAMUX_Deinit(DMAMUX_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h index f4294d4dfa8..071348b2c25 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -46,8 +45,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DMAMUX driver version 2.0.0. */ -#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief DMAMUX driver version 2.0.2. */ +#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ /******************************************************************************* @@ -59,14 +58,14 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name DMAMUX Initialize and De-initialize + * @name DMAMUX Initialization and de-initialization * @{ */ /*! - * @brief Initializes DMAMUX peripheral. + * @brief Initializes the DMAMUX peripheral. * - * This function ungate the DMAMUX clock. + * This function ungates the DMAMUX clock. * * @param base DMAMUX peripheral base address. * @@ -74,9 +73,9 @@ extern "C" { void DMAMUX_Init(DMAMUX_Type *base); /*! - * @brief Deinitializes DMAMUX peripheral. + * @brief Deinitializes the DMAMUX peripheral. * - * This function gate the DMAMUX clock. + * This function gates the DMAMUX clock. * * @param base DMAMUX peripheral base address. */ @@ -89,9 +88,9 @@ void DMAMUX_Deinit(DMAMUX_Type *base); */ /*! - * @brief Enable DMAMUX channel. + * @brief Enables the DMAMUX channel. * - * This function enable DMAMUX channel to work. + * This function enables the DMAMUX channel. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -104,11 +103,11 @@ static inline void DMAMUX_EnableChannel(DMAMUX_Type *base, uint32_t channel) } /*! - * @brief Disable DMAMUX channel. + * @brief Disables the DMAMUX channel. * - * This function disable DMAMUX channel. + * This function disables the DMAMUX channel. * - * @note User must disable DMAMUX channel before configure it. + * @note The user must disable the DMAMUX channel before configuring it. * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. */ @@ -120,13 +119,13 @@ static inline void DMAMUX_DisableChannel(DMAMUX_Type *base, uint32_t channel) } /*! - * @brief Configure DMAMUX channel source. + * @brief Configures the DMAMUX channel source. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. - * @param source Channel source which is used to trigger DMA transfer. + * @param source Channel source, which is used to trigger the DMA transfer. */ -static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint8_t source) +static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint32_t source) { assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL); @@ -135,9 +134,9 @@ static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint8_t #if defined(FSL_FEATURE_DMAMUX_HAS_TRIG) && FSL_FEATURE_DMAMUX_HAS_TRIG > 0U /*! - * @brief Enable DMAMUX period trigger. + * @brief Enables the DMAMUX period trigger. * - * This function enable DMAMUX period trigger feature. + * This function enables the DMAMUX period trigger feature. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -150,9 +149,9 @@ static inline void DMAMUX_EnablePeriodTrigger(DMAMUX_Type *base, uint32_t channe } /*! - * @brief Disable DMAMUX period trigger. + * @brief Disables the DMAMUX period trigger. * - * This function disable DMAMUX period trigger. + * This function disables the DMAMUX period trigger. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -165,6 +164,31 @@ static inline void DMAMUX_DisablePeriodTrigger(DMAMUX_Type *base, uint32_t chann } #endif /* FSL_FEATURE_DMAMUX_HAS_TRIG */ +#if (defined(FSL_FEATURE_DMAMUX_HAS_A_ON) && FSL_FEATURE_DMAMUX_HAS_A_ON) +/*! + * @brief Enables the DMA channel to be always ON. + * + * This function enables the DMAMUX channel always ON feature. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + * @param enable Switcher of the always ON feature. "true" means enabled, "false" means disabled. + */ +static inline void DMAMUX_EnableAlwaysOn(DMAMUX_Type *base, uint32_t channel, bool enable) +{ + assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + if (enable) + { + base->CHCFG[channel] |= DMAMUX_CHCFG_A_ON_MASK; + } + else + { + base->CHCFG[channel] &= ~DMAMUX_CHCFG_A_ON_MASK; + } +} +#endif /* FSL_FEATURE_DMAMUX_HAS_A_ON */ + /* @} */ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c index 5654ce7aac6..d3b3f0aa5f7 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_dspi.h" @@ -65,27 +65,27 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc /*! * @brief Master fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Master finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Slave fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle); /*! * @brief Slave finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle); @@ -100,7 +100,7 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param); /*! * @brief Master prepare the transfer. * Basically it set up dspi_master_handle . - * This is not a public API as it is called from other driver functions. fsl_dspi_edma.c also call this function. + * This is not a public API. */ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -123,11 +123,13 @@ static SPI_Type *const s_dspiBases[] = SPI_BASE_PTRS; /*! @brief Pointers to dspi IRQ number for each instance. */ static IRQn_Type const s_dspiIRQ[] = SPI_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to dspi clocks for each instance. */ static clock_ip_name_t const s_dspiClock[] = DSPI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to dspi handles for each instance. */ -static void *g_dspiHandle[FSL_FEATURE_SOC_DSPI_COUNT]; +static void *g_dspiHandle[ARRAY_SIZE(s_dspiBases)]; /*! @brief Pointer to master IRQ handler for each instance. */ static dspi_master_isr_t s_dspiMasterIsr; @@ -135,6 +137,8 @@ static dspi_master_isr_t s_dspiMasterIsr; /*! @brief Pointer to slave IRQ handler for each instance. */ static dspi_slave_isr_t s_dspiSlaveIsr; +/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/ +volatile uint8_t s_dummyData[ARRAY_SIZE(s_dspiBases)] = {0}; /********************************************************************************************************************** * Code *********************************************************************************************************************/ @@ -143,7 +147,7 @@ uint32_t DSPI_GetInstance(SPI_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DSPI_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dspiBases); instance++) { if (s_dspiBases[instance] == base) { @@ -151,16 +155,26 @@ uint32_t DSPI_GetInstance(SPI_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DSPI_COUNT); + assert(instance < ARRAY_SIZE(s_dspiBases)); return instance; } +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +{ + uint32_t instance = DSPI_GetInstance(base); + s_dummyData[instance] = dummyData; +} + void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz) { + assert(masterConfig); + uint32_t temp; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -196,11 +210,14 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { + assert(masterConfig); + masterConfig->whichCtar = kDSPI_Ctar0; masterConfig->ctarConfig.baudRate = 500000; masterConfig->ctarConfig.bitsPerFrame = 8; @@ -223,10 +240,14 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { + assert(slaveConfig); + uint32_t temp = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -250,11 +271,15 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { + assert(slaveConfig); + slaveConfig->whichCtar = kDSPI_Ctar0; slaveConfig->ctarConfig.bitsPerFrame = 8; slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; @@ -271,8 +296,10 @@ void DSPI_Deinit(SPI_Type *base) DSPI_StopTransfer(base); DSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* disable DSPI clock */ CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh) @@ -457,6 +484,8 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { + assert(command); + command->isPcsContinuous = false; command->whichCtar = kDSPI_Ctar0; command->whichPcs = kDSPI_Pcs0; @@ -466,6 +495,8 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { + assert(command); + /* First, clear Transmit Complete Flag (TCF) */ DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); @@ -562,7 +593,7 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; uint8_t bitsPerFrame; uint32_t command; @@ -598,6 +629,7 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) command = DSPI_MasterGetFormattedCommand(&(commandStruct)); + commandStruct.isEndOfQueue = true; commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); @@ -626,25 +658,6 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { if (remainingSendByteCount == 1) { - while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) - { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) { DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); @@ -702,20 +715,23 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; + if (rxData != NULL) + { + *(rxData) = DSPI_ReadData(base); + rxData++; + } + else + { + DSPI_ReadData(base); + } + remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -726,25 +742,6 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { if (remainingSendByteCount <= 2) { - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) - { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) - { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) { DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); @@ -825,20 +822,23 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; + wordReceived = DSPI_ReadData(base); + + if (rxData != NULL) + { + *rxData = wordReceived; + ++rxData; + *rxData = wordReceived >> 8; + ++rxData; + } + remainingReceiveByteCount -= 2; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -849,6 +849,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { + assert(handle); + assert(transfer); + dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); @@ -864,6 +867,7 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); + commandStruct.isEndOfQueue = true; commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); @@ -886,7 +890,8 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If the transfer count is zero, then return immediately.*/ if (transfer->dataSize == 0) @@ -903,13 +908,10 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha handle->state = kDSPI_Busy; DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); /* Enable the NVIC for DSPI peripheral. */ EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - DSPI_MasterTransferFillUpTxFifo(base, handle); - /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt * Since SPI is a synchronous interface, we only need to enable the RX interrupt. * The IRQ handler will get the status of RX and TX interrupt flags. @@ -917,7 +919,10 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); return kStatus_Success; } @@ -943,6 +948,8 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + /* Disable interrupt requests*/ DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); @@ -956,19 +963,20 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } + handle->state = kDSPI_Idle; + if (handle->callback) { handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; /* If bits/frame is greater than one byte */ if (handle->bitsPerFrame > 8) @@ -1081,6 +1089,8 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); /* Disable interrupt requests*/ @@ -1091,6 +1101,8 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ if (handle->remainingReceiveByteCount) { @@ -1212,7 +1224,8 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If receive length is zero */ if (transfer->dataSize == 0) @@ -1254,11 +1267,6 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand DSPI_FlushFifo(base, true, true); DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); - DSPI_StartTransfer(base); - - /* Prepare data to transmit */ - DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; /* Enable RX FIFO drain request, the slave only use this interrupt */ @@ -1275,6 +1283,11 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); } + DSPI_StartTransfer(base); + + /* Prepare data to transmit */ + DSPI_SlaveTransferFillUpTxFifo(base, handle); + return kStatus_Success; } @@ -1300,8 +1313,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_SLAVE_DUMMY_DATA; + uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; /* Service the transmitter, if transmit buffer provided, transmit the data, * else transmit dummy pattern @@ -1386,6 +1401,8 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + /* Disable interrupt requests */ DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); @@ -1406,16 +1423,18 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } + handle->state = kDSPI_Idle; + if (handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); /* Disable interrupt requests */ @@ -1429,7 +1448,9 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - uint8_t dummyPattern = DSPI_SLAVE_DUMMY_DATA; + assert(handle); + + uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; uint32_t dataReceived; uint32_t dataSend = 0; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h index 93da32fa2f7..abfc7707d75 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,27 +33,24 @@ #include "fsl_common.h" /*! - * @addtogroup dspi + * @addtogroup dspi_driver * @{ */ -/*! @file */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.0. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief DSPI driver version 2.2.0. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*@}*/ -/*! @name Dummy data */ -/*@{*/ -#define DSPI_MASTER_DUMMY_DATA (0x00U) /*!< Master dummy data used for tx if there is not txData. */ -#define DSPI_SLAVE_DUMMY_DATA (0x00U) /*!< Slave dummy data used for tx if there is not txData. */ -/*@}*/ +#ifndef DSPI_DUMMY_DATA +/*! @brief DSPI dummy data if there is no Tx data.*/ +#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */ +#endif /*! @brief Status for the DSPI driver.*/ enum _dspi_status @@ -61,7 +58,7 @@ enum _dspi_status kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out Of range. */ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ @@ -75,7 +72,7 @@ enum _dspi_flags kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All status above.*/ + SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ @@ -109,8 +106,9 @@ typedef enum _dspi_master_slave_mode } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in Modified Transfer Format. This field is valid - * only when CPHA bit in CTAR register is 0. + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid + * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point { @@ -169,36 +167,37 @@ typedef enum _dspi_clock_phase typedef enum _dspi_shift_direction { kDSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ - kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ + kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. + Shifting out of LSB is not supported for slave */ } dspi_shift_direction_t; /*! @brief DSPI delay type selection.*/ typedef enum _dspi_delay_type { kDSPI_PcsToSck = 1U, /*!< Pcs-to-SCK delay. */ - kDSPI_LastSckToPcs, /*!< Last SCK edge to Pcs delay. */ + kDSPI_LastSckToPcs, /*!< The last SCK edge to Pcs delay. */ kDSPI_BetweenTransfer /*!< Delay between transfers. */ } dspi_delay_type_t; /*! @brief DSPI Clock and Transfer Attributes Register (CTAR) selection.*/ typedef enum _dspi_ctar_selection { - kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode, note that CTAR0 and CTAR0_SLAVE are the + kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode; note that CTAR0 and CTAR0_SLAVE are the same register address. */ kDSPI_Ctar1 = 1U, /*!< CTAR1 selection option for master mode only. */ - kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only , note that some device do not support CTAR2. */ - kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only , note that some device do not support CTAR3. */ - kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only , note that some device do not support CTAR4. */ - kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only , note that some device do not support CTAR5. */ - kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only , note that some device do not support CTAR6. */ - kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only , note that some device do not support CTAR7. */ + kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only; note that some devices do not support CTAR2. */ + kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only; note that some devices do not support CTAR3. */ + kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only; note that some devices do not support CTAR4. */ + kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only; note that some devices do not support CTAR5. */ + kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only; note that some devices do not support CTAR6. */ + kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only; note that some devices do not support CTAR7. */ } dspi_ctar_selection_t; -#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro , internal used. */ -#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro , internal used. */ -#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro , internal used. */ -#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro , internal used. */ -/*! @brief Can use this enumeration for DSPI master transfer configFlags. */ +#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro; used internally. */ +#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro; used internally. */ +#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro; used internally. */ +#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI master transfer configFlags. */ enum _dspi_transfer_config_flag_for_master { kDSPI_MasterCtar0 = 0U << DSPI_MASTER_CTAR_SHIFT, /*!< DSPI master transfer use CTAR0 setting. */ @@ -217,20 +216,21 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Is PCS signal active after last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; -#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro , internal used. */ -#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro , internal used. */ -/*! @brief Can use this enum for DSPI slave transfer configFlags. */ +#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ +#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI slave transfer configFlags. */ enum _dspi_transfer_config_flag_for_slave { kDSPI_SlaveCtar0 = 0U << DSPI_SLAVE_CTAR_SHIFT, /*!< DSPI slave transfer use CTAR0 setting. */ /*!< DSPI slave can only use PCS0. */ }; -/*! @brief DSPI transfer state, which is used for DSPI transactional APIs' state machine. */ +/*! @brief DSPI transfer state, which is used for DSPI transactional API state machine. */ enum _dspi_transfer_state { kDSPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver. */ @@ -238,15 +238,15 @@ enum _dspi_transfer_state kDSPI_Error /*!< Transfer error. */ }; -/*! @brief DSPI master command date configuration used for SPIx_PUSHR.*/ +/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ bool isEndOfQueue; /*!< Signals that the current transfer is the last in the queue.*/ - bool clearTransferCount; /*!< Clears SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ + bool clearTransferCount; /*!< Clears the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ } dspi_command_data_config_t; /*! @brief DSPI master ctar configuration structure.*/ @@ -258,33 +258,33 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time with nanosecond , set to 0 sets the minimum - delay. It sets the boundary value if out of range that can be set.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time with nanosecond , set to 0 sets the - minimum delay.It sets the boundary value if out of range that can be - set.*/ - uint32_t betweenTransferDelayInNanoSec; /*!< After SCK delay time with nanosecond , set to 0 sets the minimum - delay.It sets the boundary value if out of range that can be set.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ + + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ } dspi_master_ctar_config_t; /*! @brief DSPI master configuration structure.*/ typedef struct _dspi_master_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_master_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - dspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs). */ - dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low. */ + dspi_which_pcs_t whichPcs; /*!< The desired Peripheral Chip Select (pcs). */ + dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< The desired PCS active high or low. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable . Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_master_config_t; @@ -294,23 +294,23 @@ typedef struct _dspi_slave_ctar_config uint32_t bitsPerFrame; /*!< Bits per frame, minimum 4, maximum 16.*/ dspi_clock_polarity_t cpol; /*!< Clock polarity. */ dspi_clock_phase_t cpha; /*!< Clock phase. */ - /*!< Slave only supports MSB , does not support LSB.*/ + /*!< Slave only supports MSB and does not support LSB.*/ } dspi_slave_ctar_config_t; /*! @brief DSPI slave configuration structure.*/ typedef struct _dspi_slave_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_slave_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_slave_config_t; @@ -357,7 +357,7 @@ typedef struct _dspi_transfer volatile size_t dataSize; /*!< Transfer bytes. */ uint32_t - configFlags; /*!< Transfer transfer configuration flags , set from _dspi_transfer_config_flag_for_master if the + configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer is used for slave.*/ } dspi_transfer_t; @@ -365,38 +365,39 @@ typedef struct _dspi_transfer /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ + volatile uint8_t state; /*!< DSPI transfer state, see _dspi_transfer_state.*/ dspi_master_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ }; -/*! @brief DSPI slave transfer handle structure used for transactional API. */ +/*! @brief DSPI slave transfer handle structure used for the transactional API. */ struct _dspi_slave_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ volatile uint8_t state; /*!< DSPI transfer state.*/ @@ -421,18 +422,18 @@ extern "C" { /*! * @brief Initializes the DSPI master. * - * This function initializes the DSPI master configuration. An example use case is as follows: + * This function initializes the DSPI master configuration. This is an example use case. * @code * dspi_master_config_t masterConfig; * masterConfig.whichCtar = kDSPI_Ctar0; - * masterConfig.ctarConfig.baudRate = 500000000; + * masterConfig.ctarConfig.baudRate = 500000000U; * masterConfig.ctarConfig.bitsPerFrame = 8; * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; - * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; * masterConfig.whichPcs = kDSPI_Pcs0; * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; * masterConfig.enableContinuousSCK = false; @@ -443,8 +444,8 @@ extern "C" { * @endcode * * @param base DSPI peripheral address. - * @param masterConfig Pointer to structure dspi_master_config_t. - * @param srcClock_Hz Module source input clock in Hertz + * @param masterConfig Pointer to the structure dspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz. */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz); @@ -452,8 +453,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u * @brief Sets the dspi_master_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). - * User may use the initialized structure unchanged in DSPI_MasterInit() or modify the structure - * before calling DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). * Example: * @code * dspi_master_config_t masterConfig; @@ -466,7 +467,7 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); /*! * @brief DSPI slave configuration. * - * This function initializes the DSPI slave configuration. An example use case is as follows: + * This function initializes the DSPI slave configuration. This is an example use case. * @code * dspi_slave_config_t slaveConfig; * slaveConfig->whichCtar = kDSPI_Ctar0; @@ -481,22 +482,22 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); * @endcode * * @param base DSPI peripheral address. - * @param slaveConfig Pointer to structure dspi_master_config_t. + * @param slaveConfig Pointer to the structure dspi_master_config_t. */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig); /*! - * @brief Sets the dspi_slave_config_t structure to default values. + * @brief Sets the dspi_slave_config_t structure to a default value. * * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). - * User may use the initialized structure unchanged in DSPI_SlaveInit(), or modify the structure - * before calling DSPI_SlaveInit(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. * @code * dspi_slave_config_t slaveConfig; * DSPI_SlaveGetDefaultConfig(&slaveConfig); * @endcode - * @param slaveConfig pointer to dspi_slave_config_t structure. + * @param slaveConfig Pointer to the dspi_slave_config_t structure. */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig); @@ -510,7 +511,7 @@ void DSPI_Deinit(SPI_Type *base); * @brief Enables the DSPI peripheral and sets the MCR MDIS to 0. * * @param base DSPI peripheral address. - * @param enable pass true to enable module, false to disable module. + * @param enable Pass true to enable module, false to disable module. */ static inline void DSPI_Enable(SPI_Type *base, bool enable) { @@ -536,7 +537,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! * @brief Gets the DSPI status flag state. * @param base DSPI peripheral address. - * @return The DSPI status(in SR register). + * @return DSPI status (in SR register). */ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) { @@ -549,13 +550,13 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the * desired status bit to clear. The list of status bits is defined in the dspi_status_and_interrupt_request_t. The * function uses these bit positions in its algorithm to clear the desired flag state. - * Example usage: + * This is an example. * @code * DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag); * @endcode * * @param base DSPI peripheral address. - * @param statusFlags The status flag , used from type dspi_flags. + * @param statusFlags The status flag used from the type dspi_flags. */ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) { @@ -574,15 +575,16 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! * @brief Enables the DSPI interrupts. * - * This function configures the various interrupt masks of the DSPI. The parameters are base and an interrupt mask. + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); @@ -594,7 +596,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) { @@ -613,13 +615,13 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! * @brief Enables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * DSPI_EnableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) { @@ -629,13 +631,13 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) /*! * @brief Disables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * SPI_DisableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask) { @@ -714,7 +716,7 @@ static inline bool DSPI_IsMaster(SPI_Type *base) /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. * - * This function sets the module to begin data transfer in either master or slave mode. + * This function sets the module to start data transfer in either master or slave mode. * * @param base DSPI peripheral address. */ @@ -723,9 +725,9 @@ static inline void DSPI_StartTransfer(SPI_Type *base) base->MCR &= ~SPI_MCR_HALT_MASK; } /*! - * @brief Stops (halts) DSPI transfers and sets HALT bit in MCR. + * @brief Stops DSPI transfers and sets the HALT bit in MCR. * - * This function stops data transfers in either master or slave mode. + * This function stops data transfers in either master or slave modes. * * @param base DSPI peripheral address. */ @@ -735,15 +737,15 @@ static inline void DSPI_StopTransfer(SPI_Type *base) } /*! - * @brief Enables (or disables) the DSPI FIFOs. + * @brief Enables or disables the DSPI FIFOs. * - * This function allows the caller to disable/enable the Tx and Rx FIFOs (independently). - * Note that to disable, the caller must pass in a logic 0 (false) for the particular FIFO configuration. To enable, - * the caller must pass in a logic 1 (true). + * This function allows the caller to disable/enable the Tx and Rx FIFOs independently. + * Note that to disable, pass in a logic 0 (false) for the particular FIFO configuration. To enable, + * pass in a logic 1 (true). * * @param base DSPI peripheral address. - * @param enableTxFifo Disables (false) the TX FIFO, else enables (true) the TX FIFO - * @param enableRxFifo Disables (false) the RX FIFO, else enables (true) the RX FIFO + * @param enableTxFifo Disables (false) the TX FIFO; Otherwise, enables (true) the TX FIFO + * @param enableRxFifo Disables (false) the RX FIFO; Otherwise, enables (true) the RX FIFO */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { @@ -755,8 +757,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en * @brief Flushes the DSPI FIFOs. * * @param base DSPI peripheral address. - * @param flushTxFifo Flushes (true) the Tx FIFO, else do not flush (false) the Tx FIFO - * @param flushRxFifo Flushes (true) the Rx FIFO, else do not flush (false) the Rx FIFO + * @param flushTxFifo Flushes (true) the Tx FIFO; Otherwise, does not flush (false) the Tx FIFO + * @param flushRxFifo Flushes (true) the Rx FIFO; Otherwise, does not flush (false) the Rx FIFO */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { @@ -766,13 +768,13 @@ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRx /*! * @brief Configures the DSPI peripheral chip select polarity simultaneously. - * For example, PCS0 and PCS1 set to active low and other PCS set to active high. Note that the number of + * For example, PCS0 and PCS1 are set to active low and other PCS is set to active high. Note that the number of * PCSs is specific to the device. * @code * DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow); @endcode * @param base DSPI peripheral address. - * @param mask The PCS polarity mask , can use the enum _dspi_pcs_polarity. + * @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity. */ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask) { @@ -801,19 +803,19 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, * @brief Manually configures the delay prescaler and scaler for a particular CTAR. * * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar - * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT)and scalar (DT). + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes the delay to configure along with the prescaler and scaler value. - * This allows the user to directly set the prescaler/scaler values if they have pre-calculated them or if they simply - * wish to manually increment either value. + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. * * @param base DSPI peripheral address. * @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. * @param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). * @param scaler The scaler delay value (can be any integer between 0 to 15). - * @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * @param whichDelay The desired delay to configure; must be of type dspi_delay_type_t */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay); @@ -821,19 +823,19 @@ void DSPI_MasterSetDelayScaler( /*! * @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. * - * This function calculates the values for: + * This function calculates the values for the following. * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or * After SCK delay pre-scalar (PASC) and scalar (ASC), or - * Delay after transfer pre-scalar (PDT)and scalar (DT). + * Delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes which delay they want to configure along with the desired delay value in nanoseconds. The function - * calculates the values needed for the prescaler and scaler and returning the actual calculated delay as an exact + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact * delay match may not be possible. In this case, the closest match is calculated without going below the desired * delay value input. * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum - * supported delay is returned. The higher level peripheral driver alerts the user of an out of range delay + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay * input. * * @param base DSPI peripheral address. @@ -853,11 +855,11 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, * @brief Writes data into the data buffer for master mode. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_data_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -869,7 +871,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, @endcode * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) @@ -883,14 +885,14 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config * @brief Sets the dspi_command_data_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). - * User may use the initialized structure unchanged in DSPI_MasterWrite_xx() or modify the structure - * before calling DSPI_MasterWrite_xx(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. * @code * dspi_command_data_config_t command; * DSPI_GetDefaultDataCommandConfig(&command); * @endcode - * @param command pointer to dspi_command_data_config_t structure. + * @param command Pointer to the dspi_command_data_config_t structure. */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); @@ -898,11 +900,11 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * @brief Writes data into the data buffer master mode and waits till complete to return. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -915,10 +917,10 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, - * receive data is available when transmit completes. + * the received data is available when the transmit completes. * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data); @@ -933,10 +935,10 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co * improve performance in cases where the command structure is constant. For example, the user calls this function * before starting a transfer to generate the command word. When they are ready to transmit the data, they OR * this formatted command word with the desired data to transmit. This process increases transmit performance when - * compared to calling send functions such as DSPI_HAL_WriteDataMastermode which format the command word each time a + * compared to calling send functions, such as DSPI_HAL_WriteDataMastermode, which format the command word each time a * data word is to be sent. * - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @return The command word formatted to the PUSHR data register bit field. */ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t *command) @@ -949,24 +951,25 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t /*! * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data - * buffer, master mode and waits till complete to return. + * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command info then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total +* 32-bit word * as the data to send. - * The command portion provides characteristics of the data such as the optional continuous chip select operation -* between - * transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the +* desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: * @code * dataWord = <16-bit command> | <16-bit data>; - * DSPI_HAL_WriteCommandDataMastermodeBlocking(base, dataWord); + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); * @endcode * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). - * Because the SPI is a synchronous protocol, the receive data is available when transmit completes. + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. * * For a blocking polling transfer, see methods below. * Option 1: @@ -985,7 +988,7 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); * * @param base DSPI peripheral address. - * @param data The data word (command and data combined) to be sent + * @param data The data word (command and data combined) to be sent. */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data); @@ -1024,6 +1027,14 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} */ @@ -1037,13 +1048,13 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) /*! * @brief Initializes the DSPI master handle. * - * This function initializes the DSPI handle which can be used for other DSPI transactional APIs. Usually, for a + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_handle_t. - * @param callback dspi callback. - * @param userData callback function parameter. + * @param callback DSPI callback. + * @param userData Callback function parameter. */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, @@ -1053,12 +1064,11 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, /*! * @brief DSPI master transfer data using polling. * - * This function transfers data with polling. This is a blocking function, which does not return until all transfers - * have been - * completed. + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. * * @param base DSPI peripheral base address. - * @param transfer pointer to dspi_transfer_t structure. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); @@ -1067,12 +1077,11 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); * @brief DSPI master transfer data using interrupts. * * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all - data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -1083,19 +1092,19 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha * This function gets the master transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count); /*! - * @brief DSPI master aborts transfer using an interrupt. + * @brief DSPI master aborts a transfer using an interrupt. * * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); @@ -1105,7 +1114,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); @@ -1115,10 +1124,10 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * @param handle DSPI handle pointer to dspi_slave_handle_t. + * @param handle DSPI handle pointer to the dspi_slave_handle_t. * @param base DSPI peripheral base address. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData Callback function parameter. */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, @@ -1129,12 +1138,11 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, * @brief DSPI slave transfers data using an interrupt. * * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all - * data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer); @@ -1145,8 +1153,8 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand * This function gets the slave transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count); @@ -1154,10 +1162,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, /*! * @brief DSPI slave aborts a transfer using an interrupt. * - * This function aborts transfer using an interrupt. + * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); @@ -1167,7 +1175,7 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c index 4d9e129ff24..ef0d15174f5 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_dspi_edma.h" @@ -57,7 +57,7 @@ typedef struct _dspi_slave_edma_private_handle ***********************************************************************************************************************/ /*! * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. +* This is not a public API. */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, @@ -66,7 +66,7 @@ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, /*! * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. +* This is not a public API. */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, @@ -102,6 +102,9 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaIntermediaryToTxRegHandle) { assert(handle); + assert(edmaRxRegToRxDataHandle); + assert(edmaTxDataToIntermediaryHandle); + assert(edmaIntermediaryToTxRegHandle); /* Zero the handle. */ memset(handle, 0, sizeof(*handle)); @@ -121,7 +124,8 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If the transfer count is zero, then return immediately.*/ if (transfer->dataSize == 0) @@ -141,9 +145,11 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand return kStatus_DSPI_Busy; } + handle->state = kDSPI_Busy; + uint32_t instance = DSPI_GetInstance(base); uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + uint8_t dummyData = DSPI_DUMMY_DATA; uint8_t dataAlreadyFed = 0; uint8_t dataFedMax = 2; @@ -156,9 +162,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigB; edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_MASTER_DUMMY_DATA << 8) | DSPI_MASTER_DUMMY_DATA; - - handle->state = kDSPI_Busy; + handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); @@ -174,6 +178,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); + commandStruct.isEndOfQueue = true; commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); @@ -193,39 +198,70 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->remainingReceiveByteCount = transfer->dataSize; handle->totalByteCount = transfer->dataSize; - /* this limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + if (handle->bitsPerFrame > 8) { - if (transfer->dataSize > 1022) + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + { + handle->state = kDSPI_Idle; + return kStatus_InvalidArgument; + } + DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ @@ -243,22 +279,16 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; /* increment to next data byte */ + wordToSend |= (unsigned)(*(handle->txData)) << 8U; } else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else /* For all words except the last word , frame > 8bits */ { @@ -291,6 +321,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (handle->remainingSendByteCount == 1) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -315,21 +346,13 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; + wordToSend |= (unsigned)(*(handle->txData)) << 8U; } else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; } handle->remainingSendByteCount = 0; base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; @@ -347,7 +370,6 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; } handle->remainingSendByteCount -= 2; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; @@ -404,7 +426,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); transferConfigA.srcAddr = (uint32_t)rxAddr; @@ -435,6 +457,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigA.minorLoopBytes = 2; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = transferConfigA.minorLoopBytes; + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, &transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, @@ -443,9 +469,82 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->remainingSendByteCount > 0) + /*Calculate the last data : handle->lastCommand*/ + if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || + ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) + { + if (handle->txData) + { + uint32_t bufferIndex = 0; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8) + { + bufferIndex = handle->remainingSendByteCount - 1; + } + else + { + bufferIndex = handle->remainingSendByteCount - 2; + } + } + else + { + bufferIndex = handle->remainingSendByteCount; + } + + if (handle->bitsPerFrame <= 8) + { + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + } + else + { + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | + ((uint32_t)handle->txData[bufferIndex - 1] << 8) | + handle->txData[bufferIndex - 2]; + } + } + else + { + if (handle->bitsPerFrame <= 8) + { + wordToSend = dummyData; + } + else + { + wordToSend = ((uint32_t)dummyData << 8) | dummyData; + } + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + } + } + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); + } + + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) || + ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { if (handle->txData) { @@ -470,8 +569,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2; } else { @@ -486,8 +584,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigB.minorLoopBytes = 2; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2; } else { @@ -497,74 +594,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + } + } + else + { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); } /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) - { - uint32_t bufferIndex = 0; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - if (handle->bitsPerFrame <= 8) - { - bufferIndex = handle->remainingSendByteCount - 1; - } - else - { - bufferIndex = handle->remainingSendByteCount - 2; - } - } - else - { - bufferIndex = handle->remainingSendByteCount; - } - - if (handle->bitsPerFrame <= 8) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; - } - else - { - if (handle->isThereExtraByte) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 2] | - ((uint32_t)dummyData << 8); - } - else - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; - } - } - } - else - { - if (handle->bitsPerFrame <= 8) - { - wordToSend = dummyData; - } - else - { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - } - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - } - } + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) { transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); transferConfigC.destAddr = (uint32_t)txAddr; @@ -580,7 +636,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { transferConfigC.srcAddr = (uint32_t)(&(handle->command)); transferConfigC.destAddr = (uint32_t)txAddr; @@ -590,18 +647,28 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigC.srcOffset = 0; transferConfigC.destOffset = 0; transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (handle->bitsPerFrame <= 8) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + } + else + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); } - EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } @@ -673,20 +740,15 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand &preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ + to prepare the next 32bits data (txData to handle->command) */ if (handle->remainingSendByteCount > 1) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } @@ -699,12 +761,6 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->isThereExtraByte) - { - EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); - } - EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); @@ -723,37 +779,28 @@ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(edmaHandle); + assert(g_dspiEdmaPrivateHandle); + dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } + dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; if (dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); @@ -783,7 +830,8 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; @@ -798,6 +846,8 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToTxRegHandle) { assert(handle); + assert(edmaRxRegToRxDataHandle); + assert(edmaTxDataToTxRegHandle); /* Zero the handle. */ memset(handle, 0, sizeof(*handle)); @@ -816,7 +866,8 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If send/receive length is zero */ if (transfer->dataSize == 0) @@ -836,7 +887,7 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle return kStatus_DSPI_Busy; } - edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU)); + handle->state = kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; @@ -846,54 +897,51 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } - if ((handle->bitsPerFrame > 8) && (transfer->dataSize < 2)) + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) { + handle->state = kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ handle->txData = transfer->txData; handle->rxData = transfer->rxData; handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; handle->totalByteCount = transfer->dataSize; - handle->errorCount = 0; - - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_SLAVE_DUMMY_DATA; + uint8_t dummyData = DSPI_DUMMY_DATA; uint8_t dataAlreadyFed = 0; uint8_t dataFedMax = 2; @@ -929,16 +977,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ - if ((handle->remainingSendByteCount == 2) && (handle->isThereExtraByte)) - { - wordToSend |= (unsigned)(dummyData) << 8U; - ++handle->txData; /* Increment to next data byte */ - } - else - { - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - ++handle->txData; /* Increment to next data byte */ - } + + wordToSend |= (unsigned)(*(handle->txData)) << 8U; + ++handle->txData; /* Increment to next data byte */ } else { @@ -1025,6 +1066,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle transferConfigA.minorLoopBytes = 2; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = transferConfigA.minorLoopBytes; + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, &transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, @@ -1036,98 +1081,47 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - /*If there is extra byte , it would use the */ - if (handle->isThereExtraByte) - { - if (handle->txData) - { - handle->txLastData = - handle->txData[handle->remainingSendByteCount - 2] | ((uint32_t)DSPI_SLAVE_DUMMY_DATA << 8); - } - else - { - handle->txLastData = DSPI_SLAVE_DUMMY_DATA | ((uint32_t)DSPI_SLAVE_DUMMY_DATA << 8); - } - transferConfigC.srcAddr = (uint32_t)(&(handle->txLastData)); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; - - EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); - } + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destOffset = 0; - /*Set another transferConfigC*/ - if ((handle->isThereExtraByte) && (handle->remainingSendByteCount == 2)) + if (handle->txData) { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcOffset = 1; } else { - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.destOffset = 0; - - if (handle->txData) - { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); - transferConfigC.srcOffset = 1; - } - else - { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) - { - handle->txBuffIfNull = DSPI_SLAVE_DUMMY_DATA; - } - else - { - handle->txBuffIfNull = (DSPI_SLAVE_DUMMY_DATA << 8) | DSPI_SLAVE_DUMMY_DATA; - } - } - - transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcOffset = 0; if (handle->bitsPerFrame <= 8) { - transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + handle->txBuffIfNull = DSPI_DUMMY_DATA; } else { - transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - if (handle->isThereExtraByte) - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; - } + handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; } + } - if (handle->isThereExtraByte) - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, softwareTCD); - EDMA_EnableAutoStopRequest(handle->edmaTxDataToTxRegHandle->base, - handle->edmaTxDataToTxRegHandle->channel, false); - } - else - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); - } + transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); + if (handle->bitsPerFrame <= 8) + { + transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; } + else + { + transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; + } + + EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, + &transferConfigC, NULL); + + EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); @@ -1195,37 +1189,28 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(edmaHandle); + assert(g_dspiEdmaPrivateHandle); + dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } + dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; if (dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); @@ -1254,7 +1239,8 @@ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h index 326b7ee442a..23e29ce2983 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,8 +37,6 @@ * @{ */ -/*! @file */ - /*********************************************************************************************************************** * Definitions **********************************************************************************************************************/ @@ -57,9 +55,9 @@ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI master. + * @param handle A pointer to the handle for the DSPI master. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, dspi_master_edma_handle_t *handle, @@ -69,38 +67,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI slave. + * @param handle A pointer to the handle for the DSPI slave. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData); -/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */ +/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */ struct _dspi_master_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/ + + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ - dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ @@ -111,33 +110,30 @@ struct _dspi_master_edma_handle edma_tcd_t dspiSoftwareTCD[2]; /*!CR; tmpreg &= ~(DMA_CR_ERCA_MASK | DMA_CR_HOE_MASK | DMA_CR_CLM_MASK | DMA_CR_EDBG_MASK); @@ -134,8 +138,10 @@ void EDMA_Init(DMA_Type *base, const edma_config_t *config) void EDMA_Deinit(DMA_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate EDMA periphral clock */ CLOCK_DisableClock(s_edmaClockName[EDMA_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void EDMA_GetDefaultConfig(edma_config_t *config) @@ -409,46 +415,32 @@ void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask) } } -uint32_t EDMA_GetRemainingBytes(DMA_Type *base, uint32_t channel) +uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel) { assert(channel < FSL_FEATURE_EDMA_MODULE_CHANNEL); - uint32_t nbytes = 0; - uint32_t remainingBytes = 0; + uint32_t remainingCount = 0; if (DMA_CSR_DONE_MASK & base->TCD[channel].CSR) { - remainingBytes = 0; + remainingCount = 0; } else { - /* Calculate the nbytes */ - if (base->TCD[channel].NBYTES_MLOFFYES & (DMA_NBYTES_MLOFFYES_SMLOE_MASK | DMA_NBYTES_MLOFFYES_DMLOE_MASK)) - { - nbytes = (base->TCD[channel].NBYTES_MLOFFYES & DMA_NBYTES_MLOFFYES_NBYTES_MASK) >> - DMA_NBYTES_MLOFFYES_NBYTES_SHIFT; - } - else - { - nbytes = - (base->TCD[channel].NBYTES_MLOFFNO & DMA_NBYTES_MLOFFNO_NBYTES_MASK) >> DMA_NBYTES_MLOFFNO_NBYTES_SHIFT; - } /* Calculate the unfinished bytes */ if (base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_ELINK_MASK) { - remainingBytes = ((base->TCD[channel].CITER_ELINKYES & DMA_CITER_ELINKYES_CITER_MASK) >> - DMA_CITER_ELINKYES_CITER_SHIFT) * - nbytes; + remainingCount = + (base->TCD[channel].CITER_ELINKYES & DMA_CITER_ELINKYES_CITER_MASK) >> DMA_CITER_ELINKYES_CITER_SHIFT; } else { - remainingBytes = - ((base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_CITER_MASK) >> DMA_CITER_ELINKNO_CITER_SHIFT) * - nbytes; + remainingCount = + (base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_CITER_MASK) >> DMA_CITER_ELINKNO_CITER_SHIFT; } } - return remainingBytes; + return remainingCount; } uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel) @@ -497,14 +489,19 @@ void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel) uint32_t channelIndex; edma_tcd_t *tcdRegs; + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + handle->base = base; handle->channel = channel; /* Get the DMA instance number */ edmaInstance = EDMA_GetInstance(base); channelIndex = (edmaInstance * FSL_FEATURE_EDMA_MODULE_CHANNEL) + channel; s_EDMAHandle[channelIndex] = handle; + /* Enable NVIC interrupt */ - EnableIRQ(s_edmaIRQNumber[channelIndex]); + EnableIRQ(s_edmaIRQNumber[edmaInstance][channel]); + /* Reset TCD registers to zero. Unlike the EDMA_TcdReset(DREQ will be set), CSR will be 0. Because in order to suit EDMA busy check mechanism in @@ -558,8 +555,8 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, assert(config != NULL); assert(srcAddr != NULL); assert(destAddr != NULL); - assert(srcWidth == 1U || srcWidth == 2U || srcWidth == 4U || srcWidth == 16U || srcWidth == 32U); - assert(destWidth == 1U || destWidth == 2U || destWidth == 4U || destWidth == 16U || destWidth == 32U); + assert((srcWidth == 1U) || (srcWidth == 2U) || (srcWidth == 4U) || (srcWidth == 16U) || (srcWidth == 32U)); + assert((destWidth == 1U) || (destWidth == 2U) || (destWidth == 4U) || (destWidth == 16U) || (destWidth == 32U)); assert(transferBytes % bytesEachRequest == 0); config->destAddr = (uint32_t)destAddr; @@ -825,11 +822,11 @@ void EDMA_HandleIRQ(edma_handle_t *handle) /* Clear EDMA interrupt flag */ handle->base->CINT = handle->channel; - if (handle->tcdPool == NULL) + if ((handle->tcdPool == NULL) && (handle->callback != NULL)) { (handle->callback)(handle, handle->userData, true, 0); } - else /* Use the TCD queue. */ + else /* Use the TCD queue. Please refer to the API descriptions in the eDMA header file for detailed information. */ { uint32_t sga = handle->base->TCD[handle->channel].DLAST_SGA; uint32_t sga_index; @@ -839,19 +836,19 @@ void EDMA_HandleIRQ(edma_handle_t *handle) /* Check if transfer is already finished. */ transfer_done = ((handle->base->TCD[handle->channel].CSR & DMA_CSR_DONE_MASK) != 0); - /* Get the offset of the current transfer TCD blcoks. */ + /* Get the offset of the next transfer TCD blcoks to be loaded into the eDMA engine. */ sga -= (uint32_t)handle->tcdPool; - /* Get the index of the current transfer TCD blcoks. */ + /* Get the index of the next transfer TCD blcoks to be loaded into the eDMA engine. */ sga_index = sga / sizeof(edma_tcd_t); /* Adjust header positions. */ if (transfer_done) { - /* New header shall point to the next TCD (current one is already finished) */ + /* New header shall point to the next TCD to be loaded (current one is already finished) */ new_header = sga_index; } else { - /* New header shall point to this descriptor (not finished yet) */ + /* New header shall point to this descriptor currently loaded (not finished yet) */ new_header = sga_index ? sga_index - 1U : handle->tcdSize - 1U; } /* Calculate the number of finished TCDs */ @@ -863,7 +860,7 @@ void EDMA_HandleIRQ(edma_handle_t *handle) } else { - /* Internal error occurs. */ + /* No TCD in the memory are going to be loaded or internal error occurs. */ tcds_done = 0; } } @@ -875,9 +872,9 @@ void EDMA_HandleIRQ(edma_handle_t *handle) tcds_done += handle->tcdSize; } } - /* Advance header to the point beyond the last finished TCD block. */ + /* Advance header which points to the TCD to be loaded into the eDMA engine from memory. */ handle->header = new_header; - /* Release TCD blocks. */ + /* Release TCD blocks. tcdUsed is the TCD number which can be used/loaded in the memory pool. */ handle->tcdUsed -= tcds_done; /* Invoke callback function. */ if (handle->callback) @@ -937,12 +934,260 @@ void DMA0_37_DriverIRQHandler(void) EDMA_HandleIRQ(s_EDMAHandle[7]); } } + +#if defined(DMA1) +void DMA1_04_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA1_15_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA1_26_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA1_37_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} +#endif #endif /* 8 channels (Shared) */ +/* 16 channels (Shared): K32H844P */ +#if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 16U + +void DMA0_08_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[0]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } +} + +void DMA0_19_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[1]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } +} + +void DMA0_210_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[2]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } +} + +void DMA0_311_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[3]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } +} + +void DMA0_412_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[4]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA0_513_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[5]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA0_614_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[6]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA0_715_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[7]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} + +#if defined(DMA1) +void DMA1_08_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[16]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[24]); + } +} + +void DMA1_19_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[17]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[25]); + } +} + +void DMA1_210_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[18]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[26]); + } +} + +void DMA1_311_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[19]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[27]); + } +} + +void DMA1_412_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[20]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[28]); + } +} + +void DMA1_513_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[21]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[29]); + } +} + +void DMA1_614_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[22]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[30]); + } +} + +void DMA1_715_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[23]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[31]); + } +} +#endif +#endif /* 16 channels (Shared) */ + /* 32 channels (Shared): k80 */ #if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 32U -void DMA0_DMA16_IRQHandler(void) +void DMA0_DMA16_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) { @@ -954,7 +1199,7 @@ void DMA0_DMA16_IRQHandler(void) } } -void DMA1_DMA17_IRQHandler(void) +void DMA1_DMA17_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) { @@ -966,7 +1211,7 @@ void DMA1_DMA17_IRQHandler(void) } } -void DMA2_DMA18_IRQHandler(void) +void DMA2_DMA18_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) { @@ -978,7 +1223,7 @@ void DMA2_DMA18_IRQHandler(void) } } -void DMA3_DMA19_IRQHandler(void) +void DMA3_DMA19_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) { @@ -990,7 +1235,7 @@ void DMA3_DMA19_IRQHandler(void) } } -void DMA4_DMA20_IRQHandler(void) +void DMA4_DMA20_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) { @@ -1002,7 +1247,7 @@ void DMA4_DMA20_IRQHandler(void) } } -void DMA5_DMA21_IRQHandler(void) +void DMA5_DMA21_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) { @@ -1014,7 +1259,7 @@ void DMA5_DMA21_IRQHandler(void) } } -void DMA6_DMA22_IRQHandler(void) +void DMA6_DMA22_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) { @@ -1026,7 +1271,7 @@ void DMA6_DMA22_IRQHandler(void) } } -void DMA7_DMA23_IRQHandler(void) +void DMA7_DMA23_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) { @@ -1038,7 +1283,7 @@ void DMA7_DMA23_IRQHandler(void) } } -void DMA8_DMA24_IRQHandler(void) +void DMA8_DMA24_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) { @@ -1050,7 +1295,7 @@ void DMA8_DMA24_IRQHandler(void) } } -void DMA9_DMA25_IRQHandler(void) +void DMA9_DMA25_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) { @@ -1062,7 +1307,7 @@ void DMA9_DMA25_IRQHandler(void) } } -void DMA10_DMA26_IRQHandler(void) +void DMA10_DMA26_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) { @@ -1074,7 +1319,7 @@ void DMA10_DMA26_IRQHandler(void) } } -void DMA11_DMA27_IRQHandler(void) +void DMA11_DMA27_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) { @@ -1086,7 +1331,7 @@ void DMA11_DMA27_IRQHandler(void) } } -void DMA12_DMA28_IRQHandler(void) +void DMA12_DMA28_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) { @@ -1098,7 +1343,7 @@ void DMA12_DMA28_IRQHandler(void) } } -void DMA13_DMA29_IRQHandler(void) +void DMA13_DMA29_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) { @@ -1110,7 +1355,7 @@ void DMA13_DMA29_IRQHandler(void) } } -void DMA14_DMA30_IRQHandler(void) +void DMA14_DMA30_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) { @@ -1122,7 +1367,7 @@ void DMA14_DMA30_IRQHandler(void) } } -void DMA15_DMA31_IRQHandler(void) +void DMA15_DMA31_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) { @@ -1135,6 +1380,202 @@ void DMA15_DMA31_IRQHandler(void) } #endif /* 32 channels (Shared) */ +/* 32 channels (Shared): MCIMX7U5_M4 */ +#if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 32U + +void DMA0_0_4_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[0]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[4]); + } +} + +void DMA0_1_5_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[1]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[5]); + } +} + +void DMA0_2_6_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[2]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[6]); + } +} + +void DMA0_3_7_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[3]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[7]); + } +} + +void DMA0_8_12_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA0_9_13_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA0_10_14_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA0_11_15_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} + +void DMA0_16_20_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 16U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[16]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 20U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[20]); + } +} + +void DMA0_17_21_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 17U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[17]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 21U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[21]); + } +} + +void DMA0_18_22_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 18U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[18]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 22U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[22]); + } +} + +void DMA0_19_23_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 19U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[19]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 23U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[23]); + } +} + +void DMA0_24_28_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 24U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[24]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 28U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[28]); + } +} + +void DMA0_25_29_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 25U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[25]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 29U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[29]); + } +} + +void DMA0_26_30_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 26U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[26]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 30U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[30]); + } +} + +void DMA0_27_31_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 27U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[27]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 31U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[31]); + } +} +#endif /* 32 channels (Shared): MCIMX7U5 */ + /* 4 channels (No Shared): kv10 */ #if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL > 0 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h index ca9632e247a..a97622d7e1e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_EDMA_H_ #define _FSL_EDMA_H_ @@ -34,11 +34,10 @@ #include "fsl_common.h" /*! - * @addtogroup edma_driver + * @addtogroup edma * @{ */ -/*! @file */ /******************************************************************************* * Definitions ******************************************************************************/ @@ -46,7 +45,7 @@ /*! @name Driver version */ /*@{*/ /*! @brief eDMA driver version */ -#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ +#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1. */ /*@}*/ /*! @brief Compute the offset unit from DCHPRI3 */ @@ -78,28 +77,28 @@ typedef enum _edma_modulo kEDMA_Modulo128bytes, /*!< Circular buffer size is 128 bytes. */ kEDMA_Modulo256bytes, /*!< Circular buffer size is 256 bytes. */ kEDMA_Modulo512bytes, /*!< Circular buffer size is 512 bytes. */ - kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1K bytes. */ - kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2K bytes. */ - kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4K bytes. */ - kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8K bytes. */ - kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16K bytes. */ - kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32K bytes. */ - kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64K bytes. */ - kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128K bytes. */ - kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256K bytes. */ - kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512K bytes. */ - kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1M bytes. */ - kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2M bytes. */ - kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4M bytes. */ - kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8M bytes. */ - kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16M bytes. */ - kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32M bytes. */ - kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64M bytes. */ - kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128M bytes. */ - kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256M bytes. */ - kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512M bytes. */ - kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1G bytes. */ - kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2G bytes. */ + kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1 K bytes. */ + kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2 K bytes. */ + kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4 K bytes. */ + kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8 K bytes. */ + kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16 K bytes. */ + kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32 K bytes. */ + kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64 K bytes. */ + kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128 K bytes. */ + kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256 K bytes. */ + kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512 K bytes. */ + kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1 M bytes. */ + kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2 M bytes. */ + kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4 M bytes. */ + kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8 M bytes. */ + kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16 M bytes. */ + kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32 M bytes. */ + kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64 M bytes. */ + kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128 M bytes. */ + kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256 M bytes. */ + kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512 M bytes. */ + kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1 G bytes. */ + kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2 G bytes. */ } edma_modulo_t; /*! @brief Bandwidth control */ @@ -143,7 +142,7 @@ enum _edma_error_status_flags #if defined(FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT) && FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT > 1 kEDMA_GroupPriorityErrorFlag = DMA_ES_GPE_MASK, /*!< Group priority is not unique. */ #endif - kEDMA_ValidFlag = DMA_ES_VLD_MASK, /*!< No error occurred, this bit will be 0, otherwise be 1 */ + kEDMA_ValidFlag = DMA_ES_VLD_MASK, /*!< No error occurred, this bit is 0. Otherwise, it is 1. */ }; /*! @brief eDMA interrupt source */ @@ -178,7 +177,7 @@ typedef struct _edma_config the link channel is itself. */ bool enableHaltOnError; /*!< Enable (true) transfer halt on error. Any error causes the HALT bit to set. Subsequently, all service requests are ignored until the HALT bit is cleared.*/ - bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method, or fixed priority + bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method or fixed priority arbitration is used for channel selection */ bool enableDebugMode; /*!< Enable(true) eDMA debug mode. When in debug mode, the eDMA stalls the start of a new channel. Executing channels are allowed to complete. */ @@ -212,15 +211,15 @@ typedef struct _edma_transfer_config form the next-state value as each source read is completed. */ int16_t destOffset; /*!< Sign-extended offset applied to the current destination address to form the next-state value as each destination write is completed. */ - uint16_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/ + uint32_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/ uint32_t majorLoopCounts; /*!< Major loop iteration count. */ } edma_transfer_config_t; /*! @brief eDMA channel priority configuration */ typedef struct _edma_channel_Preemption_config { - bool enableChannelPreemption; /*!< If true: channel can be suspended by other channel with higher priority */ - bool enablePreemptAbility; /*!< If true: channel can suspend other channel with low priority */ + bool enableChannelPreemption; /*!< If true: a channel can be suspended by other channel with higher priority */ + bool enablePreemptAbility; /*!< If true: a channel can suspend other channel with low priority */ uint8_t channelPriority; /*!< Channel priority */ } edma_channel_Preemption_config_t; @@ -229,14 +228,14 @@ typedef struct _edma_minor_offset_config { bool enableSrcMinorOffset; /*!< Enable(true) or Disable(false) source minor loop offset. */ bool enableDestMinorOffset; /*!< Enable(true) or Disable(false) destination minor loop offset. */ - uint32_t minorOffset; /*!< Offset for minor loop mapping. */ + uint32_t minorOffset; /*!< Offset for a minor loop mapping. */ } edma_minor_offset_config_t; /*! * @brief eDMA TCD. * * This structure is same as TCD register which is described in reference manual, - * and is used to configure scatter/gather feature as a next hardware TCD. + * and is used to configure the scatter/gather feature as a next hardware TCD. */ typedef struct _edma_tcd { @@ -256,20 +255,21 @@ typedef struct _edma_tcd /*! @brief Callback for eDMA */ struct _edma_handle; -/*! @brief Define Callback function for eDMA. */ +/*! @brief Define callback function for eDMA. */ typedef void (*edma_callback)(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds); /*! @brief eDMA transfer handle structure */ typedef struct _edma_handle { - edma_callback callback; /*!< Callback function for major count exhausted. */ - void *userData; /*!< Callback function parameter. */ - DMA_Type *base; /*!< eDMA peripheral base address. */ - edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */ - uint8_t channel; /*!< eDMA channel number. */ - volatile int8_t header; /*!< The first TCD index. */ - volatile int8_t tail; /*!< The last TCD index. */ - volatile int8_t tcdUsed; /*!< The number of used TCD slots. */ + edma_callback callback; /*!< Callback function for major count exhausted. */ + void *userData; /*!< Callback function parameter. */ + DMA_Type *base; /*!< eDMA peripheral base address. */ + edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */ + uint8_t channel; /*!< eDMA channel number. */ + volatile int8_t header; /*!< The first TCD index. Should point to the next TCD to be loaded into the eDMA engine. */ + volatile int8_t tail; /*!< The last TCD index. Should point to the next TCD to be stored into the memory pool. */ + volatile int8_t tcdUsed; /*!< The number of used TCD slots. Should reflect the number of TCDs can be used/loaded in + the memory. */ volatile int8_t tcdSize; /*!< The total number of TCD slots in the queue. */ uint8_t flags; /*!< The status of the current channel. */ } edma_handle_t; @@ -282,24 +282,24 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name eDMA initialization and De-initialization + * @name eDMA initialization and de-initialization * @{ */ /*! - * @brief Initializes eDMA peripheral. + * @brief Initializes the eDMA peripheral. * - * This function ungates the eDMA clock and configure eDMA peripheral according + * This function ungates the eDMA clock and configures the eDMA peripheral according * to the configuration structure. * * @param base eDMA peripheral base address. - * @param config Pointer to configuration structure, see "edma_config_t". - * @note This function enable the minor loop map feature. + * @param config A pointer to the configuration structure, see "edma_config_t". + * @note This function enables the minor loop map feature. */ void EDMA_Init(DMA_Type *base, const edma_config_t *config); /*! - * @brief Deinitializes eDMA peripheral. + * @brief Deinitializes the eDMA peripheral. * * This function gates the eDMA clock. * @@ -310,8 +310,8 @@ void EDMA_Deinit(DMA_Type *base); /*! * @brief Gets the eDMA default configuration structure. * - * This function sets the configuration structure to a default value. - * The default configuration is set to the following value: + * This function sets the configuration structure to default values. + * The default configuration is set to the following values. * @code * config.enableContinuousLinkMode = false; * config.enableHaltOnError = true; @@ -319,7 +319,7 @@ void EDMA_Deinit(DMA_Type *base); * config.enableDebugMode = false; * @endcode * - * @param config Pointer to eDMA configuration structure. + * @param config A pointer to the eDMA configuration structure. */ void EDMA_GetDefaultConfig(edma_config_t *config); @@ -330,22 +330,22 @@ void EDMA_GetDefaultConfig(edma_config_t *config); */ /*! - * @brief Sets all TCD registers to a default value. + * @brief Sets all TCD registers to default values. * - * This function sets TCD registers for this channel to default value. + * This function sets TCD registers for this channel to default values. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @note This function must not be called while the channel transfer is on-going, - * or it will case unpredicated results. - * @note This function will enable auto stop request feature. + * @note This function must not be called while the channel transfer is ongoing + * or it causes unpredictable results. + * @note This function enables the auto stop request feature. */ void EDMA_ResetChannel(DMA_Type *base, uint32_t channel); /*! * @brief Configures the eDMA transfer attribute. * - * This function configure the transfer attribute, including source address, destination address, + * This function configures the transfer attribute, including source address, destination address, * transfer size, address offset, and so on. It also configures the scatter gather feature if the * user supplies the TCD address. * Example: @@ -361,11 +361,11 @@ void EDMA_ResetChannel(DMA_Type *base, uint32_t channel); * @param base eDMA peripheral base address. * @param channel eDMA channel number. * @param config Pointer to eDMA transfer configuration structure. - * @param nextTcd Point to TCD structure. It can be NULL if user + * @param nextTcd Point to TCD structure. It can be NULL if users * do not want to enable scatter/gather feature. - * @note If nextTcd is not NULL, it means scatter gather feature will be enabled. - * And DREQ bit will be cleared in the previous transfer configuration which - * will be set in eDMA_ResetChannel. + * @note If nextTcd is not NULL, it means scatter gather feature is enabled + * and DREQ bit is cleared in the previous transfer configuration, which + * is set in the eDMA_ResetChannel. */ void EDMA_SetTransferConfig(DMA_Type *base, uint32_t channel, @@ -375,12 +375,12 @@ void EDMA_SetTransferConfig(DMA_Type *base, /*! * @brief Configures the eDMA minor offset feature. * - * Minor offset means signed-extended value added to source address or destination + * The minor offset means that the signed-extended value is added to the source address or destination * address after each minor loop. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param config Pointer to Minor offset configuration structure. + * @param config A pointer to the minor offset configuration structure. */ void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config); @@ -391,7 +391,7 @@ void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_mino * * @param base eDMA peripheral base address. * @param channel eDMA channel number - * @param config Pointer to channel preemption configuration structure. + * @param config A pointer to the channel preemption configuration structure. */ static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base, uint32_t channel, @@ -408,30 +408,31 @@ static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base, /*! * @brief Sets the channel link for the eDMA transfer. * - * This function configures minor link or major link mode. The minor link means that the channel link is - * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is exhausted. + * This function configures either the minor link or the major link mode. The minor link means that the channel link is + * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is + * exhausted. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param type Channel link type, it can be one of: + * @param type A channel link type, which can be one of the following: * @arg kEDMA_LinkNone * @arg kEDMA_MinorLink * @arg kEDMA_MajorLink * @param linkedChannel The linked channel number. - * @note User should ensure that DONE flag is cleared before call this interface, or the configuration will be invalid. + * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid. */ void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel); /*! * @brief Sets the bandwidth for the eDMA transfer. * - * In general, because the eDMA processes the minor loop, it continuously generates read/write sequences + * Because the eDMA processes the minor loop, it continuously generates read/write sequences * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of * each read/write access to control the bus request bandwidth seen by the crossbar switch. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param bandWidth Bandwidth setting, it can be one of: + * @param bandWidth A bandwidth setting, which can be one of the following: * @arg kEDMABandwidthStallNone * @arg kEDMABandwidthStall4Cycle * @arg kEDMABandwidthStall8Cycle @@ -439,7 +440,7 @@ void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_typ void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth); /*! - * @brief Sets the source modulo and destination modulo for eDMA transfer. + * @brief Sets the source modulo and the destination modulo for the eDMA transfer. * * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF) * calculation is performed or the original register value. It provides the ability to implement a circular data @@ -447,8 +448,8 @@ void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWi * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param srcModulo Source modulo value. - * @param destModulo Destination modulo value. + * @param srcModulo A source modulo value. + * @param destModulo A destination modulo value. */ void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo); @@ -458,7 +459,7 @@ void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, e * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param enable The command for enable(ture) or disable(false). + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable) { @@ -475,7 +476,7 @@ static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, boo * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param enable The command for enable (true) or disable (false). + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, bool enable) { @@ -489,7 +490,7 @@ static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param mask The mask of interrupt source to be set. User need to use + * @param mask The mask of interrupt source to be set. Users need to use * the defined edma_interrupt_enable_t type. */ void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask); @@ -499,7 +500,7 @@ void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mas * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param mask The mask of interrupt source to be set. Use + * @param mask The mask of the interrupt source to be set. Use * the defined edma_interrupt_enable_t type. */ void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask); @@ -516,15 +517,15 @@ void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t ma * This function sets all fields for this TCD structure to default value. * * @param tcd Pointer to the TCD structure. - * @note This function will enable auto stop request feature. + * @note This function enables the auto stop request feature. */ void EDMA_TcdReset(edma_tcd_t *tcd); /*! * @brief Configures the eDMA TCD transfer attribute. * - * TCD is a transfer control descriptor. The content of the TCD is the same as hardware TCD registers. - * STCD is used in scatter-gather mode. + * The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers. + * The STCD is used in the scatter-gather mode. * This function configures the TCD transfer attribute, including source address, destination address, * transfer size, address offset, and so on. It also configures the scatter gather feature if the * user supplies the next TCD address. @@ -540,33 +541,34 @@ void EDMA_TcdReset(edma_tcd_t *tcd); * * @param tcd Pointer to the TCD structure. * @param config Pointer to eDMA transfer configuration structure. - * @param nextTcd Pointer to the next TCD structure. It can be NULL if user + * @param nextTcd Pointer to the next TCD structure. It can be NULL if users * do not want to enable scatter/gather feature. - * @note TCD address should be 32 bytes aligned, or it will cause eDMA error. - * @note If nextTcd is not NULL, it means scatter gather feature will be enabled. - * And DREQ bit will be cleared in the previous transfer configuration which - * will be set in EDMA_TcdReset. + * @note TCD address should be 32 bytes aligned or it causes an eDMA error. + * @note If the nextTcd is not NULL, the scatter gather feature is enabled + * and DREQ bit is cleared in the previous transfer configuration, which + * is set in the EDMA_TcdReset. */ void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd); /*! * @brief Configures the eDMA TCD minor offset feature. * - * Minor offset is a signed-extended value added to the source address or destination + * A minor offset is a signed-extended value added to the source address or a destination * address after each minor loop. * - * @param tcd Point to the TCD structure. - * @param config Pointer to Minor offset configuration structure. + * @param tcd A point to the TCD structure. + * @param config A pointer to the minor offset configuration structure. */ void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config); /*! - * @brief Sets the channel link for eDMA TCD. + * @brief Sets the channel link for the eDMA TCD. * * This function configures either a minor link or a major link. The minor link means the channel link is - * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is exhausted. + * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is + * exhausted. * - * @note User should ensure that DONE flag is cleared before call this interface, or the configuration will be invalid. + * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid. * @param tcd Point to the TCD structure. * @param type Channel link type, it can be one of: * @arg kEDMA_LinkNone @@ -579,11 +581,11 @@ void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint /*! * @brief Sets the bandwidth for the eDMA TCD. * - * In general, because the eDMA processes the minor loop, it continuously generates read/write sequences - * until the minor count is exhausted. Bandwidth forces the eDMA to stall after the completion of + * Because the eDMA processes the minor loop, it continuously generates read/write sequences + * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of * each read/write access to control the bus request bandwidth seen by the crossbar switch. - * @param tcd Point to the TCD structure. - * @param bandWidth Bandwidth setting, it can be one of: + * @param tcd A pointer to the TCD structure. + * @param bandWidth A bandwidth setting, which can be one of the following: * @arg kEDMABandwidthStallNone * @arg kEDMABandwidthStall4Cycle * @arg kEDMABandwidthStall8Cycle @@ -597,15 +599,15 @@ static inline void EDMA_TcdSetBandWidth(edma_tcd_t *tcd, edma_bandwidth_t bandWi } /*! - * @brief Sets the source modulo and destination modulo for eDMA TCD. + * @brief Sets the source modulo and the destination modulo for the eDMA TCD. * * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF) * calculation is performed or the original register value. It provides the ability to implement a circular data * queue easily. * - * @param tcd Point to the TCD structure. - * @param srcModulo Source modulo value. - * @param destModulo Destination modulo value. + * @param tcd A pointer to the TCD structure. + * @param srcModulo A source modulo value. + * @param destModulo A destination modulo value. */ void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo); @@ -614,8 +616,8 @@ void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t d * * If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request. * - * @param tcd Point to the TCD structure. - * @param enable The command for enable(ture) or disable(false). + * @param tcd A pointer to the TCD structure. + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable) { @@ -629,7 +631,7 @@ static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable) * @brief Enables the interrupt source for the eDMA TCD. * * @param tcd Point to the TCD structure. - * @param mask The mask of interrupt source to be set. User need to use + * @param mask The mask of interrupt source to be set. Users need to use * the defined edma_interrupt_enable_t type. */ void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask); @@ -638,7 +640,7 @@ void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask); * @brief Disables the interrupt source for the eDMA TCD. * * @param tcd Point to the TCD structure. - * @param mask The mask of interrupt source to be set. User need to use + * @param mask The mask of interrupt source to be set. Users need to use * the defined edma_interrupt_enable_t type. */ void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask); @@ -680,7 +682,7 @@ static inline void EDMA_DisableChannelRequest(DMA_Type *base, uint32_t channel) } /*! - * @brief Starts the eDMA transfer by software trigger. + * @brief Starts the eDMA transfer by using the software trigger. * * This function starts a minor loop transfer. * @@ -701,25 +703,34 @@ static inline void EDMA_TriggerChannelStart(DMA_Type *base, uint32_t channel) */ /*! - * @brief Gets the Remaining bytes from the eDMA current channel TCD. + * @brief Gets the remaining major loop count from the eDMA current channel TCD. * * This function checks the TCD (Task Control Descriptor) status for a specified - * eDMA channel and returns the the number of bytes that have not finished. + * eDMA channel and returns the the number of major loop count that has not finished. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @return Bytes have not been transferred yet for the current TCD. - * @note This function can only be used to get unfinished bytes of transfer without - * the next TCD, or it might be inaccuracy. - */ -uint32_t EDMA_GetRemainingBytes(DMA_Type *base, uint32_t channel); + * @return Major loop count which has not been transferred yet for the current TCD. + * @note 1. This function can only be used to get unfinished major loop count of transfer without + * the next TCD, or it might be inaccuracy. + * 2. The unfinished/remaining transfer bytes cannot be obtained directly from registers while + * the channel is running. + * Because to calculate the remaining bytes, the initial NBYTES configured in DMA_TCDn_NBYTES_MLNO + * register is needed while the eDMA IP does not support getting it while a channel is active. + * In another word, the NBYTES value reading is always the actual (decrementing) NBYTES value the dma_engine + * is working with while a channel is running. + * Consequently, to get the remaining transfer bytes, a software-saved initial value of NBYTES (for example + * copied before enabling the channel) is needed. The formula to calculate it is shown below: + * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured) + */ +uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel); /*! * @brief Gets the eDMA channel error status flags. * * @param base eDMA peripheral base address. - * @return The mask of error status flags. User need to use the - * _edma_error_status_flags type to decode the return variables. + * @return The mask of error status flags. Users need to use the +* _edma_error_status_flags type to decode the return variables. */ static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base) { @@ -731,7 +742,7 @@ static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base) * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @return The mask of channel status flags. User need to use the + * @return The mask of channel status flags. Users need to use the * _edma_channel_status_flags type to decode the return variables. */ uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel); @@ -741,7 +752,7 @@ uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel); * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param mask The mask of channel status to be cleared. User need to use + * @param mask The mask of channel status to be cleared. Users need to use * the defined _edma_channel_status_flags type. */ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask); @@ -754,8 +765,8 @@ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mas /*! * @brief Creates the eDMA handle. * - * This function is called if using transaction API for eDMA. This function - * initializes the internal state of eDMA handle. + * This function is called if using the transactional API for eDMA. This function + * initializes the internal state of the eDMA handle. * * @param handle eDMA handle pointer. The eDMA handle stores callback function and * parameters. @@ -765,12 +776,12 @@ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mas void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel); /*! - * @brief Installs the TCDs memory pool into eDMA handle. + * @brief Installs the TCDs memory pool into the eDMA handle. * * This function is called after the EDMA_CreateHandle to use scatter/gather feature. * * @param handle eDMA handle pointer. - * @param tcdPool Memory pool to store TCDs. It must be 32 bytes aligned. + * @param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned. * @param tcdSize The number of TCD slots. */ void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize); @@ -778,12 +789,12 @@ void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t /*! * @brief Installs a callback function for the eDMA transfer. * - * This callback is called in eDMA IRQ handler. Use the callback to do something after + * This callback is called in the eDMA IRQ handler. Use the callback to do something after * the current major loop transfer completes. * * @param handle eDMA handle pointer. * @param callback eDMA callback function pointer. - * @param userData Parameter for callback function. + * @param userData A parameter for the callback function. */ void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData); @@ -801,8 +812,8 @@ void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userD * @param transferBytes eDMA transfer bytes to be transferred. * @param type eDMA transfer type. * @note The data address and the data width must be consistent. For example, if the SRC - * is 4 bytes, so the source address must be 4 bytes aligned, or it shall result in - * source address error(SAE). + * is 4 bytes, the source address must be 4 bytes aligned, or it results in + * source address error (SAE). */ void EDMA_PrepareTransfer(edma_transfer_config_t *config, void *srcAddr, @@ -817,7 +828,7 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, * @brief Submits the eDMA transfer request. * * This function submits the eDMA transfer request according to the transfer configuration structure. - * If the user submits the transfer request repeatedly, this function packs an unprocessed request as + * If submitting the transfer request repeatedly, this function packs an unprocessed request as * a TCD and enables scatter/gather feature to process it in the next time. * * @param handle eDMA handle pointer. @@ -829,9 +840,9 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config); /*! - * @brief eDMA start transfer. + * @brief eDMA starts transfer. * - * This function enables the channel request. User can call this function after submitting the transfer request + * This function enables the channel request. Users can call this function after submitting the transfer request * or before submitting the transfer request. * * @param handle eDMA handle pointer. @@ -839,9 +850,9 @@ status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t void EDMA_StartTransfer(edma_handle_t *handle); /*! - * @brief eDMA stop transfer. + * @brief eDMA stops transfer. * - * This function disables the channel request to pause the transfer. User can call EDMA_StartTransfer() + * This function disables the channel request to pause the transfer. Users can call EDMA_StartTransfer() * again to resume the transfer. * * @param handle eDMA handle pointer. @@ -849,21 +860,41 @@ void EDMA_StartTransfer(edma_handle_t *handle); void EDMA_StopTransfer(edma_handle_t *handle); /*! - * @brief eDMA abort transfer. + * @brief eDMA aborts transfer. * * This function disables the channel request and clear transfer status bits. - * User can submit another transfer after calling this API. + * Users can submit another transfer after calling this API. * * @param handle DMA handle pointer. */ void EDMA_AbortTransfer(edma_handle_t *handle); /*! - * @brief eDMA IRQ handler for current major loop transfer complete. + * @brief eDMA IRQ handler for the current major loop transfer completion. * - * This function clears the channel major interrupt flag and call + * This function clears the channel major interrupt flag and calls * the callback function if it is not NULL. * + * Note: + * For the case using TCD queue, when the major iteration count is exhausted, additional operations are performed. + * These include the final address adjustments and reloading of the BITER field into the CITER. + * Assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from + * memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled). + * + * For instance, when the time interrupt of TCD[0] happens, the TCD[1] has already been loaded into the eDMA engine. + * As sga and sga_index are calculated based on the DLAST_SGA bitfield lies in the TCD_CSR register, the sga_index + * in this case should be 2 (DLAST_SGA of TCD[1] stores the address of TCD[2]). Thus, the "tcdUsed" updated should be + * (tcdUsed - 2U) which indicates the number of TCDs can be loaded in the memory pool (because TCD[0] and TCD[1] have + * been loaded into the eDMA engine at this point already.). + * + * For the last two continuous ISRs in a scatter/gather process, they both load the last TCD (The last ISR does not + * load a new TCD) from the memory pool to the eDMA engine when major loop completes. + * Therefore, ensure that the header and tcdUsed updated are identical for them. + * tcdUsed are both 0 in this case as no TCD to be loaded. + * + * See the "eDMA basic data flow" in the eDMA Functional description section of the Reference Manual for + * further details. + * * @param handle eDMA handle pointer. */ void EDMA_HandleIRQ(edma_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c index fe6077fba8f..674f525025d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_enet.h" @@ -90,10 +90,8 @@ #define ENET_IPV6VERSION 0x0006U /*! @brief Ethernet mac address length. */ #define ENET_FRAME_MACLEN 6U -/*! @brief Ethernet Frame header length. */ -#define ENET_FRAME_HEADERLEN 14U /*! @brief Ethernet VLAN header length. */ -#define ENET_FRAME_VLAN_HEADERLEN 18U +#define ENET_FRAME_VLAN_TAGLEN 4U /*! @brief MDC frequency. */ #define ENET_MDC_FREQUENCY 2500000U /*! @brief NanoSecond in one second. */ @@ -238,8 +236,10 @@ static status_t ENET_StoreRxFrameTime(ENET_Type *base, enet_handle_t *handle, en /*! @brief Pointers to enet handles for each instance. */ static enet_handle_t *s_ENETHandle[FSL_FEATURE_SOC_ENET_COUNT] = {NULL}; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to enet clocks for each instance. */ const clock_ip_name_t s_enetClock[] = ENET_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to enet transmit IRQ number for each instance. */ static const IRQn_Type s_enetTxIrqId[] = ENET_Transmit_IRQS; @@ -259,6 +259,7 @@ static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS; static enet_isr_t s_enetTxIsr; static enet_isr_t s_enetRxIsr; static enet_isr_t s_enetErrIsr; +static enet_isr_t s_enetTsIsr; /******************************************************************************* * Code ******************************************************************************/ @@ -268,7 +269,7 @@ uint32_t ENET_GetInstance(ENET_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_ENET_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_enetBases); instance++) { if (s_enetBases[instance] == base) { @@ -276,7 +277,7 @@ uint32_t ENET_GetInstance(ENET_Type *base) } } - assert(instance < FSL_FEATURE_SOC_ENET_COUNT); + assert(instance < ARRAY_SIZE(s_enetBases)); return instance; } @@ -314,10 +315,11 @@ void ENET_Init(ENET_Type *base, assert(bufferConfig->rxBufferAlign); assert(macAddr); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) uint32_t instance = ENET_GetInstance(base); - /* Ungate ENET clock. */ CLOCK_EnableClock(s_enetClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset ENET module. */ ENET_Reset(base); @@ -346,8 +348,10 @@ void ENET_Deinit(ENET_Type *base) /* Disable ENET. */ base->ECR &= ~ENET_ECR_ETHEREN_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disables the clock source. */ CLOCK_DisableClock(s_enetClock[ENET_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void ENET_SetCallback(enet_handle_t *handle, enet_callback_t callback, void *userData) @@ -407,7 +411,13 @@ static void ENET_SetMacController(ENET_Type *base, uint32_t tcr = 0; uint32_t ecr = 0; uint32_t macSpecialConfig = config->macSpecialConfig; - uint32_t instance = ENET_GetInstance(base); + uint32_t maxFrameLen = config->rxMaxFrameLen; + + /* Maximum frame length check. */ + if ((macSpecialConfig & kENET_ControlVLANTagEnable) && (maxFrameLen <= ENET_FRAME_MAX_FRAMELEN)) + { + maxFrameLen = (ENET_FRAME_MAX_FRAMELEN + ENET_FRAME_VLAN_TAGLEN); + } /* Configures MAC receive controller with user configure structure. */ rcr = ENET_RCR_NLC(!!(macSpecialConfig & kENET_ControlRxPayloadCheckEnable)) | @@ -417,16 +427,16 @@ static void ENET_SetMacController(ENET_Type *base, ENET_RCR_BC_REJ(!!(macSpecialConfig & kENET_ControlRxBroadCastRejectEnable)) | ENET_RCR_PROM(!!(macSpecialConfig & kENET_ControlPromiscuousEnable)) | ENET_RCR_MII_MODE(1) | ENET_RCR_RMII_MODE(config->miiMode) | ENET_RCR_RMII_10T(!config->miiSpeed) | - ENET_RCR_MAX_FL(config->rxMaxFrameLen) | ENET_RCR_CRCFWD(1); + ENET_RCR_MAX_FL(maxFrameLen) | ENET_RCR_CRCFWD(1); /* Receive setting for half duplex. */ if (config->miiDuplex == kENET_MiiHalfDuplex) { - rcr |= ENET_RCR_DRT(1); + rcr |= ENET_RCR_DRT_MASK; } /* Sets internal loop only for MII mode. */ if ((config->macSpecialConfig & kENET_ControlMIILoopEnable) && (config->miiMode == kENET_MiiMode)) { - rcr |= ENET_RCR_LOOP(1); + rcr |= ENET_RCR_LOOP_MASK; rcr &= ~ENET_RCR_DRT_MASK; } base->RCR = rcr; @@ -446,7 +456,7 @@ static void ENET_SetMacController(ENET_Type *base, uint32_t reemReg; base->OPD = config->pauseDuration; reemReg = ENET_RSEM_RX_SECTION_EMPTY(config->rxFifoEmptyThreshold); -#if FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD +#if defined (FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD) && FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD reemReg |= ENET_RSEM_STAT_SECTION_EMPTY(config->rxFifoStatEmptyThreshold); #endif /* FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD */ base->RSEM = reemReg; @@ -492,7 +502,22 @@ static void ENET_SetMacController(ENET_Type *base, ENET_SetSMI(base, srcClock_Hz, !!(config->macSpecialConfig & kENET_ControlSMIPreambleDisable)); } - /* Enables Ethernet interrupt and NVIC. */ +/* Enables Ethernet interrupt and NVIC. */ +#if defined(FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE) && FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE + if (config->intCoalesceCfg) + { + uint32_t intMask = (ENET_EIMR_TXB_MASK | ENET_EIMR_RXB_MASK); + + /* Clear all buffer interrupts. */ + base->EIMR &= ~intMask; + + /* Set the interrupt coalescence. */ + base->TXIC = ENET_TXIC_ICFT(config->intCoalesceCfg->txCoalesceFrameCount[0]) | + config->intCoalesceCfg->txCoalesceTimeCount[0] | ENET_TXIC_ICCS_MASK | ENET_TXIC_ICEN_MASK; + base->RXIC = ENET_RXIC_ICFT(config->intCoalesceCfg->rxCoalesceFrameCount[0]) | + config->intCoalesceCfg->rxCoalesceTimeCount[0] | ENET_RXIC_ICCS_MASK | ENET_RXIC_ICEN_MASK; + } +#endif /* FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE */ ENET_EnableInterrupts(base, config->interrupt); /* ENET control register setting. */ @@ -545,7 +570,6 @@ static void ENET_SetTxBufferDescriptors(volatile enet_tx_bd_struct_t *txBdStartA /* Increase the index. */ curBuffDescrip++; } - } static void ENET_SetRxBufferDescriptors(volatile enet_rx_bd_struct_t *rxBdStartAlign, @@ -688,6 +712,46 @@ void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_ base->MMFR = mmfr; } +#if defined(FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO +void ENET_StartExtC45SMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data) +{ + uint32_t mmfr = 0; + + /* Parse the address from the input register. */ + uint16_t devAddr = (phyReg >> ENET_MMFR_TA_SHIFT) & 0x1FU; + uint16_t regAddr = (uint16_t)(phyReg & 0xFFFFU); + + /* Address write firstly. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiAddrWrite_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2) | ENET_MMFR_DATA(regAddr); + base->MMFR = mmfr; + + /* Build MII write command. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiWriteFrame_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2) | ENET_MMFR_DATA(data); + base->MMFR = mmfr; +} + +void ENET_StartExtC45SMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg) +{ + uint32_t mmfr = 0; + + /* Parse the address from the input register. */ + uint16_t devAddr = (phyReg >> ENET_MMFR_TA_SHIFT) & 0x1FU; + uint16_t regAddr = (uint16_t)(phyReg & 0xFFFFU); + + /* Address write firstly. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiAddrWrite_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2) | ENET_MMFR_DATA(regAddr); + base->MMFR = mmfr; + + /* Build MII read command. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiReadFrame_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2); + base->MMFR = mmfr; +} +#endif /* FSL_FEATURE_ENET_HAS_EXTEND_MDIO */ + void ENET_GetRxErrBeforeReadFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic) { assert(handle); @@ -769,13 +833,15 @@ status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length) assert(handle->rxBdCurrent); assert(length); + /* Reset the length to zero. */ + *length = 0; + uint16_t validLastMask = ENET_BUFFDESCRIPTOR_RX_LAST_MASK | ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; /* Check the current buffer descriptor's empty flag. if empty means there is no frame received. */ if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) { - *length = 0; return kStatus_ENET_RxFrameEmpty; } @@ -791,7 +857,6 @@ status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length) #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ ) { - *length = 0; return kStatus_ENET_RxFrameError; } /* FCS is removed by MAC. */ @@ -821,8 +886,9 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u uint32_t len = 0; uint32_t offset = 0; + uint16_t control; bool isLastBuff = false; - volatile enet_rx_bd_struct_t *curBuffDescrip; + volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; status_t result = kStatus_Success; /* For data-NULL input, only update the buffer descriptor. */ @@ -830,37 +896,24 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u { do { - /* Get the current buffer descriptor. */ - curBuffDescrip = handle->rxBdCurrent; - /* Increase current buffer descriptor to the next one. */ - if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) - { - handle->rxBdCurrent = handle->rxBdBase; - } - else - { - handle->rxBdCurrent++; - } + /* Update the control flag. */ + control = handle->rxBdCurrent->control; + /* Updates the receive buffer descriptors. */ + ENET_UpdateReadBuffers(base, handle); - /* The last buffer descriptor of a frame. */ - if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) + /* Find the last buffer descriptor for the frame. */ + if (control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) { - /* Find the last buffer descriptor for the frame*/ break; } - } while (handle->rxBdCurrent != handle->rxBdDirty); - /* Update all receive buffer descriptors for the whole frame. */ - ENET_UpdateReadBuffers(base, handle); + } while (handle->rxBdCurrent != curBuffDescrip); return result; } else { - /* Frame read from the MAC to user buffer and update the buffer descriptors. - Process the frame, a frame on several receive buffers are considered . */ - /* Get the current buffer descriptor. */ - curBuffDescrip = handle->rxBdCurrent; +/* A frame on one buffer or several receive buffers are both considered. */ #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE enet_ptp_time_data_t ptpTimestamp; bool isPtpEventMessage = false; @@ -871,16 +924,6 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u while (!isLastBuff) { - /* Increase current buffer descriptor to the next one. */ - if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) - { - handle->rxBdCurrent = handle->rxBdBase; - } - else - { - handle->rxBdCurrent++; - } - /* The last buffer descriptor of a frame. */ if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) { @@ -900,28 +943,39 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u result = ENET_StoreRxFrameTime(base, handle, &ptpTimestamp); } #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + + /* Updates the receive buffer descriptors. */ ENET_UpdateReadBuffers(base, handle); return result; } + else + { + /* Updates the receive buffer descriptors. */ + ENET_UpdateReadBuffers(base, handle); + } } else { - /* Store the fragments of a frame on several buffer descriptors. */ + /* Store a frame on several buffer descriptors. */ isLastBuff = false; - memcpy(data + offset, curBuffDescrip->buffer, handle->rxBuffSizeAlign); - offset += handle->rxBuffSizeAlign; + /* Length check. */ if (offset >= length) { break; } + + memcpy(data + offset, curBuffDescrip->buffer, handle->rxBuffSizeAlign); + offset += handle->rxBuffSizeAlign; + + /* Updates the receive buffer descriptors. */ + ENET_UpdateReadBuffers(base, handle); } /* Get the current buffer descriptor. */ curBuffDescrip = handle->rxBdCurrent; } - /* All error happens will break the while loop and arrive here to update receive buffers. */ - ENET_UpdateReadBuffers(base, handle); } + return kStatus_ENET_RxFrameFail; } @@ -929,26 +983,23 @@ static void ENET_UpdateReadBuffers(ENET_Type *base, enet_handle_t *handle) { assert(handle); - do - { - /* Clears status. */ - handle->rxBdDirty->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; - /* Sets the receive buffer descriptor with the empty flag. */ - handle->rxBdDirty->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; - /* Increases the buffer descriptor to the next one. */ - if (handle->rxBdDirty->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) - { - handle->rxBdDirty = handle->rxBdBase; - } - else - { - handle->rxBdDirty++; - } + /* Clears status. */ + handle->rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; + /* Sets the receive buffer descriptor with the empty flag. */ + handle->rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; - /* Actives the receive buffer descriptor. */ - base->RDAR = ENET_RDAR_RDAR_MASK; + /* Increase current buffer descriptor to the next one. */ + if (handle->rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) + { + handle->rxBdCurrent = handle->rxBdBase; + } + else + { + handle->rxBdCurrent++; + } - } while (handle->rxBdDirty != handle->rxBdCurrent); + /* Actives the receive buffer descriptor. */ + base->RDAR = ENET_RDAR_RDAR_MASK; } status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length) @@ -956,7 +1007,7 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u assert(handle); assert(handle->txBdCurrent); assert(data); - assert(length <= (ENET_FRAME_MAX_VALNFRAMELEN - 4)); + assert(length <= ENET_FRAME_MAX_FRAMELEN); volatile enet_tx_bd_struct_t *curBuffDescrip = handle->txBdCurrent; uint32_t len = 0; @@ -985,6 +1036,11 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u { curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; } + else + { + curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } + #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ curBuffDescrip->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); @@ -1013,6 +1069,10 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u { curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; } + else + { + curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ /* Increase the buffer descriptor address. */ @@ -1034,6 +1094,7 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u curBuffDescrip->length = handle->txBuffSizeAlign; len += handle->txBuffSizeAlign; /* Sets the control flag. */ + curBuffDescrip->control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK; /* Active the transmit buffer descriptor*/ base->TDAR = ENET_TDAR_TDAR_MASK; @@ -1054,7 +1115,7 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u } while (!(curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)); - return kStatus_ENET_TxFrameFail; + return kStatus_ENET_TxFrameBusy; } } @@ -1216,7 +1277,7 @@ static bool ENET_Ptp1588ParseFrame(uint8_t *data, enet_ptp_time_data_t *ptpTsDat /* Check for VLAN frame. */ if (*(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET) == ENET_HTONS(ENET_8021QVLAN)) { - buffer += (ENET_FRAME_VLAN_HEADERLEN - ENET_FRAME_HEADERLEN); + buffer += ENET_FRAME_VLAN_TAGLEN; } ptpType = *(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET); @@ -1299,7 +1360,8 @@ void ENET_Ptp1588Configure(ENET_Type *base, enet_handle_t *handle, enet_ptp_conf /* Enables the time stamp interrupt for the master clock on a device. */ ENET_EnableInterrupts(base, kENET_TsTimerInterrupt); - /* Enables the transmit interrupt to store the transmit frame time-stamp. */ + /* Enables only frame interrupt for transmit side to store the transmit + frame time-stamp when the whole frame is transmitted out. */ ENET_EnableInterrupts(base, kENET_TxFrameInterrupt); ENET_DisableInterrupts(base, kENET_TxBufferInterrupt); @@ -1318,6 +1380,7 @@ void ENET_Ptp1588Configure(ENET_Type *base, enet_handle_t *handle, enet_ptp_conf /* Set the IRQ handler when the interrupt is enabled. */ s_enetTxIsr = ENET_TransmitIRQHandler; + s_enetTsIsr = ENET_Ptp1588TimerIRQHandler; EnableIRQ(s_enetTsIrqId[instance]); EnableIRQ(s_enetTxIrqId[instance]); } @@ -1624,8 +1687,8 @@ void ENET_TransmitIRQHandler(ENET_Type *base, enet_handle_t *handle) #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE if (base->EIR & kENET_TxFrameInterrupt) { - /* Store the transmit timestamp from the buffer descriptor should be done here. */ - ENET_StoreTxFrameTime(base, handle); + /* Store the transmit timestamp from the buffer descriptor should be done here. */ + ENET_StoreTxFrameTime(base, handle); } #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ @@ -1665,7 +1728,7 @@ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle) uint32_t errMask = kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_EBusERInterrupt | kENET_PayloadRxInterrupt | kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt | kENET_UnderrunInterrupt; - /* Check if the PTP time stamp interrupt happen. */ + /* Check if the error interrupt happen. */ if (kENET_WakeupInterrupt & base->EIR) { /* Clear the wakeup interrupt. */ @@ -1680,7 +1743,7 @@ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle) } else { - /* Clear the time stamp interrupt. */ + /* Clear the error interrupt event status. */ errMask &= base->EIR; base->EIR = errMask; /* Callback function. */ @@ -1721,13 +1784,34 @@ void ENET_Ptp1588TimerIRQHandler(ENET_Type *base, enet_handle_t *handle) } } } +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ -void ENET_1588_Timer_IRQHandler(void) +void ENET_CommonFrame0IRQHandler(ENET_Type *base) { - ENET_Ptp1588TimerIRQHandler(ENET, s_ENETHandle[0]); + uint32_t event = base->EIR; + uint32_t instance = ENET_GetInstance(base); + + if (event & ENET_TX_INTERRUPT) + { + s_enetTxIsr(base, s_ENETHandle[instance]); + } + + if (event & ENET_RX_INTERRUPT) + { + s_enetRxIsr(base, s_ENETHandle[instance]); + } + + if (event & ENET_TS_INTERRUPT) + { + s_enetTsIsr(base, s_ENETHandle[instance]); + } + if (event & ENET_ERR_INTERRUPT) + { + s_enetErrIsr(base, s_ENETHandle[instance]); + } } -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ +#if defined(ENET) void ENET_Transmit_IRQHandler(void) { s_enetTxIsr(ENET, s_ENETHandle[0]); @@ -1742,3 +1826,10 @@ void ENET_Error_IRQHandler(void) { s_enetErrIsr(ENET, s_ENETHandle[0]); } + +void ENET_1588_Timer_IRQHandler(void) +{ + s_enetTsIsr(ENET, s_ENETHandle[0]); +} +#endif + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h index f35da473cd8..211a01138b4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -46,7 +45,7 @@ /*! @name Driver version */ /*@{*/ /*! @brief Defines the driver version. */ -#define FSL_ENET_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ +#define FSL_ENET_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1. */ /*@}*/ /*! @name Control and status region bit masks of the receive buffer descriptor. */ @@ -124,18 +123,18 @@ #endif #define ENET_TX_INTERRUPT (kENET_TxFrameInterrupt | kENET_TxBufferInterrupt) #define ENET_RX_INTERRUPT (kENET_RxFrameInterrupt | kENET_RxBufferInterrupt) +#define ENET_TS_INTERRUPT (kENET_TsTimerInterrupt | kENET_TsAvailInterrupt) #define ENET_ERR_INTERRUPT (kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_EBusERInterrupt | \ kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt | kENET_UnderrunInterrupt | kENET_PayloadRxInterrupt) + /*! @name Defines the maximum Ethernet frame size. */ /*@{*/ -#define ENET_FRAME_MAX_FRAMELEN 1518U /*!< Maximum Ethernet frame size. */ -#define ENET_FRAME_MAX_VALNFRAMELEN 1522U /*!< Maximum VLAN frame size. */ +#define ENET_FRAME_MAX_FRAMELEN 1518U /*!< Default maximum Ethernet frame size. */ /*@}*/ #define ENET_FIFO_MIN_RX_FULL 5U /*!< ENET minimum receive FIFO full. */ #define ENET_RX_MIN_BUFFERSIZE 256U /*!< ENET minimum buffer size. */ -#define ENET_BUFF_ALIGNMENT 16U /*!< Ethernet buffer alignment. */ /*! @brief Defines the PHY address scope for the ENET. */ #define ENET_PHY_MAXADDRESS (ENET_MMFR_PA_MASK >> ENET_MMFR_PA_SHIFT) @@ -191,6 +190,15 @@ typedef enum _enet_mii_read kENET_MiiReadNoCompliant = 3U /*!< Read frame operation, but not MII-compliant. */ } enet_mii_read_t; +#if defined (FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO +/*! @brief Define the MII opcode for extended MDIO_CLAUSES_45 Frame. */ +typedef enum _enet_mii_extend_opcode { + kENET_MiiAddrWrite_C45 = 0U, /*!< Address Write operation. */ + kENET_MiiWriteFrame_C45 = 1U, /*!< Write frame operation for a valid MII management frame. */ + kENET_MiiReadFrame_C45 = 3U /*!< Read frame operation for a valid MII management frame. */ +} enet_mii_extend_opcode; +#endif /* FSL_FEATURE_ENET_HAS_EXTEND_MDIO */ + /*! @brief Defines a special configuration for ENET MAC controller. * * These control flags are provided for special user requirements. @@ -237,12 +245,9 @@ typedef enum _enet_interrupt_enable kENET_RetryLimitInterrupt = ENET_EIR_RL_MASK, /*!< Collision Retry Limit interrupt source */ kENET_UnderrunInterrupt = ENET_EIR_UN_MASK, /*!< Transmit FIFO underrun interrupt source */ kENET_PayloadRxInterrupt = ENET_EIR_PLR_MASK, /*!< Payload Receive interrupt source */ - kENET_WakeupInterrupt = ENET_EIR_WAKEUP_MASK /*!< WAKEUP interrupt source */ -#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - , + kENET_WakeupInterrupt = ENET_EIR_WAKEUP_MASK, /*!< WAKEUP interrupt source */ kENET_TsAvailInterrupt = ENET_EIR_TS_AVAIL_MASK, /*!< TS AVAIL interrupt source for PTP */ kENET_TsTimerInterrupt = ENET_EIR_TS_TIMER_MASK /*!< TS WRAP interrupt source for PTP */ -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_interrupt_enable_t; /*! @brief Defines the common interrupt event for callback use. */ @@ -252,10 +257,8 @@ typedef enum _enet_event kENET_TxEvent, /*!< Transmit event. */ kENET_ErrEvent, /*!< Error event: BABR/BABT/EBERR/LC/RL/UN/PLR . */ kENET_WakeUpEvent, /*!< Wake up from sleep mode event. */ -#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE kENET_TimeStampEvent, /*!< Time stamp event. */ kENET_TimeStampAvailEvent /*!< Time stamp available event.*/ -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_event_t; /*! @brief Defines the transmit accelerator configuration. */ @@ -380,15 +383,20 @@ typedef struct _enet_data_error_stats #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_data_error_stats_t; -/*! @brief Defines the receive buffer descriptor configure structure. +/*! @brief Defines the receive buffer descriptor configuration structure. * - * Note: For the internal DMA requirements, the buffers have a corresponding alignment requirement: - * 1. The aligned receive and transmit buffer size must be evenly divisible by 16. + * Note that for the internal DMA requirements, the buffers have a corresponding alignment requirements. + * 1. The aligned receive and transmit buffer size must be evenly divisible by ENET_BUFF_ALIGNMENT. + * when the data buffers are in cacheable region when cache is enabled, all those size should be + * aligned to the maximum value of "ENET_BUFF_ALIGNMENT" and the cache line size. * 2. The aligned transmit and receive buffer descriptor start address must be at - * least 64 bit aligned. However, it's recommended to be evenly divisible by 16. - * 3. The aligned transmit and receive buffer start address must be evenly divisible by 16. + * least 64 bit aligned. However, it's recommended to be evenly divisible by ENET_BUFF_ALIGNMENT. + * buffer descriptors should be put in non-cacheable region when cache is enabled. + * 3. The aligned transmit and receive data buffer start address must be evenly divisible by ENET_BUFF_ALIGNMENT. * Receive buffers should be continuous with the total size equal to "rxBdNumber * rxBuffSizeAlign". * Transmit buffers should be continuous with the total size equal to "txBdNumber * txBuffSizeAlign". + * when the data buffers are in cacheable region when cache is enabled, all those size should be + * aligned to the maximum value of "ENET_BUFF_ALIGNMENT" and the cache line size. */ typedef struct _enet_buffer_config { @@ -429,7 +437,7 @@ typedef struct _enet_ptp_time_data_ring enet_ptp_time_data_t *ptpTsData; /*!< PTP message data structure. */ } enet_ptp_time_data_ring_t; -/*! @brief Defines the ENET PTP configure structure. */ +/*! @brief Defines the ENET PTP configuration structure. */ typedef struct _enet_ptp_config { uint8_t ptpTsRxBuffNum; /*!< Receive 1588 timestamp buffer number*/ @@ -441,19 +449,28 @@ typedef struct _enet_ptp_config } enet_ptp_config_t; #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ - +#if defined (FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE) && FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE +/*! @brief Defines the interrupt coalescing configure structure. */ +typedef struct _enet_intcoalesce_config +{ + uint8_t txCoalesceFrameCount[FSL_FEATURE_ENET_QUEUE]; /*!< Transmit interrupt coalescing frame count threshold. */ + uint16_t txCoalesceTimeCount[FSL_FEATURE_ENET_QUEUE]; /*!< Transmit interrupt coalescing timer count threshold. */ + uint8_t rxCoalesceFrameCount[FSL_FEATURE_ENET_QUEUE]; /*!< Receive interrupt coalescing frame count threshold. */ + uint16_t rxCoalesceTimeCount[FSL_FEATURE_ENET_QUEUE]; /*!< Receive interrupt coalescing timer count threshold. */ +} enet_intcoalesce_config_t; +#endif /* FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE */ /*! @brief Defines the basic configuration structure for the ENET device. * * Note: - * 1. macSpecialConfig is used for a special control configuration, A logical OR of + * 1. macSpecialConfig is used for a special control configuration, a logical OR of * "enet_special_control_flag_t". For a special configuration for MAC, * set this parameter to 0. - * 2. txWatermark is used for a cut-through operation. It is in steps of 64 bytes: + * 2. txWatermark is used for a cut-through operation. It is in steps of 64 bytes. * 0/1 - 64 bytes written to TX FIFO before transmission of a frame begins. * 2 - 128 bytes written to TX FIFO .... * 3 - 192 bytes written to TX FIFO .... - * The maximum of txWatermark is 0x2F - 4032 bytes written to TX FIFO .... + * The maximum of txWatermark is 0x2F - 4032 bytes written to TX FIFO. * txWatermark allows minimizing the transmit latency to set the txWatermark to 0 or 1 * or for larger bus access latency 3 or larger due to contention for the system bus. * 3. rxFifoFullThreshold is similar to the txWatermark for cut-through operation in RX. @@ -485,7 +502,7 @@ typedef struct _enet_config uint16_t pauseDuration; /*!< For flow control enabled case: Pause duration. */ uint8_t rxFifoEmptyThreshold; /*!< For flow control enabled case: when RX FIFO level reaches this value, it makes MAC generate XOFF pause frame. */ -#if FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD +#if defined (FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD) && FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD uint8_t rxFifoStatEmptyThreshold; /*!< For flow control enabled case: number of frames in the receive FIFO, independent of size, that can be accept. If the limit is reached, reception continues and a pause frame is triggered. */ @@ -494,6 +511,10 @@ typedef struct _enet_config the MAC receive ready status. */ uint8_t txFifoWatermark; /*!< For store and forward disable case, the data required in TX FIFO before a frame transmit start. */ +#if defined (FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE) && FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE + enet_intcoalesce_config_t *intCoalesceCfg; /* If the interrupt coalsecence is not required in the ring n(0,1,2), please set + to NULL. */ +#endif /* FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE */ } enet_config_t; /* Forward declaration of the handle typedef. */ @@ -507,7 +528,6 @@ struct _enet_handle { volatile enet_rx_bd_struct_t *rxBdBase; /*!< Receive buffer descriptor base address pointer. */ volatile enet_rx_bd_struct_t *rxBdCurrent; /*!< The current available receive buffer descriptor pointer. */ - volatile enet_rx_bd_struct_t *rxBdDirty; /*!< The dirty receive buffer descriptor needed to be updated from. */ volatile enet_tx_bd_struct_t *txBdBase; /*!< Transmit buffer descriptor base address pointer. */ volatile enet_tx_bd_struct_t *txBdCurrent; /*!< The current available transmit buffer descriptor pointer. */ volatile enet_tx_bd_struct_t *txBdDirty; /*!< The dirty transmit buffer descriptor needed to be updated from. */ @@ -533,7 +553,7 @@ extern "C" { #endif /*! - * @name Initialization and De-initialization + * @name Initialization and de-initialization * @{ */ @@ -541,10 +561,10 @@ extern "C" { * @brief Gets the ENET default configuration structure. * * The purpose of this API is to get the default ENET MAC controller - * configure structure for ENET_Init(). User may use the initialized - * structure unchanged in ENET_Init(), or modify some fields of the + * configuration structure for ENET_Init(). Users may use the initialized + * structure unchanged in ENET_Init() or modify fields of the * structure before calling ENET_Init(). - * Example: + * This is an example. @code enet_config_t config; ENET_GetDefaultConfig(&config); @@ -560,18 +580,18 @@ void ENET_GetDefaultConfig(enet_config_t *config); * * @param base ENET peripheral base address. * @param handle ENET handler pointer. - * @param config ENET mac configuration structure pointer. + * @param config ENET Mac configuration structure pointer. * The "enet_config_t" type mac configuration return from ENET_GetDefaultConfig * can be used directly. It is also possible to verify the Mac configuration using other methods. * @param bufferConfig ENET buffer configuration structure pointer. * The buffer configuration should be prepared for ENET Initialization. - * @param macAddr ENET mac address of Ethernet device. This MAC address should be + * @param macAddr ENET mac address of the Ethernet device. This Mac address should be * provided. * @param srcClock_Hz The internal module clock source for MII clock. * - * @note ENET has two buffer descriptors: legacy buffer descriptors and - * enhanced 1588 buffer descriptors. The legacy descriptor is used by default. To - * use 1588 feature, use the enhanced 1588 buffer descriptor + * @note ENET has two buffer descriptors legacy buffer descriptors and + * enhanced IEEE 1588 buffer descriptors. The legacy descriptor is used by default. To + * use the IEEE 1588 feature, use the enhanced IEEE 1588 buffer descriptor * by defining "ENET_ENHANCEDBUFFERDESCRIPTOR_MODE" and calling ENET_Ptp1588Configure() * to configure the 1588 feature and related buffers after calling ENET_Init(). */ @@ -593,8 +613,8 @@ void ENET_Deinit(ENET_Type *base); /*! * @brief Resets the ENET module. * - * This function restores the ENET module to reset state. - * Note that this function sets all registers to + * This function restores the ENET module to the reset state. + * Note that this function sets all registers to the * reset state. As a result, the ENET module can't work after calling this function. * * @param base ENET peripheral base address. @@ -621,7 +641,7 @@ static inline void ENET_Reset(ENET_Type *base) void ENET_SetMII(ENET_Type *base, enet_mii_speed_t speed, enet_mii_duplex_t duplex); /*! - * @brief Sets the ENET SMI(serial management interface)- MII management interface. + * @brief Sets the ENET SMI (serial management interface) - MII management interface. * * @param base ENET peripheral base address. * @param srcClock_Hz This is the ENET module clock frequency. Normally it's the system clock. See clock distribution. @@ -634,7 +654,7 @@ void ENET_SetSMI(ENET_Type *base, uint32_t srcClock_Hz, bool isPreambleDisabled) /*! * @brief Gets the ENET SMI- MII management interface configuration. * - * This API is used to get the SMI configuration to check if the MII management + * This API is used to get the SMI configuration to check whether the MII management * interface has been set. * * @param base ENET peripheral base address. @@ -646,7 +666,7 @@ static inline bool ENET_GetSMI(ENET_Type *base) } /*! - * @brief Reads data from the PHY register through SMI interface. + * @brief Reads data from the PHY register through an SMI interface. * * @param base ENET peripheral base address. * @return The data read from PHY @@ -667,7 +687,7 @@ static inline uint32_t ENET_ReadSMIData(ENET_Type *base) void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_read_t operation); /*! - * @brief Starts a SMI write command. + * @brief Starts an SMI write command. * * @param base ENET peripheral base address. * @param phyAddr The PHY address. @@ -677,6 +697,31 @@ void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_ */ void ENET_StartSMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_write_t operation, uint32_t data); +#if defined (FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO +/*! + * @brief Starts the extended IEEE802.3 Clause 45 MDIO format SMI read command. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param phyReg The PHY register. For MDIO IEEE802.3 Clause 45, + * the phyReg is a 21-bits combination of the devaddr (5 bits device address) + * and the regAddr (16 bits phy register): phyReg = (devaddr << 16) | regAddr. + */ +void ENET_StartExtC45SMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg); + +/*! + * @brief Starts the extended IEEE802.3 Clause 45 MDIO format SMI write command. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param phyReg The PHY register. For MDIO IEEE802.3 Clause 45, + * the phyReg is a 21-bits combination of the devaddr (5 bits device address) + * and the regAddr (16 bits phy register): phyReg = (devaddr << 16) | regAddr. + * @param data The data written to PHY. + */ +void ENET_StartExtC45SMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data); +#endif /* FSL_FEATURE_ENET_HAS_EXTEND_MDIO */ + /* @} */ /*! @@ -721,7 +766,7 @@ void ENET_LeaveMulticastGroup(ENET_Type *base, uint8_t *address); /* @} */ /*! - * @name Other basic operation + * @name Other basic operations * @{ */ @@ -762,13 +807,13 @@ static inline void ENET_EnableSleepMode(ENET_Type *base, bool enable) } /*! - * @brief Gets ENET transmit and receive accelerator functions from MAC controller. + * @brief Gets ENET transmit and receive accelerator functions from the MAC controller. * * @param base ENET peripheral base address. * @param txAccelOption The transmit accelerator option. The "enet_tx_accelerator_t" is - * recommended to be used to as the mask to get the exact the accelerator option. + * recommended as the mask to get the exact the accelerator option. * @param rxAccelOption The receive accelerator option. The "enet_rx_accelerator_t" is - * recommended to be used to as the mask to get the exact the accelerator option. + * recommended as the mask to get the exact the accelerator option. */ static inline void ENET_GetAccelFunction(ENET_Type *base, uint32_t *txAccelOption, uint32_t *rxAccelOption) { @@ -782,7 +827,7 @@ static inline void ENET_GetAccelFunction(ENET_Type *base, uint32_t *txAccelOptio /* @} */ /*! - * @name Interrupts. + * @name Interrupts * @{ */ @@ -791,7 +836,7 @@ static inline void ENET_GetAccelFunction(ENET_Type *base, uint32_t *txAccelOptio * * This function enables the ENET interrupt according to the provided mask. The mask * is a logical OR of enumeration members. See @ref enet_interrupt_enable_t. - * For example, to enable the TX frame interrupt and RX frame interrupt, do this: + * For example, to enable the TX frame interrupt and RX frame interrupt, do the following. * @code * ENET_EnableInterrupts(ENET, kENET_TxFrameInterrupt | kENET_RxFrameInterrupt); * @endcode @@ -810,7 +855,7 @@ static inline void ENET_EnableInterrupts(ENET_Type *base, uint32_t mask) * * This function disables the ENET interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref enet_interrupt_enable_t. - * For example, to disable the TX frame interrupt and RX frame interrupt, do this: + * For example, to disable the TX frame interrupt and RX frame interrupt, do the following. * @code * ENET_DisableInterrupts(ENET, kENET_TxFrameInterrupt | kENET_RxFrameInterrupt); * @endcode @@ -841,7 +886,7 @@ static inline uint32_t ENET_GetInterruptStatus(ENET_Type *base) * * This function clears enabled ENET interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See the @ref enet_interrupt_enable_t. - * For example, to clear the TX frame interrupt and RX frame interrupt, do this: + * For example, to clear the TX frame interrupt and RX frame interrupt, do the following. * @code * ENET_ClearInterruptStatus(ENET, kENET_TxFrameInterrupt | kENET_RxFrameInterrupt); * @endcode @@ -863,8 +908,8 @@ static inline void ENET_ClearInterruptStatus(ENET_Type *base, uint32_t mask) */ /*! - * @brief Set the callback function. - * This API is provided for application callback required case when ENET + * @brief Sets the callback function. + * This API is provided for the application callback required case when ENET * interrupt is enabled. This API should be called after calling ENET_Init. * * @param handle ENET handler pointer. Should be provided by application. @@ -879,7 +924,7 @@ void ENET_SetCallback(enet_handle_t *handle, enet_callback_t callback, void *use * This API must be called after the ENET_GetRxFrameSize and before the ENET_ReadFrame(). * If the ENET_GetRxFrameSize returns kStatus_ENET_RxFrameError, * the ENET_GetRxErrBeforeReadFrame can be used to get the exact error statistics. - * For example: + * This is an example. * @code * status = ENET_GetRxFrameSize(&g_handle, &length); * if (status == kStatus_ENET_RxFrameError) @@ -911,29 +956,54 @@ void ENET_GetRxErrBeforeReadFrame(enet_handle_t *handle, enet_data_error_stats_t */ status_t ENET_GetTxErrAfterSendFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic); #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ - /*! - * @brief Gets the size of the read frame. - * This function reads a received frame size from the ENET buffer descriptors. - * @note The FCS of the frame is removed by MAC controller and the size is the length without the FCS. - * After calling ENET_GetRxFrameSize, ENET_ReadFrame() should be called to update the - * receive buffers If the result is not "kStatus_ENET_RxFrameEmpty". - * - * @param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init. - * @param length The length of the valid frame received. - * @retval kStatus_ENET_RxFrameEmpty No frame received. Should not call ENET_ReadFrame to read frame. - * @retval kStatus_ENET_RxFrameError Data error happens. ENET_ReadFrame should be called with NULL data - * and NULL length to update the receive buffers. - * @retval kStatus_Success Receive a frame Successfully then the ENET_ReadFrame - * should be called with the right data buffer and the captured data length input. - */ +/*! +* @brief Gets the size of the read frame. +* This function gets a received frame size from the ENET buffer descriptors. +* @note The FCS of the frame is automatically removed by Mac and the size is the length without the FCS. +* After calling ENET_GetRxFrameSize, ENET_ReadFrame() should be called to update the +* receive buffers If the result is not "kStatus_ENET_RxFrameEmpty". +* +* @param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init. +* @param length The length of the valid frame received. +* @retval kStatus_ENET_RxFrameEmpty No frame received. Should not call ENET_ReadFrame to read frame. +* @retval kStatus_ENET_RxFrameError Data error happens. ENET_ReadFrame should be called with NULL data +* and NULL length to update the receive buffers. +* @retval kStatus_Success Receive a frame Successfully then the ENET_ReadFrame +* should be called with the right data buffer and the captured data length input. +*/ status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length); /*! * @brief Reads a frame from the ENET device. * This function reads a frame (both the data and the length) from the ENET buffer descriptors. * The ENET_GetRxFrameSize should be used to get the size of the prepared data buffer. - * @note The FCS of the frame is removed by MAC controller and is not delivered to the application. - * + * This is an example. + * @code + * uint32_t length; + * enet_handle_t g_handle; + * //Get the received frame size firstly. + * status = ENET_GetRxFrameSize(&g_handle, &length); + * if (length != 0) + * { + * //Allocate memory here with the size of "length" + * uint8_t *data = memory allocate interface; + * if (!data) + * { + * ENET_ReadFrame(ENET, &g_handle, NULL, 0); + * //Add the console warning log. + * } + * else + * { + * status = ENET_ReadFrame(ENET, &g_handle, data, length); + * //Call stack input API to deliver the data to stack + * } + * } + * else if (status == kStatus_ENET_RxFrameError) + * { + * //Update the received buffer when a error frame is received. + * ENET_ReadFrame(ENET, &g_handle, NULL, 0); + * } + * @endcode * @param base ENET peripheral base address. * @param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init. * @param data The data buffer provided by user to store the frame which memory size should be at least "length". @@ -952,8 +1022,10 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u * @param data The data buffer provided by user to be send. * @param length The length of the data to be send. * @retval kStatus_Success Send frame succeed. - * @retval kStatus_ENET_TxFrameBusy Transmit buffer descriptor is busy under transmit. - * @retval kStatus_ENET_TxFrameFail Transmit frame fail. + * @retval kStatus_ENET_TxFrameBusy Transmit buffer descriptor is busy under transmission. + * The transmit busy happens when the data send rate is over the MAC capacity. + * The waiting mechanism is recommended to be added after each call return with + * kStatus_ENET_TxFrameBusy. */ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length); @@ -981,6 +1053,14 @@ void ENET_ReceiveIRQHandler(ENET_Type *base, enet_handle_t *handle); */ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle); +/*! + * @brief the common IRQ handler for the tx/rx/error etc irq handler. + * + * This is used for the combined tx/rx/error interrupt for single ring (ring 0). + * + * @param base ENET peripheral base address. + */ +void ENET_CommonFrame0IRQHandler(ENET_Type *base); /* @} */ #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE @@ -990,7 +1070,7 @@ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle); */ /*! - * @brief Configures the ENET PTP 1588 feature with the basic configuration. + * @brief Configures the ENET PTP IEEE 1588 feature with the basic configuration. * The function sets the clock for PTP 1588 timer and enables * time stamp interrupts and transmit interrupts for PTP 1588 features. * This API should be called when the 1588 feature is enabled @@ -1044,7 +1124,7 @@ static inline void ENET_Ptp1588StopTimer(ENET_Type *base) void ENET_Ptp1588AdjustTimer(ENET_Type *base, uint32_t corrIncrease, uint32_t corrPeriod); /*! - * @brief Sets ENET PTP 1588 timer channel mode. + * @brief Sets the ENET PTP 1588 timer channel mode. * * @param base ENET peripheral base address. * @param channel The ENET PTP timer channel number. @@ -1064,8 +1144,55 @@ static inline void ENET_Ptp1588SetChannelMode(ENET_Type *base, base->CHANNEL[channel].TCSR = tcrReg; } +#if defined(FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL) && FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL +/*! + * @brief Sets ENET PTP 1588 timer channel mode pulse width. + * + * For the input "mode" in ENET_Ptp1588SetChannelMode, the kENET_PtpChannelPulseLowonCompare + * kENET_PtpChannelPulseHighonCompare only support the pulse width for one 1588 clock. + * this function is extended for control the pulse width from 1 to 32 1588 clock cycles. + * so call this function if you need to set the timer channel mode for + * kENET_PtpChannelPulseLowonCompare or kENET_PtpChannelPulseHighonCompare + * with pulse width more than one 1588 clock, + * + * @param base ENET peripheral base address. + * @param channel The ENET PTP timer channel number. + * @param isOutputLow True --- timer channel is configured for output compare + * pulse output low. + * false --- timer channel is configured for output compare + * pulse output high. + * @param pulseWidth The pulse width control value, range from 0 ~ 31. + * 0 --- pulse width is one 1588 clock cycle. + * 31 --- pulse width is thirty two 1588 clock cycles. + * @param intEnable Enables or disables the interrupt. + */ +static inline void ENET_Ptp1588SetChannelOutputPulseWidth(ENET_Type *base, + enet_ptp_timer_channel_t channel, + bool isOutputLow, + uint8_t pulseWidth, + bool intEnable) +{ + uint32_t tcrReg; + + tcrReg = ENET_TCSR_TIE(intEnable) | ENET_TCSR_TPWC(pulseWidth); + + if (isOutputLow) + { + tcrReg |= ENET_TCSR_TMODE(kENET_PtpChannelPulseLowonCompare); + } + else + { + tcrReg |= ENET_TCSR_TMODE(kENET_PtpChannelPulseHighonCompare); + } + + /* Disable channel mode first. */ + base->CHANNEL[channel].TCSR = 0; + base->CHANNEL[channel].TCSR = tcrReg; +} +#endif /* FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL */ + /*! - * @brief Sets ENET PTP 1588 timer channel comparison value. + * @brief Sets the ENET PTP 1588 timer channel comparison value. * * @param base ENET peripheral base address. * @param channel The PTP timer channel, see "enet_ptp_timer_channel_t". diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c index 1a71a07e582..f22eff941e9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -40,7 +40,12 @@ void EWM_Init(EWM_Type *base, const ewm_config_t *config) uint32_t value = 0U; +#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \ + (defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE)) +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Ewm0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +#endif value = EWM_CTRL_EWMEN(config->enableEwm) | EWM_CTRL_ASSIN(config->setInputAssertLogic) | EWM_CTRL_INEN(config->enableEwmInput) | EWM_CTRL_INTEN(config->enableInterrupt); #if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER @@ -59,7 +64,12 @@ void EWM_Init(EWM_Type *base, const ewm_config_t *config) void EWM_Deinit(EWM_Type *base) { EWM_DisableInterrupts(base, kEWM_InterruptEnable); +#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \ + (defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE)) +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(kCLOCK_Ewm0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +#endif /* FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE */ } void EWM_GetDefaultConfig(ewm_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h index a5c45b3fe76..aa32ed3c713 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup ewm_driver + * @addtogroup ewm * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -49,14 +48,14 @@ #define FSL_EWM_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ -/*! @brief Describes ewm clock source. */ +/*! @brief Describes EWM clock source. */ #if defined(FSL_FEATURE_EWM_HAS_CLOCK_SELECT) && FSL_FEATURE_EWM_HAS_CLOCK_SELECT typedef enum _ewm_lpo_clock_source { - kEWM_LpoClockSource0 = 0U, /*!< ewm clock sourced from lpo_clk[0]*/ - kEWM_LpoClockSource1 = 1U, /*!< ewm clock sourced from lpo_clk[1]*/ - kEWM_LpoClockSource2 = 2U, /*!< ewm clock sourced from lpo_clk[2]*/ - kEWM_LpoClockSource3 = 3U, /*!< ewm clock sourced from lpo_clk[3]*/ + kEWM_LpoClockSource0 = 0U, /*!< EWM clock sourced from lpo_clk[0]*/ + kEWM_LpoClockSource1 = 1U, /*!< EWM clock sourced from lpo_clk[1]*/ + kEWM_LpoClockSource2 = 2U, /*!< EWM clock sourced from lpo_clk[2]*/ + kEWM_LpoClockSource3 = 3U, /*!< EWM clock sourced from lpo_clk[3]*/ } ewm_lpo_clock_source_t; #endif /* FSL_FEATURE_EWM_HAS_CLOCK_SELECT */ @@ -77,18 +76,18 @@ typedef struct _ewm_config #if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER uint8_t prescaler; /*!< Clock prescaler value */ #endif /* FSL_FEATURE_EWM_HAS_PRESCALER */ - uint8_t compareLowValue; /*!< Compare low register value */ - uint8_t compareHighValue; /*!< Compare high register value */ + uint8_t compareLowValue; /*!< Compare low-register value */ + uint8_t compareHighValue; /*!< Compare high-register value */ } ewm_config_t; /*! - * @brief EWM interrupt configuration structure, default settings all disabled. + * @brief EWM interrupt configuration structure with default settings all disabled. * - * This structure contains the settings for all of the EWM interrupt configurations. + * This structure contains the settings for all of EWM interrupt configurations. */ enum _ewm_interrupt_enable_t { - kEWM_InterruptEnable = EWM_CTRL_INTEN_MASK, /*!< Enable EWM to generate an interrupt*/ + kEWM_InterruptEnable = EWM_CTRL_INTEN_MASK, /*!< Enable the EWM to generate an interrupt*/ }; /*! @@ -98,7 +97,7 @@ enum _ewm_interrupt_enable_t */ enum _ewm_status_flags_t { - kEWM_RunningFlag = EWM_CTRL_EWMEN_MASK, /*!< Running flag, set when ewm is enabled*/ + kEWM_RunningFlag = EWM_CTRL_EWMEN_MASK, /*!< Running flag, set when EWM is enabled*/ }; /******************************************************************************* @@ -110,7 +109,7 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name EWM Initialization and De-initialization + * @name EWM initialization and de-initialization * @{ */ @@ -119,10 +118,10 @@ extern "C" { * * This function is used to initialize the EWM. After calling, the EWM * runs immediately according to the configuration. - * Note that except for interrupt enable control bit, other control bits and registers are write once after a + * Note that, except for the interrupt enable control bit, other control bits and registers are write once after a * CPU reset. Modifying them more than once generates a bus transfer error. * - * Example: + * This is an example. * @code * ewm_config_t config; * EWM_GetDefaultConfig(&config); @@ -131,7 +130,7 @@ extern "C" { * @endcode * * @param base EWM peripheral base address - * @param config The configuration of EWM + * @param config The configuration of the EWM */ void EWM_Init(EWM_Type *base, const ewm_config_t *config); @@ -147,8 +146,8 @@ void EWM_Deinit(EWM_Type *base); /*! * @brief Initializes the EWM configuration structure. * - * This function initializes the EWM configure structure to default values. The default - * values are: + * This function initializes the EWM configuration structure to default values. The default + * values are as follows. * @code * ewmConfig->enableEwm = true; * ewmConfig->enableEwmInput = false; @@ -160,7 +159,7 @@ void EWM_Deinit(EWM_Type *base); * ewmConfig->compareHighValue = 0xFEU; * @endcode * - * @param config Pointer to EWM configuration structure. + * @param config Pointer to the EWM configuration structure. * @see ewm_config_t */ void EWM_GetDefaultConfig(ewm_config_t *config); @@ -179,7 +178,7 @@ void EWM_GetDefaultConfig(ewm_config_t *config); * * @param base EWM peripheral base address * @param mask The interrupts to enable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined * @arg kEWM_InterruptEnable */ static inline void EWM_EnableInterrupts(EWM_Type *base, uint32_t mask) @@ -194,7 +193,7 @@ static inline void EWM_EnableInterrupts(EWM_Type *base, uint32_t mask) * * @param base EWM peripheral base address * @param mask The interrupts to disable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined * @arg kEWM_InterruptEnable */ static inline void EWM_DisableInterrupts(EWM_Type *base, uint32_t mask) @@ -203,19 +202,19 @@ static inline void EWM_DisableInterrupts(EWM_Type *base, uint32_t mask) } /*! - * @brief Gets EWM all status flags. + * @brief Gets all status flags. * * This function gets all status flags. * - * Example for getting Running Flag: + * This is an example for getting the running flag. * @code * uint32_t status; * status = EWM_GetStatusFlags(ewm_base) & kEWM_RunningFlag; * @endcode * @param base EWM peripheral base address * @return State of the status flag: asserted (true) or not-asserted (false).@see _ewm_status_flags_t - * - true: related status flag has been set. - * - false: related status flag is not set. + * - True: a related status flag has been set. + * - False: a related status flag is not set. */ static inline uint32_t EWM_GetStatusFlags(EWM_Type *base) { @@ -223,9 +222,9 @@ static inline uint32_t EWM_GetStatusFlags(EWM_Type *base) } /*! - * @brief Service EWM. + * @brief Services the EWM. * - * This function reset EWM counter to zero. + * This function resets the EWM counter to zero. * * @param base EWM peripheral base address */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c index 2add4e96352..f63e6c98145 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,6 +38,7 @@ * @name Misc utility defines * @{ */ +/*! @brief Alignment utility. */ #ifndef ALIGN_DOWN #define ALIGN_DOWN(x, a) ((x) & (uint32_t)(-((int32_t)(a)))) #endif @@ -45,18 +46,74 @@ #define ALIGN_UP(x, a) (-((int32_t)((uint32_t)(-((int32_t)(x))) & (uint32_t)(-((int32_t)(a)))))) #endif -#define BYTES_JOIN_TO_WORD_1_3(x, y) ((((uint32_t)(x)&0xFFU) << 24) | ((uint32_t)(y)&0xFFFFFFU)) -#define BYTES_JOIN_TO_WORD_2_2(x, y) ((((uint32_t)(x)&0xFFFFU) << 16) | ((uint32_t)(y)&0xFFFFU)) -#define BYTES_JOIN_TO_WORD_3_1(x, y) ((((uint32_t)(x)&0xFFFFFFU) << 8) | ((uint32_t)(y)&0xFFU)) -#define BYTES_JOIN_TO_WORD_1_1_2(x, y, z) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFU) << 16) | ((uint32_t)(z)&0xFFFFU)) -#define BYTES_JOIN_TO_WORD_1_2_1(x, y, z) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFFFU) << 8) | ((uint32_t)(z)&0xFFU)) -#define BYTES_JOIN_TO_WORD_2_1_1(x, y, z) \ - ((((uint32_t)(x)&0xFFFFU) << 16) | (((uint32_t)(y)&0xFFU) << 8) | ((uint32_t)(z)&0xFFU)) -#define BYTES_JOIN_TO_WORD_1_1_1_1(x, y, z, w) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFU) << 16) | (((uint32_t)(z)&0xFFU) << 8) | \ - ((uint32_t)(w)&0xFFU)) +/*! @brief Join bytes to word utility. */ +#define B1P4(b) (((uint32_t)(b)&0xFFU) << 24) +#define B1P3(b) (((uint32_t)(b)&0xFFU) << 16) +#define B1P2(b) (((uint32_t)(b)&0xFFU) << 8) +#define B1P1(b) ((uint32_t)(b)&0xFFU) +#define B2P3(b) (((uint32_t)(b)&0xFFFFU) << 16) +#define B2P2(b) (((uint32_t)(b)&0xFFFFU) << 8) +#define B2P1(b) ((uint32_t)(b)&0xFFFFU) +#define B3P2(b) (((uint32_t)(b)&0xFFFFFFU) << 8) +#define B3P1(b) ((uint32_t)(b)&0xFFFFFFU) +#define BYTES_JOIN_TO_WORD_1_3(x, y) (B1P4(x) | B3P1(y)) +#define BYTES_JOIN_TO_WORD_2_2(x, y) (B2P3(x) | B2P1(y)) +#define BYTES_JOIN_TO_WORD_3_1(x, y) (B3P2(x) | B1P1(y)) +#define BYTES_JOIN_TO_WORD_1_1_2(x, y, z) (B1P4(x) | B1P3(y) | B2P1(z)) +#define BYTES_JOIN_TO_WORD_1_2_1(x, y, z) (B1P4(x) | B2P2(y) | B1P1(z)) +#define BYTES_JOIN_TO_WORD_2_1_1(x, y, z) (B2P3(x) | B1P2(y) | B1P1(z)) +#define BYTES_JOIN_TO_WORD_1_1_1_1(x, y, z, w) (B1P4(x) | B1P3(y) | B1P2(z) | B1P1(w)) +/*@}*/ + +/*! + * @name Secondary flash configuration + * @{ + */ +/*! @brief Indicates whether the secondary flash has its own protection register in flash module. */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FPROTS_PROTS_MASK) +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (1) +#else +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (0) +#endif + +/*! @brief Indicates whether the secondary flash has its own Execute-Only access register in flash module. */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FACSSS_SGSIZE_S_MASK) +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (1) +#else +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (0) +#endif +/*@}*/ + +/*! + * @name Flash cache ands speculation control defines + * @{ + */ +#if defined(MCM_PLACR_CFCC_MASK) || defined(MCM_CPCR2_CCBC_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0) +#endif +#if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0) +#endif +#if defined(MCM_PLACR_DFCS_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0) +#endif +#if defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR_OCMC1_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (0) +#endif +#if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB0CR_S_B_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) || \ + defined(FMC_PFB01CR_S_B_INV_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0) +#endif /*@}*/ /*! @brief Data flash IFR map Field*/ @@ -121,6 +178,7 @@ #define FTFx_ERASE_BLOCK 0x08U /*!< ERSBLK*/ #define FTFx_ERASE_SECTOR 0x09U /*!< ERSSCR*/ #define FTFx_PROGRAM_SECTION 0x0BU /*!< PGMSEC*/ +#define FTFx_GENERATE_CRC 0x0CU /*!< CRCGEN*/ #define FTFx_VERIFY_ALL_BLOCK 0x40U /*!< RD1ALL*/ #define FTFx_READ_ONCE 0x41U /*!< RDONCE or RDINDEX*/ #define FTFx_PROGRAM_ONCE 0x43U /*!< PGMONCE or PGMINDEX*/ @@ -192,19 +250,56 @@ /*@}*/ /*! - * @brief Enumeration for access segment property. + * @name Common flash register access info defines + * @{ */ -enum _flash_access_segment_property -{ - kFLASH_accessSegmentBase = 256UL, -}; +#define FTFx_FCCOB3_REG (FTFx->FCCOB3) +#define FTFx_FCCOB5_REG (FTFx->FCCOB5) +#define FTFx_FCCOB6_REG (FTFx->FCCOB6) +#define FTFx_FCCOB7_REG (FTFx->FCCOB7) + +#if defined(FTFA_FPROTH0_PROT_MASK) || defined(FTFE_FPROTH0_PROT_MASK) || defined(FTFL_FPROTH0_PROT_MASK) +#define FTFx_FPROT_HIGH_REG (FTFx->FPROTH3) +#define FTFx_FPROTH3_REG (FTFx->FPROTH3) +#define FTFx_FPROTH2_REG (FTFx->FPROTH2) +#define FTFx_FPROTH1_REG (FTFx->FPROTH1) +#define FTFx_FPROTH0_REG (FTFx->FPROTH0) +#endif + +#if defined(FTFA_FPROTL0_PROT_MASK) || defined(FTFE_FPROTL0_PROT_MASK) || defined(FTFL_FPROTL0_PROT_MASK) +#define FTFx_FPROT_LOW_REG (FTFx->FPROTL3) +#define FTFx_FPROTL3_REG (FTFx->FPROTL3) +#define FTFx_FPROTL2_REG (FTFx->FPROTL2) +#define FTFx_FPROTL1_REG (FTFx->FPROTL1) +#define FTFx_FPROTL0_REG (FTFx->FPROTL0) +#elif defined(FTFA_FPROT0_PROT_MASK) || defined(FTFE_FPROT0_PROT_MASK) || defined(FTFL_FPROT0_PROT_MASK) +#define FTFx_FPROT_LOW_REG (FTFx->FPROT3) +#define FTFx_FPROTL3_REG (FTFx->FPROT3) +#define FTFx_FPROTL2_REG (FTFx->FPROT2) +#define FTFx_FPROTL1_REG (FTFx->FPROT1) +#define FTFx_FPROTL0_REG (FTFx->FPROT0) +#endif + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER +#define FTFx_FPROTSH_REG (FTFx->FPROTSH) +#define FTFx_FPROTSL_REG (FTFx->FPROTSL) +#endif + +#define FTFx_XACCH3_REG (FTFx->XACCH3) +#define FTFx_XACCL3_REG (FTFx->XACCL3) + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER +#define FTFx_XACCSH_REG (FTFx->XACCSH) +#define FTFx_XACCSL_REG (FTFx->XACCSL) +#endif +/*@}*/ /*! - * @brief Enumeration for acceleration ram property. + * @brief Enumeration for access segment property. */ -enum _flash_acceleration_ram_property +enum _flash_access_segment_property { - kFLASH_accelerationRamSize = 0x400U + kFLASH_AccessSegmentBase = 256UL, }; /*! @@ -212,25 +307,78 @@ enum _flash_acceleration_ram_property */ enum _flash_config_area_range { - kFLASH_configAreaStart = 0x400U, - kFLASH_configAreaEnd = 0x40FU + kFLASH_ConfigAreaStart = 0x400U, + kFLASH_ConfigAreaEnd = 0x40FU }; -/*! @brief program Flash block base address*/ -#define PFLASH_BLOCK_BASE 0x00U - -/*! @brief Total flash region count*/ -#define FSL_FEATURE_FTFx_REGION_COUNT (32U) - /*! * @name Flash register access type defines * @{ */ -#if FLASH_DRIVER_IS_FLASH_RESIDENT -#define FTFx_REG_ACCESS_TYPE volatile uint8_t * +#define FTFx_REG8_ACCESS_TYPE volatile uint8_t * #define FTFx_REG32_ACCESS_TYPE volatile uint32_t * -#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ - /*@}*/ +/*@}*/ + +/*! + * @brief MCM cache register access info defines. + */ +#if defined(MCM_PLACR_CFCC_MASK) +#define MCM_CACHE_CLEAR_MASK MCM_PLACR_CFCC_MASK +#define MCM_CACHE_CLEAR_SHIFT MCM_PLACR_CFCC_SHIFT +#if defined(MCM) +#define MCM0_CACHE_REG MCM->PLACR +#elif defined(MCM0) +#define MCM0_CACHE_REG MCM0->PLACR +#endif +#if defined(MCM1) +#define MCM1_CACHE_REG MCM1->PLACR +#endif +#elif defined(MCM_CPCR2_CCBC_MASK) +#define MCM_CACHE_CLEAR_MASK MCM_CPCR2_CCBC_MASK +#define MCM_CACHE_CLEAR_SHIFT MCM_CPCR2_CCBC_SHIFT +#if defined(MCM) +#define MCM0_CACHE_REG MCM->CPCR2 +#elif defined(MCM0) +#define MCM0_CACHE_REG MCM0->CPCR2 +#endif +#if defined(MCM1) +#define MCM1_CACHE_REG MCM1->CPCR2 +#endif +#endif + +/*! + * @brief MSCM cache register access info defines. + */ +#if defined(MSCM_OCMDR_OCM1_MASK) +#define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCM1_MASK +#define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCM1_SHIFT +#define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCM1(x) +#elif defined(MSCM_OCMDR_OCMC1_MASK) +#define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCMC1_MASK +#define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCMC1_SHIFT +#define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCMC1(x) +#endif + +/*! + * @brief MSCM prefetch speculation defines. + */ +#define MSCM_OCMDR_OCMC1_DFDS_MASK (0x10U) +#define MSCM_OCMDR_OCMC1_DFCS_MASK (0x20U) + +#define MSCM_OCMDR_OCMC1_DFDS_SHIFT (4U) +#define MSCM_OCMDR_OCMC1_DFCS_SHIFT (5U) + +/*! + * @brief Flash size encoding rule. + */ +#define FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2 (0x00U) +#define FLASH_MEMORY_SIZE_ENCODING_RULE_K3 (0x01U) + +#if defined(K32W042S1M2_M0P_SERIES) || defined(K32W042S1M2_M4_SERIES) +#define FLASH_MEMORY_SIZE_ENCODING_RULE (FLASH_MEMORY_SIZE_ENCODING_RULE_K3) +#else +#define FLASH_MEMORY_SIZE_ENCODING_RULE (FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2) +#endif /******************************************************************************* * Prototypes @@ -238,9 +386,9 @@ enum _flash_config_area_range #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief Copy flash_run_command() to RAM*/ -static void copy_flash_run_command(uint8_t *flashRunCommand); +static void copy_flash_run_command(uint32_t *flashRunCommand); /*! @brief Copy flash_cache_clear_command() to RAM*/ -static void copy_flash_cache_clear_command(uint8_t *flashCacheClearCommand); +static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation); /*! @brief Check whether flash execute-in-ram functions are ready*/ static status_t flash_check_execute_in_ram_function_info(flash_config_t *config); #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ @@ -251,6 +399,9 @@ static status_t flash_command_sequence(flash_config_t *config); /*! @brief Perform the cache clear to the flash*/ void flash_cache_clear(flash_config_t *config); +/*! @brief Process the cache to the flash*/ +static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process); + /*! @brief Validates the range and alignment of the given address range.*/ static status_t flash_check_range(flash_config_t *config, uint32_t startAddress, @@ -291,44 +442,131 @@ static status_t flash_validate_swap_indicator_address(flash_config_t *config, ui static inline status_t flasn_check_flexram_function_option_range(flash_flexram_function_option_t option); #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ +/*! @brief Gets the flash protection information (region size, region count).*/ +static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info); + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/ +static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info); +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(flash_config_t *config); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(void); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM +/*! @brief Sets the prefetch speculation buffer to the flash by MSCM.*/ +void mscm_flash_prefetch_speculation_enable(bool enable); +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC +/*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ +void fmc_flash_prefetch_speculation_clear(void); +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ + /******************************************************************************* * Variables ******************************************************************************/ /*! @brief Access to FTFx->FCCOB */ -#if defined(FSL_FEATURE_FLASH_IS_FTFA) && FSL_FEATURE_FLASH_IS_FTFA -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFA->FCCOB3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFE->FCCOB3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFL) && FSL_FEATURE_FLASH_IS_FTFL -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFL->FCCOB3; -#else -#error "Unknown flash controller" +volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFx_FCCOB3_REG; +/*! @brief Access to FTFx->FPROT */ +volatile uint32_t *const kFPROTL = (volatile uint32_t *)&FTFx_FPROT_LOW_REG; +#if defined(FTFx_FPROT_HIGH_REG) +volatile uint32_t *const kFPROTH = (volatile uint32_t *)&FTFx_FPROT_HIGH_REG; #endif -/*! @brief Access to FTFx->FPROT */ -#if defined(FSL_FEATURE_FLASH_IS_FTFA) && FSL_FEATURE_FLASH_IS_FTFA -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFA->FPROT3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFE->FPROT3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFL) && FSL_FEATURE_FLASH_IS_FTFL -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFL->FPROT3; -#else -#error "Unknown flash controller" +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER +volatile uint8_t *const kFPROTSL = (volatile uint8_t *)&FTFx_FPROTSL_REG; +volatile uint8_t *const kFPROTSH = (volatile uint8_t *)&FTFx_FPROTSH_REG; #endif #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief A function pointer used to point to relocated flash_run_command() */ -static void (*callFlashRunCommand)(FTFx_REG_ACCESS_TYPE ftfx_fstat); -/*! @brief A function pointer used to point to relocated flash_cache_clear_command() */ -static void (*callFlashCacheClearCommand)(FTFx_REG32_ACCESS_TYPE ftfx_reg); +static void (*callFlashRunCommand)(FTFx_REG8_ACCESS_TYPE ftfx_fstat); +/*! @brief A function pointer used to point to relocated flash_common_bit_operation() */ +static void (*callFlashCommonBitOperation)(FTFx_REG32_ACCESS_TYPE base, + uint32_t bitMask, + uint32_t bitShift, + uint32_t bitValue); + +/*! + * @brief Position independent code of flash_run_command() + * + * Note1: The prototype of C function is shown as below: + * @code + * void flash_run_command(FTFx_REG8_ACCESS_TYPE ftfx_fstat) + * { + * // clear CCIF bit + * *ftfx_fstat = FTFx_FSTAT_CCIF_MASK; + * + * // Check CCIF bit of the flash status register, wait till it is set. + * // IP team indicates that this loop will always complete. + * while (!((*ftfx_fstat) & FTFx_FSTAT_CCIF_MASK)) + * { + * } + * } + * @endcode + * Note2: The binary code is generated by IAR 7.70.1 + */ +const static uint16_t s_flashRunCommandFunctionCode[] = { + 0x2180, /* MOVS R1, #128 ; 0x80 */ + 0x7001, /* STRB R1, [R0] */ + /* @4: */ + 0x7802, /* LDRB R2, [R0] */ + 0x420a, /* TST R2, R1 */ + 0xd0fc, /* BEQ.N @4 */ + 0x4770 /* BX LR */ +}; + +/*! + * @brief Position independent code of flash_common_bit_operation() + * + * Note1: The prototype of C function is shown as below: + * @code + * void flash_common_bit_operation(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t + * bitValue) + * { + * if (bitMask) + * { + * uint32_t value = (((uint32_t)(((uint32_t)(bitValue)) << bitShift)) & bitMask); + * *base = (*base & (~bitMask)) | value; + * } + * + * __ISB(); + * __DSB(); + * } + * @endcode + * Note2: The binary code is generated by IAR 7.70.1 + */ +const static uint16_t s_flashCommonBitOperationFunctionCode[] = { + 0xb510, /* PUSH {R4, LR} */ + 0x2900, /* CMP R1, #0 */ + 0xd005, /* BEQ.N @12 */ + 0x6804, /* LDR R4, [R0] */ + 0x438c, /* BICS R4, R4, R1 */ + 0x4093, /* LSLS R3, R3, R2 */ + 0x4019, /* ANDS R1, R1, R3 */ + 0x4321, /* ORRS R1, R1, R4 */ + 0x6001, /* STR R1, [R0] */ + /* @12: */ + 0xf3bf, 0x8f6f, /* ISB */ + 0xf3bf, 0x8f4f, /* DSB */ + 0xbd10 /* POP {R4, PC} */ +}; #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED) /*! @brief A static buffer used to hold flash_run_command() */ -static uint8_t s_flashRunCommand[kFLASH_executeInRamFunctionMaxSize]; -/*! @brief A static buffer used to hold flash_cache_clear_command() */ -static uint8_t s_flashCacheClearCommand[kFLASH_executeInRamFunctionMaxSize]; +static uint32_t s_flashRunCommand[kFLASH_ExecuteInRamFunctionMaxSizeInWords]; +/*! @brief A static buffer used to hold flash_common_bit_operation() */ +static uint32_t s_flashCommonBitOperation[kFLASH_ExecuteInRamFunctionMaxSizeInWords]; /*! @brief Flash execute-in-ram function information */ static flash_execute_in_ram_function_config_t s_flashExecuteInRamFunctionInfo; #endif @@ -351,6 +589,7 @@ static flash_execute_in_ram_function_config_t s_flashExecuteInRamFunctionInfo; * flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; * @endcode */ +#if (FLASH_MEMORY_SIZE_ENCODING_RULE == FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2) const uint16_t kPFlashDensities[] = { 8, /* 0x0 - 8192, 8KB */ 16, /* 0x1 - 16384, 16KB */ @@ -369,6 +608,26 @@ const uint16_t kPFlashDensities[] = { 1536, /* 0xe - 1572864, 1.5MB */ /* 2048, 0xf - 2097152, 2MB */ }; +#elif(FLASH_MEMORY_SIZE_ENCODING_RULE == FLASH_MEMORY_SIZE_ENCODING_RULE_K3) +const uint16_t kPFlashDensities[] = { + 0, /* 0x0 - undefined */ + 0, /* 0x1 - undefined */ + 0, /* 0x2 - undefined */ + 0, /* 0x3 - undefined */ + 0, /* 0x4 - undefined */ + 0, /* 0x5 - undefined */ + 0, /* 0x6 - undefined */ + 0, /* 0x7 - undefined */ + 0, /* 0x8 - undefined */ + 0, /* 0x9 - undefined */ + 256, /* 0xa - 262144, 256KB */ + 0, /* 0xb - undefined */ + 1024, /* 0xc - 1048576, 1MB */ + 0, /* 0xd - undefined */ + 0, /* 0xe - undefined */ + 0, /* 0xf - undefined */ +}; +#endif /******************************************************************************* * Code @@ -376,39 +635,86 @@ const uint16_t kPFlashDensities[] = { status_t FLASH_Init(flash_config_t *config) { - uint32_t flashDensity; - if (config == NULL) { return kStatus_FLASH_InvalidArgument; } - /* calculate the flash density from SIM_FCFG1.PFSIZE */ - uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT; - /* PFSIZE=0xf means that on customer parts the IFR was not correctly programmed. - * We just use the pre-defined flash size in feature file here to support pre-production parts */ - if (pfsize == 0xf) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - flashDensity = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE; +/* calculate the flash density from SIM_FCFG1.PFSIZE */ +#if defined(SIM_FCFG1_CORE1_PFSIZE_MASK) + uint32_t flashDensity; + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE1_PFSIZE_MASK) >> SIM_FCFG1_CORE1_PFSIZE_SHIFT; + if (pfsize == 0xf) + { + flashDensity = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; + } + else + { + flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; + } + config->PFlashTotalSize = flashDensity; +#else + /* Unused code to solve MISRA-C issue*/ + config->PFlashBlockBase = kPFlashDensities[0]; + config->PFlashTotalSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; +#endif + config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS; + config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT; + config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE; } else +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ { - flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; - } + uint32_t flashDensity; + +/* calculate the flash density from SIM_FCFG1.PFSIZE */ +#if defined(SIM_FCFG1_CORE0_PFSIZE_MASK) + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE0_PFSIZE_MASK) >> SIM_FCFG1_CORE0_PFSIZE_SHIFT; +#elif defined(SIM_FCFG1_PFSIZE_MASK) + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT; +#else +#error "Unknown flash size" +#endif + /* PFSIZE=0xf means that on customer parts the IFR was not correctly programmed. + * We just use the pre-defined flash size in feature file here to support pre-production parts */ + if (pfsize == 0xf) + { + flashDensity = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE; + } + else + { + flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; + } - /* fill out a few of the structure members */ - config->PFlashBlockBase = PFLASH_BLOCK_BASE; - config->PFlashTotalSize = flashDensity; - config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; - config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; + /* fill out a few of the structure members */ + config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; + config->PFlashTotalSize = flashDensity; + config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; + config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; + } + { #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL - config->PFlashAccessSegmentSize = kFLASH_accessSegmentBase << FTFx->FACSS; - config->PFlashAccessSegmentCount = FTFx->FACSN; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSSS; + config->PFlashAccessSegmentCount = FTFx->FACSNS; + } + else +#endif + { + config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSS; + config->PFlashAccessSegmentCount = FTFx->FACSN; + } #else - config->PFlashAccessSegmentSize = 0; - config->PFlashAccessSegmentCount = 0; + config->PFlashAccessSegmentSize = 0; + config->PFlashAccessSegmentCount = 0; #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + } config->PFlashCallback = NULL; @@ -418,7 +724,7 @@ status_t FLASH_Init(flash_config_t *config) { s_flashExecuteInRamFunctionInfo.activeFunctionCount = 0; s_flashExecuteInRamFunctionInfo.flashRunCommand = s_flashRunCommand; - s_flashExecuteInRamFunctionInfo.flashCacheClearCommand = s_flashCacheClearCommand; + s_flashExecuteInRamFunctionInfo.flashCommonBitOperation = s_flashCommonBitOperation; config->flashExecuteInRamFunctionInfo = &s_flashExecuteInRamFunctionInfo.activeFunctionCount; FLASH_PrepareExecuteInRamFunctions(config); } @@ -467,8 +773,8 @@ status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config) flashExecuteInRamFunctionInfo = (flash_execute_in_ram_function_config_t *)config->flashExecuteInRamFunctionInfo; copy_flash_run_command(flashExecuteInRamFunctionInfo->flashRunCommand); - copy_flash_cache_clear_command(flashExecuteInRamFunctionInfo->flashCacheClearCommand); - flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_executeInRamFunctionTotalNum; + copy_flash_common_bit_operation(flashExecuteInRamFunctionInfo->flashCommonBitOperation); + flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_ExecuteInRamFunctionTotalNum; return kStatus_FLASH_Success; } @@ -493,6 +799,8 @@ status_t FLASH_EraseAll(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -513,22 +821,29 @@ status_t FLASH_EraseAll(flash_config_t *config, uint32_t key) status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key) { uint32_t sectorSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; uint32_t endAddress; /* storing end address */ uint32_t numberOfSectors; /* number of sectors calculated by endAddress */ status_t returnCode; - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectorCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectorCmdAddressAligment); + if (returnCode) + { + return returnCode; + } + + /* Validate the user key */ + returnCode = flash_check_user_key(key); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; - sectorSize = flashInfo.activeSectorSize; + start = flashOperationInfo.convertedAddress; + sectorSize = flashOperationInfo.activeSectorSize; /* calculating Flash end address */ endAddress = start + lengthInBytes - 1; @@ -541,6 +856,8 @@ status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBy endAddress = numberOfSectors * sectorSize - 1; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* the start address will increment to the next sector address * until it reaches the endAdddress */ while (start <= endAddress) @@ -548,13 +865,6 @@ status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBy /* preparing passing parameter to erase a flash block */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_SECTOR, start); - /* Validate the user key */ - returnCode = flash_check_user_key(key); - if (returnCode) - { - return returnCode; - } - /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -601,6 +911,8 @@ status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -639,6 +951,8 @@ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -650,33 +964,35 @@ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key) status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if (src == NULL) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.blockWriteUnitSize); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.blockWriteUnitSize); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; + start = flashOperationInfo.convertedAddress; + + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); while (lengthInBytes > 0) { /* preparing passing parameter to program the flash block */ kFCCOBx[1] = *src++; - if (4 == flashInfo.blockWriteUnitSize) + if (4 == flashOperationInfo.blockWriteUnitSize) { kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_LONGWORD, start); } - else if (8 == flashInfo.blockWriteUnitSize) + else if (8 == flashOperationInfo.blockWriteUnitSize) { kFCCOBx[2] = *src++; kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_PHRASE, start); @@ -702,10 +1018,10 @@ status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, ui else { /* update start address for next iteration */ - start += flashInfo.blockWriteUnitSize; + start += flashOperationInfo.blockWriteUnitSize; /* update lengthInBytes for next iteration */ - lengthInBytes -= flashInfo.blockWriteUnitSize; + lengthInBytes -= flashOperationInfo.blockWriteUnitSize; } } @@ -742,6 +1058,8 @@ status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint32_t *src } #endif /* FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT */ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -755,7 +1073,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * { status_t returnCode; uint32_t sectorSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD bool needSwitchFlexRamMode = false; #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ @@ -765,17 +1083,17 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectionCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; - sectorSize = flashInfo.activeSectorSize; + start = flashOperationInfo.convertedAddress; + sectorSize = flashOperationInfo.activeSectorSize; #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD /* Switch function of FlexRAM if needed */ @@ -783,7 +1101,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * { needSwitchFlexRamMode = true; - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableAsRam); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableAsRam); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_SetFlexramAsRamError; @@ -791,6 +1109,8 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * } #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + while (lengthInBytes > 0) { /* Make sure the write operation doesn't span two sectors */ @@ -819,9 +1139,9 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * uint32_t programSizeOfCurrentPass; uint32_t numberOfPhases; - if (lengthTobeProgrammedOfCurrentSector > kFLASH_accelerationRamSize) + if (lengthTobeProgrammedOfCurrentSector > kFLASH_AccelerationRamSize) { - programSizeOfCurrentPass = kFLASH_accelerationRamSize; + programSizeOfCurrentPass = kFLASH_AccelerationRamSize; } else { @@ -833,7 +1153,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * /* Set start address of the data to be programmed */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_SECTION, start + currentOffset); /* Set program size in terms of FEATURE_FLASH_SECTION_CMD_ADDRESS_ALIGMENT */ - numberOfPhases = programSizeOfCurrentPass / flashInfo.sectionCmdAddressAligment; + numberOfPhases = programSizeOfCurrentPass / flashOperationInfo.sectionCmdAddressAligment; kFCCOBx[1] = BYTES_JOIN_TO_WORD_2_2(numberOfPhases, 0xFFFFU); @@ -867,7 +1187,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * /* Restore function of FlexRAM if needed. */ if (needSwitchFlexRamMode) { - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableForEeprom); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableForEeprom); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_RecoverFlexramAsEepromError; @@ -904,7 +1224,7 @@ status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, { needSwitchFlexRamMode = true; - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableForEeprom); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableForEeprom); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_SetFlexramAsEepromError; @@ -950,7 +1270,7 @@ status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, /* Switch function of FlexRAM if needed */ if (needSwitchFlexRamMode) { - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableAsRam); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableAsRam); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_RecoverFlexramAsRamError; @@ -966,17 +1286,18 @@ status_t FLASH_ReadResource( flash_config_t *config, uint32_t start, uint32_t *dst, uint32_t lengthInBytes, flash_read_resource_option_t option) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if ((config == NULL) || (dst == NULL)) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_resource_range(start, lengthInBytes, flashInfo.resourceCmdAddressAligment, option); + returnCode = + flash_check_resource_range(start, lengthInBytes, flashOperationInfo.resourceCmdAddressAligment, option); if (returnCode != kStatus_FLASH_Success) { return returnCode; @@ -986,11 +1307,11 @@ status_t FLASH_ReadResource( { /* preparing passing parameter */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_READ_RESOURCE, start); - if (flashInfo.resourceCmdAddressAligment == 4) + if (flashOperationInfo.resourceCmdAddressAligment == 4) { kFCCOBx[2] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU); } - else if (flashInfo.resourceCmdAddressAligment == 8) + else if (flashOperationInfo.resourceCmdAddressAligment == 8) { kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU); } @@ -1008,14 +1329,14 @@ status_t FLASH_ReadResource( /* fetch data */ *dst++ = kFCCOBx[1]; - if (flashInfo.resourceCmdAddressAligment == 8) + if (flashOperationInfo.resourceCmdAddressAligment == 8) { *dst++ = kFCCOBx[2]; } /* update start address for next iteration */ - start += flashInfo.resourceCmdAddressAligment; + start += flashOperationInfo.resourceCmdAddressAligment; /* update lengthInBytes for next iteration */ - lengthInBytes -= flashInfo.resourceCmdAddressAligment; + lengthInBytes -= flashOperationInfo.resourceCmdAddressAligment; } return (returnCode); @@ -1075,7 +1396,7 @@ status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t * if (FLASH_SECURITY_STATE_UNSECURED == (registerValue & FTFx_FSEC_SEC_MASK)) { /* Flash in unsecured state */ - *state = kFLASH_securityStateNotSecure; + *state = kFLASH_SecurityStateNotSecure; } else { @@ -1084,12 +1405,12 @@ status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t * if (FLASH_SECURITY_STATE_KEYEN == (registerValue & FTFx_FSEC_KEYEN_MASK)) { /* Backdoor key security enabled */ - *state = kFLASH_securityStateBackdoorEnabled; + *state = kFLASH_SecurityStateBackdoorEnabled; } else { /* Backdoor key security disabled */ - *state = kFLASH_securityStateBackdoorDisabled; + *state = kFLASH_SecurityStateBackdoorDisabled; } } @@ -1146,22 +1467,22 @@ status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t leng { /* Check arguments. */ uint32_t blockSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; uint32_t nextBlockStartAddress; uint32_t remainingBytes; status_t returnCode; - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectionCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment); if (returnCode) { return returnCode; } - flash_get_matched_operation_info(config, start, &flashInfo); - start = flashInfo.convertedAddress; - blockSize = flashInfo.activeBlockSize; + flash_get_matched_operation_info(config, start, &flashOperationInfo); + start = flashOperationInfo.convertedAddress; + blockSize = flashOperationInfo.activeBlockSize; nextBlockStartAddress = ALIGN_UP(start, blockSize); if (nextBlockStartAddress == start) @@ -1180,7 +1501,7 @@ status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t leng verifyLength = remainingBytes; } - numberOfPhrases = verifyLength / flashInfo.sectionCmdAddressAligment; + numberOfPhrases = verifyLength / flashOperationInfo.sectionCmdAddressAligment; /* Fill in verify section command parameters. */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_VERIFY_SECTION, start); @@ -1210,22 +1531,22 @@ status_t FLASH_VerifyProgram(flash_config_t *config, uint32_t *failedData) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if (expectedData == NULL) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.checkCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.checkCmdAddressAligment); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; + start = flashOperationInfo.convertedAddress; while (lengthInBytes) { @@ -1251,9 +1572,9 @@ status_t FLASH_VerifyProgram(flash_config_t *config, break; } - lengthInBytes -= flashInfo.checkCmdAddressAligment; - expectedData += flashInfo.checkCmdAddressAligment / sizeof(*expectedData); - start += flashInfo.checkCmdAddressAligment; + lengthInBytes -= flashOperationInfo.checkCmdAddressAligment; + expectedData += flashOperationInfo.checkCmdAddressAligment / sizeof(*expectedData); + start += flashOperationInfo.checkCmdAddressAligment; } return (returnCode); @@ -1279,19 +1600,21 @@ status_t FLASH_IsProtected(flash_config_t *config, flash_protection_state_t *protection_state) { uint32_t endAddress; /* end address for protection check */ - uint32_t protectionRegionSize; /* size of flash protection region */ uint32_t regionCheckedCounter; /* increments each time the flash address was checked for * protection status */ uint32_t regionCounter; /* incrementing variable used to increment through the flash * protection regions */ uint32_t protectStatusCounter; /* increments each time a flash region was detected as protected */ - uint8_t flashRegionProtectStatus[FSL_FEATURE_FTFx_REGION_COUNT]; /* array of the protection status for each + uint8_t flashRegionProtectStatus[FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT]; /* array of the protection + * status for each * protection region */ - uint32_t flashRegionAddress[FSL_FEATURE_FTFx_REGION_COUNT + 1]; /* array of the start addresses for each flash - * protection region. Note this is REGION_COUNT+1 - * due to requiring the next start address after - * the end of flash for loop-check purposes below */ + uint32_t flashRegionAddress[FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT + + 1]; /* array of the start addresses for each flash + * protection region. Note this is REGION_COUNT+1 + * due to requiring the next start address after + * the end of flash for loop-check purposes below */ + flash_protection_config_t flashProtectionInfo; /* flash protection information */ status_t returnCode; if (protection_state == NULL) @@ -1306,28 +1629,24 @@ status_t FLASH_IsProtected(flash_config_t *config, return returnCode; } - /* calculating Flash end address */ - endAddress = start + lengthInBytes; - - /* Calculate the size of the flash protection region - * If the flash density is > 32KB, then protection region is 1/32 of total flash density - * Else if flash density is < 32KB, then flash protection region is set to 1KB */ - if (config->PFlashTotalSize > 32 * 1024) - { - protectionRegionSize = (config->PFlashTotalSize) / FSL_FEATURE_FTFx_REGION_COUNT; - } - else + /* Get necessary flash protection information. */ + returnCode = flash_get_protection_info(config, &flashProtectionInfo); + if (returnCode) { - protectionRegionSize = 1024; + return returnCode; } + /* calculating Flash end address */ + endAddress = start + lengthInBytes; + /* populate the flashRegionAddress array with the start address of each flash region */ regionCounter = 0; /* make sure regionCounter is initialized to 0 first */ /* populate up to 33rd element of array, this is the next address after end of flash array */ - while (regionCounter <= FSL_FEATURE_FTFx_REGION_COUNT) + while (regionCounter <= flashProtectionInfo.regionCount) { - flashRegionAddress[regionCounter] = config->PFlashBlockBase + protectionRegionSize * regionCounter; + flashRegionAddress[regionCounter] = + flashProtectionInfo.regionBase + flashProtectionInfo.regionSize * regionCounter; regionCounter++; } @@ -1341,24 +1660,80 @@ status_t FLASH_IsProtected(flash_config_t *config, * regionCounter is used to determine which FPROT[3:0] register to check for protection status * Note: FPROT=1 means NOT protected, FPROT=0 means protected */ regionCounter = 0; /* make sure regionCounter is initialized to 0 first */ - while (regionCounter < FSL_FEATURE_FTFx_REGION_COUNT) + while (regionCounter < flashProtectionInfo.regionCount) { - if (regionCounter < 8) - { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT3) >> regionCounter) & (0x01u); - } - else if ((regionCounter >= 8) && (regionCounter < 16)) - { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT2) >> (regionCounter - 8)) & (0x01u); - } - else if ((regionCounter >= 16) && (regionCounter < 24)) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT1) >> (regionCounter - 16)) & (0x01u); + if (regionCounter < 8) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSL_REG >> regionCounter) & (0x01u); + } + else if ((regionCounter >= 8) && (regionCounter < 16)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSH_REG >> (regionCounter - 8)) & (0x01u); + } + else + { + break; + } } else +#endif { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT0) >> (regionCounter - 24)) & (0x01u); + /* Note: So far protection region count may be 16/20/24/32/64 */ + if (regionCounter < 8) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL3_REG >> regionCounter) & (0x01u); + } + else if ((regionCounter >= 8) && (regionCounter < 16)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL2_REG >> (regionCounter - 8)) & (0x01u); + } +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT > 16) +#if (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 20) + else if ((regionCounter >= 16) && (regionCounter < 20)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u); + } +#else + else if ((regionCounter >= 16) && (regionCounter < 24)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u); + } +#endif /* (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 20) */ +#endif +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT > 24) + else if ((regionCounter >= 24) && (regionCounter < 32)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL0_REG >> (regionCounter - 24)) & (0x01u); + } +#endif +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && \ + (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 64) + else if (regionCounter < 40) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH3_REG >> (regionCounter - 32)) & (0x01u); + } + else if (regionCounter < 48) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH2_REG >> (regionCounter - 40)) & (0x01u); + } + else if (regionCounter < 56) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH1_REG >> (regionCounter - 48)) & (0x01u); + } + else if (regionCounter < 64) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH0_REG >> (regionCounter - 56)) & (0x01u); + } +#endif + else + { + break; + } } + regionCounter++; } @@ -1386,7 +1761,7 @@ status_t FLASH_IsProtected(flash_config_t *config, /* increment protectStatusCounter to indicate this region is protected */ protectStatusCounter++; } - start += protectionRegionSize; /* increment to an address within the next region */ + start += flashProtectionInfo.regionSize; /* increment to an address within the next region */ } regionCounter++; /* increment regionCounter to check for the next flash protection region */ } @@ -1394,18 +1769,18 @@ status_t FLASH_IsProtected(flash_config_t *config, /* if protectStatusCounter == 0, then no region of the desired flash region is protected */ if (protectStatusCounter == 0) { - *protection_state = kFLASH_protectionStateUnprotected; + *protection_state = kFLASH_ProtectionStateUnprotected; } /* if protectStatusCounter == regionCheckedCounter, then each region checked was protected */ else if (protectStatusCounter == regionCheckedCounter) { - *protection_state = kFLASH_protectionStateProtected; + *protection_state = kFLASH_ProtectionStateProtected; } /* if protectStatusCounter != regionCheckedCounter, then protection status is mixed * In other words, some regions are protected while others are unprotected */ else { - *protection_state = kFLASH_protectionStateMixed; + *protection_state = kFLASH_ProtectionStateMixed; } return (returnCode); @@ -1416,6 +1791,9 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, uint32_t lengthInBytes, flash_execute_only_access_state_t *access_state) { +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL + flash_access_config_t flashAccessInfo; /* flash Execute-Only information */ +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ status_t returnCode; if (access_state == NULL) @@ -1431,6 +1809,13 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, } #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL + /* Get necessary flash Execute-Only information. */ + returnCode = flash_get_access_info(config, &flashAccessInfo); + if (returnCode) + { + return returnCode; + } + { uint32_t executeOnlySegmentCounter = 0; @@ -1438,31 +1823,56 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, uint32_t endAddress = start + lengthInBytes; /* Aligning start address and end address */ - uint32_t alignedStartAddress = ALIGN_DOWN(start, config->PFlashAccessSegmentSize); - uint32_t alignedEndAddress = ALIGN_UP(endAddress, config->PFlashAccessSegmentSize); + uint32_t alignedStartAddress = ALIGN_DOWN(start, flashAccessInfo.SegmentSize); + uint32_t alignedEndAddress = ALIGN_UP(endAddress, flashAccessInfo.SegmentSize); uint32_t segmentIndex = 0; uint32_t maxSupportedExecuteOnlySegmentCount = - (alignedEndAddress - alignedStartAddress) / config->PFlashAccessSegmentSize; + (alignedEndAddress - alignedStartAddress) / flashAccessInfo.SegmentSize; while (start < endAddress) { uint32_t xacc; - segmentIndex = start / config->PFlashAccessSegmentSize; + segmentIndex = (start - flashAccessInfo.SegmentBase) / flashAccessInfo.SegmentSize; - if (segmentIndex < 32) - { - xacc = *(const volatile uint32_t *)&FTFx->XACCL3; - } - else if (segmentIndex < config->PFlashAccessSegmentCount) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - xacc = *(const volatile uint32_t *)&FTFx->XACCH3; - segmentIndex -= 32; + /* For secondary flash, The two XACCS registers allow up to 16 restricted segments of equal memory size. + */ + if (segmentIndex < 8) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSL_REG; + } + else if (segmentIndex < flashAccessInfo.SegmentCount) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSH_REG; + segmentIndex -= 8; + } + else + { + break; + } } else +#endif { - break; + /* For primary flash, The eight XACC registers allow up to 64 restricted segments of equal memory size. + */ + if (segmentIndex < 32) + { + xacc = *(const volatile uint32_t *)&FTFx_XACCL3_REG; + } + else if (segmentIndex < flashAccessInfo.SegmentCount) + { + xacc = *(const volatile uint32_t *)&FTFx_XACCH3_REG; + segmentIndex -= 32; + } + else + { + break; + } } /* Determine if this address range is in a execute-only protection flash segment. */ @@ -1471,24 +1881,24 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, executeOnlySegmentCounter++; } - start += config->PFlashAccessSegmentSize; + start += flashAccessInfo.SegmentSize; } if (executeOnlySegmentCounter < 1u) { - *access_state = kFLASH_accessStateUnLimited; + *access_state = kFLASH_AccessStateUnLimited; } else if (executeOnlySegmentCounter < maxSupportedExecuteOnlySegmentCount) { - *access_state = kFLASH_accessStateMixed; + *access_state = kFLASH_AccessStateMixed; } else { - *access_state = kFLASH_accessStateExecuteOnly; + *access_state = kFLASH_AccessStateExecuteOnly; } } #else - *access_state = kFLASH_accessStateUnLimited; + *access_state = kFLASH_AccessStateUnLimited; #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ return (returnCode); @@ -1503,27 +1913,27 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro switch (whichProperty) { - case kFLASH_propertyPflashSectorSize: + case kFLASH_PropertyPflashSectorSize: *value = config->PFlashSectorSize; break; - case kFLASH_propertyPflashTotalSize: + case kFLASH_PropertyPflashTotalSize: *value = config->PFlashTotalSize; break; - case kFLASH_propertyPflashBlockSize: + case kFLASH_PropertyPflashBlockSize: *value = config->PFlashTotalSize / FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; break; - case kFLASH_propertyPflashBlockCount: - *value = config->PFlashBlockCount; + case kFLASH_PropertyPflashBlockCount: + *value = (uint32_t)config->PFlashBlockCount; break; - case kFLASH_propertyPflashBlockBaseAddr: + case kFLASH_PropertyPflashBlockBaseAddr: *value = config->PFlashBlockBase; break; - case kFLASH_propertyPflashFacSupport: + case kFLASH_PropertyPflashFacSupport: #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) *value = FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL; #else @@ -1531,31 +1941,39 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ break; - case kFLASH_propertyPflashAccessSegmentSize: + case kFLASH_PropertyPflashAccessSegmentSize: *value = config->PFlashAccessSegmentSize; break; - case kFLASH_propertyPflashAccessSegmentCount: + case kFLASH_PropertyPflashAccessSegmentCount: *value = config->PFlashAccessSegmentCount; break; + case kFLASH_PropertyFlexRamBlockBaseAddr: + *value = config->FlexRAMBlockBase; + break; + + case kFLASH_PropertyFlexRamTotalSize: + *value = config->FlexRAMTotalSize; + break; + #if FLASH_SSD_IS_FLEXNVM_ENABLED - case kFLASH_propertyDflashSectorSize: + case kFLASH_PropertyDflashSectorSize: *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE; break; - case kFLASH_propertyDflashTotalSize: + case kFLASH_PropertyDflashTotalSize: *value = config->DFlashTotalSize; break; - case kFLASH_propertyDflashBlockSize: + case kFLASH_PropertyDflashBlockSize: *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SIZE; break; - case kFLASH_propertyDflashBlockCount: + case kFLASH_PropertyDflashBlockCount: *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT; break; - case kFLASH_propertyDflashBlockBaseAddr: + case kFLASH_PropertyDflashBlockBaseAddr: *value = config->DFlashBlockBase; break; - case kFLASH_propertyEepromTotalSize: + case kFLASH_PropertyEepromTotalSize: *value = config->EEpromTotalSize; break; #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ @@ -1567,6 +1985,65 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro return kStatus_FLASH_Success; } +status_t FLASH_SetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t value) +{ + status_t status = kStatus_FLASH_Success; + + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + switch (whichProperty) + { +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + case kFLASH_PropertyFlashMemoryIndex: + if ((value != (uint32_t)kFLASH_MemoryIndexPrimaryFlash) && + (value != (uint32_t)kFLASH_MemoryIndexSecondaryFlash)) + { + return kStatus_FLASH_InvalidPropertyValue; + } + config->FlashMemoryIndex = (uint8_t)value; + break; +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ + + case kFLASH_PropertyFlashCacheControllerIndex: + if ((value != (uint32_t)kFLASH_CacheControllerIndexForCore0) && + (value != (uint32_t)kFLASH_CacheControllerIndexForCore1)) + { + return kStatus_FLASH_InvalidPropertyValue; + } + config->FlashCacheControllerIndex = (uint8_t)value; + break; + + case kFLASH_PropertyPflashSectorSize: + case kFLASH_PropertyPflashTotalSize: + case kFLASH_PropertyPflashBlockSize: + case kFLASH_PropertyPflashBlockCount: + case kFLASH_PropertyPflashBlockBaseAddr: + case kFLASH_PropertyPflashFacSupport: + case kFLASH_PropertyPflashAccessSegmentSize: + case kFLASH_PropertyPflashAccessSegmentCount: + case kFLASH_PropertyFlexRamBlockBaseAddr: + case kFLASH_PropertyFlexRamTotalSize: +#if FLASH_SSD_IS_FLEXNVM_ENABLED + case kFLASH_PropertyDflashSectorSize: + case kFLASH_PropertyDflashTotalSize: + case kFLASH_PropertyDflashBlockSize: + case kFLASH_PropertyDflashBlockCount: + case kFLASH_PropertyDflashBlockBaseAddr: + case kFLASH_PropertyEepromTotalSize: +#endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ + status = kStatus_FLASH_ReadOnlyProperty; + break; + default: /* catch inputs that are not recognized */ + status = kStatus_FLASH_UnknownProperty; + break; + } + + return status; +} + #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD status_t FLASH_SetFlexramFunction(flash_config_t *config, flash_flexram_function_option_t option) { @@ -1611,7 +2088,7 @@ status_t FLASH_SwapControl(flash_config_t *config, /* Make sure address provided is in the lower half of Program flash but not in the Flash Configuration Field */ if ((address >= (config->PFlashTotalSize / 2)) || - ((address >= kFLASH_configAreaStart) && (address <= kFLASH_configAreaEnd))) + ((address >= kFLASH_ConfigAreaStart) && (address <= kFLASH_ConfigAreaEnd))) { return kStatus_FLASH_SwapIndicatorAddressError; } @@ -1628,9 +2105,9 @@ status_t FLASH_SwapControl(flash_config_t *config, returnCode = flash_command_sequence(config); - returnInfo->flashSwapState = (flash_swap_state_t)FTFx->FCCOB5; - returnInfo->currentSwapBlockStatus = (flash_swap_block_status_t)FTFx->FCCOB6; - returnInfo->nextSwapBlockStatus = (flash_swap_block_status_t)FTFx->FCCOB7; + returnInfo->flashSwapState = (flash_swap_state_t)FTFx_FCCOB5_REG; + returnInfo->currentSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB6_REG; + returnInfo->nextSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB7_REG; return returnCode; } @@ -1646,23 +2123,23 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio do { - returnCode = FLASH_SwapControl(config, address, kFLASH_swapControlOptionReportStatus, &returnInfo); + returnCode = FLASH_SwapControl(config, address, kFLASH_SwapControlOptionReportStatus, &returnInfo); if (returnCode != kStatus_FLASH_Success) { return returnCode; } - if (kFLASH_swapFunctionOptionDisable == option) + if (kFLASH_SwapFunctionOptionDisable == option) { - if (returnInfo.flashSwapState == kFLASH_swapStateDisabled) + if (returnInfo.flashSwapState == kFLASH_SwapStateDisabled) { return kStatus_FLASH_Success; } - else if (returnInfo.flashSwapState == kFLASH_swapStateUninitialized) + else if (returnInfo.flashSwapState == kFLASH_SwapStateUninitialized) { /* The swap system changed to the DISABLED state with Program flash block 0 * located at relative flash address 0x0_0000 */ - returnCode = FLASH_SwapControl(config, address, kFLASH_swapControlOptionDisableSystem, &returnInfo); + returnCode = FLASH_SwapControl(config, address, kFLASH_SwapControlOptionDisableSystem, &returnInfo); } else { @@ -1679,12 +2156,12 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio * Complete. */ switch (returnInfo.flashSwapState) { - case kFLASH_swapStateUninitialized: + case kFLASH_SwapStateUninitialized: /* If current swap mode is Uninitialized, Initialize Swap to Initialized/READY state. */ returnCode = - FLASH_SwapControl(config, address, kFLASH_swapControlOptionIntializeSystem, &returnInfo); + FLASH_SwapControl(config, address, kFLASH_SwapControlOptionIntializeSystem, &returnInfo); break; - case kFLASH_swapStateReady: + case kFLASH_SwapStateReady: /* Validate whether the address provided to the swap system is matched to * swap indicator address in the IFR */ returnCode = flash_validate_swap_indicator_address(config, address); @@ -1692,23 +2169,23 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio { /* If current swap mode is Initialized/Ready, Initialize Swap to UPDATE state. */ returnCode = - FLASH_SwapControl(config, address, kFLASH_swapControlOptionSetInUpdateState, &returnInfo); + FLASH_SwapControl(config, address, kFLASH_SwapControlOptionSetInUpdateState, &returnInfo); } break; - case kFLASH_swapStateUpdate: + case kFLASH_SwapStateUpdate: /* If current swap mode is Update, Erase indicator sector in non active block * to proceed swap system to update-erased state */ returnCode = FLASH_Erase(config, address + (config->PFlashTotalSize >> 1), - FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT, kFLASH_apiEraseKey); + FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT, kFLASH_ApiEraseKey); break; - case kFLASH_swapStateUpdateErased: + case kFLASH_SwapStateUpdateErased: /* If current swap mode is Update or Update-Erased, progress Swap to COMPLETE State */ returnCode = - FLASH_SwapControl(config, address, kFLASH_swapControlOptionSetInCompleteState, &returnInfo); + FLASH_SwapControl(config, address, kFLASH_SwapControlOptionSetInCompleteState, &returnInfo); break; - case kFLASH_swapStateComplete: + case kFLASH_SwapStateComplete: break; - case kFLASH_swapStateDisabled: + case kFLASH_SwapStateDisabled: /* When swap system is in disabled state, We need to clear swap system back to uninitialized * by issuing EraseAllBlocks command */ returnCode = kStatus_FLASH_SwapSystemNotInUninitialized; @@ -1722,7 +2199,7 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio { break; } - } while (!((kFLASH_swapStateComplete == returnInfo.flashSwapState) && (kFLASH_swapFunctionOptionEnable == option))); + } while (!((kFLASH_SwapStateComplete == returnInfo.flashSwapState) && (kFLASH_SwapFunctionOptionEnable == option))); return returnCode; } @@ -1750,6 +2227,8 @@ status_t FLASH_ProgramPartition(flash_config_t *config, kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_2_1(FTFx_PROGRAM_PARTITION, 0xFFFFU, option); kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_1_2(eepromDataSizeCode, flexnvmPartitionCode, 0xFFFFU); + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -1766,31 +2245,70 @@ status_t FLASH_ProgramPartition(flash_config_t *config, } #endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD */ -status_t FLASH_PflashSetProtection(flash_config_t *config, uint32_t protectStatus) +status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus) { if (config == NULL) { return kStatus_FLASH_InvalidArgument; } - *kFPROT = protectStatus; - - if (protectStatus != *kFPROT) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - return kStatus_FLASH_CommandFailure; - } + *kFPROTSL = protectStatus->valueLow32b.prots16b.protsl; + if (protectStatus->valueLow32b.prots16b.protsl != *kFPROTSL) + { + return kStatus_FLASH_CommandFailure; + } + + *kFPROTSH = protectStatus->valueLow32b.prots16b.protsh; + if (protectStatus->valueLow32b.prots16b.protsh != *kFPROTSH) + { + return kStatus_FLASH_CommandFailure; + } + } + else +#endif + { + *kFPROTL = protectStatus->valueLow32b.protl32b; + if (protectStatus->valueLow32b.protl32b != *kFPROTL) + { + return kStatus_FLASH_CommandFailure; + } + +#if defined(FTFx_FPROT_HIGH_REG) + *kFPROTH = protectStatus->valueHigh32b.proth32b; + if (protectStatus->valueHigh32b.proth32b != *kFPROTH) + { + return kStatus_FLASH_CommandFailure; + } +#endif + } return kStatus_FLASH_Success; } -status_t FLASH_PflashGetProtection(flash_config_t *config, uint32_t *protectStatus) +status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus) { if ((config == NULL) || (protectStatus == NULL)) { return kStatus_FLASH_InvalidArgument; } - *protectStatus = *kFPROT; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + protectStatus->valueLow32b.prots16b.protsl = *kFPROTSL; + protectStatus->valueLow32b.prots16b.protsh = *kFPROTSH; + } + else +#endif + { + protectStatus->valueLow32b.protl32b = *kFPROTL; +#if defined(FTFx_FPROT_HIGH_REG) + protectStatus->valueHigh32b.proth32b = *kFPROTH; +#endif + } return kStatus_FLASH_Success; } @@ -1881,70 +2399,215 @@ status_t FLASH_EepromGetProtection(flash_config_t *config, uint8_t *protectStatu } #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ -#if FLASH_DRIVER_IS_FLASH_RESIDENT -/*! - * @brief Run flash command - * - * This function should be copied to RAM for execution to make sure that code works - * properly even flash cache is disabled. - * It is for flash-resident bootloader only, not technically required for ROM or - * flashloader (RAM-resident bootloader). - */ -void flash_run_command(FTFx_REG_ACCESS_TYPE ftfx_fstat) +status_t FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus) { - /* clear CCIF bit */ - *ftfx_fstat = FTFx_FSTAT_CCIF_MASK; +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + FTFx_REG32_ACCESS_TYPE regBase; +#if defined(MCM) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM->PLACR; +#elif defined(MCM0) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0->PLACR; +#endif + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable) + { + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + return kStatus_FLASH_InvalidSpeculationOption; + } + else + { + *regBase |= MCM_PLACR_DFCS_MASK; + } + } + else + { + *regBase &= ~MCM_PLACR_DFCS_MASK; + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= MCM_PLACR_EFDS_MASK; + } + else + { + *regBase &= ~MCM_PLACR_EFDS_MASK; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + FTFx_REG32_ACCESS_TYPE regBase; + uint32_t b0dpeMask, b0ipeMask; +#if defined(FMC_PFB01CR_B0DPE_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + b0dpeMask = FMC_PFB01CR_B0DPE_MASK; + b0ipeMask = FMC_PFB01CR_B0IPE_MASK; +#elif defined(FMC_PFB0CR_B0DPE_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + b0dpeMask = FMC_PFB0CR_B0DPE_MASK; + b0ipeMask = FMC_PFB0CR_B0IPE_MASK; +#endif + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= b0ipeMask; + } + else + { + *regBase &= ~b0ipeMask; + } + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= b0dpeMask; + } + else + { + *regBase &= ~b0dpeMask; + } - /* Check CCIF bit of the flash status register, wait till it is set. - * IP team indicates that this loop will always complete. */ - while (!((*ftfx_fstat) & FTFx_FSTAT_CCIF_MASK)) +/* Invalidate Prefetch Speculation Buffer */ +#if defined(FMC_PFB01CR_S_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK; +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK; +#elif defined(FMC_PFB0CR_S_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK; +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK; +#endif + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM { + FTFx_REG32_ACCESS_TYPE regBase; + uint32_t flashSpeculationMask, dataPrefetchMask; + regBase = (FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0]; + flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK; + dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK; + + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable) + { + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + return kStatus_FLASH_InvalidSpeculationOption; + } + else + { + *regBase |= flashSpeculationMask; + } + } + else + { + *regBase &= ~flashSpeculationMask; + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase &= ~dataPrefetchMask; + } + else + { + *regBase |= dataPrefetchMask; + } + } } -} +#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ -/*! - * @brief Be used for determining the size of flash_run_command() - * - * This function must be defined that lexically follows flash_run_command(), - * so we can determine the size of flash_run_command() at runtime and not worry - * about toolchain or code generation differences. - */ -void flash_run_command_end(void) -{ + return kStatus_FLASH_Success; } -/*! - * @brief Copy flash_run_command() to RAM - * - * This function copys the memory between flash_run_command() and flash_run_command_end() - * into the buffer which is also means that copying flash_run_command() to RAM. - */ -static void copy_flash_run_command(uint8_t *flashRunCommand) +status_t FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus) { - /* Calculate the valid length of flash_run_command() memory. - * Set max size(64 bytes) as default function size, in case some compiler allocates - * flash_run_command_end ahead of flash_run_command. */ - uint32_t funcLength = kFLASH_executeInRamFunctionMaxSize; - uint32_t flash_run_command_start_addr = (uint32_t)flash_run_command & (~1U); - uint32_t flash_run_command_end_addr = (uint32_t)flash_run_command_end & (~1U); - if (flash_run_command_end_addr > flash_run_command_start_addr) - { - funcLength = flash_run_command_end_addr - flash_run_command_start_addr; + memset(speculationStatus, 0, sizeof(flash_prefetch_speculation_status_t)); - assert(funcLength <= kFLASH_executeInRamFunctionMaxSize); + /* Assuming that all speculation options are enabled. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionEnable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionEnable; - /* In case some compiler allocates other function in the middle of flash_run_command - * and flash_run_command_end. */ - if (funcLength > kFLASH_executeInRamFunctionMaxSize) +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + uint32_t value; +#if defined(MCM) + value = MCM->PLACR; +#elif defined(MCM0) + value = MCM0->PLACR; +#endif + if (value & MCM_PLACR_DFCS_MASK) { - funcLength = kFLASH_executeInRamFunctionMaxSize; + /* Speculation buffer is off. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + else + { + /* Speculation buffer is on for instruction. */ + if (!(value & MCM_PLACR_EFDS_MASK)) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + uint32_t value; + uint32_t b0dpeMask, b0ipeMask; +#if defined(FMC_PFB01CR_B0DPE_MASK) + value = FMC->PFB01CR; + b0dpeMask = FMC_PFB01CR_B0DPE_MASK; + b0ipeMask = FMC_PFB01CR_B0IPE_MASK; +#elif defined(FMC_PFB0CR_B0DPE_MASK) + value = FMC->PFB0CR; + b0dpeMask = FMC_PFB0CR_B0DPE_MASK; + b0ipeMask = FMC_PFB0CR_B0IPE_MASK; +#endif + if (!(value & b0dpeMask)) + { + /* Do not prefetch in response to data references. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + if (!(value & b0ipeMask)) + { + /* Do not prefetch in response to instruction fetches. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + { + uint32_t value; + uint32_t flashSpeculationMask, dataPrefetchMask; + value = MSCM->OCMDR[0]; + flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK; + dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK; + + if (value & flashSpeculationMask) + { + /* Speculation buffer is off. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + else + { + /* Speculation buffer is on for instruction. */ + if (value & dataPrefetchMask) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } } } +#endif + + return kStatus_FLASH_Success; +} + +#if FLASH_DRIVER_IS_FLASH_RESIDENT +/*! + * @brief Copy PIC of flash_run_command() to RAM + */ +static void copy_flash_run_command(uint32_t *flashRunCommand) +{ + assert(sizeof(s_flashRunCommandFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4)); /* Since the value of ARM function pointer is always odd, but the real start address - * of function memory should be even, that's why -1 and +1 operation exist. */ - memcpy((void *)flashRunCommand, (void *)flash_run_command_start_addr, funcLength); - callFlashRunCommand = (void (*)(FTFx_REG_ACCESS_TYPE ftfx_fstat))((uint32_t)flashRunCommand + 1); + * of function memory should be even, that's why +1 operation exist. */ + memcpy((void *)flashRunCommand, (void *)s_flashRunCommandFunctionCode, sizeof(s_flashRunCommandFunctionCode)); + callFlashRunCommand = (void (*)(FTFx_REG8_ACCESS_TYPE ftfx_fstat))((uint32_t)flashRunCommand + 1); } #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ @@ -1973,7 +2636,7 @@ static status_t flash_command_sequence(flash_config_t *config) /* We pass the ftfx_fstat address as a parameter to flash_run_comamnd() instead of using * pre-processed MICRO sentences or operating global variable in flash_run_comamnd() * to make sure that flash_run_command() will be compiled into position-independent code (PIC). */ - callFlashRunCommand((FTFx_REG_ACCESS_TYPE)(&FTFx->FSTAT)); + callFlashRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT)); #else /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */ FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK; @@ -2015,100 +2678,173 @@ static status_t flash_command_sequence(flash_config_t *config) #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! - * @brief Run flash cache clear command + * @brief Copy PIC of flash_common_bit_operation() to RAM * - * This function should be copied to RAM for execution to make sure that code works - * properly even flash cache is disabled. - * It is for flash-resident bootloader only, not technically required for ROM or - * flashloader (RAM-resident bootloader). */ -void flash_cache_clear_command(FTFx_REG32_ACCESS_TYPE ftfx_reg) +static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation) { -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS - *ftfx_reg |= MCM_PLACR_CFCC_MASK; -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -#if defined(FMC_PFB01CR_CINV_WAY_MASK) - *ftfx_reg = (*ftfx_reg & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); -#else - *ftfx_reg = (*ftfx_reg & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); + assert(sizeof(s_flashCommonBitOperationFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4)); + + /* Since the value of ARM function pointer is always odd, but the real start address + * of function memory should be even, that's why +1 operation exist. */ + memcpy((void *)flashCommonBitOperation, (void *)s_flashCommonBitOperationFunctionCode, + sizeof(s_flashCommonBitOperationFunctionCode)); + callFlashCommonBitOperation = (void (*)(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, + uint32_t bitValue))((uint32_t)flashCommonBitOperation + 1); + /* Workround for some devices which doesn't need this function */ + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)0, 0, 0, 0); +} +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(flash_config_t *config) +{ + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG; + +#if defined(MCM0) && defined(MCM1) + if (config->FlashCacheControllerIndex == (uint8_t)kFLASH_CacheControllerIndexForCore1) + { + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG; + } #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - *ftfx_reg |= MSCM_OCMDR_OCMC1(2); - *ftfx_reg |= MSCM_OCMDR_OCMC1(1); -#else -/* #error "Unknown flash cache controller" */ -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ - /* Memory barriers for good measure. - * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + +#if FLASH_DRIVER_IS_FLASH_RESIDENT + callFlashCommonBitOperation(regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1U); +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ + *regBase |= MCM_CACHE_CLEAR_MASK; + + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ __ISB(); __DSB(); +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ } +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ -/*! - * @brief Be used for determining the size of flash_cache_clear_command() - * - * This function must be defined that lexically follows flash_cache_clear_command(), - * so we can determine the size of flash_cache_clear_command() at runtime and not worry - * about toolchain or code generation differences. - */ -void flash_cache_clear_command_end(void) +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(void) { +#if FLASH_DRIVER_IS_FLASH_RESIDENT + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0; +#if defined(FMC_PFB01CR_CINV_WAY_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_CINV_WAY_MASK, FMC_PFB01CR_CINV_WAY_SHIFT, 0xFU); +#else + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_CINV_WAY_MASK, FMC_PFB0CR_CINV_WAY_SHIFT, 0xFU); +#endif +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ +#if defined(FMC_PFB01CR_CINV_WAY_MASK) + FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); +#else + FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); +#endif + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ } +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ -/*! - * @brief Copy flash_cache_clear_command() to RAM - * - * This function copys the memory between flash_cache_clear_command() and flash_cache_clear_command_end() - * into the buffer which is also means that copying flash_cache_clear_command() to RAM. - */ -static void copy_flash_cache_clear_command(uint8_t *flashCacheClearCommand) +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM +/*! @brief Performs the prefetch speculation buffer clear to the flash by MSCM.*/ +void mscm_flash_prefetch_speculation_enable(bool enable) { - /* Calculate the valid length of flash_cache_clear_command() memory. - * Set max size(64 bytes) as default function size, in case some compiler allocates - * flash_cache_clear_command_end ahead of flash_cache_clear_command. */ - uint32_t funcLength = kFLASH_executeInRamFunctionMaxSize; - uint32_t flash_cache_clear_command_start_addr = (uint32_t)flash_cache_clear_command & (~1U); - uint32_t flash_cache_clear_command_end_addr = (uint32_t)flash_cache_clear_command_end & (~1U); - if (flash_cache_clear_command_end_addr > flash_cache_clear_command_start_addr) + uint8_t setValue; + if (enable) { - funcLength = flash_cache_clear_command_end_addr - flash_cache_clear_command_start_addr; + setValue = 0x0U; + } + else + { + setValue = 0x3U; + } - assert(funcLength <= kFLASH_executeInRamFunctionMaxSize); +/* The OCMDR[0] is always used to prefetch main Pflash*/ +/* For device with FlexNVM support, the OCMDR[1] is used to prefetch Dflash. + * For device with secondary flash support, the OCMDR[1] is used to prefetch secondary Pflash. */ +#if FLASH_DRIVER_IS_FLASH_RESIDENT + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0], MSCM_SPECULATION_DISABLE_MASK, + MSCM_SPECULATION_DISABLE_SHIFT, setValue); +#if FLASH_SSD_IS_FLEXNVM_ENABLED || BL_HAS_SECONDARY_INTERNAL_FLASH + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[1], MSCM_SPECULATION_DISABLE_MASK, + MSCM_SPECULATION_DISABLE_SHIFT, setValue); +#endif +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ + MSCM->OCMDR[0] |= MSCM_SPECULATION_DISABLE(setValue); - /* In case some compiler allocates other function in the middle of flash_cache_clear_command - * and flash_cache_clear_command_end. */ - if (funcLength > kFLASH_executeInRamFunctionMaxSize) - { - funcLength = kFLASH_executeInRamFunctionMaxSize; - } - } + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#if FLASH_SSD_IS_FLEXNVM_ENABLED || BL_HAS_SECONDARY_INTERNAL_FLASH + MSCM->OCMDR[1] |= MSCM_SPECULATION_DISABLE(setValue); - /* Since the value of ARM function pointer is always odd, but the real start address - * of function memory should be even, that's why -1 and +1 operation exist. */ - memcpy((void *)flashCacheClearCommand, (void *)flash_cache_clear_command_start_addr, funcLength); - callFlashCacheClearCommand = (void (*)(FTFx_REG32_ACCESS_TYPE ftfx_reg))((uint32_t)flashCacheClearCommand + 1); + /* Each cahce clear instaruction should be followed by below code*/ + __ISB(); + __DSB(); +#endif + +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ } +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC +/*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ +void fmc_flash_prefetch_speculation_clear(void) +{ +#if FLASH_DRIVER_IS_FLASH_RESIDENT + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0; +#if defined(FMC_PFB01CR_S_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_INV_MASK, FMC_PFB01CR_S_INV_SHIFT, 1U); +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_B_INV_MASK, FMC_PFB01CR_S_B_INV_SHIFT, 1U); +#elif defined(FMC_PFB0CR_S_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_INV_MASK, FMC_PFB0CR_S_INV_SHIFT, 1U); +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_B_INV_MASK, FMC_PFB0CR_S_B_INV_SHIFT, 1U); +#endif +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ +#if defined(FMC_PFB01CR_S_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK; +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK; +#elif defined(FMC_PFB0CR_S_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK; +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK; +#endif + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ /*! * @brief Flash Cache Clear * - * This function is used to perform the cache clear to the flash. + * This function is used to perform the cache and prefetch speculation clear to the flash. */ -#if (defined(__GNUC__)) -/* #pragma GCC push_options */ -/* #pragma GCC optimize("O0") */ -void __attribute__((optimize("O0"))) flash_cache_clear(flash_config_t *config) -#else -#if (defined(__ICCARM__)) -#pragma optimize = none -#endif -#if (defined(__CC_ARM)) -#pragma push -#pragma O0 -#endif void flash_cache_clear(flash_config_t *config) -#endif +{ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPost); +} + +/*! + * @brief Flash Cache Clear Process + * + * This function is used to perform the cache and prefetch speculation clear process to the flash. + */ +static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process) { #if FLASH_DRIVER_IS_FLASH_RESIDENT status_t returnCode = flash_check_execute_in_ram_function_info(config); @@ -2116,66 +2852,33 @@ void flash_cache_clear(flash_config_t *config) { return; } +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ -/* We pass the ftfx register address as a parameter to flash_cache_clear_comamnd() instead of using - * pre-processed MACROs or a global variable in flash_cache_clear_comamnd() - * to make sure that flash_cache_clear_command() will be compiled into position-independent code (PIC). */ -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS -#if defined(MCM) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM->PLACR); + /* We pass the ftfx register address as a parameter to flash_common_bit_operation() instead of using + * pre-processed MACROs or a global variable in flash_common_bit_operation() + * to make sure that flash_common_bit_operation() will be compiled into position-independent code (PIC). */ + if (process == kFLASH_CacheClearProcessPost) + { +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM + mcm_flash_cache_clear(config); #endif -#if defined(MCM0) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM0->PLACR); +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC + fmc_flash_cache_clear(); #endif -#if defined(MCM1) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM1->PLACR); +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(true); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -#if defined(FMC_PFB01CR_CINV_WAY_MASK) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR); -#else - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR); +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + fmc_flash_prefetch_speculation_clear(); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0]); -#else - /* #error "Unknown flash cache controller" */ - /* meaningless code, just a workaround to solve warning*/ - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)0); -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ - -#else - -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS -#if defined(MCM) - MCM->PLACR |= MCM_PLACR_CFCC_MASK; -#endif -#if defined(MCM0) - MCM0->PLACR |= MCM_PLACR_CFCC_MASK; -#endif -#if defined(MCM1) - MCM1->PLACR |= MCM_PLACR_CFCC_MASK; -#endif -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -#if defined(FMC_PFB01CR_CINV_WAY_MASK) - FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); -#else - FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); + } + if (process == kFLASH_CacheClearProcessPre) + { +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(false); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - MSCM->OCMDR[0] |= MSCM_OCMDR_OCMC1(2); - MSCM->OCMDR[0] |= MSCM_OCMDR_OCMC1(1); -#else -/* #error "Unknown flash cache controller" */ -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ -#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ + } } -#if (defined(__CC_ARM)) -#pragma pop -#endif -#if (defined(__GNUC__)) -/* #pragma GCC pop_options */ -#endif #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief Check whether flash execute-in-ram functions are ready */ @@ -2191,7 +2894,7 @@ static status_t flash_check_execute_in_ram_function_info(flash_config_t *config) flashExecuteInRamFunctionInfo = (flash_execute_in_ram_function_config_t *)config->flashExecuteInRamFunctionInfo; if ((config->flashExecuteInRamFunctionInfo) && - (kFLASH_executeInRamFunctionTotalNum == flashExecuteInRamFunctionInfo->activeFunctionCount)) + (kFLASH_ExecuteInRamFunctionTotalNum == flashExecuteInRamFunctionInfo->activeFunctionCount)) { return kStatus_FLASH_Success; } @@ -2217,21 +2920,19 @@ static status_t flash_check_range(flash_config_t *config, return kStatus_FLASH_AlignmentError; } -/* check for valid range of the target addresses */ -#if !FLASH_SSD_IS_FLEXNVM_ENABLED - if ((startAddress < config->PFlashBlockBase) || - ((startAddress + lengthInBytes) > (config->PFlashBlockBase + config->PFlashTotalSize))) -#else - if (!(((startAddress >= config->PFlashBlockBase) && - ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize))) || - ((startAddress >= config->DFlashBlockBase) && - ((startAddress + lengthInBytes) <= (config->DFlashBlockBase + config->DFlashTotalSize))))) + /* check for valid range of the target addresses */ + if ( +#if FLASH_SSD_IS_FLEXNVM_ENABLED + ((startAddress >= config->DFlashBlockBase) && + ((startAddress + lengthInBytes) <= (config->DFlashBlockBase + config->DFlashTotalSize))) || #endif + ((startAddress >= config->PFlashBlockBase) && + ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize)))) { - return kStatus_FLASH_AddressError; + return kStatus_FLASH_Success; } - return kStatus_FLASH_Success; + return kStatus_FLASH_AddressError; } /*! @brief Gets the right address, sector and block size of current flash type which is indicated by address.*/ @@ -2250,6 +2951,8 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, #if FLASH_SSD_IS_FLEXNVM_ENABLED if ((address >= config->DFlashBlockBase) && (address <= (config->DFlashBlockBase + config->DFlashTotalSize))) { + /* When required by the command, address bit 23 selects between program flash memory + * (=0) and data flash memory (=1).*/ info->convertedAddress = address - config->DFlashBlockBase + 0x800000U; info->activeSectorSize = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE; info->activeBlockSize = config->DFlashTotalSize / FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT; @@ -2263,11 +2966,25 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, else #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ { - info->convertedAddress = address; + info->convertedAddress = address - config->PFlashBlockBase; info->activeSectorSize = config->PFlashSectorSize; info->activeBlockSize = config->PFlashTotalSize / config->PFlashBlockCount; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { +#if FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER || FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + /* When required by the command, address bit 23 selects between main flash memory + * (=0) and secondary flash memory (=1).*/ + info->convertedAddress += 0x800000U; +#endif + info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE; + } + else +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ + { + info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE; + } - info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE; info->sectorCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT; info->sectionCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT; info->resourceCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_RESOURCE_CMD_ADDRESS_ALIGMENT; @@ -2281,7 +2998,7 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, static status_t flash_check_user_key(uint32_t key) { /* Validate the user key */ - if (key != kFLASH_apiEraseKey) + if (key != kFLASH_ApiEraseKey) { return kStatus_FLASH_EraseKeyError; } @@ -2307,13 +3024,17 @@ static status_t flash_update_flexnvm_memory_partition_status(flash_config_t *con return kStatus_FLASH_InvalidArgument; } +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD /* Get FlexNVM memory partition info from data flash IFR */ returnCode = FLASH_ReadResource(config, DFLASH_IFR_READRESOURCE_START_ADDRESS, (uint32_t *)&dataIFRReadOut, - sizeof(dataIFRReadOut), kFLASH_resourceOptionFlashIfr); + sizeof(dataIFRReadOut), kFLASH_ResourceOptionFlashIfr); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_PartitionStatusUpdateFailure; } +#else +#error "Cannot get FlexNVM memory partition info" +#endif /* Fill out partitioned EEPROM size */ dataIFRReadOut.EEPROMDataSetSize &= 0x0FU; @@ -2515,27 +3236,27 @@ static status_t flash_check_resource_range(uint32_t start, status = kStatus_FLASH_Success; maxReadbleAddress = start + lengthInBytes - 1; - if (option == kFLASH_resourceOptionVersionId) + if (option == kFLASH_ResourceOptionVersionId) { - if ((start != kFLASH_resourceRangeVersionIdStart) || - ((start + lengthInBytes - 1) != kFLASH_resourceRangeVersionIdEnd)) + if ((start != kFLASH_ResourceRangeVersionIdStart) || + ((start + lengthInBytes - 1) != kFLASH_ResourceRangeVersionIdEnd)) { status = kStatus_FLASH_InvalidArgument; } } - else if (option == kFLASH_resourceOptionFlashIfr) + else if (option == kFLASH_ResourceOptionFlashIfr) { - if (maxReadbleAddress < kFLASH_resourceRangePflashIfrSizeInBytes) + if (maxReadbleAddress < kFLASH_ResourceRangePflashIfrSizeInBytes) { } #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP - else if ((start >= kFLASH_resourceRangePflashSwapIfrStart) && - (maxReadbleAddress <= kFLASH_resourceRangePflashSwapIfrEnd)) + else if ((start >= kFLASH_ResourceRangePflashSwapIfrStart) && + (maxReadbleAddress <= kFLASH_ResourceRangePflashSwapIfrEnd)) { } #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */ - else if ((start >= kFLASH_resourceRangeDflashIfrStart) && - (maxReadbleAddress <= kFLASH_resourceRangeDflashIfrEnd)) + else if ((start >= kFLASH_ResourceRangeDflashIfrStart) && + (maxReadbleAddress <= kFLASH_ResourceRangeDflashIfrEnd)) { } else @@ -2556,9 +3277,9 @@ static status_t flash_check_resource_range(uint32_t start, /*! @brief Validates the gived swap control option.*/ static status_t flash_check_swap_control_option(flash_swap_control_option_t option) { - if ((option == kFLASH_swapControlOptionIntializeSystem) || (option == kFLASH_swapControlOptionSetInUpdateState) || - (option == kFLASH_swapControlOptionSetInCompleteState) || (option == kFLASH_swapControlOptionReportStatus) || - (option == kFLASH_swapControlOptionDisableSystem)) + if ((option == kFLASH_SwapControlOptionIntializeSystem) || (option == kFLASH_SwapControlOptionSetInUpdateState) || + (option == kFLASH_SwapControlOptionSetInCompleteState) || (option == kFLASH_SwapControlOptionReportStatus) || + (option == kFLASH_SwapControlOptionDisableSystem)) { return kStatus_FLASH_Success; } @@ -2571,21 +3292,48 @@ static status_t flash_check_swap_control_option(flash_swap_control_option_t opti /*! @brief Validates the gived address to see if it is equal to swap indicator address in pflash swap IFR.*/ static status_t flash_validate_swap_indicator_address(flash_config_t *config, uint32_t address) { - flash_swap_ifr_field_config_t flashSwapIfrField; + flash_swap_ifr_field_data_t flashSwapIfrFieldData; uint32_t swapIndicatorAddress; status_t returnCode; - returnCode = FLASH_ReadResource(config, kFLASH_resourceRangePflashSwapIfrStart, (uint32_t *)&flashSwapIfrField, - sizeof(flash_swap_ifr_field_config_t), kFLASH_resourceOptionFlashIfr); +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD + returnCode = + FLASH_ReadResource(config, kFLASH_ResourceRangePflashSwapIfrStart, flashSwapIfrFieldData.flashSwapIfrData, + sizeof(flashSwapIfrFieldData.flashSwapIfrData), kFLASH_ResourceOptionFlashIfr); + if (returnCode != kStatus_FLASH_Success) { return returnCode; } +#else + { + /* From RM, the actual info are stored in FCCOB6,7 */ + uint32_t returnValue[2]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapAddr, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapIndicatorAddress = (uint16_t)returnValue[0]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapEnable, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapEnableWord = (uint16_t)returnValue[0]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapDisable, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapDisableWord = (uint16_t)returnValue[0]; + } +#endif - /* The high 2 byte value of Swap Indicator Address is stored in Program Flash Swap IFR Field, - * the low 4 bit value of Swap Indicator Address is always 4'b0000 */ - swapIndicatorAddress = - (uint32_t)flashSwapIfrField.swapIndicatorAddress * FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT; + /* The high bits value of Swap Indicator Address is stored in Program Flash Swap IFR Field, + * the low severval bit value of Swap Indicator Address is always 1'b0 */ + swapIndicatorAddress = (uint32_t)flashSwapIfrFieldData.flashSwapIfrField.swapIndicatorAddress * + FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT; if (address != swapIndicatorAddress) { return kStatus_FLASH_SwapIndicatorAddressError; @@ -2599,8 +3347,8 @@ static status_t flash_validate_swap_indicator_address(flash_config_t *config, ui /*! @brief Validates the gived flexram function option.*/ static inline status_t flasn_check_flexram_function_option_range(flash_flexram_function_option_t option) { - if ((option != kFLASH_flexramFunctionOptionAvailableAsRam) && - (option != kFLASH_flexramFunctionOptionAvailableForEeprom)) + if ((option != kFLASH_FlexramFunctionOptionAvailableAsRam) && + (option != kFLASH_FlexramFunctionOptionAvailableForEeprom)) { return kStatus_FLASH_InvalidArgument; } @@ -2608,3 +3356,77 @@ static inline status_t flasn_check_flexram_function_option_range(flash_flexram_f return kStatus_FLASH_Success; } #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +/*! @brief Gets the flash protection information (region size, region count).*/ +static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info) +{ + uint32_t pflashTotalSize; + + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + /* Clean up info Structure*/ + memset(info, 0, sizeof(flash_protection_config_t)); + +/* Note: KW40 has a secondary flash, but it doesn't have independent protection register*/ +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER) + pflashTotalSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE + + FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; + info->regionBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; +#else + pflashTotalSize = config->PFlashTotalSize; + info->regionBase = config->PFlashBlockBase; +#endif + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + info->regionCount = FSL_FEATURE_FLASH_PFLASH_1_PROTECTION_REGION_COUNT; + } + else +#endif + { + info->regionCount = FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT; + } + + /* Calculate the size of the flash protection region + * If the flash density is > 32KB, then protection region is 1/32 of total flash density + * Else if flash density is < 32KB, then flash protection region is set to 1KB */ + if (pflashTotalSize > info->regionCount * 1024) + { + info->regionSize = (pflashTotalSize) / info->regionCount; + } + else + { + info->regionSize = 1024; + } + + return kStatus_FLASH_Success; +} + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/ +static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info) +{ + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + /* Clean up info Structure*/ + memset(info, 0, sizeof(flash_access_config_t)); + +/* Note: KW40 has a secondary flash, but it doesn't have independent access register*/ +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER) + info->SegmentBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; +#else + info->SegmentBase = config->PFlashBlockBase; +#endif + info->SegmentSize = config->PFlashAccessSegmentSize; + info->SegmentCount = config->PFlashAccessSegmentCount; + + return kStatus_FLASH_Success; +} +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h index 63463e03cb4..e143cb3e1f6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -53,21 +53,21 @@ * @name Flash version * @{ */ -/*! @brief Construct the version number for drivers. */ +/*! @brief Constructs the version number for drivers. */ #if !defined(MAKE_VERSION) #define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) #endif -/*! @brief FLASH driver version for SDK*/ -#define FSL_FLASH_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @brief Flash driver version for SDK*/ +#define FSL_FLASH_DRIVER_VERSION (MAKE_VERSION(2, 3, 1)) /*!< Version 2.3.1. */ -/*! @brief FLASH driver version for ROM*/ +/*! @brief Flash driver version for ROM*/ enum _flash_driver_version_constants { - kFLASH_driverVersionName = 'F', /*!< Flash driver version name.*/ - kFLASH_driverVersionMajor = 2, /*!< Major flash driver version.*/ - kFLASH_driverVersionMinor = 1, /*!< Minor flash driver version.*/ - kFLASH_driverVersionBugfix = 0 /*!< Bugfix for flash driver version.*/ + kFLASH_DriverVersionName = 'F', /*!< Flash driver version name.*/ + kFLASH_DriverVersionMajor = 2, /*!< Major flash driver version.*/ + kFLASH_DriverVersionMinor = 3, /*!< Minor flash driver version.*/ + kFLASH_DriverVersionBugfix = 1 /*!< Bugfix for flash driver version.*/ }; /*@}*/ @@ -75,29 +75,41 @@ enum _flash_driver_version_constants * @name Flash configuration * @{ */ -/*! @brief Whether to support FlexNVM in flash driver */ +/*! @brief Indicates whether to support FlexNVM in the Flash driver */ #if !defined(FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT) -#define FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT 1 /*!< Enable FlexNVM support by default. */ +#define FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT 1 /*!< Enables the FlexNVM support by default. */ #endif -/*! @brief Whether the FlexNVM is enabled in flash driver */ +/*! @brief Indicates whether the FlexNVM is enabled in the Flash driver */ #define FLASH_SSD_IS_FLEXNVM_ENABLED (FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT && FSL_FEATURE_FLASH_HAS_FLEX_NVM) +/*! @brief Indicates whether to support Secondary flash in the Flash driver */ +#if !defined(FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT) +#define FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT 1 /*!< Enables the secondary flash support by default. */ +#endif + +/*! @brief Indicates whether the secondary flash is supported in the Flash driver */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) || defined(FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS) +#define FLASH_SSD_IS_SECONDARY_FLASH_ENABLED (FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT) +#else +#define FLASH_SSD_IS_SECONDARY_FLASH_ENABLED (0) +#endif + /*! @brief Flash driver location. */ #if !defined(FLASH_DRIVER_IS_FLASH_RESIDENT) #if (!defined(BL_TARGET_ROM) && !defined(BL_TARGET_RAM)) -#define FLASH_DRIVER_IS_FLASH_RESIDENT 1 /*!< Used for flash resident application. */ +#define FLASH_DRIVER_IS_FLASH_RESIDENT 1 /*!< Used for the flash resident application. */ #else -#define FLASH_DRIVER_IS_FLASH_RESIDENT 0 /*!< Used for non-flash resident application. */ +#define FLASH_DRIVER_IS_FLASH_RESIDENT 0 /*!< Used for the non-flash resident application. */ #endif #endif /*! @brief Flash Driver Export option */ #if !defined(FLASH_DRIVER_IS_EXPORTED) #if (defined(BL_TARGET_ROM) || defined(BL_TARGET_FLASH)) -#define FLASH_DRIVER_IS_EXPORTED 1 /*!< Used for ROM bootloader. */ +#define FLASH_DRIVER_IS_EXPORTED 1 /*!< Used for the ROM bootloader. */ #else -#define FLASH_DRIVER_IS_EXPORTED 0 /*!< Used for SDK application. */ +#define FLASH_DRIVER_IS_EXPORTED 0 /*!< Used for the MCUXpresso SDK application. */ #endif #endif /*@}*/ @@ -118,7 +130,7 @@ enum _flash_driver_version_constants #define kStatusGroupFlashDriver 1 #endif -/*! @brief Construct a status code value from a group and code number. */ +/*! @brief Constructs a status code value from a group and a code number. */ #if !defined(MAKE_STATUS) #define MAKE_STATUS(group, code) ((((group)*100) + (code))) #endif @@ -128,37 +140,43 @@ enum _flash_driver_version_constants */ enum _flash_status { - kStatus_FLASH_Success = MAKE_STATUS(kStatusGroupGeneric, 0), /*!< Api is executed successfully*/ + kStatus_FLASH_Success = MAKE_STATUS(kStatusGroupGeneric, 0), /*!< API is executed successfully*/ kStatus_FLASH_InvalidArgument = MAKE_STATUS(kStatusGroupGeneric, 4), /*!< Invalid argument*/ kStatus_FLASH_SizeError = MAKE_STATUS(kStatusGroupFlashDriver, 0), /*!< Error size*/ kStatus_FLASH_AlignmentError = - MAKE_STATUS(kStatusGroupFlashDriver, 1), /*!< Parameter is not aligned with specified baseline*/ + MAKE_STATUS(kStatusGroupFlashDriver, 1), /*!< Parameter is not aligned with the specified baseline*/ kStatus_FLASH_AddressError = MAKE_STATUS(kStatusGroupFlashDriver, 2), /*!< Address is out of range */ kStatus_FLASH_AccessError = - MAKE_STATUS(kStatusGroupFlashDriver, 3), /*!< Invalid instruction codes and out-of bounds addresses */ + MAKE_STATUS(kStatusGroupFlashDriver, 3), /*!< Invalid instruction codes and out-of bound addresses */ kStatus_FLASH_ProtectionViolation = MAKE_STATUS( kStatusGroupFlashDriver, 4), /*!< The program/erase operation is requested to execute on protected areas */ kStatus_FLASH_CommandFailure = MAKE_STATUS(kStatusGroupFlashDriver, 5), /*!< Run-time error during command execution. */ - kStatus_FLASH_UnknownProperty = MAKE_STATUS(kStatusGroupFlashDriver, 6), /*!< Unknown property.*/ - kStatus_FLASH_EraseKeyError = MAKE_STATUS(kStatusGroupFlashDriver, 7), /*!< Api erase key is invalid.*/ - kStatus_FLASH_RegionExecuteOnly = MAKE_STATUS(kStatusGroupFlashDriver, 8), /*!< Current region is execute only.*/ + kStatus_FLASH_UnknownProperty = MAKE_STATUS(kStatusGroupFlashDriver, 6), /*!< Unknown property.*/ + kStatus_FLASH_EraseKeyError = MAKE_STATUS(kStatusGroupFlashDriver, 7), /*!< API erase key is invalid.*/ + kStatus_FLASH_RegionExecuteOnly = + MAKE_STATUS(kStatusGroupFlashDriver, 8), /*!< The current region is execute-only.*/ kStatus_FLASH_ExecuteInRamFunctionNotReady = - MAKE_STATUS(kStatusGroupFlashDriver, 9), /*!< Execute-in-ram function is not available.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 9), /*!< Execute-in-RAM function is not available.*/ kStatus_FLASH_PartitionStatusUpdateFailure = MAKE_STATUS(kStatusGroupFlashDriver, 10), /*!< Failed to update partition status.*/ kStatus_FLASH_SetFlexramAsEepromError = - MAKE_STATUS(kStatusGroupFlashDriver, 11), /*!< Failed to set flexram as eeprom.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 11), /*!< Failed to set FlexRAM as EEPROM.*/ kStatus_FLASH_RecoverFlexramAsRamError = - MAKE_STATUS(kStatusGroupFlashDriver, 12), /*!< Failed to recover flexram as ram.*/ - kStatus_FLASH_SetFlexramAsRamError = MAKE_STATUS(kStatusGroupFlashDriver, 13), /*!< Failed to set flexram as ram.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 12), /*!< Failed to recover FlexRAM as RAM.*/ + kStatus_FLASH_SetFlexramAsRamError = MAKE_STATUS(kStatusGroupFlashDriver, 13), /*!< Failed to set FlexRAM as RAM.*/ kStatus_FLASH_RecoverFlexramAsEepromError = - MAKE_STATUS(kStatusGroupFlashDriver, 14), /*!< Failed to recover flexram as eeprom.*/ - kStatus_FLASH_CommandNotSupported = MAKE_STATUS(kStatusGroupFlashDriver, 15), /*!< Flash api is not supported.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 14), /*!< Failed to recover FlexRAM as EEPROM.*/ + kStatus_FLASH_CommandNotSupported = MAKE_STATUS(kStatusGroupFlashDriver, 15), /*!< Flash API is not supported.*/ kStatus_FLASH_SwapSystemNotInUninitialized = - MAKE_STATUS(kStatusGroupFlashDriver, 16), /*!< Swap system is not in uninitialzed state.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 16), /*!< Swap system is not in an uninitialzed state.*/ kStatus_FLASH_SwapIndicatorAddressError = - MAKE_STATUS(kStatusGroupFlashDriver, 17), /*!< Swap indicator address is invalid.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 17), /*!< The swap indicator address is invalid.*/ + kStatus_FLASH_ReadOnlyProperty = MAKE_STATUS(kStatusGroupFlashDriver, 18), /*!< The flash property is read-only.*/ + kStatus_FLASH_InvalidPropertyValue = + MAKE_STATUS(kStatusGroupFlashDriver, 19), /*!< The flash property value is out of range.*/ + kStatus_FLASH_InvalidSpeculationOption = + MAKE_STATUS(kStatusGroupFlashDriver, 20), /*!< The option of flash prefetch speculation is invalid.*/ }; /*@}*/ @@ -166,13 +184,13 @@ enum _flash_status * @name Flash API key * @{ */ -/*! @brief Construct the four char code for flash driver API key. */ +/*! @brief Constructs the four character code for the Flash driver API key. */ #if !defined(FOUR_CHAR_CODE) #define FOUR_CHAR_CODE(a, b, c, d) (((d) << 24) | ((c) << 16) | ((b) << 8) | ((a))) #endif /*! - * @brief Enumeration for flash driver API keys. + * @brief Enumeration for Flash driver API keys. * * @note The resulting value is built with a byte order such that the string * being readable in expected order when viewed in a hex editor, if the value @@ -180,7 +198,7 @@ enum _flash_status */ enum _flash_driver_api_keys { - kFLASH_apiEraseKey = FOUR_CHAR_CODE('k', 'f', 'e', 'k') /*!< Key value used to validate all flash erase APIs.*/ + kFLASH_ApiEraseKey = FOUR_CHAR_CODE('k', 'f', 'e', 'k') /*!< Key value used to validate all flash erase APIs.*/ }; /*@}*/ @@ -189,10 +207,10 @@ enum _flash_driver_api_keys */ typedef enum _flash_margin_value { - kFLASH_marginValueNormal, /*!< Use the 'normal' read level for 1s.*/ - kFLASH_marginValueUser, /*!< Apply the 'User' margin to the normal read-1 level.*/ - kFLASH_marginValueFactory, /*!< Apply the 'Factory' margin to the normal read-1 level.*/ - kFLASH_marginValueInvalid /*!< Not real margin level, Used to determine the range of valid margin level. */ + kFLASH_MarginValueNormal, /*!< Use the 'normal' read level for 1s.*/ + kFLASH_MarginValueUser, /*!< Apply the 'User' margin to the normal read-1 level.*/ + kFLASH_MarginValueFactory, /*!< Apply the 'Factory' margin to the normal read-1 level.*/ + kFLASH_MarginValueInvalid /*!< Not real margin level, Used to determine the range of valid margin level. */ } flash_margin_value_t; /*! @@ -200,9 +218,9 @@ typedef enum _flash_margin_value */ typedef enum _flash_security_state { - kFLASH_securityStateNotSecure, /*!< Flash is not secure.*/ - kFLASH_securityStateBackdoorEnabled, /*!< Flash backdoor is enabled.*/ - kFLASH_securityStateBackdoorDisabled /*!< Flash backdoor is disabled.*/ + kFLASH_SecurityStateNotSecure, /*!< Flash is not secure.*/ + kFLASH_SecurityStateBackdoorEnabled, /*!< Flash backdoor is enabled.*/ + kFLASH_SecurityStateBackdoorDisabled /*!< Flash backdoor is disabled.*/ } flash_security_state_t; /*! @@ -210,9 +228,9 @@ typedef enum _flash_security_state */ typedef enum _flash_protection_state { - kFLASH_protectionStateUnprotected, /*!< Flash region is not protected.*/ - kFLASH_protectionStateProtected, /*!< Flash region is protected.*/ - kFLASH_protectionStateMixed /*!< Flash is mixed with protected and unprotected region.*/ + kFLASH_ProtectionStateUnprotected, /*!< Flash region is not protected.*/ + kFLASH_ProtectionStateProtected, /*!< Flash region is protected.*/ + kFLASH_ProtectionStateMixed /*!< Flash is mixed with protected and unprotected region.*/ } flash_protection_state_t; /*! @@ -220,9 +238,9 @@ typedef enum _flash_protection_state */ typedef enum _flash_execute_only_access_state { - kFLASH_accessStateUnLimited, /*!< Flash region is unLimited.*/ - kFLASH_accessStateExecuteOnly, /*!< Flash region is execute only.*/ - kFLASH_accessStateMixed /*!< Flash is mixed with unLimited and execute only region.*/ + kFLASH_AccessStateUnLimited, /*!< Flash region is unlimited.*/ + kFLASH_AccessStateExecuteOnly, /*!< Flash region is execute only.*/ + kFLASH_AccessStateMixed /*!< Flash is mixed with unlimited and execute only region.*/ } flash_execute_only_access_state_t; /*! @@ -230,41 +248,43 @@ typedef enum _flash_execute_only_access_state */ typedef enum _flash_property_tag { - kFLASH_propertyPflashSectorSize = 0x00U, /*!< Pflash sector size property.*/ - kFLASH_propertyPflashTotalSize = 0x01U, /*!< Pflash total size property.*/ - kFLASH_propertyPflashBlockSize = 0x02U, /*!< Pflash block size property.*/ - kFLASH_propertyPflashBlockCount = 0x03U, /*!< Pflash block count property.*/ - kFLASH_propertyPflashBlockBaseAddr = 0x04U, /*!< Pflash block base address property.*/ - kFLASH_propertyPflashFacSupport = 0x05U, /*!< Pflash fac support property.*/ - kFLASH_propertyPflashAccessSegmentSize = 0x06U, /*!< Pflash access segment size property.*/ - kFLASH_propertyPflashAccessSegmentCount = 0x07U, /*!< Pflash access segment count property.*/ - kFLASH_propertyFlexRamBlockBaseAddr = 0x08U, /*!< FlexRam block base address property.*/ - kFLASH_propertyFlexRamTotalSize = 0x09U, /*!< FlexRam total size property.*/ - kFLASH_propertyDflashSectorSize = 0x10U, /*!< Dflash sector size property.*/ - kFLASH_propertyDflashTotalSize = 0x11U, /*!< Dflash total size property.*/ - kFLASH_propertyDflashBlockSize = 0x12U, /*!< Dflash block count property.*/ - kFLASH_propertyDflashBlockCount = 0x13U, /*!< Dflash block base address property.*/ - kFLASH_propertyDflashBlockBaseAddr = 0x14U, /*!< Eeprom total size property.*/ - kFLASH_propertyEepromTotalSize = 0x15U + kFLASH_PropertyPflashSectorSize = 0x00U, /*!< Pflash sector size property.*/ + kFLASH_PropertyPflashTotalSize = 0x01U, /*!< Pflash total size property.*/ + kFLASH_PropertyPflashBlockSize = 0x02U, /*!< Pflash block size property.*/ + kFLASH_PropertyPflashBlockCount = 0x03U, /*!< Pflash block count property.*/ + kFLASH_PropertyPflashBlockBaseAddr = 0x04U, /*!< Pflash block base address property.*/ + kFLASH_PropertyPflashFacSupport = 0x05U, /*!< Pflash fac support property.*/ + kFLASH_PropertyPflashAccessSegmentSize = 0x06U, /*!< Pflash access segment size property.*/ + kFLASH_PropertyPflashAccessSegmentCount = 0x07U, /*!< Pflash access segment count property.*/ + kFLASH_PropertyFlexRamBlockBaseAddr = 0x08U, /*!< FlexRam block base address property.*/ + kFLASH_PropertyFlexRamTotalSize = 0x09U, /*!< FlexRam total size property.*/ + kFLASH_PropertyDflashSectorSize = 0x10U, /*!< Dflash sector size property.*/ + kFLASH_PropertyDflashTotalSize = 0x11U, /*!< Dflash total size property.*/ + kFLASH_PropertyDflashBlockSize = 0x12U, /*!< Dflash block size property.*/ + kFLASH_PropertyDflashBlockCount = 0x13U, /*!< Dflash block count property.*/ + kFLASH_PropertyDflashBlockBaseAddr = 0x14U, /*!< Dflash block base address property.*/ + kFLASH_PropertyEepromTotalSize = 0x15U, /*!< EEPROM total size property.*/ + kFLASH_PropertyFlashMemoryIndex = 0x20U, /*!< Flash memory index property.*/ + kFLASH_PropertyFlashCacheControllerIndex = 0x21U /*!< Flash cache controller index property.*/ } flash_property_tag_t; /*! - * @brief Constants for execute-in-ram flash function. + * @brief Constants for execute-in-RAM flash function. */ enum _flash_execute_in_ram_function_constants { - kFLASH_executeInRamFunctionMaxSize = 64U, /*!< Max size of execute-in-ram function.*/ - kFLASH_executeInRamFunctionTotalNum = 2U /*!< Total number of execute-in-ram functions.*/ + kFLASH_ExecuteInRamFunctionMaxSizeInWords = 16U, /*!< The maximum size of execute-in-RAM function.*/ + kFLASH_ExecuteInRamFunctionTotalNum = 2U /*!< Total number of execute-in-RAM functions.*/ }; /*! - * @brief Flash execute-in-ram function information. + * @brief Flash execute-in-RAM function information. */ typedef struct _flash_execute_in_ram_function_config { - uint32_t activeFunctionCount; /*!< Number of available execute-in-ram functions.*/ - uint8_t *flashRunCommand; /*!< execute-in-ram function: flash_run_command.*/ - uint8_t *flashCacheClearCommand; /*!< execute-in-ram function: flash_cache_clear_command.*/ + uint32_t activeFunctionCount; /*!< Number of available execute-in-RAM functions.*/ + uint32_t *flashRunCommand; /*!< Execute-in-RAM function: flash_run_command.*/ + uint32_t *flashCommonBitOperation; /*!< Execute-in-RAM function: flash_common_bit_operation.*/ } flash_execute_in_ram_function_config_t; /*! @@ -272,9 +292,9 @@ typedef struct _flash_execute_in_ram_function_config */ typedef enum _flash_read_resource_option { - kFLASH_resourceOptionFlashIfr = + kFLASH_ResourceOptionFlashIfr = 0x00U, /*!< Select code for Program flash 0 IFR, Program flash swap 0 IFR, Data flash 0 IFR */ - kFLASH_resourceOptionVersionId = 0x01U /*!< Select code for Version ID*/ + kFLASH_ResourceOptionVersionId = 0x01U /*!< Select code for the version ID*/ } flash_read_resource_option_t; /*! @@ -283,124 +303,262 @@ typedef enum _flash_read_resource_option enum _flash_read_resource_range { #if (FSL_FEATURE_FLASH_IS_FTFE == 1) - kFLASH_resourceRangePflashIfrSizeInBytes = 1024U, /*!< Pflash IFR size in byte.*/ - kFLASH_resourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ - kFLASH_resourceRangeVersionIdStart = 0x08U, /*!< Version ID IFR start address.*/ - kFLASH_resourceRangeVersionIdEnd = 0x0FU, /*!< Version ID IFR end address.*/ -#else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA = =1 */ - kFLASH_resourceRangePflashIfrSizeInBytes = 256U, /*!< Pflash IFR size in byte.*/ - kFLASH_resourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ - kFLASH_resourceRangeVersionIdStart = 0x00U, /*!< Version ID IFR start address.*/ - kFLASH_resourceRangeVersionIdEnd = 0x07U, /*!< Version ID IFR end address.*/ + kFLASH_ResourceRangePflashIfrSizeInBytes = 1024U, /*!< Pflash IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdStart = 0x08U, /*!< Version ID IFR start address.*/ + kFLASH_ResourceRangeVersionIdEnd = 0x0FU, /*!< Version ID IFR end address.*/ + kFLASH_ResourceRangePflashSwapIfrStart = 0x40000U, /*!< Pflash swap IFR start address.*/ + kFLASH_ResourceRangePflashSwapIfrEnd = + (kFLASH_ResourceRangePflashSwapIfrStart + 0x3FFU), /*!< Pflash swap IFR end address.*/ +#else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA = =1 */ + kFLASH_ResourceRangePflashIfrSizeInBytes = 256U, /*!< Pflash IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdStart = 0x00U, /*!< Version ID IFR start address.*/ + kFLASH_ResourceRangeVersionIdEnd = 0x07U, /*!< Version ID IFR end address.*/ +#if 0x20000U == (FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) + kFLASH_ResourceRangePflashSwapIfrStart = 0x8000U, /*!< Pflash swap IFR start address.*/ +#elif 0x40000U == (FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) + kFLASH_ResourceRangePflashSwapIfrStart = 0x10000U, /*!< Pflash swap IFR start address.*/ +#elif 0x80000U == (FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) + kFLASH_ResourceRangePflashSwapIfrStart = 0x20000U, /*!< Pflash swap IFR start address.*/ +#else + kFLASH_ResourceRangePflashSwapIfrStart = 0, #endif - kFLASH_resourceRangePflashSwapIfrStart = 0x40000U, /*!< Pflash swap IFR start address.*/ - kFLASH_resourceRangePflashSwapIfrEnd = 0x403FFU, /*!< Pflash swap IFR end address.*/ - kFLASH_resourceRangeDflashIfrStart = 0x800000U, /*!< Dflash IFR start address.*/ - kFLASH_resourceRangeDflashIfrEnd = 0x8003FFU, /*!< Dflash IFR end address.*/ + kFLASH_ResourceRangePflashSwapIfrEnd = + (kFLASH_ResourceRangePflashSwapIfrStart + 0xFFU), /*!< Pflash swap IFR end address.*/ +#endif + kFLASH_ResourceRangeDflashIfrStart = 0x800000U, /*!< Dflash IFR start address.*/ + kFLASH_ResourceRangeDflashIfrEnd = 0x8003FFU, /*!< Dflash IFR end address.*/ +}; + +/*! + * @brief Enumeration for the index of read/program once record + */ +enum _k3_flash_read_once_index +{ + kFLASH_RecordIndexSwapAddr = 0xA1U, /*!< Index of Swap indicator address.*/ + kFLASH_RecordIndexSwapEnable = 0xA2U, /*!< Index of Swap system enable.*/ + kFLASH_RecordIndexSwapDisable = 0xA3U, /*!< Index of Swap system disable.*/ }; /*! - * @brief Enumeration for the two possilbe options of set flexram function command. + * @brief Enumeration for the two possilbe options of set FlexRAM function command. */ typedef enum _flash_flexram_function_option { - kFLASH_flexramFunctionOptionAvailableAsRam = 0xFFU, /*!< Option used to make FlexRAM available as RAM */ - kFLASH_flexramFunctionOptionAvailableForEeprom = 0x00U /*!< Option used to make FlexRAM available for EEPROM */ + kFLASH_FlexramFunctionOptionAvailableAsRam = 0xFFU, /*!< An option used to make FlexRAM available as RAM */ + kFLASH_FlexramFunctionOptionAvailableForEeprom = 0x00U /*!< An option used to make FlexRAM available for EEPROM */ } flash_flexram_function_option_t; +/*! + * @brief Enumeration for acceleration RAM property. + */ +enum _flash_acceleration_ram_property +{ + kFLASH_AccelerationRamSize = 0x400U +}; + /*! * @brief Enumeration for the possible options of Swap function */ typedef enum _flash_swap_function_option { - kFLASH_swapFunctionOptionEnable = 0x00U, /*!< Option used to enable Swap function */ - kFLASH_swapFunctionOptionDisable = 0x01U /*!< Option used to Disable Swap function */ + kFLASH_SwapFunctionOptionEnable = 0x00U, /*!< An option used to enable the Swap function */ + kFLASH_SwapFunctionOptionDisable = 0x01U /*!< An option used to disable the Swap function */ } flash_swap_function_option_t; /*! - * @brief Enumeration for the possible options of Swap Control commands + * @brief Enumeration for the possible options of Swap control commands */ typedef enum _flash_swap_control_option { - kFLASH_swapControlOptionIntializeSystem = 0x01U, /*!< Option used to Intialize Swap System */ - kFLASH_swapControlOptionSetInUpdateState = 0x02U, /*!< Option used to Set Swap in Update State */ - kFLASH_swapControlOptionSetInCompleteState = 0x04U, /*!< Option used to Set Swap in Complete State */ - kFLASH_swapControlOptionReportStatus = 0x08U, /*!< Option used to Report Swap Status */ - kFLASH_swapControlOptionDisableSystem = 0x10U /*!< Option used to Disable Swap Status */ + kFLASH_SwapControlOptionIntializeSystem = 0x01U, /*!< An option used to initialize the Swap system */ + kFLASH_SwapControlOptionSetInUpdateState = 0x02U, /*!< An option used to set the Swap in an update state */ + kFLASH_SwapControlOptionSetInCompleteState = 0x04U, /*!< An option used to set the Swap in a complete state */ + kFLASH_SwapControlOptionReportStatus = 0x08U, /*!< An option used to report the Swap status */ + kFLASH_SwapControlOptionDisableSystem = 0x10U /*!< An option used to disable the Swap status */ } flash_swap_control_option_t; /*! - * @brief Enumeration for the possible flash swap status. + * @brief Enumeration for the possible flash Swap status. */ typedef enum _flash_swap_state { - kFLASH_swapStateUninitialized = 0x00U, /*!< Flash swap system is in uninitialized state.*/ - kFLASH_swapStateReady = 0x01U, /*!< Flash swap system is in ready state.*/ - kFLASH_swapStateUpdate = 0x02U, /*!< Flash swap system is in update state.*/ - kFLASH_swapStateUpdateErased = 0x03U, /*!< Flash swap system is in updateErased state.*/ - kFLASH_swapStateComplete = 0x04U, /*!< Flash swap system is in complete state.*/ - kFLASH_swapStateDisabled = 0x05U /*!< Flash swap system is in disabled state.*/ + kFLASH_SwapStateUninitialized = 0x00U, /*!< Flash Swap system is in an uninitialized state.*/ + kFLASH_SwapStateReady = 0x01U, /*!< Flash Swap system is in a ready state.*/ + kFLASH_SwapStateUpdate = 0x02U, /*!< Flash Swap system is in an update state.*/ + kFLASH_SwapStateUpdateErased = 0x03U, /*!< Flash Swap system is in an updateErased state.*/ + kFLASH_SwapStateComplete = 0x04U, /*!< Flash Swap system is in a complete state.*/ + kFLASH_SwapStateDisabled = 0x05U /*!< Flash Swap system is in a disabled state.*/ } flash_swap_state_t; /*! - * @breif Enumeration for the possible flash swap block status + * @breif Enumeration for the possible flash Swap block status */ typedef enum _flash_swap_block_status { - kFLASH_swapBlockStatusLowerHalfProgramBlocksAtZero = + kFLASH_SwapBlockStatusLowerHalfProgramBlocksAtZero = 0x00U, /*!< Swap block status is that lower half program block at zero.*/ - kFLASH_swapBlockStatusUpperHalfProgramBlocksAtZero = + kFLASH_SwapBlockStatusUpperHalfProgramBlocksAtZero = 0x01U, /*!< Swap block status is that upper half program block at zero.*/ } flash_swap_block_status_t; /*! - * @brief Flash Swap information. + * @brief Flash Swap information */ typedef struct _flash_swap_state_config { - flash_swap_state_t flashSwapState; /*!< Current swap system status.*/ - flash_swap_block_status_t currentSwapBlockStatus; /*!< Current swap block status.*/ - flash_swap_block_status_t nextSwapBlockStatus; /*!< Next swap block status.*/ + flash_swap_state_t flashSwapState; /*!chip = 0; fbConfig->writeProtect = 0; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c index 15e1f55f437..f58f3f55f05 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -165,8 +165,6 @@ static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_ /******************************************************************************* * Variables ******************************************************************************/ -/* Array of FlexCAN handle. */ -static flexcan_handle_t *s_flexcanHandle[FSL_FEATURE_SOC_FLEXCAN_COUNT]; /* Array of FlexCAN peripheral base address. */ static CAN_Type *const s_flexcanBases[] = CAN_BASE_PTRS; @@ -179,8 +177,17 @@ static const IRQn_Type s_flexcanErrorIRQ[] = CAN_Error_IRQS; static const IRQn_Type s_flexcanBusOffIRQ[] = CAN_Bus_Off_IRQS; static const IRQn_Type s_flexcanMbIRQ[] = CAN_ORed_Message_buffer_IRQS; +/* Array of FlexCAN handle. */ +static flexcan_handle_t *s_flexcanHandle[ARRAY_SIZE(s_flexcanBases)]; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of FlexCAN clock name. */ static const clock_ip_name_t s_flexcanClock[] = FLEXCAN_CLOCKS; +#if defined(FLEXCAN_PERIPH_CLOCKS) +/* Array of FlexCAN serial clock name. */ +static const clock_ip_name_t s_flexcanPeriphClock[] = FLEXCAN_PERIPH_CLOCKS; +#endif /* FLEXCAN_PERIPH_CLOCKS */ +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* FlexCAN ISR for transactional APIs. */ static flexcan_isr_t s_flexcanIsr; @@ -194,7 +201,7 @@ uint32_t FLEXCAN_GetInstance(CAN_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_FLEXCAN_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_flexcanBases); instance++) { if (s_flexcanBases[instance] == base) { @@ -202,7 +209,7 @@ uint32_t FLEXCAN_GetInstance(CAN_Type *base) } } - assert(instance < FSL_FEATURE_SOC_FLEXCAN_COUNT); + assert(instance < ARRAY_SIZE(s_flexcanBases)); return instance; } @@ -314,9 +321,13 @@ static bool FLEXCAN_IsMbIntEnabled(CAN_Type *base, uint8_t mbIdx) else { if (base->IMASK2 & ((uint32_t)(1 << (mbIdx - 32)))) + { return true; + } else + { return false; + } } #endif } @@ -420,14 +431,25 @@ static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz) { uint32_t mcrTemp; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance; +#endif /* Assertion. */ assert(config); assert((config->maxMbNum > 0) && (config->maxMbNum <= FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base))); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + instance = FLEXCAN_GetInstance(base); /* Enable FlexCAN clock. */ - CLOCK_EnableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); - + CLOCK_EnableClock(s_flexcanClock[instance]); +#if defined(FLEXCAN_PERIPH_CLOCKS) + /* Enable FlexCAN serial clock. */ + CLOCK_EnableClock(s_flexcanPeriphClock[instance]); +#endif /* FLEXCAN_PERIPH_CLOCKS */ +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE /* Disable FlexCAN Module. */ FLEXCAN_Enable(base, false); @@ -436,6 +458,7 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc */ base->CTRL1 = (kFLEXCAN_ClkSrcOsc == config->clkSrc) ? base->CTRL1 & ~CAN_CTRL1_CLKSRC_MASK : base->CTRL1 | CAN_CTRL1_CLKSRC_MASK; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ /* Enable FlexCAN Module for configuartion. */ FLEXCAN_Enable(base, true); @@ -472,14 +495,24 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc void FLEXCAN_Deinit(CAN_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance; +#endif /* Reset all Register Contents. */ FLEXCAN_Reset(base); /* Disable FlexCAN module. */ FLEXCAN_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + instance = FLEXCAN_GetInstance(base); +#if defined(FLEXCAN_PERIPH_CLOCKS) + /* Disable FlexCAN serial clock. */ + CLOCK_DisableClock(s_flexcanPeriphClock[instance]); +#endif /* FLEXCAN_PERIPH_CLOCKS */ /* Disable FlexCAN clock. */ - CLOCK_DisableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); + CLOCK_DisableClock(s_flexcanClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void FLEXCAN_GetDefaultConfig(flexcan_config_t *config) @@ -488,7 +521,9 @@ void FLEXCAN_GetDefaultConfig(flexcan_config_t *config) assert(config); /* Initialize FlexCAN Module config struct with default value. */ +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE config->clkSrc = kFLEXCAN_ClkSrcOsc; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ config->baudRate = 125000U; config->maxMbNum = 16; config->enableLoopBack = false; @@ -1293,13 +1328,13 @@ void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle) (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); #else - while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) || - (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | - kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); + while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) || + (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | + kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); #endif } -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 0) +#if defined(CAN0) void CAN0_DriverIRQHandler(void) { assert(s_flexcanHandle[0]); @@ -1308,7 +1343,7 @@ void CAN0_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 1) +#if defined(CAN1) void CAN1_DriverIRQHandler(void) { assert(s_flexcanHandle[1]); @@ -1317,7 +1352,7 @@ void CAN1_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 2) +#if defined(CAN2) void CAN2_DriverIRQHandler(void) { assert(s_flexcanHandle[2]); @@ -1326,7 +1361,7 @@ void CAN2_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 3) +#if defined(CAN3) void CAN3_DriverIRQHandler(void) { assert(s_flexcanHandle[3]); @@ -1335,7 +1370,7 @@ void CAN3_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 4) +#if defined(CAN4) void CAN4_DriverIRQHandler(void) { assert(s_flexcanHandle[4]); @@ -1343,3 +1378,30 @@ void CAN4_DriverIRQHandler(void) s_flexcanIsr(CAN4, s_flexcanHandle[4]); } #endif + +#if defined(DMA_CAN0) +void DMA_FLEXCAN0_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]); + + s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]); +} +#endif + +#if defined(DMA_CAN1) +void DMA_FLEXCAN1_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]); + + s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]); +} +#endif + +#if defined(DMA_CAN2) +void DMA_FLEXCAN2_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]); + + s_flexcanIsr(DMA_CAN2, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]); +} +#endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h index 13c28f357d4..118badf58fb 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,15 +37,14 @@ * @{ */ - /****************************************************************************** * Definitions *****************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief FlexCAN driver version 2.1.0. */ -#define FLEXCAN_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief FlexCAN driver version 2.2.0. */ +#define FLEXCAN_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*@}*/ /*! @brief FlexCAN Frame ID helper macro. */ @@ -69,19 +68,18 @@ (FLEXCAN_ID_STD(id) << 1)) /*!< Standard Rx FIFO Mask helper macro Type A helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_HIGH(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ - (FLEXCAN_ID_STD(id) << 16)) /*!< Standard Rx FIFO Mask helper macro Type B upper part helper macro. */ + (((uint32_t)(id) & 0x7FF) << 19)) /*!< Standard Rx FIFO Mask helper macro Type B upper part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_LOW(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 15) | (uint32_t)((uint32_t)(ide) << 14)) | \ - FLEXCAN_ID_STD(id)) /*!< Standard Rx FIFO Mask helper macro Type B lower part helper macro. */ + (((uint32_t)(id) & 0x7FF) << 3)) /*!< Standard Rx FIFO Mask helper macro Type B lower part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_HIGH(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 21) /*!< Standard Rx FIFO Mask helper macro Type C upper part helper macro. */ -#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 13) /*!< Standard Rx FIFO Mask helper macro Type C mid-upper part helper macro. \ - */ + (((uint32_t)(id) & 0x7F8) << 21) /*!< Standard Rx FIFO Mask helper macro Type C upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH(id) \ + (((uint32_t)(id) & 0x7F8) << 13) /*!< Standard Rx FIFO Mask helper macro Type C mid-upper part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_LOW(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 5) /*!< Standard Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ + (((uint32_t)(id) & 0x7F8) << 5) /*!< Standard Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_LOW(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) >> 3) /*!< Standard Rx FIFO Mask helper macro Type C lower part helper macro. */ + (((uint32_t)(id) & 0x7F8) >> 3) /*!< Standard Rx FIFO Mask helper macro Type C lower part helper macro. */ #define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_A(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ (FLEXCAN_ID_EXT(id) << 1)) /*!< Extend Rx FIFO Mask helper macro Type A helper macro. */ @@ -157,7 +155,7 @@ enum _flexcan_status kStatus_FLEXCAN_RxFifoBusy = MAKE_STATUS(kStatusGroup_FLEXCAN, 6), /*!< Rx Message FIFO is Busy. */ kStatus_FLEXCAN_RxFifoIdle = MAKE_STATUS(kStatusGroup_FLEXCAN, 7), /*!< Rx Message FIFO is Idle. */ kStatus_FLEXCAN_RxFifoOverflow = MAKE_STATUS(kStatusGroup_FLEXCAN, 8), /*!< Rx Message FIFO is overflowed. */ - kStatus_FLEXCAN_RxFifoWarning = MAKE_STATUS(kStatusGroup_FLEXCAN, 0), /*!< Rx Message FIFO is almost overflowed. */ + kStatus_FLEXCAN_RxFifoWarning = MAKE_STATUS(kStatusGroup_FLEXCAN, 9), /*!< Rx Message FIFO is almost overflowed. */ kStatus_FLEXCAN_ErrorStatus = MAKE_STATUS(kStatusGroup_FLEXCAN, 10), /*!< FlexCAN Module Error and Status. */ kStatus_FLEXCAN_UnHandled = MAKE_STATUS(kStatusGroup_FLEXCAN, 11), /*!< UnHadled Interrupt asserted. */ }; @@ -176,12 +174,14 @@ typedef enum _flexcan_frame_type kFLEXCAN_FrameTypeRemote = 0x1U, /*!< Remote frame type attribute. */ } flexcan_frame_type_t; +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE /*! @brief FlexCAN clock source. */ typedef enum _flexcan_clock_source { kFLEXCAN_ClkSrcOsc = 0x0U, /*!< FlexCAN Protocol Engine clock from Oscillator. */ kFLEXCAN_ClkSrcPeri = 0x1U, /*!< FlexCAN Protocol Engine clock from Peripheral Clock. */ } flexcan_clock_source_t; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ /*! @brief FlexCAN Rx Fifo Filter type. */ typedef enum _flexcan_rx_fifo_filter_type @@ -195,7 +195,7 @@ typedef enum _flexcan_rx_fifo_filter_type } flexcan_rx_fifo_filter_type_t; /*! - * @brief FlexCAN Rx FIFO priority + * @brief FlexCAN Rx FIFO priority. * * The matching process starts from the Rx MB(or Rx FIFO) with higher priority. * If no MB(or Rx FIFO filter) is satisfied, the matching process goes on with @@ -326,7 +326,9 @@ typedef struct _flexcan_frame typedef struct _flexcan_config { uint32_t baudRate; /*!< FlexCAN baud rate in bps. */ +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE flexcan_clock_source_t clkSrc; /*!< Clock source for FlexCAN Protocol Engine. */ +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ uint8_t maxMbNum; /*!< The maximum number of Message Buffers used by user. */ bool enableLoopBack; /*!< Enable or Disable Loop Back Self Test Mode. */ bool enableSelfWakeup; /*!< Enable or Disable Self Wakeup Mode. */ @@ -366,7 +368,7 @@ typedef struct _flexcan_rx_mb_config /*! @brief FlexCAN Rx FIFO configuration structure. */ typedef struct _flexcan_rx_fifo_config { - uint32_t *idFilterTable; /*!< Pointer to FlexCAN Rx FIFO identifier filter table. */ + uint32_t *idFilterTable; /*!< Pointer to the FlexCAN Rx FIFO identifier filter table. */ uint8_t idFilterNum; /*!< The quantity of filter elements. */ flexcan_rx_fifo_filter_type_t idFilterType; /*!< The FlexCAN Rx FIFO Filter type. */ flexcan_rx_fifo_priority_t priority; /*!< The FlexCAN Rx FIFO receive priority. */ @@ -431,7 +433,7 @@ extern "C" { * * This function initializes the FlexCAN module with user-defined settings. * This example shows how to set up the flexcan_config_t parameters and how - * to call the FLEXCAN_Init function by passing in these parameters: + * to call the FLEXCAN_Init function by passing in these parameters. * @code * flexcan_config_t flexcanConfig; * flexcanConfig.clkSrc = kFLEXCAN_ClkSrcOsc; @@ -445,7 +447,7 @@ extern "C" { * @endcode * * @param base FlexCAN peripheral base address. - * @param config Pointer to user-defined configuration structure. + * @param config Pointer to the user-defined configuration structure. * @param sourceClock_Hz FlexCAN Protocol Engine clock source frequency in Hz. */ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz); @@ -453,18 +455,18 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc /*! * @brief De-initializes a FlexCAN instance. * - * This function disable the FlexCAN module clock and set all register value - * to reset value. + * This function disables the FlexCAN module clock and sets all register values + * to the reset value. * * @param base FlexCAN peripheral base address. */ void FLEXCAN_Deinit(CAN_Type *base); /*! - * @brief Get the default configuration structure. + * @brief Gets the default configuration structure. * - * This function initializes the FlexCAN configuration structure to default value. The default - * value are: + * This function initializes the FlexCAN configuration structure to default values. The default + * values are as follows. * flexcanConfig->clkSrc = KFLEXCAN_ClkSrcOsc; * flexcanConfig->baudRate = 125000U; * flexcanConfig->maxMbNum = 16; @@ -473,7 +475,7 @@ void FLEXCAN_Deinit(CAN_Type *base); * flexcanConfig->enableIndividMask = false; * flexcanConfig->enableDoze = false; * - * @param config Pointer to FlexCAN configuration structure. + * @param config Pointer to the FlexCAN configuration structure. */ void FLEXCAN_GetDefaultConfig(flexcan_config_t *config); @@ -503,7 +505,7 @@ void FLEXCAN_SetTimingConfig(CAN_Type *base, const flexcan_timing_config_t *conf /*! * @brief Sets the FlexCAN receive message buffer global mask. * - * This function sets the global mask for FlexCAN message buffer in a matching process. + * This function sets the global mask for the FlexCAN message buffer in a matching process. * The configuration is only effective when the Rx individual mask is disabled in the FLEXCAN_Init(). * * @param base FlexCAN peripheral base address. @@ -524,12 +526,12 @@ void FLEXCAN_SetRxFifoGlobalMask(CAN_Type *base, uint32_t mask); /*! * @brief Sets the FlexCAN receive individual mask. * - * This function sets the individual mask for FlexCAN matching process. - * The configuration is only effective when the Rx individual mask is enabled in FLEXCAN_Init(). - * If Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer. - * If Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to - * the Rx Filter with same index. What calls for special attention is that only the first 32 - * individual masks can be used as Rx FIFO filter mask. + * This function sets the individual mask for the FlexCAN matching process. + * The configuration is only effective when the Rx individual mask is enabled in the FLEXCAN_Init(). + * If the Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer. + * If the Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to + * the Rx Filter with the same index. Note that only the first 32 + * individual masks can be used as the Rx FIFO filter mask. * * @param base FlexCAN peripheral base address. * @param maskIdx The Index of individual Mask. @@ -545,7 +547,7 @@ void FLEXCAN_SetRxIndividualMask(CAN_Type *base, uint8_t maskIdx, uint32_t mask) * * @param base FlexCAN peripheral base address. * @param mbIdx The Message Buffer index. - * @param enable Enable/Disable Tx Message Buffer. + * @param enable Enable/disable Tx Message Buffer. * - true: Enable Tx Message Buffer. * - false: Disable Tx Message Buffer. */ @@ -559,8 +561,8 @@ void FLEXCAN_SetTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable); * * @param base FlexCAN peripheral base address. * @param mbIdx The Message Buffer index. - * @param config Pointer to FlexCAN Message Buffer configuration structure. - * @param enable Enable/Disable Rx Message Buffer. + * @param config Pointer to the FlexCAN Message Buffer configuration structure. + * @param enable Enable/disable Rx Message Buffer. * - true: Enable Rx Message Buffer. * - false: Disable Rx Message Buffer. */ @@ -572,8 +574,8 @@ void FLEXCAN_SetRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_co * This function configures the Rx FIFO with given Rx FIFO configuration. * * @param base FlexCAN peripheral base address. - * @param config Pointer to FlexCAN Rx FIFO configuration structure. - * @param enable Enable/Disable Rx FIFO. + * @param config Pointer to the FlexCAN Rx FIFO configuration structure. + * @param enable Enable/disable Rx FIFO. * - true: Enable Rx FIFO. * - false: Disable Rx FIFO. */ @@ -676,7 +678,7 @@ static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IFLAG1 = (uint32_t)(mask & 0xFFFFFFFF); + base->IFLAG1 = (uint32_t)(mask & 0xFFFFFFFFU); base->IFLAG2 = (uint32_t)(mask >> 32); #else base->IFLAG1 = mask; @@ -691,9 +693,9 @@ static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint32_t mask) */ /*! - * @brief Enables FlexCAN interrupts according to provided mask. + * @brief Enables FlexCAN interrupts according to the provided mask. * - * This function enables the FlexCAN interrupts according to provided mask. The mask + * This function enables the FlexCAN interrupts according to the provided mask. The mask * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. * * @param base FlexCAN peripheral base address. @@ -712,9 +714,9 @@ static inline void FLEXCAN_EnableInterrupts(CAN_Type *base, uint32_t mask) } /*! - * @brief Disables FlexCAN interrupts according to provided mask. + * @brief Disables FlexCAN interrupts according to the provided mask. * - * This function disables the FlexCAN interrupts according to provided mask. The mask + * This function disables the FlexCAN interrupts according to the provided mask. The mask * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. * * @param base FlexCAN peripheral base address. @@ -735,7 +737,7 @@ static inline void FLEXCAN_DisableInterrupts(CAN_Type *base, uint32_t mask) /*! * @brief Enables FlexCAN Message Buffer interrupts. * - * This function enables the interrupts of given Message Buffers + * This function enables the interrupts of given Message Buffers. * * @param base FlexCAN peripheral base address. * @param mask The ORed FlexCAN Message Buffer mask. @@ -747,7 +749,7 @@ static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IMASK1 |= (uint32_t)(mask & 0xFFFFFFFF); + base->IMASK1 |= (uint32_t)(mask & 0xFFFFFFFFU); base->IMASK2 |= (uint32_t)(mask >> 32); #else base->IMASK1 |= mask; @@ -757,7 +759,7 @@ static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint32_t mask) /*! * @brief Disables FlexCAN Message Buffer interrupts. * - * This function disables the interrupts of given Message Buffers + * This function disables the interrupts of given Message Buffers. * * @param base FlexCAN peripheral base address. * @param mask The ORed FlexCAN Message Buffer mask. @@ -769,7 +771,7 @@ static inline void FLEXCAN_DisableMbInterrupts(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IMASK1 &= ~((uint32_t)(mask & 0xFFFFFFFF)); + base->IMASK1 &= ~((uint32_t)(mask & 0xFFFFFFFFU)); base->IMASK2 &= ~((uint32_t)(mask >> 32)); #else base->IMASK1 &= ~mask; @@ -846,7 +848,7 @@ static inline void FLEXCAN_Enable(CAN_Type *base, bool enable) } /*! - * @brief Writes a FlexCAN Message to Transmit Message Buffer. + * @brief Writes a FlexCAN Message to the Transmit Message Buffer. * * This function writes a CAN Message to the specified Transmit Message Buffer * and changes the Message Buffer state to start CAN Message transmit. After @@ -938,7 +940,7 @@ status_t FLEXCAN_TransferReceiveFifoBlocking(CAN_Type *base, flexcan_frame_t *rx /*! * @brief Initializes the FlexCAN handle. * - * This function initializes the FlexCAN handle which can be used for other FlexCAN + * This function initializes the FlexCAN handle, which can be used for other FlexCAN * transactional APIs. Usually, for a specified FlexCAN instance, * call this API once to get the initialized handle. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c index 85dc2194254..9cca44b0e41 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -72,8 +72,10 @@ static void FTM_SetReloadPoints(FTM_Type *base, uint32_t reloadPoints); /*! @brief Pointers to FTM bases for each instance. */ static FTM_Type *const s_ftmBases[] = FTM_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to FTM clocks for each instance. */ static const clock_ip_name_t s_ftmClocks[] = FTM_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -228,8 +230,10 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) return kStatus_Fail; } +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate the FTM clock*/ CLOCK_EnableClock(s_ftmClocks[FTM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure the fault mode, enable FTM mode and disable write protection */ base->MODE = FTM_MODE_FAULTM(config->faultMode) | FTM_MODE_FTMEN_MASK | FTM_MODE_WPDIS_MASK; @@ -266,7 +270,13 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) #endif /* FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER */ /* FTM deadtime insertion control */ - base->DEADTIME = (FTM_DEADTIME_DTPS(config->deadTimePrescale) | FTM_DEADTIME_DTVAL(config->deadTimeValue)); + base->DEADTIME = (0u | +#if defined(FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE) && (FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE) + /* Has extended deadtime value register) */ + FTM_DEADTIME_DTVALEX(config->deadTimeValue >> 6) | +#endif /* FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE */ + FTM_DEADTIME_DTPS(config->deadTimePrescale) | + FTM_DEADTIME_DTVAL(config->deadTimeValue)); /* FTM fault filter value */ reg = base->FLTCTRL; @@ -282,8 +292,10 @@ void FTM_Deinit(FTM_Type *base) /* Set clock source to none to disable counter */ base->SC &= ~(FTM_SC_CLKS_MASK); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the FTM clock */ CLOCK_DisableClock(s_ftmClocks[FTM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void FTM_GetDefaultConfig(ftm_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h index 2fb1c08e49c..8db81a633ac 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -#define FSL_FTM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */ -/*@}*/ +#define FSL_FTM_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2 */ + /*@}*/ /*! * @brief List of FTM channels @@ -162,7 +161,7 @@ typedef struct _ftm_phase_param typedef struct _ftm_fault_param { bool enableFaultInput; /*!< True: Fault input is enabled; false: Fault input is disabled */ - bool faultLevel; /*!< True: Fault polarity is active low i.e., '0' indicates a fault; + bool faultLevel; /*!< True: Fault polarity is active low; in other words, '0' indicates a fault; False: Fault polarity is active high */ bool useFaultFilter; /*!< True: Use the filtered fault signal; False: Use the direct path from fault input */ @@ -310,6 +309,17 @@ typedef enum _ftm_status_flags kFTM_ReloadFlag = (1U << 11) /*!< Reload Flag; Available only on certain SoC's */ } ftm_status_flags_t; +/*! + * @brief List of FTM Quad Decoder flags. + */ +enum _ftm_quad_decoder_flags +{ + kFTM_QuadDecoderCountingIncreaseFlag = FTM_QDCTRL_QUADIR_MASK, /*!< Counting direction is increasing (FTM counter + increment), or the direction is decreasing. */ + kFTM_QuadDecoderCountingOverflowOnTopFlag = FTM_QDCTRL_TOFDIR_MASK, /*!< Indicates if the TOF bit was set on the top + or the bottom of counting. */ +}; + /*! * @brief FTM configuration structure * @@ -333,7 +343,9 @@ typedef struct _ftm_config ftm_fault_mode_t faultMode; /*!< FTM fault control mode */ uint8_t faultFilterValue; /*!< Fault input filter value */ ftm_deadtime_prescale_t deadTimePrescale; /*!< The dead time prescalar value */ - uint8_t deadTimeValue; /*!< The dead time value */ + uint32_t deadTimeValue; /*!< The dead time value + deadTimeValue's available range is 0-1023 when register has DTVALEX, + otherwise its available range is 0-63. */ uint32_t extTriggers; /*!< External triggers to enable. Multiple trigger sources can be enabled by providing an OR'ed list of options available in enumeration ::ftm_external_trigger_t. */ @@ -359,7 +371,7 @@ extern "C" { /*! * @brief Ungates the FTM clock and configures the peripheral for basic operation. * - * @note This API should be called at the beginning of the application using the FTM driver. + * @note This API should be called at the beginning of the application which is using the FTM driver. * * @param base FTM peripheral base address * @param config Pointer to the user configuration structure. @@ -508,19 +520,6 @@ void FTM_SetupDualEdgeCapture(FTM_Type *base, /*! @}*/ -/*! - * @brief Configures the parameters and activates the quadrature decoder mode. - * - * @param base FTM peripheral base address - * @param phaseAParams Phase A configuration parameters - * @param phaseBParams Phase B configuration parameters - * @param quadMode Selects encoding mode used in quadrature decoder mode - */ -void FTM_SetupQuadDecode(FTM_Type *base, - const ftm_phase_params_t *phaseAParams, - const ftm_phase_params_t *phaseBParams, - ftm_quad_decode_mode_t quadMode); - /*! * @brief Sets up the working of the FTM fault protection. * @@ -593,6 +592,48 @@ void FTM_ClearStatusFlags(FTM_Type *base, uint32_t mask); /*! @}*/ +/*! + * @name Read and write the timer period + * @{ + */ + +/*! + * @brief Sets the timer period in units of ticks. + * + * Timers counts from 0 until it equals the count value set here. The count value is written to + * the MOD register. + * + * @note + * 1. This API allows the user to use the FTM module as a timer. Do not mix usage + * of this API with FTM's PWM setup API's. + * 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks. + * + * @param base FTM peripheral base address + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. + */ +static inline void FTM_SetTimerPeriod(FTM_Type *base, uint32_t ticks) +{ + base->MOD = ticks; +} + +/*! + * @brief Reads the current timer counting value. + * + * This function returns the real-time timer counting value in a range from 0 to a + * timer period. + * + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. + * + * @param base FTM peripheral base address + * + * @return The current counter value in ticks + */ +static inline uint32_t FTM_GetCurrentTimerCount(FTM_Type *base) +{ + return (uint32_t)((base->CNT & FTM_CNT_COUNT_MASK) >> FTM_CNT_COUNT_SHIFT); +} + +/*! @}*/ /*! * @name Timer Start and Stop * @{ @@ -711,7 +752,7 @@ static inline void FTM_SetOutputMask(FTM_Type *base, ftm_chnl_t chnlNumber, bool #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) /*! - * @brief Allows user to enable an output on an FTM channel. + * @brief Allows users to enable an output on an FTM channel. * * To enable the PWM channel output call this function with val=true. For input mode, * call this function with val=false. @@ -816,6 +857,76 @@ static inline void FTM_SetInvertEnable(FTM_Type *base, ftm_chnl_t chnlPairNumber /*! @}*/ +/*! + * @name Quad Decoder + * @{ + */ + +/*! + * @brief Configures the parameters and activates the quadrature decoder mode. + * + * @param base FTM peripheral base address + * @param phaseAParams Phase A configuration parameters + * @param phaseBParams Phase B configuration parameters + * @param quadMode Selects encoding mode used in quadrature decoder mode + */ +void FTM_SetupQuadDecode(FTM_Type *base, + const ftm_phase_params_t *phaseAParams, + const ftm_phase_params_t *phaseBParams, + ftm_quad_decode_mode_t quadMode); + +/*! + * @brief Gets the FTM Quad Decoder flags. + * + * @param base FTM peripheral base address. + * @return Flag mask of FTM Quad Decoder, see #_ftm_quad_decoder_flags. + */ +static inline uint32_t FTM_GetQuadDecoderFlags(FTM_Type *base) +{ + return base->QDCTRL & (FTM_QDCTRL_QUADIR_MASK | FTM_QDCTRL_TOFDIR_MASK); +} + +/*! + * @brief Sets the modulo values for Quad Decoder. + * + * The modulo values configure the minimum and maximum values that the Quad decoder counter can reach. After the counter goes + * over, the counter value goes to the other side and decrease/increase again. + * + * @param base FTM peripheral base address. + * @param startValue The low limit value for Quad Decoder counter. + * @param overValue The high limit value for Quad Decoder counter. + */ +static inline void FTM_SetQuadDecoderModuloValue(FTM_Type *base, uint32_t startValue, uint32_t overValue) +{ + base->CNTIN = startValue; + base->MOD = overValue; +} + +/*! + * @brief Gets the current Quad Decoder counter value. + * + * @param base FTM peripheral base address. + * @return Current quad Decoder counter value. + */ +static inline uint32_t FTM_GetQuadDecoderCounterValue(FTM_Type *base) +{ + return base->CNT; +} + +/*! + * @brief Clears the current Quad Decoder counter value. + * + * The counter is set as the initial value. + * + * @param base FTM peripheral base address. + */ +static inline void FTM_ClearQuadDecoderCounterValue(FTM_Type *base) +{ + base->CNT = base->CNTIN; +} + +/*! @}*/ + /*! * @brief Enables or disables the FTM software trigger for PWM synchronization. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c index 8fc068f2d6a..b40ee3ac11c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -57,7 +57,7 @@ static uint32_t GPIO_GetInstance(GPIO_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_GPIO_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++) { if (s_gpioBases[instance] == base) { @@ -65,7 +65,7 @@ static uint32_t GPIO_GetInstance(GPIO_Type *base) } } - assert(instance < FSL_FEATURE_SOC_GPIO_COUNT); + assert(instance < ARRAY_SIZE(s_gpioBases)); return instance; } @@ -103,6 +103,14 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask) portBase->ISFR = mask; } +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute) +{ + base->GACR = ((uint32_t)attribute << GPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB1_SHIFT) | + ((uint32_t)attribute << GPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB3_SHIFT); +} +#endif + #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT /******************************************************************************* @@ -130,7 +138,7 @@ static uint32_t FGPIO_GetInstance(FGPIO_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_FGPIO_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_fgpioBases); instance++) { if (s_fgpioBases[instance] == base) { @@ -138,7 +146,7 @@ static uint32_t FGPIO_GetInstance(FGPIO_Type *base) } } - assert(instance < FSL_FEATURE_SOC_FGPIO_COUNT); + assert(instance < ARRAY_SIZE(s_fgpioBases)); return instance; } @@ -176,4 +184,12 @@ void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask) portBase->ISFR = mask; } +#if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER +void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute) +{ + base->GACR = (attribute << FGPIO_GACR_ACB0_SHIFT) | (attribute << FGPIO_GACR_ACB1_SHIFT) | + (attribute << FGPIO_GACR_ACB2_SHIFT) | (attribute << FGPIO_GACR_ACB3_SHIFT); +} +#endif + #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h index 6eaaaa08744..410e2b8ee46 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -38,38 +38,60 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief GPIO driver version 2.1.0. */ -#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief GPIO driver version 2.1.1. */ +#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*@}*/ -/*! @brief GPIO direction definition*/ +/*! @brief GPIO direction definition */ typedef enum _gpio_pin_direction { kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/ kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/ } gpio_pin_direction_t; +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! @brief GPIO checker attribute */ +typedef enum _gpio_checker_attribute +{ + kGPIO_UsernonsecureRWUsersecureRWPrivilegedsecureRW = + 0x00U, /*!< User nonsecure:Read+Write; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureRUsersecureRWPrivilegedsecureRW = + 0x01U, /*!< User nonsecure:Read; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureRWPrivilegedsecureRW = + 0x02U, /*!< User nonsecure:None; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureRUsersecureRPrivilegedsecureRW = + 0x03U, /*!< User nonsecure:Read; User Secure:Read; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureRPrivilegedsecureRW = + 0x04U, /*!< User nonsecure:None; User Secure:Read; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureRW = + 0x05U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureR = + 0x06U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureN = + 0x07U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:None */ + kGPIO_IgnoreAttributeCheck = 0x10U, /*!< Ignores the attribute check */ +} gpio_checker_attribute_t; +#endif + /*! * @brief The GPIO pin configuration structure. * - * Every pin can only be configured as either output pin or input pin at a time. - * If configured as a input pin, then leave the outputConfig unused - * Note : In some cases, the corresponding port property should be configured in advance - * with the PORT_SetPinConfig() + * Each pin can only be configured as either an output pin or an input pin at a time. + * If configured as an input pin, leave the outputConfig unused. + * Note that in some use cases, the corresponding port property should be configured in advance + * with the PORT_SetPinConfig(). */ typedef struct _gpio_pin_config { - gpio_pin_direction_t pinDirection; /*!< gpio direction, input or output */ - /* Output configurations, please ignore if configured as a input one */ - uint8_t outputLogic; /*!< Set default output logic, no use in input */ + gpio_pin_direction_t pinDirection; /*!< GPIO direction, input or output */ + /* Output configurations; ignore if configured as an input pin */ + uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */ } gpio_pin_config_t; /*! @} */ @@ -93,10 +115,10 @@ extern "C" { /*! * @brief Initializes a GPIO pin used by the board. * - * To initialize the GPIO, define a pin configuration, either input or output, in the user file. + * To initialize the GPIO, define a pin configuration, as either input or output, in the user file. * Then, call the GPIO_PinInit() function. * - * This is an example to define an input pin or output pin configuration: + * This is an example to define an input pin or an output pin configuration. * @code * // Define a digital input pin configuration, * gpio_pin_config_t config = @@ -112,7 +134,7 @@ extern "C" { * } * @endcode * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param pin GPIO port pin number * @param config GPIO pin configuration pointer */ @@ -126,29 +148,29 @@ void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config /*! * @brief Sets the output level of the multiple GPIO pins to the logic 1 or 0. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin GPIO pin's number + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param pin GPIO pin number * @param output GPIO pin output logic level. - * - 0: corresponding pin output low logic level. - * - 1: corresponding pin output high logic level. + * - 0: corresponding pin output low-logic level. + * - 1: corresponding pin output high-logic level. */ static inline void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output) { if (output == 0U) { - base->PCOR = 1 << pin; + base->PCOR = 1U << pin; } else { - base->PSOR = 1 << pin; + base->PSOR = 1U << pin; } } /*! * @brief Sets the output level of the multiple GPIO pins to the logic 1. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask) { @@ -158,8 +180,8 @@ static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask) /*! * @brief Sets the output level of the multiple GPIO pins to the logic 0. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask) { @@ -167,10 +189,10 @@ static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask) } /*! - * @brief Reverses current output logic of the multiple GPIO pins. + * @brief Reverses the current output logic of the multiple GPIO pins. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask) { @@ -182,13 +204,13 @@ static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask) /*@{*/ /*! - * @brief Reads the current input value of the whole GPIO port. + * @brief Reads the current input value of the GPIO port. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin GPIO pin's number + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param pin GPIO pin number * @retval GPIO port input value - * - 0: corresponding pin input low logic level. - * - 1: corresponding pin input high logic level. + * - 0: corresponding pin input low-logic level. + * - 1: corresponding pin input high-logic level. */ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) { @@ -200,7 +222,7 @@ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) /*@{*/ /*! - * @brief Reads whole GPIO port interrupt status flag. + * @brief Reads the GPIO port interrupt status flag. * * If a pin is configured to generate the DMA request, the corresponding flag * is cleared automatically at the completion of the requested DMA transfer. @@ -208,20 +230,34 @@ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) * If configured for a level sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @retval Current GPIO port interrupt status flag, for example, 0x00010001 means the + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @retval The current GPIO port interrupt status flag, for example, 0x00010001 means the * pin 0 and 17 have the interrupt. */ uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base); /*! - * @brief Clears multiple GPIO pins' interrupt status flag. + * @brief Clears multiple GPIO pin interrupt status flags. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! + * @brief The GPIO module supports a device-specific number of data ports, organized as 32-bit + * words. Each 32-bit data port includes a GACR register, which defines the byte-level + * attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data + * bytes in the GACR follow a standard little endian + * data convention. + * + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro + */ +void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute); +#endif + /*@}*/ /*! @} */ @@ -231,10 +267,10 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); */ /* - * Introduce the FGPIO feature. + * Introduces the FGPIO feature. * - * The FGPIO features are only support on some of Kinetis chips. The FGPIO registers are aliased to the IOPORT - * interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and will therefore + * The FGPIO features are only support on some Kinetis MCUs. The FGPIO registers are aliased to the IOPORT + * interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and * complete in a single cycle. This aliased Fast GPIO memory map is called FGPIO. */ @@ -246,10 +282,10 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); /*! * @brief Initializes a FGPIO pin used by the board. * - * To initialize the FGPIO driver, define a pin configuration, either input or output, in the user file. + * To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file. * Then, call the FGPIO_PinInit() function. * - * This is an example to define an input pin or output pin configuration: + * This is an example to define an input pin or an output pin configuration: * @code * // Define a digital input pin configuration, * gpio_pin_config_t config = @@ -265,7 +301,7 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); * } * @endcode * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param pin FGPIO port pin number * @param config FGPIO pin configuration pointer */ @@ -279,11 +315,11 @@ void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *conf /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin FGPIO pin's number + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param pin FGPIO pin number * @param output FGPIOpin output logic level. - * - 0: corresponding pin output low logic level. - * - 1: corresponding pin output high logic level. + * - 0: corresponding pin output low-logic level. + * - 1: corresponding pin output high-logic level. */ static inline void FGPIO_WritePinOutput(FGPIO_Type *base, uint32_t pin, uint8_t output) { @@ -300,8 +336,8 @@ static inline void FGPIO_WritePinOutput(FGPIO_Type *base, uint32_t pin, uint8_t /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 1. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask) { @@ -311,8 +347,8 @@ static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask) /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 0. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask) { @@ -320,10 +356,10 @@ static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask) } /*! - * @brief Reverses current output logic of the multiple FGPIO pins. + * @brief Reverses the current output logic of the multiple FGPIO pins. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask) { @@ -335,13 +371,13 @@ static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask) /*@{*/ /*! - * @brief Reads the current input value of the whole FGPIO port. + * @brief Reads the current input value of the FGPIO port. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin FGPIO pin's number + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param pin FGPIO pin number * @retval FGPIO port input value - * - 0: corresponding pin input low logic level. - * - 1: corresponding pin input high logic level. + * - 0: corresponding pin input low-logic level. + * - 1: corresponding pin input high-logic level. */ static inline uint32_t FGPIO_ReadPinInput(FGPIO_Type *base, uint32_t pin) { @@ -353,28 +389,42 @@ static inline uint32_t FGPIO_ReadPinInput(FGPIO_Type *base, uint32_t pin) /*@{*/ /*! - * @brief Reads the whole FGPIO port interrupt status flag. + * @brief Reads the FGPIO port interrupt status flag. * - * If a pin is configured to generate the DMA request, the corresponding flag + * If a pin is configured to generate the DMA request, the corresponding flag * is cleared automatically at the completion of the requested DMA transfer. * Otherwise, the flag remains set until a logic one is written to that flag. - * If configured for a level sensitive interrupt that remains asserted, the flag + * If configured for a level-sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @retval Current FGPIO port interrupt status flags, for example, 0x00010001 means the + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the * pin 0 and 17 have the interrupt. */ uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base); /*! - * @brief Clears the multiple FGPIO pins' interrupt status flag. + * @brief Clears the multiple FGPIO pin interrupt status flag. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask); +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! + * @brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit + * words. Each 32-bit data port includes a GACR register, which defines the byte-level + * attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data + * bytes in the GACR follow a standard little endian + * data convention. + * + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro + */ +void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute); +#endif + /*@}*/ #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c index e77a3832399..6c9770af256 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -75,6 +75,19 @@ typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle); */ uint32_t I2C_GetInstance(I2C_Type *base); +/*! +* @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the +* closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop +* hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided, +* assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT +* value, then the related SDA hold time, SCL start and SCL stop hold time is used. +* +* @param base I2C peripheral base address. +* @param sourceClock_Hz I2C functional clock frequency in Hertz. +* @param sclStopHoldTime_ns SCL stop hold time in ns. +*/ +static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz); + /*! * @brief Set up master transfer, send slave address and decide the initial * transfer state. @@ -125,20 +138,22 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle); static void *s_i2cHandle[FSL_FEATURE_SOC_I2C_COUNT] = {NULL}; /*! @brief SCL clock divider used to calculate baudrate. */ -const uint16_t s_i2cDividerTable[] = {20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, - 48, 56, 68, 48, 56, 64, 72, 80, 88, 104, 128, 80, 96, - 112, 128, 144, 160, 192, 240, 160, 192, 224, 256, 288, 320, 384, - 480, 320, 384, 448, 512, 576, 640, 768, 960, 640, 768, 896, 1024, - 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840}; +static const uint16_t s_i2cDividerTable[] = { + 20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, 48, 56, 68, + 48, 56, 64, 72, 80, 88, 104, 128, 80, 96, 112, 128, 144, 160, 192, 240, + 160, 192, 224, 256, 288, 320, 384, 480, 320, 384, 448, 512, 576, 640, 768, 960, + 640, 768, 896, 1024, 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840}; /*! @brief Pointers to i2c bases for each instance. */ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS; /*! @brief Pointers to i2c IRQ number for each instance. */ -const IRQn_Type s_i2cIrqs[] = I2C_IRQS; +static const IRQn_Type s_i2cIrqs[] = I2C_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to i2c clocks for each instance. */ -const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS; +static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointer to master IRQ handler for each instance. */ static i2c_isr_t s_i2cMasterIsr; @@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_i2cBases); instance++) { if (s_i2cBases[instance] == base) { @@ -163,16 +178,63 @@ uint32_t I2C_GetInstance(I2C_Type *base) } } - assert(instance < FSL_FEATURE_SOC_I2C_COUNT); + assert(instance < ARRAY_SIZE(s_i2cBases)); return instance; } +static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz) +{ + uint32_t multiplier; + uint32_t computedSclHoldTime; + uint32_t absError; + uint32_t bestError = UINT32_MAX; + uint32_t bestMult = 0u; + uint32_t bestIcr = 0u; + uint8_t mult; + uint8_t i; + + /* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register, + * and ranges from 0-2. It selects the multiplier factor for the divider. */ + /* SDA hold time = bus period (s) * mul * SDA hold value. */ + /* SCL start hold time = bus period (s) * mul * SCL start hold value. */ + /* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */ + + for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult) + { + multiplier = 1u << mult; + + /* Scan table to find best match. */ + for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i) + { + /* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */ + computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz; + absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) : + (computedSclHoldTime - sclStopHoldTime_ns); + + if (absError < bestError) + { + bestMult = mult; + bestIcr = i; + bestError = absError; + + /* If the error is 0, then we can stop searching because we won't find a better match. */ + if (absError == 0) + { + break; + } + } + } + } + + /* Set frequency register based on best settings. */ + base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr); +} + static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer) { status_t result = kStatus_Success; i2c_direction_t direction = xfer->direction; - uint16_t timeout = UINT16_MAX; /* Initialize the handle transfer information. */ handle->transfer = *xfer; @@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t /* Initial transfer state. */ if (handle->transfer.subaddressSize > 0) { - handle->state = kSendCommandState; if (xfer->direction == kI2C_Read) { direction = kI2C_Write; } } - else - { - handle->state = kCheckAddressState; - } - /* Wait until the data register is ready for transmit. */ - while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout)) - { - } - - /* Failed to start the transfer. */ - if (timeout == 0) - { - return kStatus_I2C_Timeout; - } + handle->state = kCheckAddressState; /* Clear all status before transfer. */ I2C_MasterClearStatusFlags(base, kClearFlags); @@ -265,34 +313,41 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han result = kStatus_Success; } - if (result) - { - return result; - } - /* Handle Check address state to check the slave address is Acked in slave probe application. */ if (handle->state == kCheckAddressState) { if (statusFlags & kI2C_ReceiveNakFlag) { - return kStatus_I2C_Nak; + result = kStatus_I2C_Addr_Nak; } else { - if (handle->transfer.direction == kI2C_Write) + if (handle->transfer.subaddressSize > 0) { - /* Next state, send data. */ - handle->state = kSendDataState; + handle->state = kSendCommandState; } else { - /* Next state, receive data begin. */ - handle->state = kReceiveDataBeginState; + if (handle->transfer.direction == kI2C_Write) + { + /* Next state, send data. */ + handle->state = kSendDataState; + } + else + { + /* Next state, receive data begin. */ + handle->state = kReceiveDataBeginState; + } } } } + if (result) + { + return result; + } + /* Run state machine. */ switch (handle->state) { @@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han { result = I2C_MasterStop(base); } + else + { + base->C1 |= I2C_C1_TX_MASK; + } } /* Send NAK at the last receive byte. */ @@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle) { s_i2cSlaveIsr(base, handle); } + __DSB(); } void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz) @@ -415,12 +475,26 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Temporary register for filter read. */ uint8_t fltReg; -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - uint8_t c2Reg; +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + uint8_t s2Reg; #endif - +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable I2C clock. */ CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Reset the module. */ + base->A1 = 0; + base->F = 0; + base->C1 = 0; + base->S = 0xFFU; + base->C2 = 0; +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + base->FLT = 0x50U; +#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT + base->FLT = 0x40U; +#endif + base->RA = 0; /* Disable I2C prior to configuring it. */ base->C1 &= ~(I2C_C1_IICEN_MASK); @@ -431,14 +505,6 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Configure baud rate. */ I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz); -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - /* Configure high drive feature. */ - c2Reg = base->C2; - c2Reg &= ~(I2C_C2_HDRS_MASK); - c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive); - base->C2 = c2Reg; -#endif - /* Read out the FLT register. */ fltReg = base->FLT; @@ -455,6 +521,12 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Write the register value back to the filter register. */ base->FLT = fltReg; +/* Enable/Disable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + s2Reg = base->S2 & (~I2C_S2_DFEN_MASK); + base->S2 = s2Reg | I2C_S2_DFEN(masterConfig->enableDoubleBuffering); +#endif + /* Enable the I2C peripheral based on the configuration. */ base->C1 = I2C_C1_IICEN(masterConfig->enableMaster); } @@ -464,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base) /* Disable I2C module. */ I2C_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable I2C clock. */ CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) @@ -475,11 +549,6 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) /* Default baud rate at 100kbps. */ masterConfig->baudRate_Bps = 100000U; -/* Default pin high drive is disabled. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - masterConfig->enableHighDrive = false; -#endif - /* Default stop hold enable is disabled. */ #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF masterConfig->enableStopHold = false; @@ -488,12 +557,21 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) /* Default glitch filter value is no filter. */ masterConfig->glitchFilterWidth = 0U; +/* Default enable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + masterConfig->enableDoubleBuffering = true; +#endif + /* Enable the I2C peripheral. */ masterConfig->enableMaster = true; } void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask) { +#ifdef I2C_HAS_STOP_DETECT + uint8_t fltReg; +#endif + if (mask & kI2C_GlobalInterruptEnable) { base->C1 |= I2C_C1_IICIE_MASK; @@ -502,14 +580,28 @@ void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask) #if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT if (mask & kI2C_StopDetectInterruptEnable) { - base->FLT |= I2C_FLT_STOPIE_MASK; + fltReg = base->FLT; + + /* Keep STOPF flag. */ + fltReg &= ~I2C_FLT_STOPF_MASK; + + /* Stop detect enable. */ + fltReg |= I2C_FLT_STOPIE_MASK; + base->FLT = fltReg; } #endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */ #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT if (mask & kI2C_StartStopDetectInterruptEnable) { - base->FLT |= I2C_FLT_SSIE_MASK; + fltReg = base->FLT; + + /* Keep STARTF and STOPF flags. */ + fltReg &= ~(I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK); + + /* Start and stop detect enable. */ + fltReg |= I2C_FLT_SSIE_MASK; + base->FLT = fltReg; } #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ } @@ -524,14 +616,14 @@ void I2C_DisableInterrupts(I2C_Type *base, uint32_t mask) #if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT if (mask & kI2C_StopDetectInterruptEnable) { - base->FLT &= ~I2C_FLT_STOPIE_MASK; + base->FLT &= ~(I2C_FLT_STOPIE_MASK | I2C_FLT_STOPF_MASK); } #endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */ #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT if (mask & kI2C_StartStopDetectInterruptEnable) { - base->FLT &= ~I2C_FLT_SSIE_MASK; + base->FLT &= ~(I2C_FLT_SSIE_MASK | I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK); } #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ } @@ -623,7 +715,7 @@ status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_ base->F = savedMult & (~I2C_F_MULT_MASK); /* We are already in a transfer, so send a repeated start. */ - base->C1 |= I2C_C1_RSTA_MASK; + base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK; /* Restore the multiplier factor. */ base->F = savedMult; @@ -690,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base) return statusFlags; } -status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize) +status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags) { status_t result = kStatus_Success; uint8_t statusFlags = 0; @@ -728,7 +820,7 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t result = kStatus_I2C_ArbitrationLost; } - if (statusFlags & kI2C_ReceiveNakFlag) + if ((statusFlags & kI2C_ReceiveNakFlag) && txSize) { base->S = kI2C_ReceiveNakFlag; result = kStatus_I2C_Nak; @@ -741,10 +833,19 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t } } + if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak)) + { + /* Clear the IICIF flag. */ + base->S = kI2C_IntPendingFlag; + + /* Send stop. */ + result = I2C_MasterStop(base); + } + return result; } -status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) +status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags) { status_t result = kStatus_Success; volatile uint8_t dummy = 0; @@ -786,8 +887,16 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) /* Single byte use case. */ if (rxSize == 0) { - /* Read the final byte. */ - result = I2C_MasterStop(base); + if (!(flags & kI2C_TransferNoStopFlag)) + { + /* Issue STOP command before reading last byte. */ + result = I2C_MasterStop(base); + } + else + { + /* Change direction to Tx to avoid extra clocks. */ + base->C1 |= I2C_C1_TX_MASK; + } } if (rxSize == 1) @@ -840,19 +949,42 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) return result; } + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + /* Return if error. */ + if (result) + { + if (result == kStatus_I2C_Nak) + { + result = kStatus_I2C_Addr_Nak; + + I2C_MasterStop(base); + } + + return result; + } + /* Send subaddress. */ if (xfer->subaddressSize) { do { + /* Clear interrupt pending flag. */ + base->S = kI2C_IntPendingFlag; + + xfer->subaddressSize--; + base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); + /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } - /* Clear interrupt pending flag. */ - base->S = kI2C_IntPendingFlag; - /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -866,21 +998,27 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) return result; } - xfer->subaddressSize--; - base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); - } while ((xfer->subaddressSize > 0) && (result == kStatus_Success)); if (xfer->direction == kI2C_Read) { + /* Clear pending flag. */ + base->S = kI2C_IntPendingFlag; + + /* Send repeated start and slave address. */ + result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read); + + /* Return if error. */ + if (result) + { + return result; + } + /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } - /* Clear pending flag. */ - base->S = kI2C_IntPendingFlag; - /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -888,62 +1026,27 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) { if (result == kStatus_I2C_Nak) { + result = kStatus_I2C_Addr_Nak; + I2C_MasterStop(base); } return result; } - - /* Send repeated start and slave address. */ - result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read); - - /* Return if error. */ - if (result) - { - return result; - } - } - } - - /* Wait until address + command transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } - - /* Check if there's transfer error. */ - result = I2C_CheckAndClearError(base, base->S); - - /* Return if error. */ - if (result) - { - if (result == kStatus_I2C_Nak) - { - I2C_MasterStop(base); } - - return result; } /* Transmit data. */ if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0)) { /* Send Data. */ - result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize); - - if (((result == kStatus_Success) && (!(xfer->flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak)) - { - /* Clear the IICIF flag. */ - base->S = kI2C_IntPendingFlag; - - /* Send stop. */ - result = I2C_MasterStop(base); - } + result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags); } /* Receive Data. */ if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0)) { - result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize); + result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags); } return result; @@ -1006,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle) { assert(handle); + volatile uint8_t dummy = 0; + + /* Add this to avoid build warning. */ + dummy++; + /* Disable interrupt. */ I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable); /* Reset the state to idle. */ handle->state = kIdleState; + + /* Send STOP signal. */ + if (handle->transfer.direction == kI2C_Read) + { + base->C1 |= I2C_C1_TXAK_MASK; + while (!(base->S & kI2C_IntPendingFlag)) + { + } + base->S = kI2C_IntPendingFlag; + + base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + dummy = base->D; + } + else + { + while (!(base->S & kI2C_IntPendingFlag)) + { + } + base->S = kI2C_IntPendingFlag; + base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + } } status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count) @@ -1044,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle) if (isDone || result) { /* Send stop command if transfer done or received Nak. */ - if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak)) + if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) || + (result == kStatus_I2C_Addr_Nak)) { /* Ensure stop command is a need. */ if ((base->C1 & I2C_C1_MST_MASK)) @@ -1070,13 +1200,28 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } -void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig) +void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz) { assert(slaveConfig); uint8_t tmpReg; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Reset the module. */ + base->A1 = 0; + base->F = 0; + base->C1 = 0; + base->S = 0xFFU; + base->C2 = 0; +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + base->FLT = 0x50U; +#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT + base->FLT = 0x40U; +#endif + base->RA = 0; /* Configure addressing mode. */ switch (slaveConfig->addressingMode) @@ -1101,15 +1246,20 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig) tmpReg &= ~I2C_C1_WUEN_MASK; base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave); - /* Configure general call & baud rate control & high drive feature. */ + /* Configure general call & baud rate control. */ tmpReg = base->C2; tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK); tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall); -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - tmpReg &= ~I2C_C2_HDRS_MASK; - tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive); -#endif base->C2 = tmpReg; + +/* Enable/Disable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + tmpReg = base->S2 & (~I2C_S2_DFEN_MASK); + base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering); +#endif + + /* Set hold time. */ + I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz); } void I2C_SlaveDeinit(I2C_Type *base) @@ -1117,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base) /* Disable I2C module. */ I2C_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable I2C clock. */ CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) @@ -1134,48 +1286,106 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) /* Slave address match waking up MCU from low power mode is disabled. */ slaveConfig->enableWakeUp = false; -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - /* Default pin high drive is disabled. */ - slaveConfig->enableHighDrive = false; -#endif - /* Independent slave mode baud rate at maximum frequency is disabled. */ slaveConfig->enableBaudRateCtl = false; +/* Default enable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + slaveConfig->enableDoubleBuffering = true; +#endif + + /* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */ + slaveConfig->sclStopHoldTime_ns = 4000; + /* Enable the I2C peripheral. */ slaveConfig->enableSlave = true; } status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize) { - return I2C_MasterWriteBlocking(base, txBuff, txSize); + status_t result = kStatus_Success; + volatile uint8_t dummy = 0; + + /* Add this to avoid build warning. */ + dummy++; + +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + /* Check start flag. */ + while (!(base->FLT & I2C_FLT_STARTF_MASK)) + { + } + /* Clear STARTF flag. */ + base->FLT |= I2C_FLT_STARTF_MASK; + /* Clear the IICIF flag. */ + base->S = kI2C_IntPendingFlag; +#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ + + /* Wait for address match flag. */ + while (!(base->S & kI2C_AddressMatchFlag)) + { + } + + /* Read dummy to release bus. */ + dummy = base->D; + + result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag); + + /* Switch to receive mode. */ + base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + + /* Read dummy to release bus. */ + dummy = base->D; + + return result; } void I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) { + volatile uint8_t dummy = 0; + + /* Add this to avoid build warning. */ + dummy++; + +/* Wait until address match. */ +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + /* Check start flag. */ + while (!(base->FLT & I2C_FLT_STARTF_MASK)) + { + } + /* Clear STARTF flag. */ + base->FLT |= I2C_FLT_STARTF_MASK; /* Clear the IICIF flag. */ base->S = kI2C_IntPendingFlag; +#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ - /* Wait until the data register is ready for receive. */ - while (!(base->S & kI2C_TransferCompleteFlag)) + /* Wait for address match and int pending flag. */ + while (!(base->S & kI2C_AddressMatchFlag)) + { + } + while (!(base->S & kI2C_IntPendingFlag)) { } + /* Read dummy to release bus. */ + dummy = base->D; + + /* Clear the IICIF flag. */ + base->S = kI2C_IntPendingFlag; + /* Setup the I2C peripheral to receive data. */ base->C1 &= ~(I2C_C1_TX_MASK); while (rxSize--) { + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } /* Clear the IICIF flag. */ base->S = kI2C_IntPendingFlag; /* Read from the data register. */ *rxBuff++ = base->D; - - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } } } @@ -1226,7 +1436,7 @@ status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle handle->isBusy = true; /* Set up event mask. tx and rx are always enabled. */ - handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent; + handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent; /* Clear all flags. */ I2C_SlaveClearStatusFlags(base, kClearFlags); @@ -1315,7 +1525,10 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } - return; + if (!(status & kI2C_AddressMatchFlag)) + { + return; + } } #endif /* I2C_HAS_STOP_DETECT */ @@ -1328,7 +1541,7 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) /* Clear the interrupt flag. */ base->S = kI2C_IntPendingFlag; - xfer->event = kI2C_SlaveRepeatedStartEvent; + xfer->event = kI2C_SlaveStartEvent; if ((handle->eventMask & xfer->event) && (handle->callback)) { @@ -1385,31 +1598,12 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) handle->isBusy = true; xfer->event = kI2C_SlaveAddressMatchEvent; - if ((handle->eventMask & xfer->event) && (handle->callback)) - { - handle->callback(base, xfer, handle->userData); - } - /* Slave transmit, master reading from slave. */ if (status & kI2C_TransferDirectionFlag) { /* Change direction to send data. */ base->C1 |= I2C_C1_TX_MASK; - /* If we're out of data, invoke callback to get more. */ - if ((!xfer->data) || (!xfer->dataSize)) - { - xfer->event = kI2C_SlaveTransmitEvent; - - if (handle->callback) - { - handle->callback(base, xfer, handle->userData); - } - - /* Clear the transferred count now that we have a new buffer. */ - xfer->transferredCount = 0; - } - doTransmit = true; } else @@ -1417,22 +1611,18 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) /* Slave receive, master writing to slave. */ base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); - /* If we're out of data, invoke callback to get more. */ - if ((!xfer->data) || (!xfer->dataSize)) - { - xfer->event = kI2C_SlaveReceiveEvent; - - if (handle->callback) - { - handle->callback(base, xfer, handle->userData); - } + /* Read dummy to release the bus. */ + dummy = base->D; - /* Clear the transferred count now that we have a new buffer. */ - xfer->transferredCount = 0; + if (dummy == 0) + { + xfer->event = kI2C_SlaveGenaralcallEvent; } + } - /* Read dummy to release the bus. */ - dummy = base->D; + if ((handle->eventMask & xfer->event) && (handle->callback)) + { + handle->callback(base, xfer, handle->userData); } } /* Check transfer complete flag. */ @@ -1445,6 +1635,20 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } else { + /* If we're out of data, invoke callback to get more. */ + if ((!xfer->data) || (!xfer->dataSize)) + { + xfer->event = kI2C_SlaveReceiveEvent; + + if (handle->callback) + { + handle->callback(base, xfer, handle->userData); + } + + /* Clear the transferred count now that we have a new buffer. */ + xfer->transferredCount = 0; + } + /* Slave receive, master writing to slave. */ uint8_t data = base->D; @@ -1480,6 +1684,20 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) /* Send data if there is the need. */ if (doTransmit) { + /* If we're out of data, invoke callback to get more. */ + if ((!xfer->data) || (!xfer->dataSize)) + { + xfer->event = kI2C_SlaveTransmitEvent; + + if (handle->callback) + { + handle->callback(base, xfer, handle->userData); + } + + /* Clear the transferred count now that we have a new buffer. */ + xfer->transferredCount = 0; + } + if (handle->transfer.dataSize) { /* Send data. */ @@ -1510,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } +#if defined(I2C0) void I2C0_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]); } +#endif -#if (FSL_FEATURE_SOC_I2C_COUNT > 1) +#if defined(I2C1) void I2C1_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]); } -#endif /* I2C COUNT > 1 */ +#endif -#if (FSL_FEATURE_SOC_I2C_COUNT > 2) +#if defined(I2C2) void I2C2_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]); } -#endif /* I2C COUNT > 2 */ -#if (FSL_FEATURE_SOC_I2C_COUNT > 3) +#endif + +#if defined(I2C3) void I2C3_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]); } -#endif /* I2C COUNT > 3 */ +#endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h index 41a9afbdd54..d55fd1d8ea3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,16 +37,14 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief I2C driver version 2.0.0. */ -#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief I2C driver version 2.0.3. */ +#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*@}*/ #if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \ @@ -62,6 +60,7 @@ enum _i2c_status kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */ kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */ kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */ + kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_I2C, 5), /*!< NAK received during the address probe. */ }; /*! @@ -109,11 +108,11 @@ enum _i2c_interrupt_enable #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ }; -/*! @brief Direction of master and slave transfers. */ +/*! @brief The direction of master and slave transfers. */ typedef enum _i2c_direction { - kI2C_Write = 0x0U, /*!< Master transmit to slave. */ - kI2C_Read = 0x1U, /*!< Master receive from slave. */ + kI2C_Write = 0x0U, /*!< Master transmits to the slave. */ + kI2C_Read = 0x1U, /*!< Master receives from the slave. */ } i2c_direction_t; /*! @brief Addressing mode. */ @@ -126,17 +125,17 @@ typedef enum _i2c_slave_address_mode /*! @brief I2C transfer control flag. */ enum _i2c_master_transfer_flags { - kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */ - kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */ - kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */ - kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */ + kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */ + kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */ + kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */ + kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */ }; /*! * @brief Set of events sent to the callback for nonblocking slave transfers. * * These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together - * events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable. + * events is passed to I2C_SlaveTransferNonBlocking() to specify which events to enable. * Then, when the slave callback is invoked, it is passed the current event through its @a transfer * parameter. * @@ -145,33 +144,35 @@ enum _i2c_master_transfer_flags typedef enum _i2c_slave_transfer_event { kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */ - kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit + kI2C_SlaveTransmitEvent = 0x02U, /*!< A callback is requested to provide data to transmit (slave-transmitter role). */ - kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received + kI2C_SlaveReceiveEvent = 0x04U, /*!< A callback is requested to provide a buffer in which to place received data (slave-receiver role). */ - kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */ + kI2C_SlaveTransmitAckEvent = 0x08U, /*!< A callback needs to either transmit an ACK or NACK. */ #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT - kI2C_SlaveRepeatedStartEvent = 0x10U, /*!< A repeated start was detected. */ + kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */ #endif - kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */ + kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */ + kI2C_SlaveGenaralcallEvent = 0x40U, /*!< Received the general call address after a start or repeated start. */ - /*! Bit mask of all available events. */ + /*! A bit mask of all available events. */ kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT - kI2C_SlaveRepeatedStartEvent | + kI2C_SlaveStartEvent | #endif - kI2C_SlaveCompletionEvent, + kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent, } i2c_slave_transfer_event_t; /*! @brief I2C master user configuration. */ typedef struct _i2c_master_config { bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */ -#endif #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF bool enableStopHold; /*!< Controls the stop hold enable. */ +#endif +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that + enabling the double buffer disables the clock stretch. */ #endif uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */ uint8_t glitchFilterWidth; /*!< Controls the width of the glitch. */ @@ -181,15 +182,20 @@ typedef struct _i2c_master_config typedef struct _i2c_slave_config { bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */ - bool enableGeneralCall; /*!< Enable general call addressing mode. */ - bool enableWakeUp; /*!< Enables/disables waking up MCU from low power mode. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */ + bool enableGeneralCall; /*!< Enables the general call addressing mode. */ + bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that + enabling the double buffer disables the clock stretch. */ #endif bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */ - uint16_t slaveAddress; /*!< Slave address configuration. */ - uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */ - i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */ + uint16_t slaveAddress; /*!< A slave address configuration. */ + uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */ + i2c_slave_address_mode_t + addressingMode; /*!< An addressing mode configuration of i2c_slave_address_mode_config_t. */ + uint32_t sclStopHoldTime_ns; /*!< the delay from the rising edge of SCL (I2C clock) to the rising edge of SDA (I2C + data) while SCL is high (stop condition), SDA hold time and SCL start hold time + are also configured according to the SCL stop hold time. */ } i2c_slave_config_t; /*! @brief I2C master handle typedef. */ @@ -207,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t; /*! @brief I2C master transfer structure. */ typedef struct _i2c_master_transfer { - uint32_t flags; /*!< Transfer flag which controls the transfer. */ + uint32_t flags; /*!< A transfer flag which controls the transfer. */ uint8_t slaveAddress; /*!< 7-bit slave address. */ - i2c_direction_t direction; /*!< Transfer direction, read or write. */ - uint32_t subaddress; /*!< Sub address. Transferred MSB first. */ - uint8_t subaddressSize; /*!< Size of command buffer. */ - uint8_t *volatile data; /*!< Transfer buffer. */ - volatile size_t dataSize; /*!< Transfer size. */ + i2c_direction_t direction; /*!< A transfer direction, read or write. */ + uint32_t subaddress; /*!< A sub address. Transferred MSB first. */ + uint8_t subaddressSize; /*!< A size of the command buffer. */ + uint8_t *volatile data; /*!< A transfer buffer. */ + volatile size_t dataSize; /*!< A transfer size. */ } i2c_master_transfer_t; /*! @brief I2C master handle structure. */ @@ -221,20 +227,21 @@ struct _i2c_master_handle { i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */ size_t transferSize; /*!< Total bytes to be transferred. */ - uint8_t state; /*!< Transfer state maintained during transfer. */ - i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */ - void *userData; /*!< Callback parameter passed to callback function. */ + uint8_t state; /*!< A transfer state maintained during transfer. */ + i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */ + void *userData; /*!< A callback parameter passed to the callback function. */ }; /*! @brief I2C slave transfer structure. */ typedef struct _i2c_slave_transfer { - i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */ - uint8_t *volatile data; /*!< Transfer buffer. */ - volatile size_t dataSize; /*!< Transfer size. */ + i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */ + uint8_t *volatile data; /*!< A transfer buffer. */ + volatile size_t dataSize; /*!< A transfer size. */ status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for #kI2C_SlaveCompletionEvent. */ - size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */ + size_t transferredCount; /*!< A number of bytes actually transferred since the start or since the last repeated + start. */ } i2c_slave_transfer_t; /*! @brief I2C slave transfer callback typedef. */ @@ -243,11 +250,11 @@ typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer /*! @brief I2C slave handle structure. */ struct _i2c_slave_handle { - bool isBusy; /*!< Whether transfer is busy. */ + volatile bool isBusy; /*!< Indicates whether a transfer is busy. */ i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */ - uint32_t eventMask; /*!< Mask of enabled events. */ - i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */ - void *userData; /*!< Callback parameter passed to callback. */ + uint32_t eventMask; /*!< A mask of enabled events. */ + i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */ + void *userData; /*!< A callback parameter passed to the callback. */ }; /******************************************************************************* @@ -267,12 +274,12 @@ extern "C" { * @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock * and configure the I2C with master configuration. * - * @note This API should be called at the beginning of the application to use - * the I2C driver, or any operation to the I2C module could cause hard fault - * because clock is not enabled. The configuration structure can be filled by user - * from scratch, or be set with default values by I2C_MasterGetDefaultConfig(). + * @note This API should be called at the beginning of the application. + * Otherwise, any operation to the I2C module can cause a hard fault + * because the clock is not enabled. The configuration structure can be custom filled + * or it can be set with default values by using the I2C_MasterGetDefaultConfig(). * After calling this API, the master is ready to transfer. - * Example: + * This is an example. * @code * i2c_master_config_t config = { * .enableMaster = true, @@ -285,20 +292,20 @@ extern "C" { * @endcode * * @param base I2C base pointer - * @param masterConfig pointer to master configuration structure + * @param masterConfig A pointer to the master configuration structure * @param srcClock_Hz I2C peripheral clock frequency in Hz */ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz); /*! * @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock - * and initializes the I2C with slave configuration. + * and initialize the I2C with the slave configuration. * - * @note This API should be called at the beginning of the application to use - * the I2C driver, or any operation to the I2C module can cause a hard fault + * @note This API should be called at the beginning of the application. + * Otherwise, any operation to the I2C module can cause a hard fault * because the clock is not enabled. The configuration structure can partly be set - * with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user. - * Example + * with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user. + * This is an example. * @code * i2c_slave_config_t config = { * .enableSlave = true, @@ -307,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin * .slaveAddress = 0x1DU, * .enableWakeUp = false, * .enablehighDrive = false, - * .enableBaudRateCtl = false + * .enableBaudRateCtl = false, + * .sclStopHoldTime_ns = 4000 * }; - * I2C_SlaveInit(I2C0, &config); + * I2C_SlaveInit(I2C0, &config, 12000000U); * @endcode * * @param base I2C base pointer - * @param slaveConfig pointer to slave configuration structure + * @param slaveConfig A pointer to the slave configuration structure + * @param srcClock_Hz I2C peripheral clock frequency in Hz */ -void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig); +void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz); /*! * @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock. @@ -335,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base); * @brief Sets the I2C master configuration structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure(). - * Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of - * the structure before calling I2C_MasterConfigure(). - * Example: + * Use the initialized structure unchanged in the I2C_MasterConfigure() or modify + * the structure before calling the I2C_MasterConfigure(). + * This is an example. * @code * i2c_master_config_t config; * I2C_MasterGetDefaultConfig(&config); * @endcode - * @param masterConfig Pointer to the master configuration structure. + * @param masterConfig A pointer to the master configuration structure. */ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig); /*! * @brief Sets the I2C slave configuration structure to default values. * - * The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure(). + * The purpose of this API is to get the configuration structure initialized for use in the I2C_SlaveConfigure(). * Modify fields of the structure before calling the I2C_SlaveConfigure(). - * Example: + * This is an example. * @code * i2c_slave_config_t config; * I2C_SlaveGetDefaultConfig(&config); * @endcode - * @param slaveConfig Pointer to the slave configuration structure. + * @param slaveConfig A pointer to the slave configuration structure. */ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig); @@ -364,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig); * @brief Enables or disabless the I2C peripheral operation. * * @param base I2C base pointer - * @param enable pass true to enable module, false to disable module + * @param enable Pass true to enable and false to disable the module. */ static inline void I2C_Enable(I2C_Type *base, bool enable) { @@ -389,7 +398,7 @@ static inline void I2C_Enable(I2C_Type *base, bool enable) * @brief Gets the I2C status flags. * * @param base I2C base pointer - * @return status flag, use status flag to AND #_i2c_flags could get the related status. + * @return status flag, use status flag to AND #_i2c_flags to get the related status. */ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base); @@ -397,7 +406,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base); * @brief Gets the I2C status flags. * * @param base I2C base pointer - * @return status flag, use status flag to AND #_i2c_flags could get the related status. + * @return status flag, use status flag to AND #_i2c_flags to get the related status. */ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base) { @@ -407,11 +416,11 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base) /*! * @brief Clears the I2C status flag state. * - * The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag + * The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag. * * @param base I2C base pointer * @param statusMask The status flag mask, defined in type i2c_status_flag_t. - * The parameter could be any combination of the following values: + * The parameter can be any combination of the following values: * @arg kI2C_StartDetectFlag (if available) * @arg kI2C_StopDetectFlag (if available) * @arg kI2C_ArbitrationLostFlag @@ -442,11 +451,11 @@ static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMas /*! * @brief Clears the I2C status flag state. * - * The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag + * The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag * * @param base I2C base pointer * @param statusMask The status flag mask, defined in type i2c_status_flag_t. - * The parameter could be any combination of the following values: + * The parameter can be any combination of the following values: * @arg kI2C_StartDetectFlag (if available) * @arg kI2C_StopDetectFlag (if available) * @arg kI2C_ArbitrationLostFlag @@ -574,19 +583,21 @@ status_t I2C_MasterStop(I2C_Type *base); status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction); /*! - * @brief Performs a polling send transaction on the I2C bus without a STOP signal. + * @brief Performs a polling send transaction on the I2C bus. * * @param base The I2C peripheral base pointer. * @param txBuff The pointer to the data to be transferred. * @param txSize The length in bytes of the data to be transferred. + * @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag +* to issue a stop and kI2C_TransferNoStop to not send a stop. * @retval kStatus_Success Successfully complete the data transmission. * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. * @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer. */ -status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize); +status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags); /*! - * @brief Performs a polling receive transaction on the I2C bus with a STOP signal. + * @brief Performs a polling receive transaction on the I2C bus. * * @note The I2C_MasterReadBlocking function stops the bus before reading the final byte. * Without stopping the bus prior for the final read, the bus issues another read, resulting @@ -595,10 +606,12 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t * @param base I2C peripheral base pointer. * @param rxBuff The pointer to the data to store the received data. * @param rxSize The length in bytes of the data to be received. + * @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag +* to issue a stop and kI2C_TransferNoStop to not send a stop. * @retval kStatus_Success Successfully complete the data transmission. * @retval kStatus_I2C_Timeout Send stop signal failed, timeout. */ -status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize); +status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags); /*! * @brief Performs a polling send transaction on the I2C bus. @@ -650,7 +663,7 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) * @param base I2C base pointer. * @param handle pointer to i2c_master_handle_t structure to store the transfer state. * @param callback pointer to user callback function. - * @param userData user paramater passed to the callback function. + * @param userData user parameter passed to the callback function. */ void I2C_MasterTransferCreateHandle(I2C_Type *base, i2c_master_handle_t *handle, @@ -660,15 +673,15 @@ void I2C_MasterTransferCreateHandle(I2C_Type *base, /*! * @brief Performs a master interrupt non-blocking transfer on the I2C bus. * - * @note Calling the API will return immediately after transfer initiates, user needs + * @note Calling the API returns immediately after transfer initiates. The user needs * to call I2C_MasterGetTransferCount to poll the transfer status to check whether - * the transfer is finished, if the return status is not kStatus_I2C_Busy, the transfer + * the transfer is finished. If the return status is not kStatus_I2C_Busy, the transfer * is finished. * * @param base I2C base pointer. * @param handle pointer to i2c_master_handle_t structure which stores the transfer state. * @param xfer pointer to i2c_master_transfer_t structure. - * @retval kStatus_Success Sucessully start the data transmission. + * @retval kStatus_Success Successfully start the data transmission. * @retval kStatus_I2C_Busy Previous transmission still not finished. * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c index c8f7c20629f..28a415e075a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -162,6 +162,26 @@ static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData result = I2C_MasterStop(i2cPrivateHandle->base); } } + else + { + if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read) + { + /* Change to send NAK at the last byte. */ + i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK; + + /* Wait the last data to be received. */ + while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag)) + { + } + + /* Change direction to send. */ + i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK; + + /* Read the last data byte. */ + *(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) = + i2cPrivateHandle->base->D; + } + } i2cPrivateHandle->handle->state = kIdleState; @@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, assert(xfer); status_t result = kStatus_Success; - uint16_t timeout = UINT16_MAX; if (handle->state != kIdleState) { @@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, handle->state = kTransferDataState; - /* Wait until ready to complete. */ - while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout)) - { - } - - /* Failed to start the transfer. */ - if (timeout == 0) - { - return kStatus_I2C_Timeout; - } /* Clear all status before transfer. */ I2C_MasterClearStatusFlags(base, kClearFlags); @@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction); } - /* Send subaddress. */ - if (handle->transfer.subaddressSize) + if (result) { - do + return result; + } + + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + /* Return if error. */ + if (result) + { + if (result == kStatus_I2C_Nak) { - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) + result = kStatus_I2C_Addr_Nak; + + if (I2C_MasterStop(base) != kStatus_Success) { + result = kStatus_I2C_Timeout; } + if (handle->completionCallback) + { + (handle->completionCallback)(base, handle, result, handle->userData); + } + } + + return result; + } + + /* Send subaddress. */ + if (handle->transfer.subaddressSize) + { + do + { /* Clear interrupt pending flag. */ base->S = kI2C_IntPendingFlag; handle->transfer.subaddressSize--; base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)); + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } + /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -278,34 +320,34 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, if (handle->transfer.direction == kI2C_Read) { - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } - /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; /* Send repeated start and slave address. */ result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read); - } - } - if (result) - { - return result; - } + if (result) + { + return result; + } - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + if (result) + { + return result; + } + } } /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; - - /* Check if there's transfer error. */ - result = I2C_CheckAndClearError(base, base->S); } return result; @@ -319,17 +361,7 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_ { transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base); transfer_config.destAddr = (uint32_t)(handle->transfer.data); - - /* Send stop if kI2C_TransferNoStop flag is not asserted. */ - if (!(handle->transfer.flags & kI2C_TransferNoStopFlag)) - { - transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1); - } - else - { - transfer_config.majorLoopCounts = handle->transfer.dataSize; - } - + transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1); transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes; transfer_config.srcOffset = 0; transfer_config.destTransferSize = kEDMA_TransferSize1Bytes; @@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_ transfer_config.minorLoopBytes = 1; } + /* Store the initially configured eDMA minor byte transfer count into the I2C handle */ + handle->nbytes = transfer_config.minorLoopBytes; + EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config); EDMA_StartTransfer(handle->dmaHandle); } @@ -427,7 +462,7 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle if (handle->transfer.direction == kI2C_Read) { /* Change direction for receive. */ - base->C1 &= ~I2C_C1_TX_MASK; + base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); /* Read dummy to release the bus. */ dummy = base->D; @@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle { result = I2C_MasterStop(base); } + else + { + /* Change direction to send. */ + base->C1 |= I2C_C1_TX_MASK; + } /* Read the last byte of data. */ if (handle->transfer.direction == kI2C_Read) @@ -504,7 +544,9 @@ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t if (kIdleState != handle->state) { - *count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + *count = (handle->transferSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } else { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h index 234876d451c..40cb648ea99 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,31 +39,30 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ -/*! @brief I2C master edma handle typedef. */ +/*! @brief I2C master eDMA handle typedef. */ typedef struct _i2c_master_edma_handle i2c_master_edma_handle_t; -/*! @brief I2C master edma transfer callback typedef. */ +/*! @brief I2C master eDMA transfer callback typedef. */ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base, i2c_master_edma_handle_t *handle, status_t status, void *userData); -/*! @brief I2C master edma transfer structure. */ +/*! @brief I2C master eDMA transfer structure. */ struct _i2c_master_edma_handle { - i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */ + i2c_master_transfer_t transfer; /*!< I2C master transfer structure. */ size_t transferSize; /*!< Total bytes to be transferred. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ uint8_t state; /*!< I2C master transfer status. */ edma_handle_t *dmaHandle; /*!< The eDMA handler used. */ i2c_master_edma_transfer_callback_t - completionCallback; /*!< Callback function called after edma transfer finished. */ - void *userData; /*!< Callback parameter passed to callback function. */ + completionCallback; /*!< A callback function called after the eDMA transfer is finished. */ + void *userData; /*!< A callback parameter passed to the callback function. */ }; /******************************************************************************* @@ -75,18 +74,18 @@ extern "C" { #endif /*_cplusplus. */ /*! - * @name I2C Block EDMA Transfer Operation + * @name I2C Block eDMA Transfer Operation * @{ */ /*! - * @brief Init the I2C handle which is used in transcational functions. + * @brief Initializes the I2C handle which is used in transcational functions. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param callback pointer to user callback function. - * @param userData user param passed to the callback function. - * @param edmaHandle EDMA handle pointer. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param callback A pointer to the user callback function. + * @param userData A user parameter passed to the callback function. + * @param edmaHandle eDMA handle pointer. */ void I2C_MasterCreateEDMAHandle(I2C_Type *base, i2c_master_edma_handle_t *handle, @@ -95,33 +94,33 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base, edma_handle_t *edmaHandle); /*! - * @brief Performs a master edma non-blocking transfer on the I2C bus. + * @brief Performs a master eDMA non-blocking transfer on the I2C bus. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param xfer pointer to transfer structure of i2c_master_transfer_t. - * @retval kStatus_Success Sucessully complete the data transmission. - * @retval kStatus_I2C_Busy Previous transmission still not finished. - * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param xfer A pointer to the transfer structure of i2c_master_transfer_t. + * @retval kStatus_Success Sucessfully completed the data transmission. + * @retval kStatus_I2C_Busy A previous transmission is still not finished. + * @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout. * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. - * @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer. + * @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer. */ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer); /*! - * @brief Get master transfer status during a edma non-blocking transfer. + * @brief Gets a master transfer status during the eDMA non-blocking transfer. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param count A number of bytes transferred by the non-blocking transaction. */ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count); /*! - * @brief Abort a master edma non-blocking transfer in a early time. + * @brief Aborts a master eDMA non-blocking transfer early. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. + * @param handle A pointer to the i2c_master_edma_handle_t structure. */ void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c index c27b91e9f04..74b1001a88a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h index 7c11572e806..d5a0037bb58 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,7 +35,6 @@ /*! @addtogroup llwu */ /*! @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -52,9 +51,9 @@ */ typedef enum _llwu_external_pin_mode { - kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as wakeup input. */ - kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with rising edge detection. */ - kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with falling edge detection.*/ + kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as a wakeup input. */ + kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with the rising edge detection. */ + kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with the falling edge detection.*/ kLLWU_ExternalPinAnyEdge = 3U /*!< Pin enabled with any change detection. */ } llwu_external_pin_mode_t; @@ -75,9 +74,9 @@ typedef enum _llwu_pin_filter_mode */ typedef struct _llwu_version_id { - uint16_t feature; /*!< Feature Specification Number. */ - uint8_t minor; /*!< Minor version number. */ - uint8_t major; /*!< Major version number. */ + uint16_t feature; /*!< A feature specification number. */ + uint8_t minor; /*!< The minor version number. */ + uint8_t major; /*!< The major version number. */ } llwu_version_id_t; #endif /* FSL_FEATURE_LLWU_HAS_VERID */ @@ -87,20 +86,20 @@ typedef struct _llwu_version_id */ typedef struct _llwu_param { - uint8_t filters; /*!< Number of pin filter. */ - uint8_t dmas; /*!< Number of wakeup DMA. */ - uint8_t modules; /*!< Number of wakeup module. */ - uint8_t pins; /*!< Number of wake up pin. */ + uint8_t filters; /*!< A number of the pin filter. */ + uint8_t dmas; /*!< A number of the wakeup DMA. */ + uint8_t modules; /*!< A number of the wakeup module. */ + uint8_t pins; /*!< A number of the wake up pin. */ } llwu_param_t; #endif /* FSL_FEATURE_LLWU_HAS_PARAM */ #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER) /*! - * @brief External input pin filter control structure + * @brief An external input pin filter control structure */ typedef struct _llwu_external_pin_filter_mode { - uint32_t pinIndex; /*!< Pin number */ + uint32_t pinIndex; /*!< A pin number */ llwu_pin_filter_mode_t filterMode; /*!< Filter mode */ } llwu_external_pin_filter_mode_t; #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */ @@ -122,11 +121,11 @@ extern "C" { /*! * @brief Gets the LLWU version ID. * - * This function gets the LLWU version ID, including major version number, - * minor version number, and feature specification number. + * This function gets the LLWU version ID, including the major version number, + * the minor version number, and the feature specification number. * * @param base LLWU peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId A pointer to the version ID structure. */ static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *versionId) { @@ -138,11 +137,11 @@ static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *version /*! * @brief Gets the LLWU parameter. * - * This function gets the LLWU parameter, including wakeup pin number, module - * number, DMA number, and pin filter number. + * This function gets the LLWU parameter, including a wakeup pin number, a module + * number, a DMA number, and a pin filter number. * * @param base LLWU peripheral base address. - * @param param Pointer to LLWU param structure. + * @param param A pointer to the LLWU parameter structure. */ static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param) { @@ -158,8 +157,8 @@ static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param) * as a wake up source. * * @param base LLWU peripheral base address. - * @param pinIndex pin index which to be enabled as external wakeup source, start from 1. - * @param pinMode pin configuration mode defined in llwu_external_pin_modes_t + * @param pinIndex A pin index to be enabled as an external wakeup source starting from 1. + * @param pinMode A pin configuration mode defined in the llwu_external_pin_modes_t. */ void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode); @@ -167,11 +166,11 @@ void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_exte * @brief Gets the external wakeup source flag. * * This function checks the external pin flag to detect whether the MCU is - * woke up by the specific pin. + * woken up by the specific pin. * * @param base LLWU peripheral base address. - * @param pinIndex pin index, start from 1. - * @return true if the specific pin is wake up source. + * @param pinIndex A pin index, which starts from 1. + * @return True if the specific pin is a wakeup source. */ bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); @@ -181,7 +180,7 @@ bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); * This function clears the external wakeup source flag for a specific pin. * * @param base LLWU peripheral base address. - * @param pinIndex pin index, start from 1. + * @param pinIndex A pin index, which starts from 1. */ void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */ @@ -194,8 +193,8 @@ void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); * as a wake up source. * * @param base LLWU peripheral base address. - * @param moduleIndex module index which to be enabled as internal wakeup source, start from 1. - * @param enable enable or disable setting + * @param moduleIndex A module index to be enabled as an internal wakeup source starting from 1. + * @param enable An enable or a disable setting */ static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable) { @@ -213,31 +212,31 @@ static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint * @brief Gets the external wakeup source flag. * * This function checks the external pin flag to detect whether the system is - * woke up by the specific pin. + * woken up by the specific pin. * * @param base LLWU peripheral base address. - * @param moduleIndex module index, start from 1. - * @return true if the specific pin is wake up source. + * @param moduleIndex A module index, which starts from 1. + * @return True if the specific pin is a wake up source. */ static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t moduleIndex) { +#if (defined(FSL_FEATURE_LLWU_HAS_MF) && FSL_FEATURE_LLWU_HAS_MF) #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32)) return (bool)(base->MF & (1U << moduleIndex)); #else -#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16)) -#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF) return (bool)(base->MF5 & (1U << moduleIndex)); +#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */ #else +#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16)) return (bool)(base->F5 & (1U << moduleIndex)); -#endif /* FSL_FEATURE_LLWU_HAS_PF */ #else #if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF) return (bool)(base->PF3 & (1U << moduleIndex)); #else return (bool)(base->F3 & (1U << moduleIndex)); -#endif +#endif /* FSL_FEATURE_LLWU_HAS_PF */ #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */ -#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */ +#endif /* FSL_FEATURE_LLWU_HAS_MF */ } #endif /* FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE */ @@ -248,8 +247,8 @@ static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t mo * This function enables/disables the internal DMA that is used as a wake up source. * * @param base LLWU peripheral base address. - * @param moduleIndex Internal module index which used as DMA request source, start from 1. - * @param enable Enable or disable DMA request source + * @param moduleIndex An internal module index which is used as a DMA request source, starting from 1. + * @param enable Enable or disable the DMA request source */ static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable) { @@ -271,8 +270,8 @@ static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uin * This function sets the pin filter configuration. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index which used to enable/disable the digital filter, start from 1. - * @param filterMode filter mode configuration + * @param filterIndex A pin filter index used to enable/disable the digital filter, starting from 1. + * @param filterMode A filter mode configuration */ void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode); @@ -282,18 +281,18 @@ void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_ * This function gets the pin filter flag. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index, start from 1. - * @return true if the flag is a source of existing a low-leakage power mode. + * @param filterIndex A pin filter index, which starts from 1. + * @return True if the flag is a source of the existing low-leakage power mode. */ bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); /*! - * @brief Clear the pin filter configuration. + * @brief Clears the pin filter configuration. * - * This function clear the pin filter flag. + * This function clears the pin filter flag. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index which to be clear the flag, start from 1. + * @param filterIndex A pin filter index to clear the flag, starting from 1. */ void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); @@ -303,10 +302,10 @@ void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); /*! * @brief Sets the reset pin mode. * - * This function sets how the reset pin is used as a low leakage mode exit source. + * This function determines how the reset pin is used as a low leakage mode exit source. * - * @param pinEnable Enable reset pin filter - * @param pinFilterEnable Specify whether pin filter is enabled in Low-Leakage power mode. + * @param pinEnable Enable reset the pin filter + * @param pinFilterEnable Specify whether the pin filter is enabled in Low-Leakage power mode. */ void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool enableInLowLeakageMode); #endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c index fb6f06c3ac2..bff12af5655 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,7 +48,7 @@ void LMEM_EnableCodeCache(LMEM_Type *base, bool enable) LMEM_CodeCacheInvalidateAll(base); /* Now enable the cache. */ - base->PCCCR |= LMEM_PCCCR_ENCACHE_MASK | LMEM_PCCCR_ENWRBUF_MASK; + base->PCCCR |= LMEM_PCCCR_ENCACHE_MASK; } else { @@ -56,7 +56,7 @@ void LMEM_EnableCodeCache(LMEM_Type *base, bool enable) LMEM_CodeCachePushAll(base); /* Now disable the cache. */ - base->PCCCR &= ~(LMEM_PCCCR_ENCACHE_MASK | LMEM_PCCCR_ENWRBUF_MASK); + base->PCCCR &= ~LMEM_PCCCR_ENCACHE_MASK; } } @@ -236,7 +236,7 @@ void LMEM_CodeCacheClearMultiLines(LMEM_Type *base, uint32_t address, uint32_t l } } } - +#if (!defined(FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE)) || !FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, lmem_cache_mode_t cacheMode) { uint32_t mode = base->PCCRMR; @@ -255,6 +255,7 @@ status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, return kStatus_Success; } } +#endif /* FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE */ #if FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE void LMEM_EnableSystemCache(LMEM_Type *base, bool enable) @@ -265,7 +266,7 @@ void LMEM_EnableSystemCache(LMEM_Type *base, bool enable) LMEM_SystemCacheInvalidateAll(base); /* Now enable the cache. */ - base->PSCCR |= LMEM_PSCCR_ENCACHE_MASK | LMEM_PSCCR_ENWRBUF_MASK; + base->PSCCR |= LMEM_PSCCR_ENCACHE_MASK ; } else { @@ -273,7 +274,7 @@ void LMEM_EnableSystemCache(LMEM_Type *base, bool enable) LMEM_SystemCachePushAll(base); /* Now disable the cache. */ - base->PSCCR &= ~(LMEM_PSCCR_ENCACHE_MASK | LMEM_PSCCR_ENWRBUF_MASK); + base->PSCCR &= ~LMEM_PSCCR_ENCACHE_MASK; } } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h index 9e69feb4130..8df4cea3d3d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief LMEM controller driver version 2.0.0. */ -#define FSL_LMEM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief LMEM controller driver version 2.1.0. */ +#define FSL_LMEM_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*@}*/ #define LMEM_CACHE_LINE_SIZE (0x10U) /*!< Cache line is 16-bytes. */ @@ -55,9 +54,9 @@ /*! @brief LMEM cache mode options. */ typedef enum _lmem_cache_mode { - kLMEM_NonCacheable = 0x0U, /*!< CACHE mode: non-cacheable. */ - kLMEM_CacheWriteThrough = 0x2U, /*!< CACHE mode: write-through. */ - kLMEM_CacheWriteBack = 0x3U /*!< CACHE mode: write-back. */ + kLMEM_NonCacheable = 0x0U, /*!< Cache mode: non-cacheable. */ + kLMEM_CacheWriteThrough = 0x2U, /*!< Cache mode: write-through. */ + kLMEM_CacheWriteBack = 0x3U /*!< Cache mode: write-back. */ } lmem_cache_mode_t; /*! @brief LMEM cache regions. */ @@ -106,7 +105,7 @@ extern "C" { /*! * @brief Enables/disables the processor code bus cache. * This function enables/disables the cache. The function first invalidates the entire cache - * and then enables/disable both the cache and write buffers. + * and then enables/disables both the cache and write buffers. * * @param base LMEM peripheral base address. * @param enable The enable or disable flag. @@ -115,6 +114,26 @@ extern "C" { */ void LMEM_EnableCodeCache(LMEM_Type *base, bool enable); +/*! + * @brief Enables/disables the processor code bus write buffer. + * + * @param base LMEM peripheral base address. + * @param enable The enable or disable flag. + * true - enable the code bus write buffer. + * false - disable the code bus write buffer. + */ +static inline void LMEM_EnableCodeWriteBuffer(LMEM_Type *base, bool enable) +{ + if (enable) + { + base->PCCCR |= LMEM_PCCCR_ENWRBUF_MASK; + } + else + { + base->PCCCR &= ~LMEM_PCCCR_ENWRBUF_MASK; + } +} + /*! * @brief Invalidates the processor code bus cache. * This function invalidates the cache both ways, which means that @@ -163,10 +182,10 @@ void LMEM_CodeCacheInvalidateLine(LMEM_Type *base, uint32_t address); * This function invalidates multiple lines in the cache * based on the physical address and length in bytes passed in by the * user. If the function detects that the length meets or exceeds half the - * cache. Then the function performs an entire cache invalidate function, which is + * cache, the function performs an entire cache invalidate function, which is * more efficient than invalidating the cache line-by-line. - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Invalidate - Unconditionally clear valid and modified bits of a cache entry. * * @param base LMEM peripheral base address. @@ -197,8 +216,8 @@ void LMEM_CodeCachePushLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an cache push function, which is * more efficient than pushing the modified lines in the cache line-by-line. - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Push - Push a cache entry if it is valid and modified, then clear the modified bit. If * the entry is not valid or not modified, leave as is. This action does not clear the valid * bit. A cache push is synonymous with a cache flush. @@ -230,8 +249,8 @@ void LMEM_CodeCacheClearLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half the total amount of * cache, the function performs a cache clear function which is * more efficient than clearing the lines in the cache line-by-line. - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Clear - Push a cache entry if it is valid and modified, then clear the valid and * modify bits. If entry not valid or not modified, clear the valid bit. * @@ -242,6 +261,7 @@ void LMEM_CodeCacheClearLine(LMEM_Type *base, uint32_t address); */ void LMEM_CodeCacheClearMultiLines(LMEM_Type *base, uint32_t address, uint32_t length); +#if (!defined(FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE)) || !FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE /*! * @brief Demotes the cache mode of a region in processor code bus cache. * This function allows the user to demote the cache mode of a region within the device's @@ -264,6 +284,7 @@ void LMEM_CodeCacheClearMultiLines(LMEM_Type *base, uint32_t address, uint32_t l * kStatus_Fail The cache demote operation is failure. */ status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, lmem_cache_mode_t cacheMode); +#endif /* FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE */ /*@}*/ @@ -285,6 +306,26 @@ status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, */ void LMEM_EnableSystemCache(LMEM_Type *base, bool enable); +/*! + * @brief Enables/disables the processor system bus write buffer. + * + * @param base LMEM peripheral base address. + * @param enable The enable or disable flag. + * true - enable the system bus write buffer. + * false - disable the system bus write buffer. + */ +static inline void LMEM_EnableSystemWriteBuffer(LMEM_Type *base, bool enable) +{ + if (enable) + { + base->PSCCR |= LMEM_PSCCR_ENWRBUF_MASK; + } + else + { + base->PSCCR &= ~LMEM_PSCCR_ENWRBUF_MASK; + } +} + /*! * @brief Invalidates the processor system bus cache. * This function invalidates the entire cache both ways. @@ -320,7 +361,7 @@ void LMEM_SystemCacheClearAll(LMEM_Type *base); * @brief Invalidates a specific line in the processor system bus cache. * This function invalidates a specific line in the cache * based on the physical address passed in by the user. - * Invalidate - Unconditionally clear valid and modify bits of a cache entry + * Invalidate - Unconditionally clears valid and modify bits of a cache entry. * * @param base LMEM peripheral base address. Should be 16-byte aligned address. * If not, it is changed to the 16-byte aligned memory address. @@ -335,8 +376,8 @@ void LMEM_SystemCacheInvalidateLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an entire cache invalidate function (which is * more efficient than invalidating the cache line-by-line). - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Invalidate - Unconditionally clear valid and modify bits of a cache entry * * @param base LMEM peripheral base address. @@ -367,8 +408,8 @@ void LMEM_SystemCachePushLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an entire cache push function (which is * more efficient than pushing the modified lines in the cache line-by-line). - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Push - Push a cache entry if it is valid and modified, then clear the modify bit. If * the entry is not valid or not modified, leave as is. This action does not clear the valid * bit. A cache push is synonymous with a cache flush. @@ -400,8 +441,8 @@ void LMEM_SystemCacheClearLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an entire cache clear function (which is * more efficient than clearing the lines in the cache line-by-line). - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Clear - Push a cache entry if it is valid and modified, then clear the valid and * modify bits. If the entry is not valid or not modified, clear the valid bit. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c index b3dcc89d55d..67b3b9785cf 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,9 +48,17 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base); /*! @brief Pointers to LPTMR bases for each instance. */ static LPTMR_Type *const s_lptmrBases[] = LPTMR_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to LPTMR clocks for each instance. */ static const clock_ip_name_t s_lptmrClocks[] = LPTMR_CLOCKS; +#if defined(LPTMR_PERIPH_CLOCKS) +/* Array of LPTMR functional clock name. */ +static const clock_ip_name_t s_lptmrPeriphClocks[] = LPTMR_PERIPH_CLOCKS; +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + /******************************************************************************* * Code ******************************************************************************/ @@ -59,7 +67,7 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_LPTMR_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_lptmrBases); instance++) { if (s_lptmrBases[instance] == base) { @@ -67,7 +75,7 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base) } } - assert(instance < FSL_FEATURE_SOC_LPTMR_COUNT); + assert(instance < ARRAY_SIZE(s_lptmrBases)); return instance; } @@ -76,8 +84,17 @@ void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPTMR_GetInstance(base); + /* Ungate the LPTMR clock*/ - CLOCK_EnableClock(s_lptmrClocks[LPTMR_GetInstance(base)]); + CLOCK_EnableClock(s_lptmrClocks[instance]); +#if defined(LPTMR_PERIPH_CLOCKS) + CLOCK_EnableClock(s_lptmrPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure the timers operation mode and input pin setup */ base->CSR = (LPTMR_CSR_TMS(config->timerMode) | LPTMR_CSR_TFC(config->enableFreeRunning) | @@ -92,8 +109,17 @@ void LPTMR_Deinit(LPTMR_Type *base) { /* Disable the LPTMR and reset the internal logic */ base->CSR &= ~LPTMR_CSR_TEN_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPTMR_GetInstance(base); + /* Gate the LPTMR clock*/ - CLOCK_DisableClock(s_lptmrClocks[LPTMR_GetInstance(base)]); + CLOCK_DisableClock(s_lptmrClocks[instance]); +#if defined(LPTMR_PERIPH_CLOCKS) + CLOCK_DisableClock(s_lptmrPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void LPTMR_GetDefaultConfig(lptmr_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h index fd3cb1ed242..6cc909b3148 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,22 +33,20 @@ #include "fsl_common.h" /*! - * @addtogroup lptmr_driver + * @addtogroup lptmr * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */ +#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1 */ /*@}*/ -/*! @brief LPTMR pin selection, used in pulse counter mode.*/ +/*! @brief LPTMR pin selection used in pulse counter mode.*/ typedef enum _lptmr_pin_select { kLPTMR_PinSelectInput_0 = 0x0U, /*!< Pulse counter input 0 is selected */ @@ -57,7 +55,7 @@ typedef enum _lptmr_pin_select kLPTMR_PinSelectInput_3 = 0x3U /*!< Pulse counter input 3 is selected */ } lptmr_pin_select_t; -/*! @brief LPTMR pin polarity, used in pulse counter mode.*/ +/*! @brief LPTMR pin polarity used in pulse counter mode.*/ typedef enum _lptmr_pin_polarity { kLPTMR_PinPolarityActiveHigh = 0x0U, /*!< Pulse Counter input source is active-high */ @@ -104,13 +102,13 @@ typedef enum _lptmr_prescaler_clock_select kLPTMR_PrescalerClock_3 = 0x3U, /*!< Prescaler/glitch filter clock 3 selected. */ } lptmr_prescaler_clock_select_t; -/*! @brief List of LPTMR interrupts */ +/*! @brief List of the LPTMR interrupts */ typedef enum _lptmr_interrupt_enable { kLPTMR_TimerInterruptEnable = LPTMR_CSR_TIE_MASK, /*!< Timer interrupt enable */ } lptmr_interrupt_enable_t; -/*! @brief List of LPTMR status flags */ +/*! @brief List of the LPTMR status flags */ typedef enum _lptmr_status_flags { kLPTMR_TimerCompareFlag = LPTMR_CSR_TCF_MASK, /*!< Timer compare flag */ @@ -121,18 +119,18 @@ typedef enum _lptmr_status_flags * * This structure holds the configuration settings for the LPTMR peripheral. To initialize this * structure to reasonable defaults, call the LPTMR_GetDefaultConfig() function and pass a - * pointer to your config structure instance. + * pointer to your configuration structure instance. * - * The config struct can be made const so it resides in flash + * The configuration struct can be made constant so it resides in flash. */ typedef struct _lptmr_config { lptmr_timer_mode_t timerMode; /*!< Time counter mode or pulse counter mode */ lptmr_pin_select_t pinSelect; /*!< LPTMR pulse input pin select; used only in pulse counter mode */ lptmr_pin_polarity_t pinPolarity; /*!< LPTMR pulse input pin polarity; used only in pulse counter mode */ - bool enableFreeRunning; /*!< true: enable free running, counter is reset on overflow - false: counter is reset when the compare flag is set */ - bool bypassPrescaler; /*!< true: bypass prescaler; false: use clock from prescaler */ + bool enableFreeRunning; /*!< True: enable free running, counter is reset on overflow + False: counter is reset when the compare flag is set */ + bool bypassPrescaler; /*!< True: bypass prescaler; false: use clock from prescaler */ lptmr_prescaler_clock_select_t prescalerClockSource; /*!< LPTMR clock source */ lptmr_prescaler_glitch_value_t value; /*!< Prescaler or glitch filter value */ } lptmr_config_t; @@ -151,26 +149,26 @@ extern "C" { */ /*! - * @brief Ungate the LPTMR clock and configures the peripheral for basic operation. + * @brief Ungates the LPTMR clock and configures the peripheral for a basic operation. * * @note This API should be called at the beginning of the application using the LPTMR driver. * * @param base LPTMR peripheral base address - * @param config Pointer to user's LPTMR config structure. + * @param config A pointer to the LPTMR configuration structure. */ void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config); /*! - * @brief Gate the LPTMR clock + * @brief Gates the LPTMR clock. * * @param base LPTMR peripheral base address */ void LPTMR_Deinit(LPTMR_Type *base); /*! - * @brief Fill in the LPTMR config struct with the default settings + * @brief Fills in the LPTMR configuration structure with default settings. * - * The default values are: + * The default values are as follows. * @code * config->timerMode = kLPTMR_TimerModeTimeCounter; * config->pinSelect = kLPTMR_PinSelectInput_0; @@ -180,7 +178,7 @@ void LPTMR_Deinit(LPTMR_Type *base); * config->prescalerClockSource = kLPTMR_PrescalerClock_1; * config->value = kLPTMR_Prescale_Glitch_0; * @endcode - * @param config Pointer to user's LPTMR config structure. + * @param config A pointer to the LPTMR configuration structure. */ void LPTMR_GetDefaultConfig(lptmr_config_t *config); @@ -200,7 +198,12 @@ void LPTMR_GetDefaultConfig(lptmr_config_t *config); */ static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask) { - base->CSR |= mask; + uint32_t reg = base->CSR; + + /* Clear the TCF bit so that we don't clear this w1c bit when writing back */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg |= mask; + base->CSR = reg; } /*! @@ -208,11 +211,16 @@ static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask) * * @param base LPTMR peripheral base address * @param mask The interrupts to disable. This is a logical OR of members of the - * enumeration ::lptmr_interrupt_enable_t + * enumeration ::lptmr_interrupt_enable_t. */ static inline void LPTMR_DisableInterrupts(LPTMR_Type *base, uint32_t mask) { - base->CSR &= ~mask; + uint32_t reg = base->CSR; + + /* Clear the TCF bit so that we don't clear this w1c bit when writing back */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg &= ~mask; + base->CSR = reg; } /*! @@ -236,7 +244,7 @@ static inline uint32_t LPTMR_GetEnabledInterrupts(LPTMR_Type *base) */ /*! - * @brief Gets the LPTMR status flags + * @brief Gets the LPTMR status flags. * * @param base LPTMR peripheral base address * @@ -249,11 +257,11 @@ static inline uint32_t LPTMR_GetStatusFlags(LPTMR_Type *base) } /*! - * @brief Clears the LPTMR status flags + * @brief Clears the LPTMR status flags. * * @param base LPTMR peripheral base address * @param mask The status flags to clear. This is a logical OR of members of the - * enumeration ::lptmr_status_flags_t + * enumeration ::lptmr_status_flags_t. */ static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask) { @@ -263,47 +271,48 @@ static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask) /*! @}*/ /*! - * @name Read and Write the timer period + * @name Read and write the timer period * @{ */ /*! * @brief Sets the timer period in units of count. * - * Timers counts from 0 till it equals the count value set here. The count value is written to + * Timers counts from 0 until it equals the count value set here. The count value is written to * the CMR register. * * @note * 1. The TCF flag is set with the CNR equals the count provided here and then increments. - * 2. User can call the utility macros provided in fsl_common.h to convert to ticks + * 2. Call the utility macros provided in the fsl_common.h to convert to ticks. * * @param base LPTMR peripheral base address - * @param ticks Timer period in units of ticks + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. */ -static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint16_t ticks) +static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint32_t ticks) { - base->CMR = ticks; + assert(ticks > 0); + base->CMR = ticks - 1; } /*! * @brief Reads the current timer counting value. * - * This function returns the real-time timer counting value, in a range from 0 to a + * This function returns the real-time timer counting value in a range from 0 to a * timer period. * - * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. * * @param base LPTMR peripheral base address * - * @return Current counter value in ticks + * @return The current counter value in ticks */ -static inline uint16_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) +static inline uint32_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) { - /* Must first write any value to the CNR. This will synchronize and register the current value + /* Must first write any value to the CNR. This synchronizes and registers the current value * of the CNR into a temporary register which can then be read */ base->CNR = 0U; - return (uint16_t)base->CNR; + return (uint32_t)((base->CNR & LPTMR_CNR_COUNTER_MASK) >> LPTMR_CNR_COUNTER_SHIFT); } /*! @}*/ @@ -314,30 +323,40 @@ static inline uint16_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) */ /*! - * @brief Starts the timer counting. + * @brief Starts the timer. * * After calling this function, the timer counts up to the CMR register value. - * Each time the timer reaches CMR value and then increments, it generates a - * trigger pulse and sets the timeout interrupt flag. An interrupt will also be + * Each time the timer reaches the CMR value and then increments, it generates a + * trigger pulse and sets the timeout interrupt flag. An interrupt is also * triggered if the timer interrupt is enabled. * * @param base LPTMR peripheral base address */ static inline void LPTMR_StartTimer(LPTMR_Type *base) { - base->CSR |= LPTMR_CSR_TEN_MASK; + uint32_t reg = base->CSR; + + /* Clear the TCF bit to avoid clearing the w1c bit when writing back. */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg |= LPTMR_CSR_TEN_MASK; + base->CSR = reg; } /*! - * @brief Stops the timer counting. + * @brief Stops the timer. * - * This function stops the timer counting and resets the timer's counter register + * This function stops the timer and resets the timer's counter register. * * @param base LPTMR peripheral base address */ static inline void LPTMR_StopTimer(LPTMR_Type *base) { - base->CSR &= ~LPTMR_CSR_TEN_MASK; + uint32_t reg = base->CSR; + + /* Clear the TCF bit to avoid clearing the w1c bit when writing back. */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg &= ~LPTMR_CSR_TEN_MASK; + base->CSR = reg; } /*! @}*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c index b1b015f6f49..9a83b5698d2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -109,9 +109,23 @@ static lpuart_handle_t *s_lpuartHandle[FSL_FEATURE_SOC_LPUART_COUNT]; /* Array of LPUART peripheral base address. */ static LPUART_Type *const s_lpuartBases[] = LPUART_BASE_PTRS; /* Array of LPUART IRQ number. */ +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +static const IRQn_Type s_lpuartRxIRQ[] = LPUART_RX_IRQS; +static const IRQn_Type s_lpuartTxIRQ[] = LPUART_TX_IRQS; +#else static const IRQn_Type s_lpuartIRQ[] = LPUART_RX_TX_IRQS; +#endif +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of LPUART clock name. */ static const clock_ip_name_t s_lpuartClock[] = LPUART_CLOCKS; + +#if defined(LPUART_PERIPH_CLOCKS) +/* Array of LPUART functional clock name. */ +static const clock_ip_name_t s_lpuartPeriphClocks[] = LPUART_PERIPH_CLOCKS; +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + /* LPUART ISR for transactional APIs. */ static lpuart_isr_t s_lpuartIsr; @@ -123,7 +137,7 @@ uint32_t LPUART_GetInstance(LPUART_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_LPUART_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_lpuartBases); instance++) { if (s_lpuartBases[instance] == base) { @@ -131,13 +145,15 @@ uint32_t LPUART_GetInstance(LPUART_Type *base) } } - assert(instance < FSL_FEATURE_SOC_LPUART_COUNT); + assert(instance < ARRAY_SIZE(s_lpuartBases)); return instance; } static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + size_t size; if (handle->rxRingBufferTail > handle->rxRingBufferHead) @@ -154,6 +170,8 @@ static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_han static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + bool full; if (LPUART_TransferGetRxRingBufferLength(base, handle) == (handle->rxRingBufferSize - 1U)) @@ -169,6 +187,8 @@ static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length) { + assert(data); + size_t i; /* The Non Blocking write data API assume user have ensured there is enough space in @@ -181,33 +201,48 @@ static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length) { + assert(data); + size_t i; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); +#endif /* The Non Blocking read data API assume user have ensured there is enough space in peripheral to write. */ for (i = 0; i < length; i++) { +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (isSevenDataBits) + { + data[i] = (base->DATA & 0x7F); + } + else + { + data[i] = base->DATA; + } +#else data[i] = base->DATA; +#endif } } -void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz) +status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz) { assert(config); + assert(config->baudRate_Bps); #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->txFifoWatermark); assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->rxFifoWatermark); #endif + uint32_t temp; uint16_t sbr, sbrTemp; uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff; - /* Enable lpuart clock */ - CLOCK_EnableClock(s_lpuartClock[LPUART_GetInstance(base)]); - - /* Disable LPUART TX RX before setting. */ - base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); - /* This LPUART instantiation uses a slightly different baud rate calculation * The idea is to use the best OSR (over-sampling rate) possible * Note, OSR is typically hard-set to 16 in other LPUART instantiations @@ -248,34 +283,75 @@ void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcC /* Check to see if actual baud rate is within 3% of desired baud rate * based on the best calculate OSR value */ - if (baudDiff < ((config->baudRate_Bps / 100) * 3)) + if (baudDiff > ((config->baudRate_Bps / 100) * 3)) { - temp = base->BAUD; + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_LPUART_BaudrateNotSupport; + } - /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. - * If so, then "BOTHEDGE" sampling must be turned on */ - if ((osr > 3) && (osr < 8)) - { - temp |= LPUART_BAUD_BOTHEDGE_MASK; - } +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPUART_GetInstance(base); - /* program the osr value (bit value is one less than actual value) */ - temp &= ~LPUART_BAUD_OSR_MASK; - temp |= LPUART_BAUD_OSR(osr - 1); + /* Enable lpuart clock */ + CLOCK_EnableClock(s_lpuartClock[instance]); +#if defined(LPUART_PERIPH_CLOCKS) + CLOCK_EnableClock(s_lpuartPeriphClocks[instance]); +#endif - /* write the sbr value to the BAUD registers */ - temp &= ~LPUART_BAUD_SBR_MASK; - base->BAUD = temp | LPUART_BAUD_SBR(sbr); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL + /*Reset all internal logic and registers, except the Global Register */ + LPUART_SoftwareReset(base); +#else + /* Disable LPUART TX RX before setting. */ + base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); +#endif + + temp = base->BAUD; + + /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. + * If so, then "BOTHEDGE" sampling must be turned on */ + if ((osr > 3) && (osr < 8)) + { + temp |= LPUART_BAUD_BOTHEDGE_MASK; } + /* program the osr value (bit value is one less than actual value) */ + temp &= ~LPUART_BAUD_OSR_MASK; + temp |= LPUART_BAUD_OSR(osr - 1); + + /* write the sbr value to the BAUD registers */ + temp &= ~LPUART_BAUD_SBR_MASK; + base->BAUD = temp | LPUART_BAUD_SBR(sbr); + /* Set bit count and parity mode. */ base->BAUD &= ~LPUART_BAUD_M10_MASK; temp = base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK); - if (kLPUART_ParityDisabled != config->parityMode) + temp |= (uint8_t)config->parityMode; + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (kLPUART_SevenDataBits == config->dataBitsCount) + { + if (kLPUART_ParityDisabled != config->parityMode) + { + temp &= ~LPUART_CTRL_M7_MASK; /* Seven data bits and one parity bit */ + } + else + { + temp |= LPUART_CTRL_M7_MASK; + } + } + else +#endif { - temp |= (LPUART_CTRL_M_MASK | (uint8_t)config->parityMode); + if (kLPUART_ParityDisabled != config->parityMode) + { + temp |= LPUART_CTRL_M_MASK; /* Eight data bits and one parity bit */ + } } base->CTRL = temp; @@ -298,17 +374,27 @@ void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcC #endif /* Clear all status flags */ - temp = (LPUART_STAT_LBKDIF_MASK | LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT - temp |= LPUART_STAT_IDLE_MASK; + temp |= LPUART_STAT_LBKDIF_MASK; #endif #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK); #endif + /* Set data bits order. */ + if (config->isMsb) + { + temp |= LPUART_STAT_MSBF_MASK; + } + else + { + temp &= ~LPUART_STAT_MSBF_MASK; + } + base->STAT |= temp; /* Enable TX/RX base on configure structure. */ @@ -324,6 +410,8 @@ void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcC } base->CTRL = temp; + + return kStatus_Success; } void LPUART_Deinit(LPUART_Type *base) { @@ -341,11 +429,11 @@ void LPUART_Deinit(LPUART_Type *base) } /* Clear all status flags */ - temp = (LPUART_STAT_LBKDIF_MASK | LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT - temp |= LPUART_STAT_IDLE_MASK; + temp |= LPUART_STAT_LBKDIF_MASK; #endif #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING @@ -357,15 +445,27 @@ void LPUART_Deinit(LPUART_Type *base) /* Disable the module. */ base->CTRL = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance = LPUART_GetInstance(base); + /* Disable lpuart clock */ - CLOCK_DisableClock(s_lpuartClock[LPUART_GetInstance(base)]); + CLOCK_DisableClock(s_lpuartClock[instance]); + +#if defined(LPUART_PERIPH_CLOCKS) + CLOCK_DisableClock(s_lpuartPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void LPUART_GetDefaultConfig(lpuart_config_t *config) { assert(config); + config->baudRate_Bps = 115200U; config->parityMode = kLPUART_ParityDisabled; + config->dataBitsCount = kLPUART_EightDataBits; + config->isMsb = false; #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT config->stopBitCount = kLPUART_OneStopBit; #endif @@ -377,18 +477,14 @@ void LPUART_GetDefaultConfig(lpuart_config_t *config) config->enableRx = false; } -void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) +status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) { + assert(baudRate_Bps); + uint32_t temp, oldCtrl; uint16_t sbr, sbrTemp; uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff; - /* Store CTRL before disable Tx and Rx */ - oldCtrl = base->CTRL; - - /* Disable LPUART TX RX before setting. */ - base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); - /* This LPUART instantiation uses a slightly different baud rate calculation * The idea is to use the best OSR (over-sampling rate) possible * Note, OSR is typically hard-set to 16 in other LPUART instantiations @@ -431,6 +527,12 @@ void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcCl * based on the best calculate OSR value */ if (baudDiff < ((baudRate_Bps / 100) * 3)) { + /* Store CTRL before disable Tx and Rx */ + oldCtrl = base->CTRL; + + /* Disable LPUART TX RX before setting. */ + base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); + temp = base->BAUD; /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. @@ -447,17 +549,25 @@ void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcCl /* write the sbr value to the BAUD registers */ temp &= ~LPUART_BAUD_SBR_MASK; base->BAUD = temp | LPUART_BAUD_SBR(sbr); - } - /* Restore CTRL. */ - base->CTRL = oldCtrl; + /* Restore CTRL. */ + base->CTRL = oldCtrl; + + return kStatus_Success; + } + else + { + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_LPUART_BaudrateNotSupport; + } } void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask) { base->BAUD |= ((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)); #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO - base->FIFO |= ((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); + base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) | + ((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); #endif mask &= 0xFFFFFF00U; base->CTRL |= mask; @@ -467,7 +577,8 @@ void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask) { base->BAUD &= ~((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)); #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO - base->FIFO &= ~((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); + base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) & + ~((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); #endif mask &= 0xFFFFFF00U; base->CTRL &= ~mask; @@ -503,24 +614,24 @@ status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask) status_t status; #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO temp = (uint32_t)base->FIFO; - temp &= (uint32_t)(~(kLPUART_TxFifoOverflowFlag | kLPUART_RxFifoUnderflowFlag)); - temp |= mask & (kLPUART_TxFifoOverflowFlag | kLPUART_RxFifoUnderflowFlag); + temp &= (uint32_t)(~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)); + temp |= (mask << 16) & (LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK); base->FIFO = temp; #endif temp = (uint32_t)base->STAT; #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT - temp &= (uint32_t)(~(kLPUART_LinBreakFlag)); - temp |= mask & kLPUART_LinBreakFlag; + temp &= (uint32_t)(~(LPUART_STAT_LBKDIF_MASK)); + temp |= mask & LPUART_STAT_LBKDIF_MASK; #endif - temp &= (uint32_t)(~(kLPUART_RxActiveEdgeFlag | kLPUART_IdleLineFlag | kLPUART_RxOverrunFlag | - kLPUART_NoiseErrorFlag | kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag)); - temp |= mask & (kLPUART_RxActiveEdgeFlag | kLPUART_IdleLineFlag | kLPUART_RxOverrunFlag | kLPUART_NoiseErrorFlag | - kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag); + temp &= (uint32_t)(~(LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK)); + temp |= mask & (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING - temp &= (uint32_t)(~(kLPUART_DataMatch2Flag | kLPUART_DataMatch2Flag)); - temp |= mask & (kLPUART_DataMatch2Flag | kLPUART_DataMatch2Flag); + temp &= (uint32_t)(~(LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK)); + temp |= mask & (LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK); #endif - base->STAT |= temp; + base->STAT = temp; /* If some flags still pending. */ if (mask & LPUART_GetStatusFlags(base)) { @@ -540,6 +651,8 @@ status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask) void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length) { + assert(data); + /* This API can only ensure that the data is written into the data buffer but can't ensure all data in the data buffer are sent into the transmit shift buffer. */ while (length--) @@ -553,7 +666,15 @@ void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length) status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length) { + assert(data); + uint32_t statusFlag; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); +#endif while (length--) { @@ -589,7 +710,18 @@ status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length) return kStatus_LPUART_ParityError; } } +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (isSevenDataBits) + { + *(data++) = (base->DATA & 0x7F); + } + else + { + *(data++) = base->DATA; + } +#else *(data++) = base->DATA; +#endif } return kStatus_Success; @@ -603,6 +735,12 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, assert(handle); uint32_t instance; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); +#endif /* Zero the handle. */ memset(handle, 0, sizeof(lpuart_handle_t)); @@ -615,6 +753,11 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, handle->callback = callback; handle->userData = userData; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + /* Initial seven data bits flag */ + handle->isSevenDataBits = isSevenDataBits; +#endif + #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO /* Note: Take care of the RX FIFO, RX interrupt request only assert when received bytes @@ -624,7 +767,7 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, 5 bytes are received. the last byte will be saved in FIFO but not trigger RX interrupt because the water mark is 2. */ - base->WATER &= (~LPUART_WATER_RXWATER_SHIFT); + base->WATER &= (~LPUART_WATER_RXWATER_MASK); #endif /* Get instance from peripheral base address. */ @@ -635,8 +778,13 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, s_lpuartIsr = LPUART_TransferHandleIRQ; - /* Enable interrupt in NVIC. */ +/* Enable interrupt in NVIC. */ +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ + EnableIRQ(s_lpuartRxIRQ[instance]); + EnableIRQ(s_lpuartTxIRQ[instance]); +#else EnableIRQ(s_lpuartIRQ[instance]); +#endif } void LPUART_TransferStartRingBuffer(LPUART_Type *base, @@ -645,18 +793,16 @@ void LPUART_TransferStartRingBuffer(LPUART_Type *base, size_t ringBufferSize) { assert(handle); + assert(ringBuffer); /* Setup the ring buffer address */ - if (ringBuffer) - { - handle->rxRingBuffer = ringBuffer; - handle->rxRingBufferSize = ringBufferSize; - handle->rxRingBufferHead = 0U; - handle->rxRingBufferTail = 0U; + handle->rxRingBuffer = ringBuffer; + handle->rxRingBufferSize = ringBufferSize; + handle->rxRingBufferHead = 0U; + handle->rxRingBufferTail = 0U; - /* Enable the interrupt to accept the data when user need the ring buffer. */ - LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); - } + /* Enable the interrupt to accept the data when user need the ring buffer. */ + LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); } void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle) @@ -676,13 +822,12 @@ void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle) status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer) { - status_t status; + assert(handle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } + status_t status; /* Return error if current TX busy. */ if (kLPUART_TxBusy == handle->txState) @@ -707,6 +852,8 @@ status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *hand void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + LPUART_DisableInterrupts(base, kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_TransmissionCompleteInterruptEnable); handle->txDataSize = 0; @@ -715,16 +862,14 @@ void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle) status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kLPUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - *count = handle->txDataSizeAll - handle->txDataSize; return kStatus_Success; @@ -735,6 +880,11 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, lpuart_transfer_t *xfer, size_t *receivedBytes) { + assert(handle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); + uint32_t i; status_t status; /* How many bytes to copy from ring buffer to user memory. */ @@ -743,13 +893,6 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, size_t bytesToReceive; /* How many bytes currently have received. */ size_t bytesCurrentReceived; - uint32_t regPrimask = 0U; - - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } /* How to get data: 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize @@ -773,8 +916,8 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, /* If RX ring buffer is used. */ if (handle->rxRingBuffer) { - /* Disable IRQ, protect ring buffer. */ - regPrimask = DisableGlobalIRQ(); + /* Disable LPUART RX IRQ, protect ring buffer. */ + LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable); /* How many bytes in RX ring buffer currently. */ bytesToCopy = LPUART_TransferGetRxRingBufferLength(base, handle); @@ -811,8 +954,8 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, handle->rxDataSizeAll = bytesToReceive; handle->rxState = kLPUART_RxBusy; } - /* Enable IRQ if previously enabled. */ - EnableGlobalIRQ(regPrimask); + /* Enable LPUART RX IRQ if previously enabled. */ + LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable); /* Call user callback since all data are received. */ if (0 == bytesToReceive) @@ -849,6 +992,8 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */ if (!handle->rxRingBuffer) { @@ -862,16 +1007,14 @@ void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle) status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kLPUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - *count = handle->rxDataSizeAll - handle->rxDataSize; return kStatus_Success; @@ -879,19 +1022,17 @@ status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *hand void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + uint8_t count; uint8_t tempCount; - volatile uint8_t dummy; - - assert(handle); /* If RX overrun. */ if (LPUART_STAT_OR_MASK & base->STAT) { - /* Read base->DATA, otherwise the RX does not work. */ - dummy = base->DATA; - /* Avoid optimization */ - dummy++; + /* Clear overrun flag, otherwise the RX does not work. */ + base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK); + /* Trigger callback. */ if (handle->callback) { @@ -964,8 +1105,19 @@ void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle) } } - /* Read data. */ +/* Read data. */ +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (handle->isSevenDataBits) + { + handle->rxRingBuffer[handle->rxRingBufferHead] = (base->DATA & 0x7F); + } + else + { + handle->rxRingBuffer[handle->rxRingBufferHead] = base->DATA; + } +#else handle->rxRingBuffer[handle->rxRingBufferHead] = base->DATA; +#endif /* Increase handle->rxRingBufferHead. */ if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize) @@ -1033,71 +1185,113 @@ void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle) void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle) { - /* TODO: To be implemented. */ + /* To be implemented by User. */ } #if defined(LPUART0) -void LPUART0_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART0_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); +} +void LPUART0_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART0, s_lpuartHandle[0]); } -void LPUART0_RX_TX_DriverIRQHandler(void) +#else +void LPUART0_DriverIRQHandler(void) { - LPUART0_DriverIRQHandler(); + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); } #endif +#endif #if defined(LPUART1) -void LPUART1_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART1_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); +} +void LPUART1_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART1, s_lpuartHandle[1]); } -void LPUART1_RX_TX_DriverIRQHandler(void) +#else +void LPUART1_DriverIRQHandler(void) { - LPUART1_DriverIRQHandler(); + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); } #endif +#endif #if defined(LPUART2) -void LPUART2_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART2_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART2, s_lpuartHandle[2]); +} +void LPUART2_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART2, s_lpuartHandle[2]); } -void LPUART2_RX_TX_DriverIRQHandler(void) +#else +void LPUART2_DriverIRQHandler(void) { - LPUART2_DriverIRQHandler(); + s_lpuartIsr(LPUART2, s_lpuartHandle[2]); } #endif +#endif #if defined(LPUART3) -void LPUART3_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART3_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART3, s_lpuartHandle[3]); +} +void LPUART3_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART3, s_lpuartHandle[3]); } -void LPUART3_RX_TX_DriverIRQHandler(void) +#else +void LPUART3_DriverIRQHandler(void) { - LPUART3_DriverIRQHandler(); + s_lpuartIsr(LPUART3, s_lpuartHandle[3]); } #endif +#endif #if defined(LPUART4) -void LPUART4_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART4_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART4, s_lpuartHandle[4]); +} +void LPUART4_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART4, s_lpuartHandle[4]); } -void LPUART4_RX_TX_DriverIRQHandler(void) +#else +void LPUART4_DriverIRQHandler(void) { - LPUART4_DriverIRQHandler(); + s_lpuartIsr(LPUART4, s_lpuartHandle[4]); } #endif +#endif #if defined(LPUART5) -void LPUART5_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART5_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART5, s_lpuartHandle[5]); +} +void LPUART5_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART5, s_lpuartHandle[5]); } -void LPUART5_RX_TX_DriverIRQHandler(void) +#else +void LPUART5_DriverIRQHandler(void) { - LPUART5_DriverIRQHandler(); + s_lpuartIsr(LPUART5, s_lpuartHandle[5]); } #endif +#endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h index a357400b56a..0c60f82d88f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,36 +37,35 @@ * @{ */ -/*! @file*/ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief LPUART driver version 2.1.0. */ -#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief LPUART driver version 2.2.3. */ +#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 2, 3)) /*@}*/ /*! @brief Error codes for the LPUART driver. */ enum _lpuart_status { - kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */ - kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */ - kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */ - kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */ - kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */ - kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */ - kStatus_LPUART_FlagCannotClearManually = - MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */ - kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */ + kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */ + kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */ + kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */ + kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */ + kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */ + kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */ + kStatus_LPUART_FlagCannotClearManually = MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */ + kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */ kStatus_LPUART_RxRingBufferOverrun = MAKE_STATUS(kStatusGroup_LPUART, 8), /*!< LPUART RX software ring buffer overrun. */ kStatus_LPUART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_LPUART, 9), /*!< LPUART RX receiver overrun. */ kStatus_LPUART_NoiseError = MAKE_STATUS(kStatusGroup_LPUART, 10), /*!< LPUART noise error. */ kStatus_LPUART_FramingError = MAKE_STATUS(kStatusGroup_LPUART, 11), /*!< LPUART framing error. */ kStatus_LPUART_ParityError = MAKE_STATUS(kStatusGroup_LPUART, 12), /*!< LPUART parity error. */ + kStatus_LPUART_BaudrateNotSupport = + MAKE_STATUS(kStatusGroup_LPUART, 13), /*!< Baudrate is not support in current clock source */ }; /*! @brief LPUART parity mode. */ @@ -77,6 +76,15 @@ typedef enum _lpuart_parity_mode kLPUART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */ } lpuart_parity_mode_t; +/*! @brief LPUART data bits count. */ +typedef enum _lpuart_data_bits +{ + kLPUART_EightDataBits = 0x0U, /*!< Eight data bit */ +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + kLPUART_SevenDataBits = 0x1U, /*!< Seven data bit */ +#endif +} lpuart_data_bits_t; + /*! @brief LPUART stop bit count. */ typedef enum _lpuart_stop_bit_count { @@ -158,11 +166,13 @@ enum _lpuart_flags #endif }; -/*! @brief LPUART configure structure. */ +/*! @brief LPUART configuration structure. */ typedef struct _lpuart_config { - uint32_t baudRate_Bps; /*!< LPUART baud rate */ - lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */ + uint32_t baudRate_Bps; /*!< LPUART baud rate */ + lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */ + lpuart_data_bits_t dataBitsCount; /*!< Data bits count, eight (default), seven */ + bool isMsb; /*!< Data bits order, LSB (default), MSB */ #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT lpuart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */ #endif @@ -206,7 +216,11 @@ struct _lpuart_handle void *userData; /*!< LPUART callback function parameter.*/ volatile uint8_t txState; /*!< TX transfer state. */ - volatile uint8_t rxState; /*!< RX transfer state */ + volatile uint8_t rxState; /*!< RX transfer state. */ + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + bool isSevenDataBits; /*!< Seven data bits flag. */ +#endif }; /******************************************************************************* @@ -217,32 +231,59 @@ struct _lpuart_handle extern "C" { #endif /* _cplusplus */ +#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL + +/*! + * @name Software Reset + * @{ + */ + +/*! + * @brief Resets the LPUART using software. + * + * This function resets all internal logic and registers except the Global Register. + * Remains set until cleared by software. + * + * @param base LPUART peripheral base address. + */ +static inline void LPUART_SoftwareReset(LPUART_Type *base) +{ + base->GLOBAL |= LPUART_GLOBAL_RST_MASK; + base->GLOBAL &= ~LPUART_GLOBAL_RST_MASK; +} +/* @} */ +#endif /*FSL_FEATURE_LPUART_HAS_GLOBAL*/ + /*! * @name Initialization and deinitialization * @{ */ /*! -* @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock. -* -* This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function -* to configure the configuration structure and get the default configuration. -* The example below shows how to use this API to configure the LPUART. -* @code -* lpuart_config_t lpuartConfig; -* lpuartConfig.baudRate_Bps = 115200U; -* lpuartConfig.parityMode = kLPUART_ParityDisabled; -* lpuartConfig.stopBitCount = kLPUART_OneStopBit; -* lpuartConfig.txFifoWatermark = 0; -* lpuartConfig.rxFifoWatermark = 1; -* LPUART_Init(LPUART1, &lpuartConfig, 20000000U); -* @endcode -* -* @param base LPUART peripheral base address. -* @param config Pointer to a user-defined configuration structure. -* @param srcClock_Hz LPUART clock source frequency in HZ. -*/ -void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz); + * @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock. + * + * This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function + * to configure the configuration structure and get the default configuration. + * The example below shows how to use this API to configure the LPUART. + * @code + * lpuart_config_t lpuartConfig; + * lpuartConfig.baudRate_Bps = 115200U; + * lpuartConfig.parityMode = kLPUART_ParityDisabled; + * lpuartConfig.dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig.isMsb = false; + * lpuartConfig.stopBitCount = kLPUART_OneStopBit; + * lpuartConfig.txFifoWatermark = 0; + * lpuartConfig.rxFifoWatermark = 1; + * LPUART_Init(LPUART1, &lpuartConfig, 20000000U); + * @endcode + * + * @param base LPUART peripheral base address. + * @param config Pointer to a user-defined configuration structure. + * @param srcClock_Hz LPUART clock source frequency in HZ. + * @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not support in current clock source. + * @retval kStatus_Success LPUART initialize succeed + */ +status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz); /*! * @brief Deinitializes a LPUART instance. @@ -260,6 +301,8 @@ void LPUART_Deinit(LPUART_Type *base); * values are: * lpuartConfig->baudRate_Bps = 115200U; * lpuartConfig->parityMode = kLPUART_ParityDisabled; + * lpuartConfig->dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig->isMsb = false; * lpuartConfig->stopBitCount = kLPUART_OneStopBit; * lpuartConfig->txFifoWatermark = 0; * lpuartConfig->rxFifoWatermark = 1; @@ -282,8 +325,10 @@ void LPUART_GetDefaultConfig(lpuart_config_t *config); * @param base LPUART peripheral base address. * @param baudRate_Bps LPUART baudrate to be set. * @param srcClock_Hz LPUART clock source frequency in HZ. + * @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not supported in the current clock source. + * @retval kStatus_Success Set baudrate succeeded. */ -void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); +status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); /* @} */ @@ -512,24 +557,40 @@ static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data) } /*! - * @brief Reads the RX register. + * @brief Reads the receiver register. * - * This function reads data from the TX register directly. The upper layer must - * ensure that the RX register is full or that the TX FIFO has data before calling this function. + * This function reads data from the receiver register directly. The upper layer must + * ensure that the receiver register is full or that the RX FIFO has data before calling this function. * * @param base LPUART peripheral base address. * @return Data read from data register. */ static inline uint8_t LPUART_ReadByte(LPUART_Type *base) { +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); + + if (isSevenDataBits) + { + return (base->DATA & 0x7F); + } + else + { + return base->DATA; + } +#else return base->DATA; +#endif } /*! - * @brief Writes to transmitter register using a blocking method. + * @brief Writes to the transmitter register using a blocking method. * * This function polls the transmitter register, waits for the register to be empty or for TX FIFO to have - * room and then writes data to the transmitter buffer. + * room, and writes data to the transmitter buffer. * * @note This function does not check whether all data has been sent out to the bus. * Before disabling the transmitter, check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is @@ -542,10 +603,10 @@ static inline uint8_t LPUART_ReadByte(LPUART_Type *base) void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length); /*! -* @brief Reads the RX data register using a blocking method. +* @brief Reads the receiver data register using a blocking method. * - * This function polls the RX register, waits for the RX register full or RX FIFO - * has data then reads data from the TX register. + * This function polls the receiver register, waits for the receiver register full or receiver FIFO + * has data, and reads data from the TX register. * * @param base LPUART peripheral base address. * @param data Start address of the buffer to store the received data. @@ -601,7 +662,7 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. - * @param xfer LPUART transfer structure, refer to #lpuart_transfer_t. + * @param xfer LPUART transfer structure, see #lpuart_transfer_t. * @retval kStatus_Success Successfully start the data transmission. * @retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register. * @retval kStatus_InvalidArgument Invalid argument. @@ -631,7 +692,7 @@ void LPUART_TransferStartRingBuffer(LPUART_Type *base, size_t ringBufferSize); /*! - * @brief Abort the background transfer and uninstall the ring buffer. + * @brief Aborts the background transfer and uninstalls the ring buffer. * * This function aborts the background transfer and uninstalls the ring buffer. * @@ -644,7 +705,7 @@ void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle); * @brief Aborts the interrupt-driven data transmit. * * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out - * how many bytes are still not sent out. + * how many bytes are not sent out. * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. @@ -652,10 +713,10 @@ void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle); void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to LPUART TX register. + * @brief Gets the number of bytes that have been written to the LPUART transmitter register. * * This function gets the number of bytes that have been written to LPUART TX - * register by interrupt method. + * register by an interrupt method. * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. @@ -686,7 +747,7 @@ status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. - * @param xfer LPUART transfer structure, refer to #uart_transfer_t. + * @param xfer LPUART transfer structure, see #uart_transfer_t. * @param receivedBytes Bytes received from the ring buffer directly. * @retval kStatus_Success Successfully queue the transfer into the transmit queue. * @retval kStatus_LPUART_RxBusy Previous receive request is not finished. @@ -709,7 +770,7 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of bytes that have been received. * * This function gets the number of bytes that have been received. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c index b4242f62625..24da4831477 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -98,6 +98,8 @@ extern uint32_t LPUART_GetInstance(LPUART_Type *base); static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param; /* Avoid the warning for unused variables. */ @@ -118,6 +120,8 @@ static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool tra static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param; /* Avoid warning for unused parameters. */ @@ -138,11 +142,11 @@ static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool } void LPUART_TransferCreateHandleEDMA(LPUART_Type *base, - lpuart_edma_handle_t *handle, - lpuart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle) + lpuart_edma_handle_t *handle, + lpuart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle) { assert(handle); @@ -189,19 +193,18 @@ void LPUART_TransferCreateHandleEDMA(LPUART_Type *base, EDMA_SetCallback(handle->rxEdmaHandle, LPUART_ReceiveEDMACallback, &s_edmaPrivateHandle[instance]); } } + status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer) { + assert(handle); assert(handle->txEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous TX not finished. */ if (kLPUART_TxBusy == handle->txState) { @@ -216,6 +219,9 @@ status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the LPUART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -231,17 +237,15 @@ status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer) { + assert(handle); assert(handle->rxEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous RX not finished. */ if (kLPUART_RxBusy == handle->rxState) { @@ -256,6 +260,9 @@ status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpu EDMA_PrepareTransfer(&xferConfig, (void *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the LPUART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -271,6 +278,7 @@ status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpu void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle) { + assert(handle); assert(handle->txEdmaHandle); /* Disable LPUART TX EDMA. */ @@ -284,6 +292,7 @@ void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handl void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle) { + assert(handle); assert(handle->rxEdmaHandle); /* Disable LPUART RX EDMA. */ @@ -297,38 +306,36 @@ void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *ha status_t LPUART_TransferGetReceiveCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->rxEdmaHandle); + assert(count); if (kLPUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->rxDataSizeAll - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->txEdmaHandle); + assert(count); if (kLPUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->txDataSizeAll - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h index 35e922e1251..79565c688d6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,8 +39,6 @@ * @{ */ -/*! @file*/ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -67,6 +65,8 @@ struct _lpuart_edma_handle edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -94,11 +94,11 @@ extern "C" { * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. */ void LPUART_TransferCreateHandleEDMA(LPUART_Type *base, - lpuart_edma_handle_t *handle, - lpuart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle); + lpuart_edma_handle_t *handle, + lpuart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle); /*! * @brief Sends data using eDMA. @@ -123,7 +123,7 @@ status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart * * @param base LPUART peripheral base address. * @param handle Pointer to lpuart_edma_handle_t structure. - * @param xfer LPUART eDMA transfer structure, refer to #lpuart_transfer_t. + * @param xfer LPUART eDMA transfer structure, see #lpuart_transfer_t. * @retval kStatus_Success if succeed, others fail. * @retval kStatus_LPUART_RxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. @@ -151,9 +151,9 @@ void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handl void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to LPUART TX register. + * @brief Gets the number of bytes written to the LPUART TX register. * - * This function gets the number of bytes that have been written to LPUART TX + * This function gets the number of bytes written to the LPUART TX * register by DMA. * * @param base LPUART peripheral base address. @@ -166,9 +166,9 @@ void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *ha status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of received bytes. * - * This function gets the number of bytes that have been received. + * This function gets the number of received bytes. * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.c deleted file mode 100644 index 926eff9641f..00000000000 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fsl_mpu.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/* Defines the register numbers of the region descriptor configure. */ -#define MPU_REGIONDESCRIPTOR_WROD_REGNUM (4U) - -/******************************************************************************* - * Variables - ******************************************************************************/ - -const clock_ip_name_t g_mpuClock[FSL_FEATURE_SOC_MPU_COUNT] = MPU_CLOCKS; - -/******************************************************************************* - * Codes - ******************************************************************************/ - -void MPU_Init(MPU_Type *base, const mpu_config_t *config) -{ - assert(config); - uint8_t count; - - /* Un-gate MPU clock */ - CLOCK_EnableClock(g_mpuClock[0]); - - /* Initializes the regions. */ - for (count = 1; count < FSL_FEATURE_MPU_DESCRIPTOR_COUNT; count++) - { - base->WORD[count][3] = 0; /* VLD/VID+PID. */ - base->WORD[count][0] = 0; /* Start address. */ - base->WORD[count][1] = 0; /* End address. */ - base->WORD[count][2] = 0; /* Access rights. */ - base->RGDAAC[count] = 0; /* Alternate access rights. */ - } - - /* MPU configure. */ - while (config) - { - MPU_SetRegionConfig(base, &(config->regionConfig)); - config = config->next; - } - /* Enable MPU. */ - MPU_Enable(base, true); -} - -void MPU_Deinit(MPU_Type *base) -{ - /* Disable MPU. */ - MPU_Enable(base, false); - - /* Gate the clock. */ - CLOCK_DisableClock(g_mpuClock[0]); -} - -void MPU_GetHardwareInfo(MPU_Type *base, mpu_hardware_info_t *hardwareInform) -{ - assert(hardwareInform); - - uint32_t cesReg = base->CESR; - - hardwareInform->hardwareRevisionLevel = (cesReg & MPU_CESR_HRL_MASK) >> MPU_CESR_HRL_SHIFT; - hardwareInform->slavePortsNumbers = (cesReg & MPU_CESR_NSP_MASK) >> MPU_CESR_NSP_SHIFT; - hardwareInform->regionsNumbers = (mpu_region_total_num_t)((cesReg & MPU_CESR_NRGD_MASK) >> MPU_CESR_NRGD_SHIFT); -} - -void MPU_SetRegionConfig(MPU_Type *base, const mpu_region_config_t *regionConfig) -{ - assert(regionConfig); - - uint32_t wordReg = 0; - uint8_t count; - uint8_t number = regionConfig->regionNum; - - /* The start and end address of the region descriptor. */ - base->WORD[number][0] = regionConfig->startAddress; - base->WORD[number][1] = regionConfig->endAddress; - - /* The region descriptor access rights control. */ - for (count = 0; count < MPU_REGIONDESCRIPTOR_WROD_REGNUM; count++) - { - wordReg |= MPU_WORD_LOW_MASTER(count, (((uint32_t)regionConfig->accessRights1[count].superAccessRights << 3U) | - (uint8_t)regionConfig->accessRights1[count].userAccessRights)) | - MPU_WORD_HIGH_MASTER(count, ((uint32_t)regionConfig->accessRights2[count].readEnable << 1U | - (uint8_t)regionConfig->accessRights2[count].writeEnable)); - -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - wordReg |= MPU_WORD_MASTER_PE(count, regionConfig->accessRights1[count].processIdentifierEnable); -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ - } - - /* Set region descriptor access rights. */ - base->WORD[number][2] = wordReg; - - wordReg = MPU_WORD_VLD(1); -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - wordReg |= MPU_WORD_PID(regionConfig->processIdentifier) | MPU_WORD_PIDMASK(regionConfig->processIdMask); -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ - - base->WORD[number][3] = wordReg; -} - -void MPU_SetRegionAddr(MPU_Type *base, mpu_region_num_t regionNum, uint32_t startAddr, uint32_t endAddr) -{ - base->WORD[regionNum][0] = startAddr; - base->WORD[regionNum][1] = endAddr; -} - -void MPU_SetRegionLowMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_low_masters_access_rights_t *accessRights) -{ - assert(accessRights); -#if FSL_FEATURE_MPU_HAS_MASTER4 - assert(masterNum < kMPU_Master4); -#endif - uint32_t mask = MPU_WORD_LOW_MASTER_MASK(masterNum); - uint32_t right = base->RGDAAC[regionNum]; - -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - mask |= MPU_LOW_MASTER_PE_MASK(masterNum); -#endif - - /* Build rights control value. */ - right &= ~mask; - right |= MPU_WORD_LOW_MASTER(masterNum, - ((uint32_t)(accessRights->superAccessRights << 3U) | accessRights->userAccessRights)); -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - right |= MPU_WORD_MASTER_PE(masterNum, accessRights->processIdentifierEnable); -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ - - /* Set low master region access rights. */ - base->RGDAAC[regionNum] = right; -} - -void MPU_SetRegionHighMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_high_masters_access_rights_t *accessRights) -{ - assert(accessRights); -#if FSL_FEATURE_MPU_HAS_MASTER3 - assert(masterNum > kMPU_Master3); -#endif - uint32_t mask = MPU_WORD_HIGH_MASTER_MASK(masterNum); - uint32_t right = base->RGDAAC[regionNum]; - - /* Build rights control value. */ - right &= ~mask; - right |= MPU_WORD_HIGH_MASTER((masterNum - (uint8_t)kMPU_RegionNum04), - (((uint32_t)accessRights->readEnable << 1U) | accessRights->writeEnable)); - /* Set low master region access rights. */ - base->RGDAAC[regionNum] = right; -} - -bool MPU_GetSlavePortErrorStatus(MPU_Type *base, mpu_slave_t slaveNum) -{ - uint8_t sperr; - - sperr = ((base->CESR & MPU_CESR_SPERR_MASK) >> MPU_CESR_SPERR_SHIFT) & (0x1U << slaveNum); - - return (sperr != 0) ? true : false; -} - -void MPU_GetDetailErrorAccessInfo(MPU_Type *base, mpu_slave_t slaveNum, mpu_access_err_info_t *errInform) -{ - assert(errInform); - - uint16_t value; - - /* Error address. */ - errInform->address = base->SP[slaveNum].EAR; - - /* Error detail information. */ - value = (base->SP[slaveNum].EDR & MPU_EDR_EACD_MASK) >> MPU_EDR_EACD_SHIFT; - if (!value) - { - errInform->accessControl = kMPU_NoRegionHit; - } - else if (!(value & (uint16_t)(value - 1))) - { - errInform->accessControl = kMPU_NoneOverlappRegion; - } - else - { - errInform->accessControl = kMPU_OverlappRegion; - } - - value = base->SP[slaveNum].EDR; - errInform->master = (mpu_master_t)((value & MPU_EDR_EMN_MASK) >> MPU_EDR_EMN_SHIFT); - errInform->attributes = (mpu_err_attributes_t)((value & MPU_EDR_EATTR_MASK) >> MPU_EDR_EATTR_SHIFT); - errInform->accessType = (mpu_err_access_type_t)((value & MPU_EDR_ERW_MASK) >> MPU_EDR_ERW_SHIFT); -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - errInform->processorIdentification = (uint8_t)((value & MPU_EDR_EPID_MASK) >> MPU_EDR_EPID_SHIFT); -#endif - - /*!< Clears error slave port bit. */ - value = (base->CESR & ~MPU_CESR_SPERR_MASK) | (0x1U << slaveNum); - base->CESR = value; -} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.h deleted file mode 100644 index acdcfd1be38..00000000000 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.h +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _FSL_MPU_H_ -#define _FSL_MPU_H_ - -#include "fsl_common.h" - -/*! - * @addtogroup mpu - * @{ - */ - -/*! @file */ - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/*! @name Driver version */ -/*@{*/ -/*! @brief MPU driver version 2.0.0. */ -#define FSL_MPU_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) -/*@}*/ - -/*! @brief MPU low master bit shift. */ -#define MPU_WORD_LOW_MASTER_SHIFT(n) (n * 6) - -/*! @brief MPU low master bit mask. */ -#define MPU_WORD_LOW_MASTER_MASK(n) (0x1Fu << MPU_WORD_LOW_MASTER_SHIFT(n)) - -/*! @brief MPU low master bit width. */ -#define MPU_WORD_LOW_MASTER_WIDTH 5 - -/*! @brief MPU low master priority setting. */ -#define MPU_WORD_LOW_MASTER(n, x) \ - (((uint32_t)(((uint32_t)(x)) << MPU_WORD_LOW_MASTER_SHIFT(n))) & MPU_WORD_LOW_MASTER_MASK(n)) - -/*! @brief MPU low master process enable bit shift. */ -#define MPU_LOW_MASTER_PE_SHIFT(n) (n * 6 + 5) - -/*! @brief MPU low master process enable bit mask. */ -#define MPU_LOW_MASTER_PE_MASK(n) (0x1u << MPU_LOW_MASTER_PE_SHIFT(n)) - -/*! @brief MPU low master process enable width. */ -#define MPU_WORD_MASTER_PE_WIDTH 1 - -/*! @brief MPU low master process enable setting. */ -#define MPU_WORD_MASTER_PE(n, x) \ - (((uint32_t)(((uint32_t)(x)) << MPU_LOW_MASTER_PE_SHIFT(n))) & MPU_LOW_MASTER_PE_MASK(n)) - -/*! @brief MPU high master bit shift. */ -#define MPU_WORD_HIGH_MASTER_SHIFT(n) (n * 2 + 24) - -/*! @brief MPU high master bit mask. */ -#define MPU_WORD_HIGH_MASTER_MASK(n) (0x03u << MPU_WORD_HIGH_MASTER_SHIFT(n)) - -/*! @brief MPU high master bit width. */ -#define MPU_WORD_HIGH_MASTER_WIDTH 2 - -/*! @brief MPU high master priority setting. */ -#define MPU_WORD_HIGH_MASTER(n, x) \ - (((uint32_t)(((uint32_t)(x)) << MPU_WORD_HIGH_MASTER_SHIFT(n))) & MPU_WORD_HIGH_MASTER_MASK(n)) - -/*! @brief MPU region number. */ -typedef enum _mpu_region_num -{ -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 0U - kMPU_RegionNum00 = 0U, /*!< MPU region number 0. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 1U - kMPU_RegionNum01 = 1U, /*!< MPU region number 1. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 2U - kMPU_RegionNum02 = 2U, /*!< MPU region number 2. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 3U - kMPU_RegionNum03 = 3U, /*!< MPU region number 3. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 4U - kMPU_RegionNum04 = 4U, /*!< MPU region number 4. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 5U - kMPU_RegionNum05 = 5U, /*!< MPU region number 5. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 6U - kMPU_RegionNum06 = 6U, /*!< MPU region number 6. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 7U - kMPU_RegionNum07 = 7U, /*!< MPU region number 7. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 8U - kMPU_RegionNum08 = 8U, /*!< MPU region number 8. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 9U - kMPU_RegionNum09 = 9U, /*!< MPU region number 9. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 10U - kMPU_RegionNum10 = 10U, /*!< MPU region number 10. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 11U - kMPU_RegionNum11 = 11U, /*!< MPU region number 11. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 12U - kMPU_RegionNum12 = 12U, /*!< MPU region number 12. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 13U - kMPU_RegionNum13 = 13U, /*!< MPU region number 13. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 14U - kMPU_RegionNum14 = 14U, /*!< MPU region number 14. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 15U - kMPU_RegionNum15 = 15U, /*!< MPU region number 15. */ -#endif -} mpu_region_num_t; - -/*! @brief MPU master number. */ -typedef enum _mpu_master -{ -#if FSL_FEATURE_MPU_HAS_MASTER0 - kMPU_Master0 = 0U, /*!< MPU master core. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER1 - kMPU_Master1 = 1U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER2 - kMPU_Master2 = 2U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER3 - kMPU_Master3 = 3U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER4 - kMPU_Master4 = 4U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER5 - kMPU_Master5 = 5U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER6 - kMPU_Master6 = 6U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER7 - kMPU_Master7 = 7U /*!< MPU master defined in SoC. */ -#endif -} mpu_master_t; - -/*! @brief Describes the number of MPU regions. */ -typedef enum _mpu_region_total_num -{ - kMPU_8Regions = 0x0U, /*!< MPU supports 8 regions. */ - kMPU_12Regions = 0x1U, /*!< MPU supports 12 regions. */ - kMPU_16Regions = 0x2U /*!< MPU supports 16 regions. */ -} mpu_region_total_num_t; - -/*! @brief MPU slave port number. */ -typedef enum _mpu_slave -{ - kMPU_Slave0 = 4U, /*!< MPU slave port 0. */ - kMPU_Slave1 = 3U, /*!< MPU slave port 1. */ - kMPU_Slave2 = 2U, /*!< MPU slave port 2. */ - kMPU_Slave3 = 1U, /*!< MPU slave port 3. */ - kMPU_Slave4 = 0U /*!< MPU slave port 4. */ -} mpu_slave_t; - -/*! @brief MPU error access control detail. */ -typedef enum _mpu_err_access_control -{ - kMPU_NoRegionHit = 0U, /*!< No region hit error. */ - kMPU_NoneOverlappRegion = 1U, /*!< Access single region error. */ - kMPU_OverlappRegion = 2U /*!< Access overlapping region error. */ -} mpu_err_access_control_t; - -/*! @brief MPU error access type. */ -typedef enum _mpu_err_access_type -{ - kMPU_ErrTypeRead = 0U, /*!< MPU error access type --- read. */ - kMPU_ErrTypeWrite = 1U /*!< MPU error access type --- write. */ -} mpu_err_access_type_t; - -/*! @brief MPU access error attributes.*/ -typedef enum _mpu_err_attributes -{ - kMPU_InstructionAccessInUserMode = 0U, /*!< Access instruction error in user mode. */ - kMPU_DataAccessInUserMode = 1U, /*!< Access data error in user mode. */ - kMPU_InstructionAccessInSupervisorMode = 2U, /*!< Access instruction error in supervisor mode. */ - kMPU_DataAccessInSupervisorMode = 3U /*!< Access data error in supervisor mode. */ -} mpu_err_attributes_t; - -/*! @brief MPU access rights in supervisor mode for master port 0 ~ port 3. */ -typedef enum _mpu_supervisor_access_rights -{ - kMPU_SupervisorReadWriteExecute = 0U, /*!< Read write and execute operations are allowed in supervisor mode. */ - kMPU_SupervisorReadExecute = 1U, /*!< Read and execute operations are allowed in supervisor mode. */ - kMPU_SupervisorReadWrite = 2U, /*!< Read write operations are allowed in supervisor mode. */ - kMPU_SupervisorEqualToUsermode = 3U /*!< Access permission equal to user mode. */ -} mpu_supervisor_access_rights_t; - -/*! @brief MPU access rights in user mode for master port 0 ~ port 3. */ -typedef enum _mpu_user_access_rights -{ - kMPU_UserNoAccessRights = 0U, /*!< No access allowed in user mode. */ - kMPU_UserExecute = 1U, /*!< Execute operation is allowed in user mode. */ - kMPU_UserWrite = 2U, /*!< Write operation is allowed in user mode. */ - kMPU_UserWriteExecute = 3U, /*!< Write and execute operations are allowed in user mode. */ - kMPU_UserRead = 4U, /*!< Read is allowed in user mode. */ - kMPU_UserReadExecute = 5U, /*!< Read and execute operations are allowed in user mode. */ - kMPU_UserReadWrite = 6U, /*!< Read and write operations are allowed in user mode. */ - kMPU_UserReadWriteExecute = 7U /*!< Read write and execute operations are allowed in user mode. */ -} mpu_user_access_rights_t; - -/*! @brief MPU hardware basic information. */ -typedef struct _mpu_hardware_info -{ - uint8_t hardwareRevisionLevel; /*!< Specifies the MPU's hardware and definition reversion level. */ - uint8_t slavePortsNumbers; /*!< Specifies the number of slave ports connected to MPU. */ - mpu_region_total_num_t regionsNumbers; /*!< Indicates the number of region descriptors implemented. */ -} mpu_hardware_info_t; - -/*! @brief MPU detail error access information. */ -typedef struct _mpu_access_err_info -{ - mpu_master_t master; /*!< Access error master. */ - mpu_err_attributes_t attributes; /*!< Access error attributes. */ - mpu_err_access_type_t accessType; /*!< Access error type. */ - mpu_err_access_control_t accessControl; /*!< Access error control. */ - uint32_t address; /*!< Access error address. */ -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - uint8_t processorIdentification; /*!< Access error processor identification. */ -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ -} mpu_access_err_info_t; - -/*! @brief MPU access rights for low master master port 0 ~ port 3. */ -typedef struct _mpu_low_masters_access_rights -{ - mpu_supervisor_access_rights_t superAccessRights; /*!< Master access rights in supervisor mode. */ - mpu_user_access_rights_t userAccessRights; /*!< Master access rights in user mode. */ -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - bool processIdentifierEnable; /*!< Enables or disables process identifier. */ -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ -} mpu_low_masters_access_rights_t; - -/*! @brief MPU access rights mode for high master port 4 ~ port 7. */ -typedef struct _mpu_high_masters_access_rights -{ - bool writeEnable; /*!< Enables or disables write permission. */ - bool readEnable; /*!< Enables or disables read permission. */ -} mpu_high_masters_access_rights_t; - -/*! - * @brief MPU region configuration structure. - * - * This structure is used to configure the regionNum region. - * The accessRights1[0] ~ accessRights1[3] are used to configure the four low master - * numbers: master 0 ~ master 3. The accessRights2[0] ~ accessRights2[3] are - * used to configure the four high master numbers: master 4 ~ master 7. - * The master port assignment is the chip configuration. Normally, the core is the - * master 0, debugger is the master 1. - * Note: MPU assigns a priority scheme where the debugger is treated as the highest - * priority master followed by the core and then all the remaining masters. - * MPU protection does not allow writes from the core to affect the "regionNum 0" start - * and end address nor the permissions associated with the debugger. It can only write - * the permission fields associated with the other masters. This protection guarantee - * the debugger always has access to the entire address space and those rights can't - * be changed by the core or any other bus master. Prepare - * the region configuration when regionNum is kMPU_RegionNum00. - */ -typedef struct _mpu_region_config -{ - mpu_region_num_t regionNum; /*!< MPU region number. */ - uint32_t startAddress; /*!< Memory region start address. Note: bit0 ~ bit4 always be marked as 0 by MPU. The actual - start address is 0-modulo-32 byte address. */ - uint32_t endAddress; /*!< Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by MPU. The actual end - address is 31-modulo-32 byte address. */ - mpu_low_masters_access_rights_t accessRights1[4]; /*!< Low masters access permission. */ - mpu_high_masters_access_rights_t accessRights2[4]; /*!< High masters access permission. */ -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - uint8_t processIdentifier; /*!< Process identifier used when "processIdentifierEnable" set with true. */ - uint8_t - processIdMask; /*!< Process identifier mask. The setting bit will ignore the same bit in process identifier. */ -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ -} mpu_region_config_t; - -/*! - * @brief The configuration structure for the MPU initialization. - * - * This structure is used when calling the MPU_Init function. - */ -typedef struct _mpu_config -{ - mpu_region_config_t regionConfig; /*!< region access permission. */ - struct _mpu_config *next; /*!< pointer to the next structure. */ -} mpu_config_t; - -/******************************************************************************* - * API - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif /* _cplusplus */ - -/*! - * @name Initialization and deinitialization - * @{ - */ - -/*! - * @brief Initializes the MPU with the user configuration structure. - * - * This function configures the MPU module with the user-defined configuration. - * - * @param base MPU peripheral base address. - * @param config The pointer to the configuration structure. - */ -void MPU_Init(MPU_Type *base, const mpu_config_t *config); - -/*! - * @brief Deinitializes the MPU regions. - * - * @param base MPU peripheral base address. - */ -void MPU_Deinit(MPU_Type *base); - -/* @}*/ - -/*! - * @name Basic Control Operations - * @{ - */ - -/*! - * @brief Enables/disables the MPU globally. - * - * Call this API to enable or disable the MPU module. - * - * @param base MPU peripheral base address. - * @param enable True enable MPU, false disable MPU. - */ -static inline void MPU_Enable(MPU_Type *base, bool enable) -{ - if (enable) - { - /* Enable the MPU globally. */ - base->CESR |= MPU_CESR_VLD_MASK; - } - else - { /* Disable the MPU globally. */ - base->CESR &= ~MPU_CESR_VLD_MASK; - } -} - -/*! - * @brief Enables/disables the MPU for a special region. - * - * When MPU is enabled, call this API to disable an unused region - * of an enabled MPU. Call this API to minimize the power dissipation. - * - * @param base MPU peripheral base address. - * @param number MPU region number. - * @param enable True enable the special region MPU, false disable the special region MPU. - */ -static inline void MPU_RegionEnable(MPU_Type *base, mpu_region_num_t number, bool enable) -{ - if (enable) - { - /* Enable the #number region MPU. */ - base->WORD[number][3] |= MPU_WORD_VLD_MASK; - } - else - { /* Disable the #number region MPU. */ - base->WORD[number][3] &= ~MPU_WORD_VLD_MASK; - } -} - -/*! - * @brief Gets the MPU basic hardware information. - * - * @param base MPU peripheral base address. - * @param hardwareInform The pointer to the MPU hardware information structure. See "mpu_hardware_info_t". - */ -void MPU_GetHardwareInfo(MPU_Type *base, mpu_hardware_info_t *hardwareInform); - -/*! - * @brief Sets the MPU region. - * - * Note: Due to the MPU protection, the kMPU_RegionNum00 does not allow writes from the - * core to affect the start and end address nor the permissions associated with - * the debugger. It can only write the permission fields associated - * with the other masters. - * - * @param base MPU peripheral base address. - * @param regionConfig The pointer to the MPU user configuration structure. See "mpu_region_config_t". - */ -void MPU_SetRegionConfig(MPU_Type *base, const mpu_region_config_t *regionConfig); - -/*! - * @brief Sets the region start and end address. - * - * Memory region start address. Note: bit0 ~ bit4 is always marked as 0 by MPU. - * The actual start address by MPU is 0-modulo-32 byte address. - * Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by MPU. - * The actual end address used by MPU is 31-modulo-32 byte address. - * Note: Due to the MPU protection, the startAddr and endAddr can't be - * changed by the core when regionNum is "kMPU_RegionNum00". - * - * @param base MPU peripheral base address. - * @param regionNum MPU region number. - * @param startAddr Region start address. - * @param endAddr Region end address. - */ -void MPU_SetRegionAddr(MPU_Type *base, mpu_region_num_t regionNum, uint32_t startAddr, uint32_t endAddr); - -/*! - * @brief Sets the MPU region access rights for low master port 0 ~ port 3. - * This can be used to change the region access rights for any master port for any region. - * - * @param base MPU peripheral base address. - * @param regionNum MPU region number. - * @param masterNum MPU master number. Should range from kMPU_Master0 ~ kMPU_Master3. - * @param accessRights The pointer to the MPU access rights configuration. See "mpu_low_masters_access_rights_t". - */ -void MPU_SetRegionLowMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_low_masters_access_rights_t *accessRights); - -/*! - * @brief Sets the MPU region access rights for high master port 4 ~ port 7. - * This can be used to change the region access rights for any master port for any region. - * - * @param base MPU peripheral base address. - * @param regionNum MPU region number. - * @param masterNum MPU master number. Should range from kMPU_Master4 ~ kMPU_Master7. - * @param accessRights The pointer to the MPU access rights configuration. See "mpu_high_masters_access_rights_t". - */ -void MPU_SetRegionHighMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_high_masters_access_rights_t *accessRights); - -/*! - * @brief Gets the numbers of slave ports where errors occur. - * - * @param base MPU peripheral base address. - * @param slaveNum MPU slave port number. - * @return The slave ports error status. - * true - error happens in this slave port. - * false - error didn't happen in this slave port. - */ -bool MPU_GetSlavePortErrorStatus(MPU_Type *base, mpu_slave_t slaveNum); - -/*! - * @brief Gets the MPU detailed error access information. - * - * @param base MPU peripheral base address. - * @param slaveNum MPU slave port number. - * @param errInform The pointer to the MPU access error information. See "mpu_access_err_info_t". - */ -void MPU_GetDetailErrorAccessInfo(MPU_Type *base, mpu_slave_t slaveNum, mpu_access_err_info_t *errInform); - -/* @} */ - -#if defined(__cplusplus) -} -#endif - -/*! @}*/ - -#endif /* _FSL_MPU_H_ */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c index b5c9b88ec6c..1fc4a9a486a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t PDB_GetInstance(PDB_Type *base); ******************************************************************************/ /*! @brief Pointers to PDB bases for each instance. */ static PDB_Type *const s_pdbBases[] = PDB_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to PDB clocks for each instance. */ -const clock_ip_name_t s_pdbClocks[] = PDB_CLOCKS; +static const clock_ip_name_t s_pdbClocks[] = PDB_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t PDB_GetInstance(PDB_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_PDB_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_pdbBases); instance++) { if (s_pdbBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t PDB_GetInstance(PDB_Type *base) } } - assert(instance < FSL_FEATURE_SOC_PDB_COUNT); + assert(instance < ARRAY_SIZE(s_pdbBases)); return instance; } @@ -75,8 +77,10 @@ void PDB_Init(PDB_Type *base, const pdb_config_t *config) uint32_t tmp32; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_pdbClocks[PDB_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ /* PDBx_SC. */ @@ -98,8 +102,10 @@ void PDB_Deinit(PDB_Type *base) { PDB_Enable(base, false); /* Disable the PDB module. */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_pdbClocks[PDB_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void PDB_GetDefaultConfig(pdb_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h index 1f05b61b26b..3dec9463462 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -67,32 +66,32 @@ enum _pdb_status_flags enum _pdb_adc_pretrigger_flags { /* PDB PreTrigger channel match flags. */ - kPDB_ADCPreTriggerChannel0Flag = PDB_S_CF(1U << 0), /*!< Pre-Trigger 0 flag. */ - kPDB_ADCPreTriggerChannel1Flag = PDB_S_CF(1U << 1), /*!< Pre-Trigger 1 flag. */ -#if (PDB_DLY_COUNT > 2) - kPDB_ADCPreTriggerChannel2Flag = PDB_S_CF(1U << 2), /*!< Pre-Trigger 2 flag. */ - kPDB_ADCPreTriggerChannel3Flag = PDB_S_CF(1U << 3), /*!< Pre-Trigger 3 flag. */ -#endif /* PDB_DLY_COUNT > 2 */ -#if (PDB_DLY_COUNT > 4) - kPDB_ADCPreTriggerChannel4Flag = PDB_S_CF(1U << 4), /*!< Pre-Trigger 4 flag. */ - kPDB_ADCPreTriggerChannel5Flag = PDB_S_CF(1U << 5), /*!< Pre-Trigger 5 flag. */ - kPDB_ADCPreTriggerChannel6Flag = PDB_S_CF(1U << 6), /*!< Pre-Trigger 6 flag. */ - kPDB_ADCPreTriggerChannel7Flag = PDB_S_CF(1U << 7), /*!< Pre-Trigger 7 flag. */ -#endif /* PDB_DLY_COUNT > 4 */ + kPDB_ADCPreTriggerChannel0Flag = PDB_S_CF(1U << 0), /*!< Pre-trigger 0 flag. */ + kPDB_ADCPreTriggerChannel1Flag = PDB_S_CF(1U << 1), /*!< Pre-trigger 1 flag. */ +#if (PDB_DLY_COUNT2 > 2) + kPDB_ADCPreTriggerChannel2Flag = PDB_S_CF(1U << 2), /*!< Pre-trigger 2 flag. */ + kPDB_ADCPreTriggerChannel3Flag = PDB_S_CF(1U << 3), /*!< Pre-trigger 3 flag. */ +#endif /* PDB_DLY_COUNT2 > 2 */ +#if (PDB_DLY_COUNT2 > 4) + kPDB_ADCPreTriggerChannel4Flag = PDB_S_CF(1U << 4), /*!< Pre-trigger 4 flag. */ + kPDB_ADCPreTriggerChannel5Flag = PDB_S_CF(1U << 5), /*!< Pre-trigger 5 flag. */ + kPDB_ADCPreTriggerChannel6Flag = PDB_S_CF(1U << 6), /*!< Pre-trigger 6 flag. */ + kPDB_ADCPreTriggerChannel7Flag = PDB_S_CF(1U << 7), /*!< Pre-trigger 7 flag. */ +#endif /* PDB_DLY_COUNT2 > 4 */ /* PDB PreTrigger channel error flags. */ - kPDB_ADCPreTriggerChannel0ErrorFlag = PDB_S_ERR(1U << 0), /*!< Pre-Trigger 0 Error. */ - kPDB_ADCPreTriggerChannel1ErrorFlag = PDB_S_ERR(1U << 1), /*!< Pre-Trigger 1 Error. */ -#if (PDB_DLY_COUNT > 2) - kPDB_ADCPreTriggerChannel2ErrorFlag = PDB_S_ERR(1U << 2), /*!< Pre-Trigger 2 Error. */ - kPDB_ADCPreTriggerChannel3ErrorFlag = PDB_S_ERR(1U << 3), /*!< Pre-Trigger 3 Error. */ -#endif /* PDB_DLY_COUNT > 2 */ -#if (PDB_DLY_COUNT > 4) - kPDB_ADCPreTriggerChannel4ErrorFlag = PDB_S_ERR(1U << 4), /*!< Pre-Trigger 4 Error. */ - kPDB_ADCPreTriggerChannel5ErrorFlag = PDB_S_ERR(1U << 5), /*!< Pre-Trigger 5 Error. */ - kPDB_ADCPreTriggerChannel6ErrorFlag = PDB_S_ERR(1U << 6), /*!< Pre-Trigger 6 Error. */ - kPDB_ADCPreTriggerChannel7ErrorFlag = PDB_S_ERR(1U << 7), /*!< Pre-Trigger 7 Error. */ -#endif /* PDB_DLY_COUNT > 4 */ + kPDB_ADCPreTriggerChannel0ErrorFlag = PDB_S_ERR(1U << 0), /*!< Pre-trigger 0 Error. */ + kPDB_ADCPreTriggerChannel1ErrorFlag = PDB_S_ERR(1U << 1), /*!< Pre-trigger 1 Error. */ +#if (PDB_DLY_COUNT2 > 2) + kPDB_ADCPreTriggerChannel2ErrorFlag = PDB_S_ERR(1U << 2), /*!< Pre-trigger 2 Error. */ + kPDB_ADCPreTriggerChannel3ErrorFlag = PDB_S_ERR(1U << 3), /*!< Pre-trigger 3 Error. */ +#endif /* PDB_DLY_COUNT2 > 2 */ +#if (PDB_DLY_COUNT2 > 4) + kPDB_ADCPreTriggerChannel4ErrorFlag = PDB_S_ERR(1U << 4), /*!< Pre-trigger 4 Error. */ + kPDB_ADCPreTriggerChannel5ErrorFlag = PDB_S_ERR(1U << 5), /*!< Pre-trigger 5 Error. */ + kPDB_ADCPreTriggerChannel6ErrorFlag = PDB_S_ERR(1U << 6), /*!< Pre-trigger 6 Error. */ + kPDB_ADCPreTriggerChannel7ErrorFlag = PDB_S_ERR(1U << 7), /*!< Pre-trigger 7 Error. */ +#endif /* PDB_DLY_COUNT2 > 4 */ }; /*! @@ -108,7 +107,7 @@ enum _pdb_interrupt_enable * @brief PDB load value mode. * * Selects the mode to load the internal values after doing the load operation (write 1 to PDBx_SC[LDOK]). - * These values are for: + * These values are for the following operations. * - PDB counter (PDBx_MOD, PDBx_IDLY) * - ADC trigger (PDBx_CHnDLYm) * - DAC trigger (PDBx_DACINTx) @@ -158,7 +157,7 @@ typedef enum _pdb_divider_multiplication_factor * @brief Trigger input source * * Selects the trigger input source for the PDB. The trigger input source can be internal or external (EXTRG pin), or - * the software trigger. Refer to chip configuration details for the actual PDB input trigger connections. + * the software trigger. See chip configuration details for the actual PDB input trigger connections. */ typedef enum _pdb_trigger_input_source { @@ -177,7 +176,7 @@ typedef enum _pdb_trigger_input_source kPDB_TriggerInput12 = 12U, /*!< Trigger-In 12. */ kPDB_TriggerInput13 = 13U, /*!< Trigger-In 13. */ kPDB_TriggerInput14 = 14U, /*!< Trigger-In 14. */ - kPDB_TriggerSoftware = 15U, /*!< Trigger-In 15. */ + kPDB_TriggerSoftware = 15U, /*!< Trigger-In 15, software trigger. */ } pdb_trigger_input_source_t; /*! @@ -193,15 +192,15 @@ typedef struct _pdb_config } pdb_config_t; /*! - * @brief PDB ADC Pre-Trigger configuration. + * @brief PDB ADC Pre-trigger configuration. */ typedef struct _pdb_adc_pretrigger_config { - uint32_t enablePreTriggerMask; /*!< PDB Channel Pre-Trigger Enable. */ - uint32_t enableOutputMask; /*!< PDB Channel Pre-Trigger Output Select. + uint32_t enablePreTriggerMask; /*!< PDB Channel Pre-trigger Enable. */ + uint32_t enableOutputMask; /*!< PDB Channel Pre-trigger Output Select. PDB channel's corresponding pre-trigger asserts when the counter reaches the channel delay register. */ - uint32_t enableBackToBackOperationMask; /*!< PDB Channel Pre-Trigger Back-to-Back Operation Enable. + uint32_t enableBackToBackOperationMask; /*!< PDB Channel pre-trigger Back-to-Back Operation Enable. Back-to-back operation enables the ADC conversions complete to trigger the next PDB channel pre-trigger and trigger output, so that the ADC conversions can be triggered on next set of configuration and results @@ -230,29 +229,29 @@ extern "C" { */ /*! - * @brief Initializes the PDB module. + * @brief Initializes the PDB module. * - * This function is to make the initialization for PDB module. The operations includes are: + * This function initializes the PDB module. The operations included are as follows. * - Enable the clock for PDB instance. * - Configure the PDB module. * - Enable the PDB module. * * @param base PDB peripheral base address. - * @param config Pointer to configuration structure. See "pdb_config_t". + * @param config Pointer to the configuration structure. See "pdb_config_t". */ void PDB_Init(PDB_Type *base, const pdb_config_t *config); /*! - * @brief De-initializes the PDB module. + * @brief De-initializes the PDB module. * * @param base PDB peripheral base address. */ void PDB_Deinit(PDB_Type *base); /*! - * @brief Initializes the PDB user configure structure. + * @brief Initializes the PDB user configuration structure. * - * This function initializes the user configure structure to default value. the default value are: + * This function initializes the user configuration structure to a default value. The default values are as follows. * @code * config->loadValueMode = kPDB_LoadValueImmediately; * config->prescalerDivider = kPDB_PrescalerDivider1; @@ -302,7 +301,7 @@ static inline void PDB_DoSoftwareTrigger(PDB_Type *base) /*! * @brief Loads the counter values. * - * This function is to load the counter values from their internal buffer. + * This function loads the counter values from the internal buffer. * See "pdb_load_value_mode_t" about PDB's load mode. * * @param base PDB peripheral base address. @@ -382,7 +381,7 @@ static inline void PDB_ClearStatusFlags(PDB_Type *base, uint32_t mask) } /*! - * @brief Specifies the period of the counter. + * @brief Specifies the counter period. * * @param base PDB peripheral base address. * @param value Setting value for the modulus. 16-bit is available. @@ -405,7 +404,7 @@ static inline uint32_t PDB_GetCounterValue(PDB_Type *base) } /*! - * @brief Sets the value for PDB counter delay event. + * @brief Sets the value for the PDB counter delay event. * * @param base PDB peripheral base address. * @param value Setting value for PDB counter delay event. 16-bit is available. @@ -417,16 +416,16 @@ static inline void PDB_SetCounterDelayValue(PDB_Type *base, uint32_t value) /* @} */ /*! - * @name ADC Pre-Trigger + * @name ADC Pre-trigger * @{ */ /*! - * @brief Configures the ADC PreTrigger in PDB module. + * @brief Configures the ADC pre-trigger in the PDB module. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. - * @param config Pointer to configuration structure. See "pdb_adc_pretrigger_config_t". + * @param config Pointer to the configuration structure. See "pdb_adc_pretrigger_config_t". */ static inline void PDB_SetADCPreTriggerConfig(PDB_Type *base, uint32_t channel, pdb_adc_pretrigger_config_t *config) { @@ -434,30 +433,31 @@ static inline void PDB_SetADCPreTriggerConfig(PDB_Type *base, uint32_t channel, assert(NULL != config); base->CH[channel].C1 = PDB_C1_BB(config->enableBackToBackOperationMask) | PDB_C1_TOS(config->enableOutputMask) | - PDB_C1_EN(config->enableOutputMask); + PDB_C1_EN(config->enablePreTriggerMask); } /*! - * @brief Sets the value for ADC Pre-Trigger delay event. + * @brief Sets the value for the ADC pre-trigger delay event. * - * This function is to set the value for ADC Pre-Trigger delay event. IT Specifies the delay value for the channel's - * corresponding pre-trigger. The pre-trigger asserts when the PDB counter is equal to the setting value here. + * This function sets the value for ADC pre-trigger delay event. It specifies the delay value for the channel's + * corresponding pre-trigger. The pre-trigger asserts when the PDB counter is equal to the set value. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. * @param preChannel Channel group index for ADC instance. - * @param value Setting value for ADC Pre-Trigger delay event. 16-bit is available. + * @param value Setting value for ADC pre-trigger delay event. 16-bit is available. */ static inline void PDB_SetADCPreTriggerDelayValue(PDB_Type *base, uint32_t channel, uint32_t preChannel, uint32_t value) { assert(channel < PDB_C1_COUNT); - assert(preChannel < PDB_DLY_COUNT); + assert(preChannel < PDB_DLY_COUNT2); + /* xx_COUNT2 is actually the count for pre-triggers in header file. xx_COUNT is used for the count of channels. */ base->CH[channel].DLY[preChannel] = PDB_DLY_DLY(value); } /*! - * @brief Gets the ADC Pre-Trigger's status flags. + * @brief Gets the ADC pre-trigger's status flags. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. @@ -472,7 +472,7 @@ static inline uint32_t PDB_GetADCPreTriggerStatusFlags(PDB_Type *base, uint32_t } /*! - * @brief Clears the ADC Pre-Trigger's status flags. + * @brief Clears the ADC pre-trigger status flags. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. @@ -494,19 +494,19 @@ static inline void PDB_ClearADCPreTriggerStatusFlags(PDB_Type *base, uint32_t ch */ /*! - * @brief Configures the DAC trigger in PDB module. + * @brief Configures the DAC trigger in the PDB module. * * @param base PDB peripheral base address. * @param channel Channel index for DAC instance. - * @param config Pointer to configuration structure. See "pdb_dac_trigger_config_t". + * @param config Pointer to the configuration structure. See "pdb_dac_trigger_config_t". */ void PDB_SetDACTriggerConfig(PDB_Type *base, uint32_t channel, pdb_dac_trigger_config_t *config); /*! * @brief Sets the value for the DAC interval event. * - * This fucntion is to set the value for DAC interval event. DAC interval trigger would trigger the DAC module to update - * buffer when the DAC interval counter is equal to the setting value here. + * This fucntion sets the value for DAC interval event. DAC interval trigger triggers the DAC module to update + * the buffer when the DAC interval counter is equal to the set value. * * @param base PDB peripheral base address. * @param channel Channel index for DAC instance. @@ -532,7 +532,7 @@ static inline void PDB_SetDACTriggerIntervalValue(PDB_Type *base, uint32_t chann * * @param base PDB peripheral base address. * @param channelMask Channel mask value for multiple pulse out trigger channel. - * @param enable Enable the feature or not. + * @param enable Whether the feature is enabled or not. */ static inline void PDB_EnablePulseOutTrigger(PDB_Type *base, uint32_t channelMask, bool enable) { @@ -547,11 +547,11 @@ static inline void PDB_EnablePulseOutTrigger(PDB_Type *base, uint32_t channelMas } /*! - * @brief Sets event values for pulse out trigger. + * @brief Sets event values for the pulse out trigger. * - * This function is used to set event values for pulse output trigger. - * These pulse output trigger delay values specify the delay for the PDB Pulse-Out. Pulse-Out goes high when the PDB - * counter is equal to the pulse output high value (value1). Pulse-Out goes low when the PDB counter is equal to the + * This function is used to set event values for the pulse output trigger. + * These pulse output trigger delay values specify the delay for the PDB Pulse-out. Pulse-out goes high when the PDB + * counter is equal to the pulse output high value (value1). Pulse-out goes low when the PDB counter is equal to the * pulse output low value (value2). * * @param base PDB peripheral base address. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c index 1f2fdfe8b45..e5c3c4e013d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,8 +48,10 @@ static uint32_t PIT_GetInstance(PIT_Type *base); /*! @brief Pointers to PIT bases for each instance. */ static PIT_Type *const s_pitBases[] = PIT_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to PIT clocks for each instance. */ static const clock_ip_name_t s_pitClocks[] = PIT_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -59,7 +61,7 @@ static uint32_t PIT_GetInstance(PIT_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_PIT_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_pitBases); instance++) { if (s_pitBases[instance] == base) { @@ -67,7 +69,7 @@ static uint32_t PIT_GetInstance(PIT_Type *base) } } - assert(instance < FSL_FEATURE_SOC_PIT_COUNT); + assert(instance < ARRAY_SIZE(s_pitBases)); return instance; } @@ -76,8 +78,10 @@ void PIT_Init(PIT_Type *base, const pit_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate the PIT clock*/ CLOCK_EnableClock(s_pitClocks[PIT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Enable PIT timers */ base->MCR &= ~PIT_MCR_MDIS_MASK; @@ -98,8 +102,10 @@ void PIT_Deinit(PIT_Type *base) /* Disable PIT timers */ base->MCR |= PIT_MCR_MDIS_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the PIT clock*/ CLOCK_DisableClock(s_pitClocks[PIT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } #if defined(FSL_FEATURE_PIT_HAS_LIFETIME_TIMER) && FSL_FEATURE_PIT_HAS_LIFETIME_TIMER diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h index 61606e7e8bd..99c30e1e4bc 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup pit_driver + * @addtogroup pit * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -73,13 +72,13 @@ typedef enum _pit_status_flags } pit_status_flags_t; /*! - * @brief PIT config structure + * @brief PIT configuration structure * * This structure holds the configuration settings for the PIT peripheral. To initialize this * structure to reasonable defaults, call the PIT_GetDefaultConfig() function and pass a * pointer to your config structure instance. * - * The config struct can be made const so it resides in flash + * The configuration structure can be made constant so it resides in flash. */ typedef struct _pit_config { @@ -100,30 +99,30 @@ extern "C" { */ /*! - * @brief Ungates the PIT clock, enables the PIT module and configures the peripheral for basic operation. + * @brief Ungates the PIT clock, enables the PIT module, and configures the peripheral for basic operations. * * @note This API should be called at the beginning of the application using the PIT driver. * * @param base PIT peripheral base address - * @param config Pointer to user's PIT config structure + * @param config Pointer to the user's PIT config structure */ void PIT_Init(PIT_Type *base, const pit_config_t *config); /*! - * @brief Gate the PIT clock and disable the PIT module + * @brief Gates the PIT clock and disables the PIT module. * * @param base PIT peripheral base address */ void PIT_Deinit(PIT_Type *base); /*! - * @brief Fill in the PIT config struct with the default settings + * @brief Fills in the PIT configuration structure with the default settings. * - * The default values are: + * The default values are as follows. * @code * config->enableRunInDebug = false; * @endcode - * @param config Pointer to user's PIT config structure. + * @param config Pointer to the onfiguration structure. */ static inline void PIT_GetDefaultConfig(pit_config_t *config) { @@ -140,9 +139,9 @@ static inline void PIT_GetDefaultConfig(pit_config_t *config) * * When a timer has a chain mode enabled, it only counts after the previous * timer has expired. If the timer n-1 has counted down to 0, counter n - * decrements the value by one. Each timer is 32-bits, this allows the developers + * decrements the value by one. Each timer is 32-bits, which allows the developers * to chain timers together and form a longer timer (64-bits and larger). The first timer - * (timer 0) cannot be chained to any other timer. + * (timer 0) can't be chained to any other timer. * * @param base PIT peripheral base address * @param channel Timer channel number which is chained with the previous timer @@ -219,7 +218,7 @@ static inline uint32_t PIT_GetEnabledInterrupts(PIT_Type *base, pit_chnl_t chann */ /*! - * @brief Gets the PIT status flags + * @brief Gets the PIT status flags. * * @param base PIT peripheral base address * @param channel Timer channel number @@ -256,11 +255,11 @@ static inline void PIT_ClearStatusFlags(PIT_Type *base, pit_chnl_t channel, uint * @brief Sets the timer period in units of count. * * Timers begin counting from the value set by this function until it reaches 0, - * then it will generate an interrupt and load this regiter value again. - * Writing a new value to this register will not restart the timer; instead the value - * will be loaded after the timer expires. + * then it generates an interrupt and load this register value again. + * Writing a new value to this register does not restart the timer. Instead, the value + * is loaded after the timer expires. * - * @note User can call the utility macros provided in fsl_common.h to convert to ticks + * @note Users can call the utility macros provided in fsl_common.h to convert to ticks. * * @param base PIT peripheral base address * @param channel Timer channel number @@ -277,7 +276,7 @@ static inline void PIT_SetTimerPeriod(PIT_Type *base, pit_chnl_t channel, uint32 * This function returns the real-time timer counting value, in a range from 0 to a * timer period. * - * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec + * @note Users can call the utility macros provided in fsl_common.h to convert ticks to usec or msec. * * @param base PIT peripheral base address * @param channel Timer channel number diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c index 82d7b7ace13..bcdd5cb8231 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h index c60c19c01e9..99fc149fc22 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,7 +35,6 @@ /*! @addtogroup pmc */ /*! @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -49,36 +48,36 @@ #if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV) /*! - * @brief Low-Voltage Detect Voltage Select + * @brief Low-voltage Detect Voltage Select */ typedef enum _pmc_low_volt_detect_volt_select { - kPMC_LowVoltDetectLowTrip = 0U, /*!< Low trip point selected (VLVD = VLVDL )*/ - kPMC_LowVoltDetectHighTrip = 1U /*!< High trip point selected (VLVD = VLVDH )*/ + kPMC_LowVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VLVD = VLVDL )*/ + kPMC_LowVoltDetectHighTrip = 1U /*!< High-trip point selected (VLVD = VLVDH )*/ } pmc_low_volt_detect_volt_select_t; #endif #if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV) /*! - * @brief Low-Voltage Warning Voltage Select + * @brief Low-voltage Warning Voltage Select */ typedef enum _pmc_low_volt_warning_volt_select { - kPMC_LowVoltWarningLowTrip = 0U, /*!< Low trip point selected (VLVW = VLVW1)*/ + kPMC_LowVoltWarningLowTrip = 0U, /*!< Low-trip point selected (VLVW = VLVW1)*/ kPMC_LowVoltWarningMid1Trip = 1U, /*!< Mid 1 trip point selected (VLVW = VLVW2)*/ kPMC_LowVoltWarningMid2Trip = 2U, /*!< Mid 2 trip point selected (VLVW = VLVW3)*/ - kPMC_LowVoltWarningHighTrip = 3U /*!< High trip point selected (VLVW = VLVW4)*/ + kPMC_LowVoltWarningHighTrip = 3U /*!< High-trip point selected (VLVW = VLVW4)*/ } pmc_low_volt_warning_volt_select_t; #endif #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief High-Voltage Detect Voltage Select + * @brief High-voltage Detect Voltage Select */ typedef enum _pmc_high_volt_detect_volt_select { - kPMC_HighVoltDetectLowTrip = 0U, /*!< Low trip point selected (VHVD = VHVDL )*/ - kPMC_HighVoltDetectHighTrip = 1U /*!< High trip point selected (VHVD = VHVDH )*/ + kPMC_HighVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VHVD = VHVDL )*/ + kPMC_HighVoltDetectHighTrip = 1U /*!< High-trip point selected (VHVD = VHVDH )*/ } pmc_high_volt_detect_volt_select_t; #endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */ @@ -88,8 +87,8 @@ typedef enum _pmc_high_volt_detect_volt_select */ typedef enum _pmc_bandgap_buffer_drive_select { - kPMC_BandgapBufferDriveLow = 0U, /*!< Low drive. */ - kPMC_BandgapBufferDriveHigh = 1U /*!< High drive. */ + kPMC_BandgapBufferDriveLow = 0U, /*!< Low-drive. */ + kPMC_BandgapBufferDriveHigh = 1U /*!< High-drive. */ } pmc_bandgap_buffer_drive_select_t; #endif /* FSL_FEATURE_PMC_HAS_BGBDS */ @@ -126,37 +125,37 @@ typedef struct _pmc_param #endif /* FSL_FEATURE_PMC_HAS_PARAM */ /*! - * @brief Low-Voltage Detect Configuration Structure + * @brief Low-voltage Detect Configuration Structure */ typedef struct _pmc_low_volt_detect_config { - bool enableInt; /*!< Enable interrupt when low voltage detect*/ - bool enableReset; /*!< Enable system reset when low voltage detect*/ + bool enableInt; /*!< Enable interrupt when Low-voltage detect*/ + bool enableReset; /*!< Enable system reset when Low-voltage detect*/ #if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV) - pmc_low_volt_detect_volt_select_t voltSelect; /*!< Low voltage detect trip point voltage selection*/ + pmc_low_volt_detect_volt_select_t voltSelect; /*!< Low-voltage detect trip point voltage selection*/ #endif } pmc_low_volt_detect_config_t; /*! - * @brief Low-Voltage Warning Configuration Structure + * @brief Low-voltage Warning Configuration Structure */ typedef struct _pmc_low_volt_warning_config { - bool enableInt; /*!< Enable interrupt when low voltage warning*/ + bool enableInt; /*!< Enable interrupt when low-voltage warning*/ #if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV) - pmc_low_volt_warning_volt_select_t voltSelect; /*!< Low voltage warning trip point voltage selection*/ + pmc_low_volt_warning_volt_select_t voltSelect; /*!< Low-voltage warning trip point voltage selection*/ #endif } pmc_low_volt_warning_config_t; #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief High-Voltage Detect Configuration Structure + * @brief High-voltage Detect Configuration Structure */ typedef struct _pmc_high_volt_detect_config { - bool enableInt; /*!< Enable interrupt when high voltage detect*/ - bool enableReset; /*!< Enable system reset when high voltage detect*/ - pmc_high_volt_detect_volt_select_t voltSelect; /*!< High voltage detect trip point voltage selection*/ + bool enableInt; /*!< Enable interrupt when high-voltage detect*/ + bool enableReset; /*!< Enable system reset when high-voltage detect*/ + pmc_high_volt_detect_volt_select_t voltSelect; /*!< High-voltage detect trip point voltage selection*/ } pmc_high_volt_detect_config_t; #endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */ @@ -172,7 +171,7 @@ typedef struct _pmc_bandgap_buffer_config bool enable; /*!< Enable bandgap buffer. */ #endif #if (defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) - bool enableInLowPowerMode; /*!< Enable bandgap buffer in low power mode. */ + bool enableInLowPowerMode; /*!< Enable bandgap buffer in low-power mode. */ #endif /* FSL_FEATURE_PMC_HAS_BGEN */ #if (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS) pmc_bandgap_buffer_drive_select_t drive; /*!< Bandgap buffer drive select. */ @@ -196,7 +195,7 @@ extern "C" { * @brief Gets the PMC version ID. * * This function gets the PMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and a feature specification number. * * @param base PMC peripheral base address. * @param versionId Pointer to version ID structure. @@ -211,7 +210,7 @@ static inline void PMC_GetVersionId(PMC_Type *base, pmc_version_id_t *versionId) /*! * @brief Gets the PMC parameter. * - * This function gets the PMC parameter, including VLPO enable and HVD enable. + * This function gets the PMC parameter including the VLPO enable and the HVD enable. * * @param base PMC peripheral base address. * @param param Pointer to PMC param structure. @@ -220,26 +219,25 @@ void PMC_GetParam(PMC_Type *base, pmc_param_t *param); #endif /*! - * @brief Configure the low voltage detect setting. + * @brief Configures the low-voltage detect setting. * - * This function configures the low voltage detect setting, including the trip - * point voltage setting, enable interrupt or not, enable system reset or not. + * This function configures the low-voltage detect setting, including the trip + * point voltage setting, enables or disables the interrupt, enables or disables the system reset. * * @param base PMC peripheral base address. - * @param config Low-Voltage detect configuration structure. + * @param config Low-voltage detect configuration structure. */ void PMC_ConfigureLowVoltDetect(PMC_Type *base, const pmc_low_volt_detect_config_t *config); /*! - * @brief Get Low-Voltage Detect Flag status + * @brief Gets the Low-voltage Detect Flag status. * - * This function reads the current LVDF status. If it returns 1, a low - * voltage event is detected. + * This function reads the current LVDF status. If it returns 1, a low-voltage event is detected. * * @param base PMC peripheral base address. - * @return Current low voltage detect flag - * - true: Low-Voltage detected - * - false: Low-Voltage not detected + * @return Current low-voltage detect flag + * - true: Low-voltage detected + * - false: Low-voltage not detected */ static inline bool PMC_GetLowVoltDetectFlag(PMC_Type *base) { @@ -247,9 +245,9 @@ static inline bool PMC_GetLowVoltDetectFlag(PMC_Type *base) } /*! - * @brief Acknowledge to clear the Low-Voltage Detect flag + * @brief Acknowledges clearing the Low-voltage Detect flag. * - * This function acknowledges the low voltage detection errors (write 1 to + * This function acknowledges the low-voltage detection errors (write 1 to * clear LVDF). * * @param base PMC peripheral base address. @@ -260,18 +258,18 @@ static inline void PMC_ClearLowVoltDetectFlag(PMC_Type *base) } /*! - * @brief Configure the low voltage warning setting. + * @brief Configures the low-voltage warning setting. * - * This function configures the low voltage warning setting, including the trip - * point voltage setting and enable interrupt or not. + * This function configures the low-voltage warning setting, including the trip + * point voltage setting and enabling or disabling the interrupt. * * @param base PMC peripheral base address. - * @param config Low-Voltage warning configuration structure. + * @param config Low-voltage warning configuration structure. */ void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_config_t *config); /*! - * @brief Get Low-Voltage Warning Flag status + * @brief Gets the Low-voltage Warning Flag status. * * This function polls the current LVWF status. When 1 is returned, it * indicates a low-voltage warning event. LVWF is set when V Supply transitions @@ -279,8 +277,8 @@ void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_conf * * @param base PMC peripheral base address. * @return Current LVWF status - * - true: Low-Voltage Warning Flag is set. - * - false: the Low-Voltage Warning does not happen. + * - true: Low-voltage Warning Flag is set. + * - false: the Low-voltage Warning does not happen. */ static inline bool PMC_GetLowVoltWarningFlag(PMC_Type *base) { @@ -288,7 +286,7 @@ static inline bool PMC_GetLowVoltWarningFlag(PMC_Type *base) } /*! - * @brief Acknowledge to Low-Voltage Warning flag + * @brief Acknowledges the Low-voltage Warning flag. * * This function acknowledges the low voltage warning errors (write 1 to * clear LVWF). @@ -302,26 +300,26 @@ static inline void PMC_ClearLowVoltWarningFlag(PMC_Type *base) #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief Configure the high voltage detect setting. + * @brief Configures the high-voltage detect setting. * - * This function configures the high voltage detect setting, including the trip - * point voltage setting, enable interrupt or not, enable system reset or not. + * This function configures the high-voltage detect setting, including the trip + * point voltage setting, enabling or disabling the interrupt, enabling or disabling the system reset. * * @param base PMC peripheral base address. - * @param config High-Voltage detect configuration structure. + * @param config High-voltage detect configuration structure. */ void PMC_ConfigureHighVoltDetect(PMC_Type *base, const pmc_high_volt_detect_config_t *config); /*! - * @brief Get High-Voltage Detect Flag status + * @brief Gets the High-voltage Detect Flag status. * * This function reads the current HVDF status. If it returns 1, a low * voltage event is detected. * * @param base PMC peripheral base address. - * @return Current high voltage detect flag - * - true: High-Voltage detected - * - false: High-Voltage not detected + * @return Current high-voltage detect flag + * - true: High-voltage detected + * - false: High-voltage not detected */ static inline bool PMC_GetHighVoltDetectFlag(PMC_Type *base) { @@ -329,9 +327,9 @@ static inline bool PMC_GetHighVoltDetectFlag(PMC_Type *base) } /*! - * @brief Acknowledge to clear the High-Voltage Detect flag + * @brief Acknowledges clearing the High-voltage Detect flag. * - * This function acknowledges the high voltage detection errors (write 1 to + * This function acknowledges the high-voltage detection errors (write 1 to * clear HVDF). * * @param base PMC peripheral base address. @@ -346,10 +344,10 @@ static inline void PMC_ClearHighVoltDetectFlag(PMC_Type *base) (defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) || \ (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS)) /*! - * @brief Configure the PMC bandgap + * @brief Configures the PMC bandgap. * * This function configures the PMC bandgap, including the drive select and - * behavior in low power mode. + * behavior in low-power mode. * * @param base PMC peripheral base address. * @param config Pointer to the configuration structure @@ -378,7 +376,7 @@ static inline bool PMC_GetPeriphIOIsolationFlag(PMC_Type *base) } /*! - * @brief Acknowledge to Peripherals and I/O pads isolation flag. + * @brief Acknowledges the isolation flag to Peripherals and I/O pads. * * This function clears the ACK Isolation flag. Writing one to this setting * when it is set releases the I/O pads and certain peripherals to their normal @@ -394,9 +392,9 @@ static inline void PMC_ClearPeriphIOIsolationFlag(PMC_Type *base) #if (defined(FSL_FEATURE_PMC_HAS_REGONS) && FSL_FEATURE_PMC_HAS_REGONS) /*! - * @brief Gets the Regulator regulation status. + * @brief Gets the regulator regulation status. * - * This function returns the regulator to a run regulation status. It provides + * This function returns the regulator to run a regulation status. It provides * the current status of the internal voltage regulator. * * @param base PMC peripheral base address. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h index 790518ccd3c..eb8e77e6ddd 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -33,59 +33,65 @@ #include "fsl_common.h" /*! - * @addtogroup port_driver + * @addtogroup port * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! Version 2.0.1. */ -#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! Version 2.0.2. */ +#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ +#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE /*! @brief Internal resistor pull feature selection */ enum _port_pull { - kPORT_PullDisable = 0U, /*!< internal pull-up/down resistor is disabled. */ - kPORT_PullDown = 2U, /*!< internal pull-down resistor is enabled. */ - kPORT_PullUp = 3U, /*!< internal pull-up resistor is enabled. */ + kPORT_PullDisable = 0U, /*!< Internal pull-up/down resistor is disabled. */ + kPORT_PullDown = 2U, /*!< Internal pull-down resistor is enabled. */ + kPORT_PullUp = 3U, /*!< Internal pull-up resistor is enabled. */ }; +#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */ +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE /*! @brief Slew rate selection */ enum _port_slew_rate { - kPORT_FastSlewRate = 0U, /*!< fast slew rate is configured. */ - kPORT_SlowSlewRate = 1U, /*!< slow slew rate is configured. */ + kPORT_FastSlewRate = 0U, /*!< Fast slew rate is configured. */ + kPORT_SlowSlewRate = 1U, /*!< Slow slew rate is configured. */ }; +#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */ #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN -/*! @brief Internal resistor pull feature enable/disable */ +/*! @brief Open Drain feature enable/disable */ enum _port_open_drain_enable { - kPORT_OpenDrainDisable = 0U, /*!< internal pull-down resistor is disabled. */ - kPORT_OpenDrainEnable = 1U, /*!< internal pull-up resistor is enabled. */ + kPORT_OpenDrainDisable = 0U, /*!< Open drain output is disabled. */ + kPORT_OpenDrainEnable = 1U, /*!< Open drain output is enabled. */ }; #endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER /*! @brief Passive filter feature enable/disable */ enum _port_passive_filter_enable { - kPORT_PassiveFilterDisable = 0U, /*!< fast slew rate is configured. */ - kPORT_PassiveFilterEnable = 1U, /*!< slow slew rate is configured. */ + kPORT_PassiveFilterDisable = 0U, /*!< Passive input filter is disabled. */ + kPORT_PassiveFilterEnable = 1U, /*!< Passive input filter is enabled. */ }; +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH /*! @brief Configures the drive strength. */ enum _port_drive_strength { - kPORT_LowDriveStrength = 0U, /*!< low drive strength is configured. */ - kPORT_HighDriveStrength = 1U, /*!< high drive strength is configured. */ + kPORT_LowDriveStrength = 0U, /*!< Low-drive strength is configured. */ + kPORT_HighDriveStrength = 1U, /*!< High-drive strength is configured. */ }; +#endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */ #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK /*! @brief Unlock/lock the pin control register field[15:0] */ @@ -96,18 +102,28 @@ enum _port_lock_register }; #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */ +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH /*! @brief Pin mux selection */ typedef enum _port_mux { - kPORT_PinDisabledOrAnalog = 0U, /*!< corresponding pin is disabled, but is used as an analog pin. */ - kPORT_MuxAsGpio = 1U, /*!< corresponding pin is configured as GPIO. */ - kPORT_MuxAlt2 = 2U, /*!< chip-specific */ - kPORT_MuxAlt3 = 3U, /*!< chip-specific */ - kPORT_MuxAlt4 = 4U, /*!< chip-specific */ - kPORT_MuxAlt5 = 5U, /*!< chip-specific */ - kPORT_MuxAlt6 = 6U, /*!< chip-specific */ - kPORT_MuxAlt7 = 7U, /*!< chip-specific */ + kPORT_PinDisabledOrAnalog = 0U, /*!< Corresponding pin is disabled, but is used as an analog pin. */ + kPORT_MuxAsGpio = 1U, /*!< Corresponding pin is configured as GPIO. */ + kPORT_MuxAlt2 = 2U, /*!< Chip-specific */ + kPORT_MuxAlt3 = 3U, /*!< Chip-specific */ + kPORT_MuxAlt4 = 4U, /*!< Chip-specific */ + kPORT_MuxAlt5 = 5U, /*!< Chip-specific */ + kPORT_MuxAlt6 = 6U, /*!< Chip-specific */ + kPORT_MuxAlt7 = 7U, /*!< Chip-specific */ + kPORT_MuxAlt8 = 8U, /*!< Chip-specific */ + kPORT_MuxAlt9 = 9U, /*!< Chip-specific */ + kPORT_MuxAlt10 = 10U, /*!< Chip-specific */ + kPORT_MuxAlt11 = 11U, /*!< Chip-specific */ + kPORT_MuxAlt12 = 12U, /*!< Chip-specific */ + kPORT_MuxAlt13 = 13U, /*!< Chip-specific */ + kPORT_MuxAlt14 = 14U, /*!< Chip-specific */ + kPORT_MuxAlt15 = 15U, /*!< Chip-specific */ } port_mux_t; +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ /*! @brief Configures the interrupt generation condition. */ typedef enum _port_interrupt @@ -129,8 +145,8 @@ typedef enum _port_interrupt kPORT_InterruptEitherEdge = 0xBU, /*!< Interrupt on either edge. */ kPORT_InterruptLogicOne = 0xCU, /*!< Interrupt when logic one. */ #if defined(FSL_FEATURE_PORT_HAS_IRQC_TRIGGER) && FSL_FEATURE_PORT_HAS_IRQC_TRIGGER - kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high trigger output. */ - kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low trigger output. */ + kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high-trigger output. */ + kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low-trigger output. */ #endif } port_interrupt_t; @@ -150,44 +166,76 @@ typedef struct _port_digital_filter_config } port_digital_filter_config_t; #endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */ -/*! @brief PORT pin config structure */ +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH +/*! @brief PORT pin configuration structure */ typedef struct _port_pin_config { - uint16_t pullSelect : 2; /*!< no-pull/pull-down/pull-up select */ - uint16_t slewRate : 1; /*!< fast/slow slew rate Configure */ +#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE + uint16_t pullSelect : 2; /*!< No-pull/pull-down/pull-up select */ +#else + uint16_t : 2; +#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */ + +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE + uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */ +#else + uint16_t : 1; +#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */ + + uint16_t : 1; + +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER + uint16_t passiveFilterEnable : 1; /*!< Passive filter enable/disable */ +#else uint16_t : 1; - uint16_t passiveFilterEnable : 1; /*!< passive filter enable/disable */ +#endif /* FSL_FEATURE_PORT_HAS_PASSIVE_FILTER */ + #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN - uint16_t openDrainEnable : 1; /*!< open drain enable/disable */ + uint16_t openDrainEnable : 1; /*!< Open drain enable/disable */ +#else + uint16_t : 1; +#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ + +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH + uint16_t driveStrength : 1; /*!< Fast/slow drive strength configure */ #else uint16_t : 1; -#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ - uint16_t driveStrength : 1; /*!< fast/slow drive strength configure */ +#endif + uint16_t : 1; - uint16_t mux : 3; /*!< pin mux Configure */ + +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH + uint16_t mux : 3; /*!< Pin mux Configure */ +#else + uint16_t : 3; +#endif + uint16_t : 4; + #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK - uint16_t lockRegister : 1; /*!< lock/unlock the pcr field[15:0] */ + uint16_t lockRegister : 1; /*!< Lock/unlock the PCR field[15:0] */ #else uint16_t : 1; #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */ } port_pin_config_t; +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ /******************************************************************************* - * API - ******************************************************************************/ +* API +******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH /*! @name Configuration */ /*@{*/ /*! * @brief Sets the port PCR register. * - * This is an example to define an input pin or output pin PCR configuration: + * This is an example to define an input pin or output pin PCR configuration. * @code * // Define a digital input pin PCR configuration * port_pin_config_t config = { @@ -203,7 +251,7 @@ extern "C" { * * @param base PORT peripheral base pointer. * @param pin PORT pin number. - * @param config PORT PCR register configure structure. + * @param config PORT PCR register configuration structure. */ static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config) { @@ -215,7 +263,7 @@ static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_p /*! * @brief Sets the port PCR register for multiple pins. * - * This is an example to define input pins or output pins PCR configuration: + * This is an example to define input pins or output pins PCR configuration. * @code * // Define a digital input pin PCR configuration * port_pin_config_t config = { @@ -231,8 +279,8 @@ static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_p * @endcode * * @param base PORT peripheral base pointer. - * @param mask PORT pins' numbers macro. - * @param config PORT PCR register configure structure. + * @param mask PORT pin number macro. + * @param config PORT PCR register configuration structure. */ static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, const port_pin_config_t *config) { @@ -265,15 +313,16 @@ static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, co * - #kPORT_MuxAlt6 : chip-specific. * - #kPORT_MuxAlt7 : chip-specific. * @Note : This function is NOT recommended to use together with the PORT_SetPinsConfig, because - * the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux will - * be reset to zero : kPORT_PinDisabledOrAnalog). - * This function is recommended to use in the case you just need to reset the pin mux + * the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is + * reset to zero : kPORT_PinDisabledOrAnalog). + * This function is recommended to use to reset the pin mux * */ static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux) { base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux); } +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ #if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER @@ -281,7 +330,7 @@ static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux) * @brief Enables the digital filter in one port, each bit of the 32-bit register represents one pin. * * @param base PORT peripheral base pointer. - * @param mask PORT pins' numbers macro. + * @param mask PORT pin number macro. */ static inline void PORT_EnablePinsDigitalFilter(PORT_Type *base, uint32_t mask, bool enable) { @@ -334,8 +383,8 @@ static inline void PORT_SetDigitalFilterConfig(PORT_Type *base, const port_digit * - #kPORT_InterruptFallingEdge: Interrupt on falling edge. * - #kPORT_InterruptEitherEdge : Interrupt on either edge. * - #kPORT_InterruptLogicOne : Interrupt when logic one. - * - #kPORT_ActiveHighTriggerOutputEnable : Enable active high trigger output(if the trigger states exit). - * - #kPORT_ActiveLowTriggerOutputEnable : Enable active low trigger output(if the trigger states exit). + * - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit). + * - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit). */ static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config) { @@ -351,9 +400,9 @@ static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, por * If configured for a level sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base PORT peripheral base pointer. + * @param base PORT peripheral base pointer. * @return Current port interrupt status flags, for example, 0x00010001 means the - * pin 0 and 17 have the interrupt. + * pin 0 and 16 have the interrupt. */ static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base) { @@ -361,10 +410,10 @@ static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base) } /*! - * @brief Clears the multiple pins' interrupt status flag. + * @brief Clears the multiple pin interrupt status flag. * * @param base PORT peripheral base pointer. - * @param mask PORT pins' numbers macro. + * @param mask PORT pin number macro. */ static inline void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c index 538f6872a3a..0d738643b53 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -32,6 +32,8 @@ void RCM_ConfigureResetPinFilter(RCM_Type *base, const rcm_reset_pin_filter_config_t *config) { + assert(config); + #if (defined(FSL_FEATURE_RCM_REG_WIDTH) && (FSL_FEATURE_RCM_REG_WIDTH == 32)) uint32_t reg; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h index 81e25559eaf..99b843aaf3a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,7 +35,6 @@ /*! @addtogroup rcm */ /*! @{*/ -/*! @file */ /******************************************************************************* * Definitions @@ -43,8 +42,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief RCM driver version 2.0.0. */ -#define FSL_RCM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief RCM driver version 2.0.1. */ +#define FSL_RCM_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ /*! @@ -57,7 +56,7 @@ typedef enum _rcm_reset_source #if (defined(FSL_FEATURE_RCM_HAS_WAKEUP) && FSL_FEATURE_RCM_HAS_WAKEUP) kRCM_SourceWakeup = RCM_SRS_WAKEUP_MASK, /*!< Low-leakage wakeup reset */ #endif - kRCM_SourceLvd = RCM_SRS_LVD_MASK, /*!< low voltage detect reset */ + kRCM_SourceLvd = RCM_SRS_LVD_MASK, /*!< Low-voltage detect reset */ #if (defined(FSL_FEATURE_RCM_HAS_LOC) && FSL_FEATURE_RCM_HAS_LOC) kRCM_SourceLoc = RCM_SRS_LOC_MASK, /*!< Loss of clock reset */ #endif /* FSL_FEATURE_RCM_HAS_LOC */ @@ -85,7 +84,7 @@ typedef enum _rcm_reset_source #if (defined(FSL_FEATURE_RCM_HAS_WAKEUP) && FSL_FEATURE_RCM_HAS_WAKEUP) kRCM_SourceWakeup = RCM_SRS0_WAKEUP_MASK, /*!< Low-leakage wakeup reset */ #endif - kRCM_SourceLvd = RCM_SRS0_LVD_MASK, /*!< low voltage detect reset */ + kRCM_SourceLvd = RCM_SRS0_LVD_MASK, /*!< Low-voltage detect reset */ #if (defined(FSL_FEATURE_RCM_HAS_LOC) && FSL_FEATURE_RCM_HAS_LOC) kRCM_SourceLoc = RCM_SRS0_LOC_MASK, /*!< Loss of clock reset */ #endif /* FSL_FEATURE_RCM_HAS_LOC */ @@ -99,7 +98,7 @@ typedef enum _rcm_reset_source kRCM_SourceJtag = RCM_SRS1_JTAG_MASK << 8U, /*!< JTAG generated reset */ #endif /* FSL_FEATURE_RCM_HAS_JTAG */ kRCM_SourceLockup = RCM_SRS1_LOCKUP_MASK << 8U, /*!< Core lock up reset */ - kRCM_SourceSw = RCM_SRS1_SW_MASK, /*!< Software reset */ + kRCM_SourceSw = RCM_SRS1_SW_MASK << 8U, /*!< Software reset */ #if (defined(FSL_FEATURE_RCM_HAS_MDM_AP) && FSL_FEATURE_RCM_HAS_MDM_AP) kRCM_SourceMdmap = RCM_SRS1_MDM_AP_MASK << 8U, /*!< MDM-AP system reset */ #endif /* FSL_FEATURE_RCM_HAS_MDM_AP */ @@ -112,7 +111,7 @@ typedef enum _rcm_reset_source } rcm_reset_source_t; /*! - * @brief Reset pin filter select in Run and Wait modes + * @brief Reset pin filter select in Run and Wait modes. */ typedef enum _rcm_run_wait_filter_mode { @@ -136,7 +135,7 @@ typedef enum _rcm_boot_rom_config #if (defined(FSL_FEATURE_RCM_HAS_SRIE) && FSL_FEATURE_RCM_HAS_SRIE) /*! - * @brief Max delay time from interrupt asserts to system reset. + * @brief Maximum delay time from interrupt asserts to system reset. */ typedef enum _rcm_reset_delay { @@ -187,7 +186,7 @@ typedef struct _rcm_version_id #endif /*! - * @brief Reset pin filter configuration + * @brief Reset pin filter configuration. */ typedef struct _rcm_reset_pin_filter_config { @@ -214,7 +213,7 @@ extern "C" { * the minor version number, and the feature specification number. * * @param base RCM peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void RCM_GetVersionId(RCM_Type *base, rcm_version_id_t *versionId) { @@ -229,7 +228,7 @@ static inline void RCM_GetVersionId(RCM_Type *base, rcm_version_id_t *versionId) * This function gets the RCM parameter that indicates whether the corresponding reset source is implemented. * Use source masks defined in the rcm_reset_source_t to get the desired source status. * - * Example: + * This is an example. @code uint32_t status; @@ -252,7 +251,7 @@ static inline uint32_t RCM_GetResetSourceImplementedStatus(RCM_Type *base) * This function gets the current reset source status. Use source masks * defined in the rcm_reset_source_t to get the desired source status. * - * Example: + * This is an example. @code uint32_t resetStatus; @@ -283,9 +282,9 @@ static inline uint32_t RCM_GetPreviousResetSources(RCM_Type *base) * @brief Gets the sticky reset source status. * * This function gets the current reset source status that has not been cleared - * by software for some specific source. + * by software for a specific source. * - * Example: + * This is an example. @code uint32_t resetStatus; @@ -316,7 +315,7 @@ static inline uint32_t RCM_GetStickyResetSources(RCM_Type *base) * * This function clears the sticky system reset flags indicated by source masks. * - * Example: + * This is an example. @code // Clears multiple reset sources. RCM_ClearStickyResetSources(kRCM_SourceWdog | kRCM_SourcePin); @@ -403,7 +402,7 @@ void RCM_SetForceBootRomSource(RCM_Type *base, rcm_boot_rom_config_t config); /*! * @brief Sets the system reset interrupt configuration. * - * For graceful shutdown, the RCM supports delaying the assertion of the system + * For a graceful shut down, the RCM supports delaying the assertion of the system * reset for a period of time when the reset interrupt is generated. This function * can be used to enable the interrupt and the delay period. The interrupts * are passed in as bit mask. See rcm_int_t for details. For example, to diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c index 9be27499efd..6f0adc66f59 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -181,10 +181,14 @@ static uint32_t rnga_ReadEntropy(RNG_Type *base); void RNGA_Init(RNG_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock gate. */ CLOCK_EnableClock(kCLOCK_Rnga0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ CLOCK_DisableClock(kCLOCK_Rnga0); /* To solve the release version on twrkm43z75m */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Rnga0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset the registers for RNGA module to reset state. */ RNG_WR_CR(base, 0); @@ -194,8 +198,10 @@ void RNGA_Init(RNG_Type *base) void RNGA_Deinit(RNG_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock for RNGA module.*/ CLOCK_DisableClock(kCLOCK_Rnga0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h index 04950a4540c..92f5bff8bec 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -34,11 +34,10 @@ #if defined(FSL_FEATURE_SOC_RNG_COUNT) && FSL_FEATURE_SOC_RNG_COUNT /*! - * @addtogroup rnga_driver + * @addtogroup rnga * @{ */ -/*! @file */ /******************************************************************************* * Definitions diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c index 898a544a467..d68055a2690 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -74,6 +74,8 @@ static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datet ******************************************************************************/ static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime) { + assert(datetime); + /* Table of days in a month for a non leap year. First entry in the table is not used, * valid months start from 1 */ @@ -88,13 +90,13 @@ static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime) } /* Adjust the days in February for a leap year */ - if (!(datetime->year & 3U)) + if ((((datetime->year & 3U) == 0) && (datetime->year % 100 != 0)) || (datetime->year % 400 == 0)) { daysPerMonth[2] = 29U; } /* Check the validity of the day */ - if (datetime->day > daysPerMonth[datetime->month]) + if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U)) { return false; } @@ -104,6 +106,9 @@ static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime) static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime) { + assert(datetime); + + /* Number of days from begin of the non Leap-year*/ /* Number of days from begin of the non Leap-year*/ uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U}; uint32_t seconds; @@ -131,6 +136,8 @@ static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime) static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime) { + assert(datetime); + uint32_t x; uint32_t secondsRemaining, days; uint16_t daysInYear; @@ -204,7 +211,9 @@ void RTC_Init(RTC_Type *base, const rtc_config_t *config) uint32_t reg; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Rtc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Issue a software reset if timer is invalid */ if (RTC_GetStatusFlags(RTC) & kRTC_TimeInvalidFlag) @@ -216,7 +225,7 @@ void RTC_Init(RTC_Type *base, const rtc_config_t *config) /* Setup the update mode and supervisor access mode */ reg &= ~(RTC_CR_UM_MASK | RTC_CR_SUP_MASK); reg |= RTC_CR_UM(config->updateMode) | RTC_CR_SUP(config->supervisorAccess); -#if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN +#if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION /* Setup the wakeup pin select */ reg &= ~(RTC_CR_WPS_MASK); reg |= RTC_CR_WPS(config->wakeupSelect); @@ -340,6 +349,8 @@ void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask) void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter) { + assert(counter); + *counter = (((uint64_t)base->MCHR << 32) | ((uint64_t)base->MCLR)); } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h index 063d1d40c34..99effc6dcb9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup rtc_driver + * @addtogroup rtc * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -65,15 +64,19 @@ typedef enum _rtc_status_flags kRTC_AlarmFlag = RTC_SR_TAF_MASK /*!< Alarm flag*/ } rtc_status_flags_t; +#if (defined(FSL_FEATURE_RTC_HAS_OSC_SCXP) && FSL_FEATURE_RTC_HAS_OSC_SCXP) + /*! @brief List of RTC Oscillator capacitor load settings */ typedef enum _rtc_osc_cap_load { - kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2pF capacitor load */ - kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4pF capacitor load */ - kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8pF capacitor load */ - kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16pF capacitor load */ + kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16 pF capacitor load */ } rtc_osc_cap_load_t; +#endif /* FSL_FEATURE_SCG_HAS_OSC_SCXP */ + /*! @brief Structure is used to hold the date and time */ typedef struct _rtc_datetime { @@ -96,7 +99,7 @@ typedef struct _rtc_datetime */ typedef struct _rtc_config { - bool wakeupSelect; /*!< true: Wakeup pin outputs the 32KHz clock; + bool wakeupSelect; /*!< true: Wakeup pin outputs the 32 KHz clock; false:Wakeup pin used to wakeup the chip */ bool updateMode; /*!< true: Registers can be written even when locked under certain conditions, false: No writes allowed when registers are locked */ @@ -122,17 +125,17 @@ extern "C" { /*! * @brief Ungates the RTC clock and configures the peripheral for basic operation. * - * This function will issue a software reset if the timer invalid flag is set. + * This function issues a software reset if the timer invalid flag is set. * * @note This API should be called at the beginning of the application using the RTC driver. * * @param base RTC peripheral base address - * @param config Pointer to user's RTC config structure. + * @param config Pointer to the user's RTC configuration structure. */ void RTC_Init(RTC_Type *base, const rtc_config_t *config); /*! - * @brief Stop the timer and gate the RTC clock + * @brief Stops the timer and gate the RTC clock. * * @param base RTC peripheral base address */ @@ -141,14 +144,16 @@ static inline void RTC_Deinit(RTC_Type *base) /* Stop the RTC timer */ base->SR &= ~RTC_SR_TCE_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the module clock */ CLOCK_DisableClock(kCLOCK_Rtc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! - * @brief Fill in the RTC config struct with the default settings + * @brief Fills in the RTC config struct with the default settings. * - * The default values are: + * The default values are as follows. * @code * config->wakeupSelect = false; * config->updateMode = false; @@ -156,7 +161,7 @@ static inline void RTC_Deinit(RTC_Type *base) * config->compensationInterval = 0; * config->compensationTime = 0; * @endcode - * @param config Pointer to user's RTC config structure. + * @param config Pointer to the user's RTC configuration structure. */ void RTC_GetDefaultConfig(rtc_config_t *config); @@ -170,11 +175,11 @@ void RTC_GetDefaultConfig(rtc_config_t *config); /*! * @brief Sets the RTC date and time according to the given time structure. * - * The RTC counter must be stopped prior to calling this function as writes to the RTC - * seconds register will fail if the RTC counter is running. + * The RTC counter must be stopped prior to calling this function because writes to the RTC + * seconds register fail if the RTC counter is running. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the date and time details to set are stored + * @param datetime Pointer to the structure where the date and time details are stored. * * @return kStatus_Success: Success in setting the time and starting the RTC * kStatus_InvalidArgument: Error because the datetime format is incorrect @@ -185,18 +190,18 @@ status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime); * @brief Gets the RTC time and stores it in the given time structure. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the date and time details are stored. + * @param datetime Pointer to the structure where the date and time details are stored. */ void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime); /*! - * @brief Sets the RTC alarm time + * @brief Sets the RTC alarm time. * * The function checks whether the specified alarm time is greater than the present * time. If not, the function does not set the alarm and returns an error. * * @param base RTC peripheral base address - * @param alarmTime Pointer to structure where the alarm time is stored. + * @param alarmTime Pointer to the structure where the alarm time is stored. * * @return kStatus_Success: success in setting the RTC alarm * kStatus_InvalidArgument: Error because the alarm datetime format is incorrect @@ -208,7 +213,7 @@ status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime); * @brief Returns the RTC alarm time. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the alarm date and time details are stored. + * @param datetime Pointer to the structure where the alarm date and time details are stored. */ void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime); @@ -264,7 +269,7 @@ static inline uint32_t RTC_GetEnabledInterrupts(RTC_Type *base) */ /*! - * @brief Gets the RTC status flags + * @brief Gets the RTC status flags. * * @param base RTC peripheral base address * @@ -319,6 +324,8 @@ static inline void RTC_StopTimer(RTC_Type *base) /*! @}*/ +#if (defined(FSL_FEATURE_RTC_HAS_OSC_SCXP) && FSL_FEATURE_RTC_HAS_OSC_SCXP) + /*! * @brief This function sets the specified capacitor configuration for the RTC oscillator. * @@ -336,6 +343,8 @@ static inline void RTC_SetOscCapLoad(RTC_Type *base, uint32_t capLoad) base->CR = reg; } +#endif /* FSL_FEATURE_SCG_HAS_OSC_SCXP */ + /*! * @brief Performs a software reset on the RTC module. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c index c38165ec045..73ea64fa4ee 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -95,15 +95,17 @@ static void SAI_ReadNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWi /******************************************************************************* * Variables ******************************************************************************/ -/*!@brief SAI handle pointer */ -sai_handle_t *s_saiHandle[FSL_FEATURE_SOC_I2S_COUNT][2]; /* Base pointer array */ static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS; +/*!@brief SAI handle pointer */ +sai_handle_t *s_saiHandle[ARRAY_SIZE(s_saiBases)][2]; /* IRQ number array */ static const IRQn_Type s_saiTxIRQ[] = I2S_TX_IRQS; static const IRQn_Type s_saiRxIRQ[] = I2S_RX_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Clock name array */ static const clock_ip_name_t s_saiClock[] = SAI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointer to tx IRQ handler for each instance. */ static sai_tx_isr_t s_saiTxIsr; /*! @brief Pointer to tx IRQ handler for each instance. */ @@ -181,7 +183,7 @@ uint32_t SAI_GetInstance(I2S_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_I2S_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_saiBases); instance++) { if (s_saiBases[instance] == base) { @@ -189,7 +191,7 @@ uint32_t SAI_GetInstance(I2S_Type *base) } } - assert(instance < FSL_FEATURE_SOC_I2S_COUNT); + assert(instance < ARRAY_SIZE(s_saiBases)); return instance; } @@ -237,8 +239,10 @@ void SAI_TxInit(I2S_Type *base, const sai_config_t *config) { uint32_t val = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the SAI clock */ CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) /* Master clock source setting */ @@ -339,8 +343,10 @@ void SAI_RxInit(I2S_Type *base, const sai_config_t *config) { uint32_t val = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable SAI clock first. */ CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) /* Master clock source setting */ @@ -441,7 +447,9 @@ void SAI_Deinit(I2S_Type *base) { SAI_TxEnable(base, false); SAI_RxEnable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(s_saiClock[SAI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void SAI_TxGetDefaultConfig(sai_config_t *config) @@ -632,7 +640,7 @@ void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint uint32_t i = 0; uint8_t bytesPerWord = bitWidth / 8U; - for (i = 0; i < size; i++) + while (i < size) { /* Wait until it can write data */ while (!(base->TCSR & I2S_TCSR_FWF_MASK)) @@ -641,6 +649,7 @@ void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint SAI_WriteNonBlocking(base, channel, bitWidth, buffer, bytesPerWord); buffer += bytesPerWord; + i += bytesPerWord; } /* Wait until the last data is sent */ @@ -654,7 +663,7 @@ void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8 uint32_t i = 0; uint8_t bytesPerWord = bitWidth / 8U; - for (i = 0; i < size; i++) + while (i < size) { /* Wait until data is received */ while (!(base->RCSR & I2S_RCSR_FWF_MASK)) @@ -663,6 +672,7 @@ void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8 SAI_ReadNonBlocking(base, channel, bitWidth, buffer, bytesPerWord); buffer += bytesPerWord; + i += bytesPerWord; } } @@ -670,6 +680,9 @@ void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transf { assert(handle); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + s_saiHandle[SAI_GetInstance(base)][0] = handle; handle->callback = callback; @@ -686,6 +699,9 @@ void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transf { assert(handle); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + s_saiHandle[SAI_GetInstance(base)][1] = handle; handle->callback = callback; @@ -1024,19 +1040,30 @@ void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle) } #if defined(I2S0) -#if defined(FSL_FEATURE_SAI_INT_SOURCE_NUM) && (FSL_FEATURE_SAI_INT_SOURCE_NUM == 1) void I2S0_DriverIRQHandler(void) { - if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFOWarningFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag))) +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFORequestFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFOWarningFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif { s_saiRxIsr(I2S0, s_saiHandle[0][1]); } - if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFOWarningFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag))) +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFORequestFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFOWarningFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable))) +#endif { s_saiTxIsr(I2S0, s_saiHandle[0][0]); } } -#else + void I2S0_Tx_DriverIRQHandler(void) { assert(s_saiHandle[0][0]); @@ -1048,10 +1075,33 @@ void I2S0_Rx_DriverIRQHandler(void) assert(s_saiHandle[0][1]); s_saiRxIsr(I2S0, s_saiHandle[0][1]); } -#endif /* FSL_FEATURE_SAI_INT_SOURCE_NUM */ #endif /* I2S0*/ #if defined(I2S1) +void I2S1_DriverIRQHandler(void) +{ +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFORequestFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFOWarningFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiRxIsr(I2S1, s_saiHandle[1][1]); + } +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFORequestFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFOWarningFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiTxIsr(I2S1, s_saiHandle[1][0]); + } +} + void I2S1_Tx_DriverIRQHandler(void) { assert(s_saiHandle[1][0]); @@ -1063,4 +1113,80 @@ void I2S1_Rx_DriverIRQHandler(void) assert(s_saiHandle[1][1]); s_saiRxIsr(I2S1, s_saiHandle[1][1]); } +#endif /* I2S1*/ + +#if defined(I2S2) +void I2S2_DriverIRQHandler(void) +{ +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFORequestFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFOWarningFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiRxIsr(I2S2, s_saiHandle[2][1]); + } +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFORequestFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFOWarningFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiTxIsr(I2S2, s_saiHandle[2][0]); + } +} + +void I2S2_Tx_DriverIRQHandler(void) +{ + assert(s_saiHandle[2][0]); + s_saiTxIsr(I2S2, s_saiHandle[2][0]); +} + +void I2S2_Rx_DriverIRQHandler(void) +{ + assert(s_saiHandle[2][1]); + s_saiRxIsr(I2S2, s_saiHandle[2][1]); +} +#endif /* I2S2*/ + +#if defined(I2S3) +void I2S3_DriverIRQHandler(void) +{ +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFORequestFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFOWarningFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiRxIsr(I2S3, s_saiHandle[3][1]); + } +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFORequestFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFOWarningFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable))) #endif + { + s_saiTxIsr(I2S3, s_saiHandle[3][0]); + } +} + +void I2S3_Tx_DriverIRQHandler(void) +{ + assert(s_saiHandle[3][0]); + s_saiTxIsr(I2S3, s_saiHandle[3][0]); +} + +void I2S3_Rx_DriverIRQHandler(void) +{ + assert(s_saiHandle[3][1]); + s_saiRxIsr(I2S3, s_saiHandle[3][1]); +} +#endif /* I2S3*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h index cb38688cd92..64a2f667fce 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,14 +38,13 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -#define FSL_SAI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1 */ +#define FSL_SAI_DRIVER_VERSION (MAKE_VERSION(2, 1, 2)) /*!< Version 2.1.2 */ /*@}*/ /*! @brief SAI return status*/ @@ -186,16 +185,16 @@ typedef struct _sai_config /*! @brief Audio sample rate */ typedef enum _sai_sample_rate { - kSAI_SampleRate8KHz = 8000U, /*!< Sample rate 8000Hz */ - kSAI_SampleRate11025Hz = 11025U, /*!< Sample rate 11025Hz */ - kSAI_SampleRate12KHz = 12000U, /*!< Sample rate 12000Hz */ - kSAI_SampleRate16KHz = 16000U, /*!< Sample rate 16000Hz */ - kSAI_SampleRate22050Hz = 22050U, /*!< Sample rate 22050Hz */ - kSAI_SampleRate24KHz = 24000U, /*!< Sample rate 24000Hz */ - kSAI_SampleRate32KHz = 32000U, /*!< Sample rate 32000Hz */ - kSAI_SampleRate44100Hz = 44100U, /*!< Sample rate 44100Hz */ - kSAI_SampleRate48KHz = 48000U, /*!< Sample rate 48000Hz */ - kSAI_SampleRate96KHz = 96000U /*!< Sample rate 96000Hz */ + kSAI_SampleRate8KHz = 8000U, /*!< Sample rate 8000 Hz */ + kSAI_SampleRate11025Hz = 11025U, /*!< Sample rate 11025 Hz */ + kSAI_SampleRate12KHz = 12000U, /*!< Sample rate 12000 Hz */ + kSAI_SampleRate16KHz = 16000U, /*!< Sample rate 16000 Hz */ + kSAI_SampleRate22050Hz = 22050U, /*!< Sample rate 22050 Hz */ + kSAI_SampleRate24KHz = 24000U, /*!< Sample rate 24000 Hz */ + kSAI_SampleRate32KHz = 32000U, /*!< Sample rate 32000 Hz */ + kSAI_SampleRate44100Hz = 44100U, /*!< Sample rate 44100 Hz */ + kSAI_SampleRate48KHz = 48000U, /*!< Sample rate 48000 Hz */ + kSAI_SampleRate96KHz = 96000U /*!< Sample rate 96000 Hz */ } sai_sample_rate_t; /*! @brief Audio word width */ @@ -211,7 +210,7 @@ typedef enum _sai_word_width typedef struct _sai_transfer_format { uint32_t sampleRate_Hz; /*!< Sample rate of audio data */ - uint32_t bitWidth; /*!< Data length of audio data, usually 8/16/24/32bits */ + uint32_t bitWidth; /*!< Data length of audio data, usually 8/16/24/32 bits */ sai_mono_stereo_t stereo; /*!< Mono or stereo */ uint32_t masterClockHz; /*!< Master clock frequency in Hz */ #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) @@ -239,7 +238,7 @@ struct _sai_handle uint32_t state; /*!< Transfer status */ sai_transfer_callback_t callback; /*!< Callback function called at transfer event*/ void *userData; /*!< Callback parameter passed to callback function*/ - uint8_t bitWidth; /*!< Bit width for transfer, 8/16/24/32bits */ + uint8_t bitWidth; /*!< Bit width for transfer, 8/16/24/32 bits */ uint8_t channel; /*!< Transfer channel */ sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */ size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */ @@ -301,7 +300,7 @@ void SAI_RxInit(I2S_Type *base, const sai_config_t *config); * This API initializes the configuration structure for use in SAI_TxConfig(). * The initialized structure can remain unchanged in SAI_TxConfig(), or it can be modified * before calling SAI_TxConfig(). - * Example: + * This is an example. @code sai_config_t config; SAI_TxGetDefaultConfig(&config); @@ -317,7 +316,7 @@ void SAI_TxGetDefaultConfig(sai_config_t *config); * This API initializes the configuration structure for use in SAI_RxConfig(). * The initialized structure can remain unchanged in SAI_RxConfig() or it can be modified * before calling SAI_RxConfig(). - * Example: + * This is an example. @code sai_config_t config; SAI_RxGetDefaultConfig(&config); @@ -356,7 +355,7 @@ void SAI_TxReset(I2S_Type *base); void SAI_RxReset(I2S_Type *base); /*! - * @brief Enables/disables SAI Tx. + * @brief Enables/disables the SAI Tx. * * @param base SAI base pointer * @param enable True means enable SAI Tx, false means disable. @@ -364,7 +363,7 @@ void SAI_RxReset(I2S_Type *base); void SAI_TxEnable(I2S_Type *base, bool enable); /*! - * @brief Enables/disables SAI Rx. + * @brief Enables/disables the SAI Rx. * * @param base SAI base pointer * @param enable True means enable SAI Rx, false means disable. @@ -418,7 +417,7 @@ static inline uint32_t SAI_RxGetStatusFlag(I2S_Type *base) * @brief Clears the SAI Rx status flag state. * * @param base SAI base pointer - * @param mask State mask. It can be a combination of the following source if defined: + * @param mask State mask. It can be a combination of the following sources if defined. * @arg kSAI_WordStartFlag * @arg kSAI_SyncErrorFlag * @arg kSAI_FIFOErrorFlag @@ -436,11 +435,11 @@ static inline void SAI_RxClearStatusFlags(I2S_Type *base, uint32_t mask) */ /*! - * @brief Enables SAI Tx interrupt requests. + * @brief Enables the SAI Tx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -453,11 +452,11 @@ static inline void SAI_TxEnableInterrupts(I2S_Type *base, uint32_t mask) } /*! - * @brief Enables SAI Rx interrupt requests. + * @brief Enables the SAI Rx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -470,11 +469,11 @@ static inline void SAI_RxEnableInterrupts(I2S_Type *base, uint32_t mask) } /*! - * @brief Disables SAI Tx interrupt requests. + * @brief Disables the SAI Tx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -487,11 +486,11 @@ static inline void SAI_TxDisableInterrupts(I2S_Type *base, uint32_t mask) } /*! - * @brief Disables SAI Rx interrupt requests. + * @brief Disables the SAI Rx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -511,10 +510,10 @@ static inline void SAI_RxDisableInterrupts(I2S_Type *base, uint32_t mask) */ /*! - * @brief Enables/disables SAI Tx DMA requests. + * @brief Enables/disables the SAI Tx DMA requests. * @param base SAI base pointer * @param mask DMA source - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following sources if defined. * @arg kSAI_FIFOWarningDMAEnable * @arg kSAI_FIFORequestDMAEnable * @param enable True means enable DMA, false means disable DMA. @@ -532,10 +531,10 @@ static inline void SAI_TxEnableDMA(I2S_Type *base, uint32_t mask, bool enable) } /*! - * @brief Enables/disables SAI Rx DMA requests. + * @brief Enables/disables the SAI Rx DMA requests. * @param base SAI base pointer * @param mask DMA source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_FIFOWarningDMAEnable * @arg kSAI_FIFORequestDMAEnable * @param enable True means enable DMA, false means disable DMA. @@ -555,7 +554,7 @@ static inline void SAI_RxEnableDMA(I2S_Type *base, uint32_t mask, bool enable) /*! * @brief Gets the SAI Tx data register address. * - * This API is used to provide a transfer address for SAI DMA transfer configuration. + * This API is used to provide a transfer address for the SAI DMA transfer configuration. * * @param base SAI base pointer. * @param channel Which data channel used. @@ -569,7 +568,7 @@ static inline uint32_t SAI_TxGetDataRegisterAddress(I2S_Type *base, uint32_t cha /*! * @brief Gets the SAI Rx data register address. * - * This API is used to provide a transfer address for SAI DMA transfer configuration. + * This API is used to provide a transfer address for the SAI DMA transfer configuration. * * @param base SAI base pointer. * @param channel Which data channel used. @@ -594,10 +593,10 @@ static inline uint32_t SAI_RxGetDataRegisterAddress(I2S_Type *base, uint32_t cha * format to be transferred. * * @param base SAI base pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. - * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master - * clock, this value should equals to masterClockHz in format. + * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If the bit clock source is a master + * clock, this value should equal the masterClockHz. */ void SAI_TxSetFormat(I2S_Type *base, sai_transfer_format_t *format, @@ -611,10 +610,10 @@ void SAI_TxSetFormat(I2S_Type *base, * format to be transferred. * * @param base SAI base pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. - * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master - * clock, this value should equals to masterClockHz in format. + * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If the bit clock source is a master + * clock, this value should equal the masterClockHz. */ void SAI_RxSetFormat(I2S_Type *base, sai_transfer_format_t *format, @@ -628,7 +627,7 @@ void SAI_RxSetFormat(I2S_Type *base, * * @param base SAI base pointer. * @param channel Data channel used. - * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits. + * @param bitWidth How many bits in an audio word; usually 8/16/24/32 bits. * @param buffer Pointer to the data to be written. * @param size Bytes to be written. */ @@ -653,14 +652,14 @@ static inline void SAI_WriteData(I2S_Type *base, uint32_t channel, uint32_t data * * @param base SAI base pointer. * @param channel Data channel used. - * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits. + * @param bitWidth How many bits in an audio word; usually 8/16/24/32 bits. * @param buffer Pointer to the data to be read. * @param size Bytes to be read. */ void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size); /*! - * @brief Reads data from SAI FIFO. + * @brief Reads data from the SAI FIFO. * * @param base SAI base pointer. * @param channel Data channel used. @@ -681,26 +680,26 @@ static inline uint32_t SAI_ReadData(I2S_Type *base, uint32_t channel) /*! * @brief Initializes the SAI Tx handle. * - * This function initializes the Tx handle for SAI Tx transactional APIs. Call - * this function one time to get the handle initialized. + * This function initializes the Tx handle for the SAI Tx transactional APIs. Call + * this function once to get the handle initialized. * * @param base SAI base pointer * @param handle SAI handle pointer. - * @param callback pointer to user callback function - * @param userData user parameter passed to the callback function + * @param callback Pointer to the user callback function. + * @param userData User parameter passed to the callback function */ void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData); /*! * @brief Initializes the SAI Rx handle. * - * This function initializes the Rx handle for SAI Rx transactional APIs. Call - * this function one time to get the handle initialized. + * This function initializes the Rx handle for the SAI Rx transactional APIs. Call + * this function once to get the handle initialized. * * @param base SAI base pointer. * @param handle SAI handle pointer. - * @param callback pointer to user callback function - * @param userData user parameter passed to the callback function + * @param callback Pointer to the user callback function. + * @param userData User parameter passed to the callback function. */ void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData); @@ -712,11 +711,11 @@ void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transf * * @param base SAI base pointer. * @param handle SAI handle pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is a master - * clock, this value should equal to masterClockHz in format. - * @return Status of this function. Return value is one of status_t. + * clock, this value should equal the masterClockHz in format. + * @return Status of this function. Return value is the status_t. */ status_t SAI_TransferTxSetFormat(I2S_Type *base, sai_handle_t *handle, @@ -732,10 +731,10 @@ status_t SAI_TransferTxSetFormat(I2S_Type *base, * * @param base SAI base pointer. * @param handle SAI handle pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. - * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master - * clock, this value should equals to masterClockHz in format. + * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is a master + * clock, this value should equal the masterClockHz in format. * @return Status of this function. Return value is one of status_t. */ status_t SAI_TransferRxSetFormat(I2S_Type *base, @@ -752,9 +751,9 @@ status_t SAI_TransferRxSetFormat(I2S_Type *base, * the transfer is finished. If the return status is not kStatus_SAI_Busy, the transfer * is finished. * - * @param base SAI base pointer - * @param handle pointer to sai_handle_t structure which stores the transfer state - * @param xfer pointer to sai_transfer_t structure + * @param base SAI base pointer. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. + * @param xfer Pointer to the sai_transfer_t structure. * @retval kStatus_Success Successfully started the data receive. * @retval kStatus_SAI_TxBusy Previous receive still not finished. * @retval kStatus_InvalidArgument The input parameter is invalid. @@ -770,8 +769,8 @@ status_t SAI_TransferSendNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_t * is finished. * * @param base SAI base pointer - * @param handle pointer to sai_handle_t structure which stores the transfer state - * @param xfer pointer to sai_transfer_t structure + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. + * @param xfer Pointer to the sai_transfer_t structure. * @retval kStatus_Success Successfully started the data receive. * @retval kStatus_SAI_RxBusy Previous receive still not finished. * @retval kStatus_InvalidArgument The input parameter is invalid. @@ -782,7 +781,7 @@ status_t SAI_TransferReceiveNonBlocking(I2S_Type *base, sai_handle_t *handle, sa * @brief Gets a set byte count. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. * @param count Bytes count sent. * @retval kStatus_Success Succeed get the transfer count. * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress. @@ -793,7 +792,7 @@ status_t SAI_TransferGetSendCount(I2S_Type *base, sai_handle_t *handle, size_t * * @brief Gets a received byte count. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. * @param count Bytes count received. * @retval kStatus_Success Succeed get the transfer count. * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress. @@ -807,18 +806,18 @@ status_t SAI_TransferGetReceiveCount(I2S_Type *base, sai_handle_t *handle, size_ * to abort the transfer early. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. */ void SAI_TransferAbortSend(I2S_Type *base, sai_handle_t *handle); /*! * @brief Aborts the the current IRQ receive. * - * @note This API can be called any time when an interrupt non-blocking transfer initiates + * @note This API can be called when an interrupt non-blocking transfer initiates * to abort the transfer early. * * @param base SAI base pointer - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. */ void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle); @@ -826,7 +825,7 @@ void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle); * @brief Tx interrupt handler. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure. + * @param handle Pointer to the sai_handle_t structure. */ void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle); @@ -834,7 +833,7 @@ void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle); * @brief Tx interrupt handler. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure. + * @param handle Pointer to the sai_handle_t structure. */ void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c index 9b1b2f6c490..dce5a87bfa1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -132,6 +132,9 @@ void SAI_TransferTxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -157,6 +160,9 @@ void SAI_TransferRxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -187,7 +193,14 @@ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; @@ -210,7 +223,14 @@ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; @@ -253,6 +273,9 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra EDMA_PrepareTransfer(&config, xfer->data, handle->bytesPerFrame, (void *)destAddr, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -298,6 +321,9 @@ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_ EDMA_PrepareTransfer(&config, (void *)srcAddr, handle->bytesPerFrame, xfer->data, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -322,6 +348,9 @@ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable DMA enable bit */ SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Tx */ + SAI_TxEnable(base, false); + /* Set the handle state */ handle->state = kSAI_Idle; } @@ -336,6 +365,9 @@ void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable DMA enable bit */ SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Rx */ + SAI_RxEnable(base, false); + /* Set the handle state */ handle->state = kSAI_Idle; } @@ -353,7 +385,8 @@ status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; @@ -372,7 +405,8 @@ status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *hand else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h index 44506fa039d..9ae05db0e95 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,8 +38,6 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -53,6 +51,7 @@ typedef void (*sai_edma_callback_t)(I2S_Type *base, sai_edma_handle_t *handle, s struct _sai_edma_handle { edma_handle_t *dmaHandle; /*!< DMA handler for SAI send */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ uint8_t bytesPerFrame; /*!< Bytes in a frame */ uint8_t channel; /*!< Which data channel */ uint8_t count; /*!< The transfer data count in a DMA request */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c index d2774eeabc9..3151cd22ed9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c @@ -1,34 +1,28 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * - * Redistribution and use in source and binary forms, with or without - * modification, + * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * - * o Redistributions of source code must retain the above copyright notice, this - * list + * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * - * o Redistributions in binary form must reproduce the above copyright notice, - * this + * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @@ -42,12 +36,8 @@ /*! @brief Clock setting */ /* Max SD clock divisor from base clock */ #define SDHC_MAX_DVS ((SDHC_SYSCTL_DVS_MASK >> SDHC_SYSCTL_DVS_SHIFT) + 1U) -#define SDHC_INITIAL_DVS (1U) /* Initial value of SD clock divisor */ -#define SDHC_INITIAL_CLKFS (2U) /* Initial value of SD clock frequency selector */ -#define SDHC_NEXT_DVS(x) ((x) += 1U) #define SDHC_PREV_DVS(x) ((x) -= 1U) #define SDHC_MAX_CLKFS ((SDHC_SYSCTL_SDCLKFS_MASK >> SDHC_SYSCTL_SDCLKFS_SHIFT) + 1U) -#define SDHC_NEXT_CLKFS(x) ((x) <<= 1U) #define SDHC_PREV_CLKFS(x) ((x) >>= 1U) /* Typedef for interrupt handler. */ @@ -85,8 +75,9 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal * @param base SDHC peripheral base address. * @param command Command to be sent. * @param data Data to be transferred. + * @param DMA mode selection */ -static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data); +static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode); /*! * @brief Receive command response @@ -94,7 +85,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da * @param base SDHC peripheral base address. * @param command Command to be sent. */ -static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command); +static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command); /*! * @brief Read DATAPORT when buffer enable bit is set. @@ -230,8 +221,10 @@ static SDHC_Type *const s_sdhcBase[] = SDHC_BASE_PTRS; /*! @brief SDHC IRQ name array */ static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief SDHC clock array name */ static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* SDHC ISR for transactional APIs. */ static sdhc_isr_t s_sdhcIsr; @@ -243,12 +236,12 @@ static uint32_t SDHC_GetInstance(SDHC_Type *base) { uint8_t instance = 0; - while ((instance < FSL_FEATURE_SOC_SDHC_COUNT) && (s_sdhcBase[instance] != base)) + while ((instance < ARRAY_SIZE(s_sdhcBase)) && (s_sdhcBase[instance] != base)) { instance++; } - assert(instance < FSL_FEATURE_SOC_SDHC_COUNT); + assert(instance < ARRAY_SIZE(s_sdhcBase)); return instance; } @@ -256,7 +249,6 @@ static uint32_t SDHC_GetInstance(SDHC_Type *base) static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal) { uint32_t interruptEnabled; /* The Interrupt status flags to be enabled */ - sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); bool cardDetectDat3 = (bool)(base->PROCTL & SDHC_PROCTL_D3CD_MASK); /* Disable all interrupts */ @@ -267,23 +259,12 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal interruptEnabled = (kSDHC_CommandIndexErrorFlag | kSDHC_CommandCrcErrorFlag | kSDHC_CommandEndBitErrorFlag | kSDHC_CommandTimeoutFlag | kSDHC_CommandCompleteFlag | kSDHC_DataTimeoutFlag | kSDHC_DataCrcErrorFlag | - kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag); + kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag | kSDHC_BufferReadReadyFlag | + kSDHC_BufferWriteReadyFlag | kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag); if (cardDetectDat3) { interruptEnabled |= (kSDHC_CardInsertionFlag | kSDHC_CardRemovalFlag); } - switch (dmaMode) - { - case kSDHC_DmaModeAdma1: - case kSDHC_DmaModeAdma2: - interruptEnabled |= (kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag); - break; - case kSDHC_DmaModeNo: - interruptEnabled |= (kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); - break; - default: - break; - } SDHC_EnableInterruptStatus(base, interruptEnabled); if (usingInterruptSignal) @@ -292,48 +273,47 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal } } -static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data) +static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode) { uint32_t flags = 0U; sdhc_transfer_config_t sdhcTransferConfig = {0}; - sdhc_dma_mode_t dmaMode; /* Define the flag corresponding to each response type. */ switch (command->responseType) { - case kSDHC_ResponseTypeNone: + case kCARD_ResponseTypeNone: break; - case kSDHC_ResponseTypeR1: /* Response 1 */ + case kCARD_ResponseTypeR1: /* Response 1 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR1b: /* Response 1 with busy */ + case kCARD_ResponseTypeR1b: /* Response 1 with busy */ flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR2: /* Response 2 */ + case kCARD_ResponseTypeR2: /* Response 2 */ flags |= (kSDHC_ResponseLength136Flag | kSDHC_EnableCrcCheckFlag); break; - case kSDHC_ResponseTypeR3: /* Response 3 */ + case kCARD_ResponseTypeR3: /* Response 3 */ flags |= (kSDHC_ResponseLength48Flag); break; - case kSDHC_ResponseTypeR4: /* Response 4 */ + case kCARD_ResponseTypeR4: /* Response 4 */ flags |= (kSDHC_ResponseLength48Flag); break; - case kSDHC_ResponseTypeR5: /* Response 5 */ + case kCARD_ResponseTypeR5: /* Response 5 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR5b: /* Response 5 with busy */ + case kCARD_ResponseTypeR5b: /* Response 5 with busy */ flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR6: /* Response 6 */ + case kCARD_ResponseTypeR6: /* Response 6 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR7: /* Response 7 */ + case kCARD_ResponseTypeR7: /* Response 7 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; default: break; } - if (command->type == kSDHC_CommandTypeAbort) + if (command->type == kCARD_CommandTypeAbort) { flags |= kSDHC_CommandTypeAbortFlag; } @@ -341,7 +321,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da if (data) { flags |= kSDHC_DataPresentFlag; - dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); + if (dmaMode != kSDHC_DmaModeNo) { flags |= kSDHC_EnableDmaFlag; @@ -375,14 +355,14 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da SDHC_SetTransferConfig(base, &sdhcTransferConfig); } -static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) +static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) { uint32_t i; - if (command->responseType != kSDHC_ResponseTypeNone) + if (command->responseType != kCARD_ResponseTypeNone) { command->response[0U] = SDHC_GetCommandResponse(base, 0U); - if (command->responseType == kSDHC_ResponseTypeR2) + if (command->responseType == kCARD_ResponseTypeR2) { command->response[1U] = SDHC_GetCommandResponse(base, 1U); command->response[2U] = SDHC_GetCommandResponse(base, 2U); @@ -401,6 +381,18 @@ static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command } while (i--); } } + /* check response error flag */ + if ((command->responseErrorFlags != 0U) && + ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR1b) || + (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR5))) + { + if (((command->responseErrorFlags) & (command->response[0U])) != 0U) + { + return kStatus_SDHC_SendCommandFailed; + } + } + + return kStatus_Success; } static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) @@ -411,10 +403,10 @@ static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t t uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT); /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -458,10 +450,10 @@ static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) status_t error = kStatus_Success; /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -487,13 +479,12 @@ static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) { transferredWords = SDHC_ReadDataPort(base, data, transferredWords); } - - /* Clear buffer enable flag to trigger transfer. Clear data error flag when SDHC encounter error */ - SDHC_ClearInterruptStatusFlags(base, (kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag)); + /* clear buffer ready and error */ + SDHC_ClearInterruptStatusFlags(base, kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag); } /* Clear data complete flag after the last read operation. */ - SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag); + SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag); return error; } @@ -506,10 +497,10 @@ static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT); /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -553,10 +544,10 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) status_t error = kStatus_Success; /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -598,6 +589,7 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) error = kStatus_Fail; } } + SDHC_ClearInterruptStatusFlags(base, (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag)); return error; @@ -619,7 +611,7 @@ static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *comman /* Receive response when command completes successfully. */ if (error == kStatus_Success) { - SDHC_ReceiveCommandResponse(base, command); + error = SDHC_ReceiveCommandResponse(base, command); } SDHC_ClearInterruptStatusFlags(base, (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag)); @@ -748,7 +740,11 @@ static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint { handle->transferredWords = SDHC_WriteDataPort(base, handle->data, handle->transferredWords); } - else if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete)) + else + { + } + + if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete)) { handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData); } @@ -787,8 +783,10 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config) uint32_t proctl; uint32_t wml; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable SDHC clock. */ CLOCK_EnableClock(s_sdhcClock[SDHC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset SDHC. */ SDHC_Reset(base, kSDHC_ResetAll, 100); @@ -822,8 +820,10 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config) void SDHC_Deinit(SDHC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable clock. */ CLOCK_DisableClock(s_sdhcClock[SDHC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout) @@ -877,44 +877,83 @@ uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busCloc assert(srcClock_Hz != 0U); assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz)); - uint32_t divisor; - uint32_t prescaler; - uint32_t sysctl; - uint32_t nearestFrequency = 0; + uint32_t totalDiv = 0U; + uint32_t divisor = 0U; + uint32_t prescaler = 0U; + uint32_t sysctl = 0U; + uint32_t nearestFrequency = 0U; - divisor = SDHC_INITIAL_DVS; - prescaler = SDHC_INITIAL_CLKFS; - - /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/ - base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK; + /* calucate total divisor first */ + totalDiv = srcClock_Hz / busClock_Hz; - if (busClock_Hz > 0U) + if (totalDiv != 0U) { - while ((srcClock_Hz / prescaler / SDHC_MAX_DVS > busClock_Hz) && (prescaler < SDHC_MAX_CLKFS)) + /* calucate the divisor (srcClock_Hz / divisor) <= busClock_Hz */ + if ((srcClock_Hz / totalDiv) > busClock_Hz) { - SDHC_NEXT_CLKFS(prescaler); + totalDiv++; } - while ((srcClock_Hz / prescaler / divisor > busClock_Hz) && (divisor < SDHC_MAX_DVS)) + + /* divide the total divisor to div and prescaler */ + if (totalDiv > SDHC_MAX_DVS) { - SDHC_NEXT_DVS(divisor); + prescaler = totalDiv / SDHC_MAX_DVS; + /* prescaler must be a value which equal 2^n and smaller than SDHC_MAX_CLKFS */ + while (((SDHC_MAX_CLKFS % prescaler) != 0U) || (prescaler == 1U)) + { + prescaler++; + } + /* calucate the divisor */ + divisor = totalDiv / prescaler; + /* fine tuning the divisor until divisor * prescaler >= totalDiv */ + while ((divisor * prescaler) < totalDiv) + { + divisor++; + } + nearestFrequency = srcClock_Hz / divisor / prescaler; } - nearestFrequency = srcClock_Hz / prescaler / divisor; - SDHC_PREV_CLKFS(prescaler); + else + { + divisor = totalDiv; + prescaler = 0U; + nearestFrequency = srcClock_Hz / divisor; + } + } + /* in this condition , srcClock_Hz = busClock_Hz, */ + else + { + /* total divider = 1U */ + divisor = 0U; + prescaler = 0U; + nearestFrequency = srcClock_Hz; + } + + /* calucate the value write to register */ + if (divisor != 0U) + { SDHC_PREV_DVS(divisor); + } + /* calucate the value write to register */ + if (prescaler != 0U) + { + SDHC_PREV_CLKFS(prescaler); + } - /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */ - sysctl = base->SYSCTL; - sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK); - sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU)); - base->SYSCTL = sysctl; + /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/ + base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK; - /* Wait until the SD clock is stable. */ - while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK)) - { - } - /* Enable the SD clock. */ - base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK; + /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */ + sysctl = base->SYSCTL; + sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK); + sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU)); + base->SYSCTL = sysctl; + + /* Wait until the SD clock is stable. */ + while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK)) + { } + /* Enable the SD clock. */ + base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK; return nearestFrequency; } @@ -1008,7 +1047,7 @@ void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config) uint32_t mmcboot = 0U; mmcboot = (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) | - SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount)); + SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount)); if (config->enableBootAck) { mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK; @@ -1032,7 +1071,7 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, uint32_t dataBytes) { status_t error = kStatus_Success; - const uint32_t *startAddress; + const uint32_t *startAddress = data; uint32_t entries; uint32_t i; #if defined FSL_SDHC_ENABLE_ADMA1 @@ -1044,14 +1083,19 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, (!data) || (!dataBytes) #if !defined FSL_SDHC_ENABLE_ADMA1 || (dmaMode == kSDHC_DmaModeAdma1) -#else - /* Buffer address configured in ADMA1 descriptor must be 4KB aligned. */ - || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)data % SDHC_ADMA1_LENGTH_ALIGN) != 0U)) -#endif /* FSL_SDHC_ENABLE_ADMA1 */ +#endif ) { error = kStatus_InvalidArgument; } + else if (((dmaMode == kSDHC_DmaModeAdma2) && (((uint32_t)startAddress % SDHC_ADMA2_LENGTH_ALIGN) != 0U)) +#if defined FSL_SDHC_ENABLE_ADMA1 + || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)startAddress % SDHC_ADMA1_LENGTH_ALIGN) != 0U)) +#endif + ) + { + error = kStatus_SDHC_DMADataBufferAddrNotAlign; + } else { switch (dmaMode) @@ -1071,7 +1115,6 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */ } - startAddress = data; /* Check if ADMA descriptor's number is enough. */ entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); /* ADMA1 needs two descriptors to finish a transfer */ @@ -1113,22 +1156,24 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, /* When use ADMA, disable simple DMA */ base->DSADDR = 0U; base->ADSADDR = (uint32_t)table; + /* disable the buffer ready flag in DMA mode */ + SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } break; #endif /* FSL_SDHC_ENABLE_ADMA1 */ case kSDHC_DmaModeAdma2: /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (dataBytes % sizeof(uint32_t) != 0U) { dataBytes += sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */ } - startAddress = data; /* Check if ADMA descriptor's number is enough. */ entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma2_descriptor_t))) @@ -1165,6 +1210,9 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, /* When use ADMA, disable simple DMA */ base->DSADDR = 0U; base->ADSADDR = (uint32_t)table; + /* disable the buffer read flag in DMA mode */ + SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } break; default: @@ -1187,44 +1235,53 @@ status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t ad /* make sure the cmd/block count is valid */ if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT))) { - error = kStatus_InvalidArgument; + return kStatus_InvalidArgument; } - else + + /* Wait until command/data bus out of busy status. */ + while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) { - /* Wait until command/data bus out of busy status. */ - while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) + } + while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)) + { + } + + /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ + if (data && (NULL != admaTable)) + { + error = + SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, + (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize)); + /* in this situation , we disable the DMA instead of polling transfer mode */ + if (error == kStatus_SDHC_DMADataBufferAddrNotAlign) { + dmaMode = kSDHC_DmaModeNo; + SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } - while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)) + else if (error != kStatus_Success) { - } - - /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ - if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, - (data->rxData ? data->rxData : data->txData), - (data->blockCount * data->blockSize)))) - { - error = kStatus_SDHC_PrepareAdmaDescriptorFailed; + return error; } else { - /* Send command and receive data. */ - SDHC_StartTransfer(base, command, data); - if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) - { - error = kStatus_SDHC_SendCommandFailed; - } - else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data))) - { - error = kStatus_SDHC_TransferDataFailed; - } - else - { - } } } - return error; + /* Send command and receive data. */ + SDHC_StartTransfer(base, command, data, dmaMode); + if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) + { + return kStatus_SDHC_SendCommandFailed; + } + else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data))) + { + return kStatus_SDHC_TransferDataFailed; + } + else + { + } + + return kStatus_Success; } void SDHC_TransferCreateHandle(SDHC_Type *base, @@ -1271,40 +1328,49 @@ status_t SDHC_TransferNonBlocking( /* make sure cmd/block count is valid */ if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT))) { - error = kStatus_InvalidArgument; + return kStatus_InvalidArgument; } - else + + /* Wait until command/data bus out of busy status. */ + if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) || + (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))) { - /* Wait until command/data bus out of busy status. */ - if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) || - (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))) + return kStatus_SDHC_BusyTransferring; + } + + /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ + if (data && (NULL != admaTable)) + { + error = + SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, + (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize)); + /* in this situation , we disable the DMA instead of polling transfer mode */ + if (error == kStatus_SDHC_DMADataBufferAddrNotAlign) { - error = kStatus_SDHC_BusyTransferring; + /* change to polling mode */ + dmaMode = kSDHC_DmaModeNo; + SDHC_EnableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + } + else if (error != kStatus_Success) + { + return error; } else { - /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ - if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, - (data->rxData ? data->rxData : data->txData), - (data->blockCount * data->blockSize)))) - { - error = kStatus_SDHC_PrepareAdmaDescriptorFailed; - } - else - { - /* Save command and data into handle before transferring. */ - handle->command = command; - handle->data = data; - handle->interruptFlags = 0U; - /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ - handle->transferredWords = 0U; - - SDHC_StartTransfer(base, command, data); - } } } - return error; + /* Save command and data into handle before transferring. */ + handle->command = command; + handle->data = data; + handle->interruptFlags = 0U; + /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ + handle->transferredWords = 0U; + + SDHC_StartTransfer(base, command, data, dmaMode); + + return kStatus_Success; } void SDHC_TransferHandleIRQ(SDHC_Type *base, sdhc_handle_t *handle) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h index 4976649d91a..336b9618e5b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -43,8 +43,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief Driver version 2.1.2. */ -#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 2U)) +/*! @brief Driver version 2.1.5. */ +#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 5U)) /*@}*/ /*! @brief Maximum block count can be set one time */ @@ -57,6 +57,8 @@ enum _sdhc_status kStatus_SDHC_PrepareAdmaDescriptorFailed = MAKE_STATUS(kStatusGroup_SDHC, 1U), /*!< Set DMA descriptor failed */ kStatus_SDHC_SendCommandFailed = MAKE_STATUS(kStatusGroup_SDHC, 2U), /*!< Send command failed */ kStatus_SDHC_TransferDataFailed = MAKE_STATUS(kStatusGroup_SDHC, 3U), /*!< Transfer data failed */ + kStatus_SDHC_DMADataBufferAddrNotAlign = + MAKE_STATUS(kStatusGroup_SDHC, 4U), /*!< data buffer addr not align in DMA mode */ }; /*! @brief Host controller capabilities flag mask */ @@ -282,32 +284,32 @@ typedef enum _sdhc_boot_mode } sdhc_boot_mode_t; /*! @brief The command type */ -typedef enum _sdhc_command_type +typedef enum _sdhc_card_command_type { - kSDHC_CommandTypeNormal = 0U, /*!< Normal command */ - kSDHC_CommandTypeSuspend = 1U, /*!< Suspend command */ - kSDHC_CommandTypeResume = 2U, /*!< Resume command */ - kSDHC_CommandTypeAbort = 3U, /*!< Abort command */ -} sdhc_command_type_t; + kCARD_CommandTypeNormal = 0U, /*!< Normal command */ + kCARD_CommandTypeSuspend = 1U, /*!< Suspend command */ + kCARD_CommandTypeResume = 2U, /*!< Resume command */ + kCARD_CommandTypeAbort = 3U, /*!< Abort command */ +} sdhc_card_command_type_t; /*! * @brief The command response type. * * Define the command response type from card to host controller. */ -typedef enum _sdhc_response_type +typedef enum _sdhc_card_response_type { - kSDHC_ResponseTypeNone = 0U, /*!< Response type: none */ - kSDHC_ResponseTypeR1 = 1U, /*!< Response type: R1 */ - kSDHC_ResponseTypeR1b = 2U, /*!< Response type: R1b */ - kSDHC_ResponseTypeR2 = 3U, /*!< Response type: R2 */ - kSDHC_ResponseTypeR3 = 4U, /*!< Response type: R3 */ - kSDHC_ResponseTypeR4 = 5U, /*!< Response type: R4 */ - kSDHC_ResponseTypeR5 = 6U, /*!< Response type: R5 */ - kSDHC_ResponseTypeR5b = 7U, /*!< Response type: R5b */ - kSDHC_ResponseTypeR6 = 8U, /*!< Response type: R6 */ - kSDHC_ResponseTypeR7 = 9U, /*!< Response type: R7 */ -} sdhc_response_type_t; + kCARD_ResponseTypeNone = 0U, /*!< Response type: none */ + kCARD_ResponseTypeR1 = 1U, /*!< Response type: R1 */ + kCARD_ResponseTypeR1b = 2U, /*!< Response type: R1b */ + kCARD_ResponseTypeR2 = 3U, /*!< Response type: R2 */ + kCARD_ResponseTypeR3 = 4U, /*!< Response type: R3 */ + kCARD_ResponseTypeR4 = 5U, /*!< Response type: R4 */ + kCARD_ResponseTypeR5 = 6U, /*!< Response type: R5 */ + kCARD_ResponseTypeR5b = 7U, /*!< Response type: R5b */ + kCARD_ResponseTypeR6 = 8U, /*!< Response type: R6 */ + kCARD_ResponseTypeR7 = 9U, /*!< Response type: R7 */ +} sdhc_card_response_type_t; /*! @brief The alignment size for ADDRESS filed in ADMA1's descriptor */ #define SDHC_ADMA1_ADDRESS_ALIGN (4096U) @@ -477,7 +479,8 @@ typedef struct _sdhc_config * @brief Card data descriptor * * Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card - * driver want to ignore the error event to read/write all the data not to stop read/write immediately when error event + * driver + * want to ignore the error event to read/write all the data not to stop read/write immediately when error event * happen for example bus testing procedure for MMC card. */ typedef struct _sdhc_data @@ -497,11 +500,13 @@ typedef struct _sdhc_data */ typedef struct _sdhc_command { - uint32_t index; /*!< Command index */ - uint32_t argument; /*!< Command argument */ - sdhc_command_type_t type; /*!< Command type */ - sdhc_response_type_t responseType; /*!< Command response type */ - uint32_t response[4U]; /*!< Response for this command */ + uint32_t index; /*!< Command index */ + uint32_t argument; /*!< Command argument */ + sdhc_card_command_type_t type; /*!< Command type */ + sdhc_card_response_type_t responseType; /*!< Command response type */ + uint32_t response[4U]; /*!< Response for this command */ + uint32_t responseErrorFlags; /*!< response error flag, the flag which need to check + the command reponse*/ } sdhc_command_t; /*! @brief Transfer state */ @@ -829,7 +834,8 @@ static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t w * @brief Sets the card transfer-related configuration. * * This function fills the card transfer-related command argument/transfer flag/data size. The command and data are sent - * by SDHC after calling this function. + by + * SDHC after calling this function. * * Example: @code @@ -929,7 +935,8 @@ static inline void SDHC_EnableCardDetectTest(SDHC_Type *base, bool enable) * * This function sets the card detection test level to indicate whether the card is inserted into the SDHC when DAT[3]/ * CD pin is selected as a card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is - * selected as the card detection pin. + * selected + * as the card detection pin. * * @param base SDHC peripheral base address. * @param high True to set the card detect level to high. @@ -1007,7 +1014,10 @@ static inline void SDHC_SetForceEvent(SDHC_Type *base, uint32_t mask) * @brief Transfers the command/data using a blocking method. * * This function waits until the command response/data is received or the SDHC encounters an error by polling the status - * flag. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support + * flag. + * This function support non word align data addr transfer support, if data buffer addr is not align in DMA mode, + * the API will continue finish the transfer by polling IO directly + * The application must not call this API in multiple threads at the same time. Because of that this API doesn't support * the re-entry mechanism. * * @note There is no need to call the API 'SDHC_TransferCreateHandle' when calling this API. @@ -1044,7 +1054,10 @@ void SDHC_TransferCreateHandle(SDHC_Type *base, * @brief Transfers the command/data using an interrupt and an asynchronous method. * * This function sends a command and data and returns immediately. It doesn't wait the transfer complete or encounter an - * error. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support + * error. + * This function support non word align data addr transfer support, if data buffer addr is not align in DMA mode, + * the API will continue finish the transfer by polling IO directly + * The application must not call this API in multiple threads at the same time. Because of that this API doesn't support * the re-entry mechanism. * * @note Call the API 'SDHC_TransferCreateHandle' when calling this API. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c index ad672cfd604..baf432ed8b5 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ /*! @brief Define macros for SDRAM driver. */ #define SDRAMC_ONEMILLSEC_NANOSECONDS (1000000U) #define SDRAMC_ONESECOND_MILLISECONDS (1000U) -#define SDRAMC_TIMEOUT_COUNT (0xFFFFU) /******************************************************************************* * Prototypes @@ -53,8 +52,10 @@ static uint32_t SDRAMC_GetInstance(SDRAM_Type *base); * Variables ******************************************************************************/ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to SDRAMC clocks for each instance. */ -const clock_ip_name_t s_sdramClock[FSL_FEATURE_SOC_SDRAM_COUNT] = SDRAM_CLOCKS; +static const clock_ip_name_t s_sdramClock[FSL_FEATURE_SOC_SDRAM_COUNT] = SDRAM_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to SDRAMC bases for each instance. */ static SDRAM_Type *const s_sdramcBases[] = SDRAM_BASE_PTRS; @@ -67,7 +68,7 @@ static uint32_t SDRAMC_GetInstance(SDRAM_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_SDRAM_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_sdramcBases); instance++) { if (s_sdramcBases[instance] == base) { @@ -75,7 +76,7 @@ static uint32_t SDRAMC_GetInstance(SDRAM_Type *base) } } - assert(instance < FSL_FEATURE_SOC_SDRAM_COUNT); + assert(instance < ARRAY_SIZE(s_sdramcBases)); return instance; } @@ -92,8 +93,10 @@ void SDRAMC_Init(SDRAM_Type *base, sdramc_config_t *configure) uint32_t count; uint32_t index; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Un-gate sdram controller clock. */ CLOCK_EnableClock(s_sdramClock[SDRAMC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Initialize sdram Auto refresh timing. */ count = refreshConfig->sdramRefreshRow * (refreshConfig->busClock_Hz / SDRAMC_ONESECOND_MILLISECONDS); @@ -119,50 +122,23 @@ void SDRAMC_Deinit(SDRAM_Type *base) SDRAMC_EnableOperateValid(base, kSDRAMC_Block0, false); SDRAMC_EnableOperateValid(base, kSDRAMC_Block1, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable SDRAM clock. */ CLOCK_DisableClock(s_sdramClock[SDRAMC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } -status_t SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command) +void SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command) { - status_t result = kStatus_Success; - uint32_t count = SDRAMC_TIMEOUT_COUNT; - switch (command) { /* Initiate mrs command. */ case kSDRAMC_ImrsCommand: base->BLOCK[block].AC |= SDRAM_AC_IMRS_MASK; - while (count--) - { - if (!(base->BLOCK[block].AC & SDRAM_AC_IMRS_MASK)) - { - break; - } - } - - if (!count) - { - /* Timeout the mrs command is unfinished. */ - result = kStatus_Fail; - } - break; + break; /* Initiate precharge command. */ case kSDRAMC_PrechargeCommand: base->BLOCK[block].AC |= SDRAM_AC_IP_MASK; - while (count--) - { - if (!(base->BLOCK[block].AC & SDRAM_AC_IP_MASK)) - { - break; - } - } - - /* Timeout the precharge command is unfinished. */ - if (!count) - { - result = kStatus_Fail; - } break; /* Enable Auto refresh command. */ case kSDRAMC_AutoRefreshEnableCommand: @@ -183,5 +159,4 @@ status_t SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sd default: break; } - return result; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h index 4da5ad756f8..c409fe456ee 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief SDRAMC driver version 2.0.0. */ -#define FSL_SDRAMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief SDRAMC driver version 2.1.0. */ +#define FSL_SDRAMC_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*@}*/ /*! @brief SDRAM controller auto-refresh timing. */ @@ -60,14 +59,14 @@ typedef enum _sdramc_refresh_time /*! * @brief Setting latency for SDRAM controller timing specifications. * - * The latency setting will affects the following SDRAM timing specifications: + * The latency setting affects the following SDRAM timing specifications: * - trcd: SRAS assertion to SCAS assertion \n * - tcasl: SCAS assertion to data out \n * - tras: ACTV command to Precharge command \n * - trp: Precharge command to ACTV command \n * - trwl, trdl: Last data input to Precharge command \n * - tep: Last data out to Precharge command \n - * the details of the latency setting and timing specifications are shown on the following table list: \n + * The details of the latency setting and timing specifications are shown in the following table list. \n * latency trcd: tcasl tras trp trwl,trdl tep \n * 0 1 bus clock 1 bus clock 2 bus clocks 1 bus clock 1 bus clock 1 bus clock \n * 1 2 bus clock 2 bus clock 4 bus clocks 2 bus clock 1 bus clock 1 bus clock \n @@ -219,10 +218,10 @@ void SDRAMC_Deinit(SDRAM_Type *base); /*! * @brief Sends the SDRAM command. - * This function sends the command to SDRAM. There are precharge command, initialize MRS command, + * This function sends commands to SDRAM. The commands are precharge command, initialization MRS command, * auto-refresh enable/disable command, and self-refresh enter/exit commands. - * Note the self-refresh enter/exit commands are all blocks setting and "block" - * are ignored. Ensure to set the right "block" when send other commands. + * Note that the self-refresh enter/exit commands are all blocks setting and "block" + * is ignored. Ensure to set the correct "block" when send other commands. * * @param base SDRAM controller peripheral base address. * @param block The block selection. @@ -233,13 +232,8 @@ void SDRAMC_Deinit(SDRAM_Type *base); * kSDRAMC_SelfrefreshExitCommand - Exit self-refresh command \n * kSDRAMC_AutoRefreshEnableCommand - Enable auto refresh command \n * kSDRAMC_AutoRefreshDisableCommand - Disable auto refresh command - * @return Command execution status. - * All commands except the "initialize MRS command" and "precharge command" - * return kStatus_Success directly. - * For "initialize MRS command" and "precharge command" - * return kStatus_Success when the command success else return kStatus_Fail. */ -status_t SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command); +void SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command); /*! * @brief Enables/disables the write protection. @@ -261,11 +255,11 @@ static inline void SDRAMC_EnableWriteProtect(SDRAM_Type *base, sdramc_block_sele } /*! - * @brief Enables/disables the operation valid. + * @brief Enables/disables the valid operation. * * @param base SDRAM peripheral base address. * @param block The block which is selected. - * @param enable True enable the operation valid, false disable the operation valid. + * @param enable True enable the valid operation; false disable the valid operation. */ static inline void SDRAMC_EnableOperateValid(SDRAM_Type *base, sdramc_block_selection_t block, bool enable) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c index 3a4b801b7b3..ade512f0306 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_sim.h" diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h index a3b69188841..0a0e4fb3092 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_SIM_H_ #define _FSL_SIM_H_ @@ -36,7 +36,6 @@ /*! @addtogroup sim */ /*! @{*/ -/*! @file */ /******************************************************************************* * Definitions @@ -90,10 +89,10 @@ extern "C" { * @brief Sets the USB voltage regulator setting. * * This function configures whether the USB voltage regulator is enabled in - * normal RUN mode, STOP/VLPS/LLS/VLLS modes and VLPR/VLPW modes. The configurations - * are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, enable + * normal RUN mode, STOP/VLPS/LLS/VLLS modes, and VLPR/VLPW modes. The configurations + * are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, to enable * USB voltage regulator in RUN/VLPR/VLPW modes and disable in STOP/VLPS/LLS/VLLS mode, - * please use: + * use: * * SIM_SetUsbVoltRegulatorEnableMode(kSIM_UsbVoltRegEnable | kSIM_UsbVoltRegEnableInLowPower); * @@ -103,16 +102,16 @@ void SIM_SetUsbVoltRegulatorEnableMode(uint32_t mask); #endif /* FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR */ /*! - * @brief Get the unique identification register value. + * @brief Gets the unique identification register value. * * @param uid Pointer to the structure to save the UID value. */ void SIM_GetUniqueId(sim_uid_t *uid); /*! - * @brief Set the flash enable mode. + * @brief Sets the flash enable mode. * - * @param mode The mode to set, see \ref _sim_flash_mode for mode details. + * @param mode The mode to set; see \ref _sim_flash_mode for mode details. */ static inline void SIM_SetFlashMode(uint8_t mode) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c index 0018cf7dce2..dacf193476c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -29,6 +29,7 @@ */ #include "fsl_smc.h" +#include "fsl_flash.h" #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) void SMC_GetParam(SMC_Type *base, smc_param_t *param) @@ -41,6 +42,39 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param) } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +void SMC_PreEnterStopModes(void) +{ + flash_prefetch_speculation_status_t speculationStatus = + { + kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/ + kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/ + }; + + __disable_irq(); + __ISB(); + + /* + * Before enter stop modes, the flash cache prefetch should be disabled. + * Otherwise the prefetch might be interrupted by stop, then the data and + * and instruction from flash are wrong. + */ + FLASH_PflashSetPrefetchSpeculation(&speculationStatus); +} + +void SMC_PostExitStopModes(void) +{ + flash_prefetch_speculation_status_t speculationStatus = + { + kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/ + kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/ + }; + + FLASH_PflashSetPrefetchSpeculation(&speculationStatus); + + __enable_irq(); + __ISB(); +} + status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; @@ -73,7 +107,9 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } @@ -101,7 +137,9 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter Stop mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) @@ -148,16 +186,12 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base status_t SMC_SetPowerModeVlpw(SMC_Type *base) { - /* Power mode transaction to VLPW can only happen in VLPR mode */ - if (kSMC_PowerStateVlpr != SMC_GetPowerModeState(base)) - { - return kStatus_Fail; - } - /* configure VLPW mode */ /* Set the SLEEPDEEP bit to enable deep sleep mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } @@ -177,7 +211,9 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter VLPS mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) @@ -231,7 +267,9 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter LLS mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) @@ -345,7 +383,9 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter LLS mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h index 5149f87e346..168ce835013 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -36,7 +36,6 @@ /*! @addtogroup smc */ /*! @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -44,8 +43,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.1. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief SMC driver version 2.0.3. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*@}*/ /*! @@ -54,14 +53,14 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) @@ -107,10 +106,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -120,12 +119,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -155,7 +154,7 @@ typedef enum _smc_partial_stop_mode } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -190,7 +189,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -205,7 +204,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -242,10 +241,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -257,10 +256,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -274,7 +273,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -289,13 +288,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -306,7 +305,45 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +static inline void SMC_PreEnterWaitModes(void) +{ + __disable_irq(); + __ISB(); +} + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +static inline void SMC_PostExitWaitModes(void) +{ + __enable_irq(); + __ISB(); +} + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -315,7 +352,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -324,7 +361,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -332,7 +369,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -342,7 +379,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -351,7 +388,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -360,7 +397,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -368,7 +405,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -379,7 +416,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -388,7 +425,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -399,7 +436,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.c new file mode 100755 index 00000000000..b89a7b20e4e --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_sysmpu.h" + +/******************************************************************************* + * Variables + ******************************************************************************/ + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +const clock_ip_name_t g_sysmpuClock[FSL_FEATURE_SOC_SYSMPU_COUNT] = SYSMPU_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/******************************************************************************* + * Codes + ******************************************************************************/ + +void SYSMPU_Init(SYSMPU_Type *base, const sysmpu_config_t *config) +{ + assert(config); + uint8_t count; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Un-gate SYSMPU clock */ + CLOCK_EnableClock(g_sysmpuClock[0]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Initializes the regions. */ + for (count = 1; count < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT; count++) + { + base->WORD[count][3] = 0; /* VLD/VID+PID. */ + base->WORD[count][0] = 0; /* Start address. */ + base->WORD[count][1] = 0; /* End address. */ + base->WORD[count][2] = 0; /* Access rights. */ + base->RGDAAC[count] = 0; /* Alternate access rights. */ + } + + /* SYSMPU configure. */ + while (config) + { + SYSMPU_SetRegionConfig(base, &(config->regionConfig)); + config = config->next; + } + /* Enable SYSMPU. */ + SYSMPU_Enable(base, true); +} + +void SYSMPU_Deinit(SYSMPU_Type *base) +{ + /* Disable SYSMPU. */ + SYSMPU_Enable(base, false); + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Gate the clock. */ + CLOCK_DisableClock(g_sysmpuClock[0]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +void SYSMPU_GetHardwareInfo(SYSMPU_Type *base, sysmpu_hardware_info_t *hardwareInform) +{ + assert(hardwareInform); + + uint32_t cesReg = base->CESR; + + hardwareInform->hardwareRevisionLevel = (cesReg & SYSMPU_CESR_HRL_MASK) >> SYSMPU_CESR_HRL_SHIFT; + hardwareInform->slavePortsNumbers = (cesReg & SYSMPU_CESR_NSP_MASK) >> SYSMPU_CESR_NSP_SHIFT; + hardwareInform->regionsNumbers = (sysmpu_region_total_num_t)((cesReg & SYSMPU_CESR_NRGD_MASK) >> SYSMPU_CESR_NRGD_SHIFT); +} + +void SYSMPU_SetRegionConfig(SYSMPU_Type *base, const sysmpu_region_config_t *regionConfig) +{ + assert(regionConfig); + assert(regionConfig->regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + + uint32_t wordReg = 0; + uint8_t msPortNum; + uint8_t regNumber = regionConfig->regionNum; + + /* The start and end address of the region descriptor. */ + base->WORD[regNumber][0] = regionConfig->startAddress; + base->WORD[regNumber][1] = regionConfig->endAddress; + + /* Set the privilege rights for master 0 ~ master 3. */ + for (msPortNum = 0; msPortNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum++) + { + wordReg |= SYSMPU_REGION_RWXRIGHTS_MASTER( + msPortNum, (((uint32_t)regionConfig->accessRights1[msPortNum].superAccessRights << 3U) | + (uint32_t)regionConfig->accessRights1[msPortNum].userAccessRights)); + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + wordReg |= + SYSMPU_REGION_RWXRIGHTS_MASTER_PE(msPortNum, regionConfig->accessRights1[msPortNum].processIdentifierEnable); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + } + +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT + /* Set the normal read write rights for master 4 ~ master 7. */ + for (msPortNum = SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum < FSL_FEATURE_SYSMPU_MASTER_COUNT; + msPortNum++) + { + wordReg |= SYSMPU_REGION_RWRIGHTS_MASTER(msPortNum, + ((uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].readEnable << 1U | + (uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].writeEnable)); + } +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT */ + + /* Set region descriptor access rights. */ + base->WORD[regNumber][2] = wordReg; + + wordReg = SYSMPU_WORD_VLD(1); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + wordReg |= SYSMPU_WORD_PID(regionConfig->processIdentifier) | SYSMPU_WORD_PIDMASK(regionConfig->processIdMask); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + + base->WORD[regNumber][3] = wordReg; +} + +void SYSMPU_SetRegionAddr(SYSMPU_Type *base, uint32_t regionNum, uint32_t startAddr, uint32_t endAddr) +{ + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + + base->WORD[regionNum][0] = startAddr; + base->WORD[regionNum][1] = endAddr; +} + +void SYSMPU_SetRegionRwxMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwxrights_master_access_control_t *accessRights) +{ + assert(accessRights); + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + assert(masterNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT); + + uint32_t mask = SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(masterNum); + uint32_t right = base->RGDAAC[regionNum]; + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + mask |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(masterNum); +#endif + + /* Build rights control value. */ + right &= ~mask; + right |= SYSMPU_REGION_RWXRIGHTS_MASTER( + masterNum, ((uint32_t)(accessRights->superAccessRights << 3U) | accessRights->userAccessRights)); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + right |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE(masterNum, accessRights->processIdentifierEnable); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + + /* Set low master region access rights. */ + base->RGDAAC[regionNum] = right; +} + +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 +void SYSMPU_SetRegionRwMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwrights_master_access_control_t *accessRights) +{ + assert(accessRights); + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + assert(masterNum >= SYSMPU_MASTER_RWATTRIBUTE_START_PORT); + assert(masterNum <= (FSL_FEATURE_SYSMPU_MASTER_COUNT - 1)); + + uint32_t mask = SYSMPU_REGION_RWRIGHTS_MASTER_MASK(masterNum); + uint32_t right = base->RGDAAC[regionNum]; + + /* Build rights control value. */ + right &= ~mask; + right |= + SYSMPU_REGION_RWRIGHTS_MASTER(masterNum, (((uint32_t)accessRights->readEnable << 1U) | accessRights->writeEnable)); + /* Set low master region access rights. */ + base->RGDAAC[regionNum] = right; +} +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 */ + +bool SYSMPU_GetSlavePortErrorStatus(SYSMPU_Type *base, sysmpu_slave_t slaveNum) +{ + uint8_t sperr; + + sperr = ((base->CESR & SYSMPU_CESR_SPERR_MASK) >> SYSMPU_CESR_SPERR_SHIFT) & (0x1U << (FSL_FEATURE_SYSMPU_SLAVE_COUNT - slaveNum - 1)); + + return (sperr != 0) ? true : false; +} + +void SYSMPU_GetDetailErrorAccessInfo(SYSMPU_Type *base, sysmpu_slave_t slaveNum, sysmpu_access_err_info_t *errInform) +{ + assert(errInform); + + uint16_t value; + uint32_t cesReg; + + /* Error address. */ + errInform->address = base->SP[slaveNum].EAR; + + /* Error detail information. */ + value = (base->SP[slaveNum].EDR & SYSMPU_EDR_EACD_MASK) >> SYSMPU_EDR_EACD_SHIFT; + if (!value) + { + errInform->accessControl = kSYSMPU_NoRegionHit; + } + else if (!(value & (uint16_t)(value - 1))) + { + errInform->accessControl = kSYSMPU_NoneOverlappRegion; + } + else + { + errInform->accessControl = kSYSMPU_OverlappRegion; + } + + value = base->SP[slaveNum].EDR; + errInform->master = (uint32_t)((value & SYSMPU_EDR_EMN_MASK) >> SYSMPU_EDR_EMN_SHIFT); + errInform->attributes = (sysmpu_err_attributes_t)((value & SYSMPU_EDR_EATTR_MASK) >> SYSMPU_EDR_EATTR_SHIFT); + errInform->accessType = (sysmpu_err_access_type_t)((value & SYSMPU_EDR_ERW_MASK) >> SYSMPU_EDR_ERW_SHIFT); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + errInform->processorIdentification = (uint8_t)((value & SYSMPU_EDR_EPID_MASK) >> SYSMPU_EDR_EPID_SHIFT); +#endif + + /* Clears error slave port bit. */ + cesReg = (base->CESR & ~SYSMPU_CESR_SPERR_MASK) | ((0x1U << (FSL_FEATURE_SYSMPU_SLAVE_COUNT - slaveNum - 1)) << SYSMPU_CESR_SPERR_SHIFT); + base->CESR = cesReg; +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.h new file mode 100755 index 00000000000..6341a31e9d1 --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FSL_SYSMPU_H_ +#define _FSL_SYSMPU_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup sysmpu + * @{ + */ + + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief SYSMPU driver version 2.2.0. */ +#define FSL_SYSMPU_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*@}*/ + +/*! @brief define the start master port with read and write attributes. */ +#define SYSMPU_MASTER_RWATTRIBUTE_START_PORT (4) + +/*! @brief SYSMPU the bit shift for masters with privilege rights: read write and execute. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n) (n * 6) + +/*! @brief SYSMPU masters with read, write and execute rights bit mask. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(n) (0x1Fu << SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n)) + +/*! @brief SYSMPU masters with read, write and execute rights bit width. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_WIDTH 5 + +/*! @brief SYSMPU masters with read, write and execute rights priority setting. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n))) & SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(n)) + +/*! @brief SYSMPU masters with read, write and execute rights process enable bit shift. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n) (n * 6 + SYSMPU_REGION_RWXRIGHTS_MASTER_WIDTH) + +/*! @brief SYSMPU masters with read, write and execute rights process enable bit mask. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(n) (0x1u << SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n)) + +/*! @brief SYSMPU masters with read, write and execute rights process enable setting. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n))) & SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(n)) + +/*! @brief SYSMPU masters with normal read write permission bit shift. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n) ((n - SYSMPU_MASTER_RWATTRIBUTE_START_PORT) * 2 + 24) + +/*! @brief SYSMPU masters with normal read write rights bit mask. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER_MASK(n) (0x3u << SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n)) + +/*! @brief SYSMPU masters with normal read write rights priority setting. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n))) & SYSMPU_REGION_RWRIGHTS_MASTER_MASK(n)) + + +/*! @brief Describes the number of SYSMPU regions. */ +typedef enum _sysmpu_region_total_num +{ + kSYSMPU_8Regions = 0x0U, /*!< SYSMPU supports 8 regions. */ + kSYSMPU_12Regions = 0x1U, /*!< SYSMPU supports 12 regions. */ + kSYSMPU_16Regions = 0x2U /*!< SYSMPU supports 16 regions. */ +} sysmpu_region_total_num_t; + +/*! @brief SYSMPU slave port number. */ +typedef enum _sysmpu_slave +{ + kSYSMPU_Slave0 = 0U, /*!< SYSMPU slave port 0. */ + kSYSMPU_Slave1 = 1U, /*!< SYSMPU slave port 1. */ + kSYSMPU_Slave2 = 2U, /*!< SYSMPU slave port 2. */ + kSYSMPU_Slave3 = 3U, /*!< SYSMPU slave port 3. */ + kSYSMPU_Slave4 = 4U, /*!< SYSMPU slave port 4. */ +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 5 + kSYSMPU_Slave5 = 5U, /*!< SYSMPU slave port 5. */ +#endif +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 6 + kSYSMPU_Slave6 = 6U, /*!< SYSMPU slave port 6. */ +#endif +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 7 + kSYSMPU_Slave7 = 7U, /*!< SYSMPU slave port 7. */ +#endif +} sysmpu_slave_t; + +/*! @brief SYSMPU error access control detail. */ +typedef enum _sysmpu_err_access_control +{ + kSYSMPU_NoRegionHit = 0U, /*!< No region hit error. */ + kSYSMPU_NoneOverlappRegion = 1U, /*!< Access single region error. */ + kSYSMPU_OverlappRegion = 2U /*!< Access overlapping region error. */ +} sysmpu_err_access_control_t; + +/*! @brief SYSMPU error access type. */ +typedef enum _sysmpu_err_access_type +{ + kSYSMPU_ErrTypeRead = 0U, /*!< SYSMPU error access type --- read. */ + kSYSMPU_ErrTypeWrite = 1U /*!< SYSMPU error access type --- write. */ +} sysmpu_err_access_type_t; + +/*! @brief SYSMPU access error attributes.*/ +typedef enum _sysmpu_err_attributes +{ + kSYSMPU_InstructionAccessInUserMode = 0U, /*!< Access instruction error in user mode. */ + kSYSMPU_DataAccessInUserMode = 1U, /*!< Access data error in user mode. */ + kSYSMPU_InstructionAccessInSupervisorMode = 2U, /*!< Access instruction error in supervisor mode. */ + kSYSMPU_DataAccessInSupervisorMode = 3U /*!< Access data error in supervisor mode. */ +} sysmpu_err_attributes_t; + +/*! @brief SYSMPU access rights in supervisor mode for bus master 0 ~ 3. */ +typedef enum _sysmpu_supervisor_access_rights +{ + kSYSMPU_SupervisorReadWriteExecute = 0U, /*!< Read write and execute operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorReadExecute = 1U, /*!< Read and execute operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorReadWrite = 2U, /*!< Read write operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorEqualToUsermode = 3U /*!< Access permission equal to user mode. */ +} sysmpu_supervisor_access_rights_t; + +/*! @brief SYSMPU access rights in user mode for bus master 0 ~ 3. */ +typedef enum _sysmpu_user_access_rights +{ + kSYSMPU_UserNoAccessRights = 0U, /*!< No access allowed in user mode. */ + kSYSMPU_UserExecute = 1U, /*!< Execute operation is allowed in user mode. */ + kSYSMPU_UserWrite = 2U, /*!< Write operation is allowed in user mode. */ + kSYSMPU_UserWriteExecute = 3U, /*!< Write and execute operations are allowed in user mode. */ + kSYSMPU_UserRead = 4U, /*!< Read is allowed in user mode. */ + kSYSMPU_UserReadExecute = 5U, /*!< Read and execute operations are allowed in user mode. */ + kSYSMPU_UserReadWrite = 6U, /*!< Read and write operations are allowed in user mode. */ + kSYSMPU_UserReadWriteExecute = 7U /*!< Read write and execute operations are allowed in user mode. */ +} sysmpu_user_access_rights_t; + +/*! @brief SYSMPU hardware basic information. */ +typedef struct _sysmpu_hardware_info +{ + uint8_t hardwareRevisionLevel; /*!< Specifies the SYSMPU's hardware and definition reversion level. */ + uint8_t slavePortsNumbers; /*!< Specifies the number of slave ports connected to SYSMPU. */ + sysmpu_region_total_num_t regionsNumbers; /*!< Indicates the number of region descriptors implemented. */ +} sysmpu_hardware_info_t; + +/*! @brief SYSMPU detail error access information. */ +typedef struct _sysmpu_access_err_info +{ + uint32_t master; /*!< Access error master. */ + sysmpu_err_attributes_t attributes; /*!< Access error attributes. */ + sysmpu_err_access_type_t accessType; /*!< Access error type. */ + sysmpu_err_access_control_t accessControl; /*!< Access error control. */ + uint32_t address; /*!< Access error address. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + uint8_t processorIdentification; /*!< Access error processor identification. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_access_err_info_t; + +/*! @brief SYSMPU read/write/execute rights control for bus master 0 ~ 3. */ +typedef struct _sysmpu_rwxrights_master_access_control +{ + sysmpu_supervisor_access_rights_t superAccessRights; /*!< Master access rights in supervisor mode. */ + sysmpu_user_access_rights_t userAccessRights; /*!< Master access rights in user mode. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + bool processIdentifierEnable; /*!< Enables or disables process identifier. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_rwxrights_master_access_control_t; + +/*! @brief SYSMPU read/write access control for bus master 4 ~ 7. */ +typedef struct _sysmpu_rwrights_master_access_control +{ + bool writeEnable; /*!< Enables or disables write permission. */ + bool readEnable; /*!< Enables or disables read permission. */ +} sysmpu_rwrights_master_access_control_t; + +/*! + * @brief SYSMPU region configuration structure. + * + * This structure is used to configure the regionNum region. + * The accessRights1[0] ~ accessRights1[3] are used to configure the bus master + * 0 ~ 3 with the privilege rights setting. The accessRights2[0] ~ accessRights2[3] + * are used to configure the high master 4 ~ 7 with the normal read write permission. + * The master port assignment is the chip configuration. Normally, the core is the + * master 0, debugger is the master 1. + * Note that the SYSMPU assigns a priority scheme where the debugger is treated as the highest + * priority master followed by the core and then all the remaining masters. + * SYSMPU protection does not allow writes from the core to affect the "regionNum 0" start + * and end address nor the permissions associated with the debugger. It can only write + * the permission fields associated with the other masters. This protection guarantees that + * the debugger always has access to the entire address space and those rights can't + * be changed by the core or any other bus master. Prepare + * the region configuration when regionNum is 0. + */ +typedef struct _sysmpu_region_config +{ + uint32_t regionNum; /*!< SYSMPU region number, range form 0 ~ FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. */ + uint32_t startAddress; /*!< Memory region start address. Note: bit0 ~ bit4 always be marked as 0 by SYSMPU. The actual + start address is 0-modulo-32 byte address. */ + uint32_t endAddress; /*!< Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by SYSMPU. The actual end + address is 31-modulo-32 byte address. */ + sysmpu_rwxrights_master_access_control_t accessRights1[4]; /*!< Masters with read, write and execute rights setting. */ + sysmpu_rwrights_master_access_control_t accessRights2[4]; /*!< Masters with normal read write rights setting. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + uint8_t processIdentifier; /*!< Process identifier used when "processIdentifierEnable" set with true. */ + uint8_t + processIdMask; /*!< Process identifier mask. The setting bit will ignore the same bit in process identifier. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_region_config_t; + +/*! + * @brief The configuration structure for the SYSMPU initialization. + * + * This structure is used when calling the SYSMPU_Init function. + */ +typedef struct _sysmpu_config +{ + sysmpu_region_config_t regionConfig; /*!< Region access permission. */ + struct _sysmpu_config *next; /*!< Pointer to the next structure. */ +} sysmpu_config_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +/*! + * @name Initialization and deinitialization + * @{ + */ + +/*! + * @brief Initializes the SYSMPU with the user configuration structure. + * + * This function configures the SYSMPU module with the user-defined configuration. + * + * @param base SYSMPU peripheral base address. + * @param config The pointer to the configuration structure. + */ +void SYSMPU_Init(SYSMPU_Type *base, const sysmpu_config_t *config); + +/*! + * @brief Deinitializes the SYSMPU regions. + * + * @param base SYSMPU peripheral base address. + */ +void SYSMPU_Deinit(SYSMPU_Type *base); + +/* @}*/ + +/*! + * @name Basic Control Operations + * @{ + */ + +/*! + * @brief Enables/disables the SYSMPU globally. + * + * Call this API to enable or disable the SYSMPU module. + * + * @param base SYSMPU peripheral base address. + * @param enable True enable SYSMPU, false disable SYSMPU. + */ +static inline void SYSMPU_Enable(SYSMPU_Type *base, bool enable) +{ + if (enable) + { + /* Enable the SYSMPU globally. */ + base->CESR |= SYSMPU_CESR_VLD_MASK; + } + else + { /* Disable the SYSMPU globally. */ + base->CESR &= ~SYSMPU_CESR_VLD_MASK; + } +} + +/*! + * @brief Enables/disables the SYSMPU for a special region. + * + * When SYSMPU is enabled, call this API to disable an unused region + * of an enabled SYSMPU. Call this API to minimize the power dissipation. + * + * @param base SYSMPU peripheral base address. + * @param number SYSMPU region number. + * @param enable True enable the special region SYSMPU, false disable the special region SYSMPU. + */ +static inline void SYSMPU_RegionEnable(SYSMPU_Type *base, uint32_t number, bool enable) +{ + if (enable) + { + /* Enable the #number region SYSMPU. */ + base->WORD[number][3] |= SYSMPU_WORD_VLD_MASK; + } + else + { /* Disable the #number region SYSMPU. */ + base->WORD[number][3] &= ~SYSMPU_WORD_VLD_MASK; + } +} + +/*! + * @brief Gets the SYSMPU basic hardware information. + * + * @param base SYSMPU peripheral base address. + * @param hardwareInform The pointer to the SYSMPU hardware information structure. See "sysmpu_hardware_info_t". + */ +void SYSMPU_GetHardwareInfo(SYSMPU_Type *base, sysmpu_hardware_info_t *hardwareInform); + +/*! + * @brief Sets the SYSMPU region. + * + * Note: Due to the SYSMPU protection, the region number 0 does not allow writes from + * core to affect the start and end address nor the permissions associated with + * the debugger. It can only write the permission fields associated + * with the other masters. + * + * @param base SYSMPU peripheral base address. + * @param regionConfig The pointer to the SYSMPU user configuration structure. See "sysmpu_region_config_t". + */ +void SYSMPU_SetRegionConfig(SYSMPU_Type *base, const sysmpu_region_config_t *regionConfig); + +/*! + * @brief Sets the region start and end address. + * + * Memory region start address. Note: bit0 ~ bit4 is always marked as 0 by SYSMPU. + * The actual start address by SYSMPU is 0-modulo-32 byte address. + * Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by SYSMPU. + * The end address used by the SYSMPU is 31-modulo-32 byte address. + * Note: Due to the SYSMPU protection, the startAddr and endAddr can't be + * changed by the core when regionNum is 0. + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. The range is from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param startAddr Region start address. + * @param endAddr Region end address. + */ +void SYSMPU_SetRegionAddr(SYSMPU_Type *base, uint32_t regionNum, uint32_t startAddr, uint32_t endAddr); + +/*! + * @brief Sets the SYSMPU region access rights for masters with read, write, and execute rights. + * The SYSMPU access rights depend on two board classifications of bus masters. + * The privilege rights masters and the normal rights masters. + * The privilege rights masters have the read, write, and execute access rights. + * Except the normal read and write rights, the execute rights are also + * allowed for these masters. The privilege rights masters normally range from + * bus masters 0 - 3. However, the maximum master number is device-specific. + * See the "SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX". + * The normal rights masters access rights control see + * "SYSMPU_SetRegionRwMasterAccessRights()". + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. Should range from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param masterNum SYSMPU bus master number. Should range from 0 to + * SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX. + * @param accessRights The pointer to the SYSMPU access rights configuration. See "sysmpu_rwxrights_master_access_control_t". + */ +void SYSMPU_SetRegionRwxMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwxrights_master_access_control_t *accessRights); +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 +/*! + * @brief Sets the SYSMPU region access rights for masters with read and write rights. + * The SYSMPU access rights depend on two board classifications of bus masters. + * The privilege rights masters and the normal rights masters. + * The normal rights masters only have the read and write access permissions. + * The privilege rights access control see "SYSMPU_SetRegionRwxMasterAccessRights". + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. The range is from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param masterNum SYSMPU bus master number. Should range from SYSMPU_MASTER_RWATTRIBUTE_START_PORT + * to ~ FSL_FEATURE_SYSMPU_MASTER_COUNT - 1. + * @param accessRights The pointer to the SYSMPU access rights configuration. See "sysmpu_rwrights_master_access_control_t". + */ +void SYSMPU_SetRegionRwMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwrights_master_access_control_t *accessRights); +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 */ +/*! + * @brief Gets the numbers of slave ports where errors occur. + * + * @param base SYSMPU peripheral base address. + * @param slaveNum SYSMPU slave port number. + * @return The slave ports error status. + * true - error happens in this slave port. + * false - error didn't happen in this slave port. + */ +bool SYSMPU_GetSlavePortErrorStatus(SYSMPU_Type *base, sysmpu_slave_t slaveNum); + +/*! + * @brief Gets the SYSMPU detailed error access information. + * + * @param base SYSMPU peripheral base address. + * @param slaveNum SYSMPU slave port number. + * @param errInform The pointer to the SYSMPU access error information. See "sysmpu_access_err_info_t". + */ +void SYSMPU_GetDetailErrorAccessInfo(SYSMPU_Type *base, sysmpu_slave_t slaveNum, sysmpu_access_err_info_t *errInform); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_SYSMPU_H_ */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c index 079c06df586..9a390a2be47 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -53,8 +53,10 @@ static uint32_t TPM_GetInstance(TPM_Type *base); /*! @brief Pointers to TPM bases for each instance. */ static TPM_Type *const s_tpmBases[] = TPM_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to TPM clocks for each instance. */ static const clock_ip_name_t s_tpmClocks[] = TPM_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -82,8 +84,10 @@ void TPM_Init(TPM_Type *base, const tpm_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the module clock */ CLOCK_EnableClock(s_tpmClocks[TPM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(FSL_FEATURE_TPM_HAS_GLOBAL) && FSL_FEATURE_TPM_HAS_GLOBAL /* TPM reset is available on certain SoC's */ @@ -118,8 +122,10 @@ void TPM_Deinit(TPM_Type *base) { /* Stop the counter */ base->SC &= ~TPM_SC_CMOD_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the TPM clock */ CLOCK_DisableClock(s_tpmClocks[TPM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void TPM_GetDefaultConfig(tpm_config_t *config) @@ -162,6 +168,12 @@ status_t TPM_SetupPwm(TPM_Type *base, assert(pwmFreq_Hz); assert(numOfChnls); assert(srcClock_Hz); +#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE + if(mode == kTPM_CombinedPwm) + { + assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base)); + } +#endif uint32_t mod; uint32_t tpmClock = (srcClock_Hz / (1U << (base->SC & TPM_SC_PS_MASK))); @@ -169,8 +181,12 @@ status_t TPM_SetupPwm(TPM_Type *base, uint8_t i; #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - /* Clear quadrature Decoder mode because in quadrature Decoder mode PWM doesn't operate*/ - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) + { + /* Clear quadrature Decoder mode because in quadrature Decoder mode PWM doesn't operate*/ + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } #endif switch (mode) @@ -351,6 +367,12 @@ void TPM_UpdatePwmDutycycle(TPM_Type *base, uint8_t dutyCyclePercent) { assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); +#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE + if(currentPwmMode == kTPM_CombinedPwm) + { + assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base)); + } +#endif uint16_t cnv, mod; @@ -401,7 +423,7 @@ void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_ /* Wait till mode change to disable channel is acknowledged */ while ((base->CONTROLS[chnlNumber].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } @@ -424,16 +446,24 @@ void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capt assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - /* Clear quadrature Decoder mode for channel 0 or 1*/ - if ((chnlNumber == 0) || (chnlNumber == 1)) + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) { - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* Clear quadrature Decoder mode for channel 0 or 1*/ + if ((chnlNumber == 0) || (chnlNumber == 1)) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } } #endif #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE - /* Clear the combine bit for chnlNumber */ - base->COMBINE &= ~(1U << TPM_COMBINE_SHIFT * (chnlNumber / 2)); + /* The TPM's COMBINE register required to be effective */ + if( FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base) ) + { + /* Clear the combine bit for chnlNumber */ + base->COMBINE &= ~(1U << TPM_COMBINE_SHIFT * (chnlNumber / 2)); + } #endif /* When switching mode, disable channel first */ @@ -464,10 +494,14 @@ void TPM_SetupOutputCompare(TPM_Type *base, assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - /* Clear quadrature Decoder mode for channel 0 or 1 */ - if ((chnlNumber == 0) || (chnlNumber == 1)) + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) { - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* Clear quadrature Decoder mode for channel 0 or 1 */ + if ((chnlNumber == 0) || (chnlNumber == 1)) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } } #endif @@ -502,13 +536,19 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, { assert(edgeParam); assert(chnlPairNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2); + assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base)); uint32_t reg; -/* Clear quadrature Decoder mode for channel 0 or 1*/ + #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - if (chnlPairNumber == 0) + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) { - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* Clear quadrature Decoder mode for channel 0 or 1*/ + if (chnlPairNumber == 0) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } } #endif @@ -518,7 +558,7 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, /* Wait till mode change to disable channel is acknowledged */ while ((base->CONTROLS[chnlPairNumber * 2].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } @@ -527,7 +567,7 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, /* Wait till mode change to disable channel is acknowledged */ while ((base->CONTROLS[chnlPairNumber * 2 + 1].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } @@ -589,6 +629,7 @@ void TPM_SetupQuadDecode(TPM_Type *base, { assert(phaseAParams); assert(phaseBParams); + assert(FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base)); base->CONTROLS[0].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h index a15e44c1fbf..a1694b37d32 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,8 +37,6 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -525,6 +523,47 @@ static inline void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask) /*! @}*/ +/*! + * @name Read and write the timer period + * @{ + */ + +/*! + * @brief Sets the timer period in units of ticks. + * + * Timers counts from 0 until it equals the count value set here. The count value is written to + * the MOD register. + * + * @note + * 1. This API allows the user to use the TPM module as a timer. Do not mix usage + * of this API with TPM's PWM setup API's. + * 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks. + * + * @param base TPM peripheral base address + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. + */ +static inline void TPM_SetTimerPeriod(TPM_Type *base, uint32_t ticks) +{ + base->MOD = ticks; +} + +/*! + * @brief Reads the current timer counting value. + * + * This function returns the real-time timer counting value in a range from 0 to a + * timer period. + * + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. + * + * @param base TPM peripheral base address + * + * @return The current counter value in ticks + */ +static inline uint32_t TPM_GetCurrentTimerCount(TPM_Type *base) +{ + return (uint32_t)((base->CNT & TPM_CNT_COUNT_MASK) >> TPM_CNT_COUNT_SHIFT); +} + /*! * @name Timer Start and Stop * @{ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c index 6acb64e7e0b..c299c90f633 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014 - 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -36,7 +36,9 @@ void TSI_Init(TSI_Type *base, const tsi_config_t *config) bool is_module_enabled = false; bool is_int_enabled = false; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Tsi0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ if (base->GENCS & TSI_GENCS_TSIEN_MASK) { is_module_enabled = true; @@ -47,18 +49,31 @@ void TSI_Init(TSI_Type *base, const tsi_config_t *config) is_int_enabled = true; TSI_DisableInterrupts(base, kTSI_GlobalInterruptEnable); } - - TSI_SetHighThreshold(base, config->thresh); - TSI_SetLowThreshold(base, config->thresl); - TSI_SetElectrodeOSCPrescaler(base, config->prescaler); - TSI_SetReferenceChargeCurrent(base, config->refchrg); - TSI_SetElectrodeChargeCurrent(base, config->extchrg); - TSI_SetNumberOfScans(base, config->nscn); - TSI_SetAnalogMode(base, config->mode); - TSI_SetOscVoltageRails(base, config->dvolt); - TSI_SetElectrodeSeriesResistor(base, config->resistor); - TSI_SetFilterBits(base, config->filter); - + + if(config->mode == kTSI_AnalogModeSel_Capacitive) + { + TSI_SetHighThreshold(base, config->thresh); + TSI_SetLowThreshold(base, config->thresl); + TSI_SetElectrodeOSCPrescaler(base, config->prescaler); + TSI_SetReferenceChargeCurrent(base, config->refchrg); + TSI_SetElectrodeChargeCurrent(base, config->extchrg); + TSI_SetNumberOfScans(base, config->nscn); + TSI_SetAnalogMode(base, config->mode); + TSI_SetOscVoltageRails(base, config->dvolt); + } + else /* For noise modes */ + { + TSI_SetHighThreshold(base, config->thresh); + TSI_SetLowThreshold(base, config->thresl); + TSI_SetElectrodeOSCPrescaler(base, config->prescaler); + TSI_SetReferenceChargeCurrent(base, config->refchrg); + TSI_SetNumberOfScans(base, config->nscn); + TSI_SetAnalogMode(base, config->mode); + TSI_SetOscVoltageRails(base, config->dvolt); + TSI_SetElectrodeSeriesResistor(base, config->resistor); + TSI_SetFilterBits(base, config->filter); + } + if (is_module_enabled) { TSI_EnableModule(base, true); @@ -74,7 +89,9 @@ void TSI_Deinit(TSI_Type *base) base->GENCS = 0U; base->DATA = 0U; base->TSHD = 0U; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(kCLOCK_Tsi0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void TSI_GetNormalModeDefaultConfig(tsi_config_t *userConfig) @@ -82,13 +99,11 @@ void TSI_GetNormalModeDefaultConfig(tsi_config_t *userConfig) userConfig->thresh = 0U; userConfig->thresl = 0U; userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_5time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_3; } void TSI_GetLowPowerModeDefaultConfig(tsi_config_t *userConfig) @@ -96,13 +111,11 @@ void TSI_GetLowPowerModeDefaultConfig(tsi_config_t *userConfig) userConfig->thresh = 400U; userConfig->thresl = 0U; userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_5time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_3; } void TSI_Calibrate(TSI_Type *base, tsi_calibration_data_t *calBuff) @@ -135,44 +148,56 @@ void TSI_Calibrate(TSI_Type *base, tsi_calibration_data_t *calBuff) void TSI_EnableInterrupts(TSI_Type *base, uint32_t mask) { + uint32_t regValue = base->GENCS & (~ALL_FLAGS_MASK); + if (mask & kTSI_GlobalInterruptEnable) { - base->GENCS |= TSI_GENCS_TSIIEN_MASK; + regValue |= TSI_GENCS_TSIIEN_MASK; } if (mask & kTSI_OutOfRangeInterruptEnable) { - base->GENCS &= ~TSI_GENCS_ESOR_MASK; + regValue &= (~TSI_GENCS_ESOR_MASK); } if (mask & kTSI_EndOfScanInterruptEnable) { - base->GENCS |= TSI_GENCS_ESOR_MASK; + regValue |= TSI_GENCS_ESOR_MASK; } + + base->GENCS = regValue; /* write value to register */ } void TSI_DisableInterrupts(TSI_Type *base, uint32_t mask) { + uint32_t regValue = base->GENCS & (~ALL_FLAGS_MASK); + if (mask & kTSI_GlobalInterruptEnable) { - base->GENCS &= ~TSI_GENCS_TSIIEN_MASK; + regValue &= (~TSI_GENCS_TSIIEN_MASK); } if (mask & kTSI_OutOfRangeInterruptEnable) { - base->GENCS |= TSI_GENCS_ESOR_MASK; + regValue |= TSI_GENCS_ESOR_MASK; } if (mask & kTSI_EndOfScanInterruptEnable) { - base->GENCS &= ~TSI_GENCS_ESOR_MASK; + regValue &= (~TSI_GENCS_ESOR_MASK); } + + base->GENCS = regValue; /* write value to register */ } void TSI_ClearStatusFlags(TSI_Type *base, uint32_t mask) { + uint32_t regValue = base->GENCS & (~ALL_FLAGS_MASK); + if (mask & kTSI_EndOfScanFlag) { - base->GENCS = (base->GENCS & ~(TSI_GENCS_EOSF_MASK | TSI_GENCS_OUTRGF_MASK)) | TSI_GENCS_EOSF_MASK; + regValue |= TSI_GENCS_EOSF_MASK; } if (mask & kTSI_OutOfRangeFlag) { - base->GENCS = (base->GENCS & ~(TSI_GENCS_EOSF_MASK | TSI_GENCS_OUTRGF_MASK)) | TSI_GENCS_OUTRGF_MASK; + regValue |= TSI_GENCS_OUTRGF_MASK; } + + base->GENCS = regValue; /* write value to register */ } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h index d389a4d505f..3c204807db6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,10 +44,13 @@ /*! @name Driver version */ /*@{*/ -/*! @brief TSI driver version 2.0.0. */ -#define FSL_TSI_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief TSI driver version */ +#define FSL_TSI_DRIVER_VERSION (MAKE_VERSION(2, 1, 2)) /*@}*/ +/*! @brief TSI status flags macro collection */ +#define ALL_FLAGS_MASK (TSI_GENCS_EOSF_MASK | TSI_GENCS_OUTRGF_MASK) + /*! @brief resistor bit shift in EXTCHRG bit-field */ #define TSI_V4_EXTCHRG_RESISTOR_BIT_SHIFT TSI_GENCS_EXTCHRG_SHIFT @@ -57,11 +59,11 @@ /*! @brief macro of clearing the resistor bit in EXTCHRG bit-field */ #define TSI_V4_EXTCHRG_RESISTOR_BIT_CLEAR \ - ((uint32_t)((~TSI_GENCS_EXTCHRG_MASK) | (3U << TSI_V4_EXTCHRG_FILTER_BITS_SHIFT))) + ((uint32_t)((~(ALL_FLAGS_MASK | TSI_GENCS_EXTCHRG_MASK)) | (3U << TSI_V4_EXTCHRG_FILTER_BITS_SHIFT))) /*! @brief macro of clearing the filter bits in EXTCHRG bit-field */ #define TSI_V4_EXTCHRG_FILTER_BITS_CLEAR \ - ((uint32_t)((~TSI_GENCS_EXTCHRG_MASK) | (1U << TSI_V4_EXTCHRG_RESISTOR_BIT_SHIFT))) + ((uint32_t)((~(ALL_FLAGS_MASK | TSI_GENCS_EXTCHRG_MASK)) | (1U << TSI_V4_EXTCHRG_RESISTOR_BIT_SHIFT))) /*! * @brief TSI number of scan intervals for each electrode. @@ -286,13 +288,11 @@ void TSI_Deinit(TSI_Type *base); * The user configure is set to these values: * @code userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_10time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_1; userConfig->thresh = 0U; userConfig->thresl = 0U; @endcode @@ -308,13 +308,11 @@ void TSI_GetNormalModeDefaultConfig(tsi_config_t *userConfig); * The user configure is set to these values: * @code userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_10time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_1; userConfig->thresh = 400U; userConfig->thresl = 0U; @endcode @@ -417,7 +415,7 @@ static inline bool TSI_IsScanInProgress(TSI_Type *base) */ static inline void TSI_SetElectrodeOSCPrescaler(TSI_Type *base, tsi_electrode_osc_prescaler_t prescaler) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_PS_MASK) | (TSI_GENCS_PS(prescaler)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_PS_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_PS(prescaler)); } /*! @@ -429,7 +427,7 @@ static inline void TSI_SetElectrodeOSCPrescaler(TSI_Type *base, tsi_electrode_os */ static inline void TSI_SetNumberOfScans(TSI_Type *base, tsi_n_consecutive_scans_t number) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_NSCN_MASK) | (TSI_GENCS_NSCN(number)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_NSCN_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_NSCN(number)); } /*! @@ -445,11 +443,11 @@ static inline void TSI_EnableModule(TSI_Type *base, bool enable) { if (enable) { - base->GENCS |= TSI_GENCS_TSIEN_MASK; /* Enable module */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_TSIEN_MASK; /* Enable module */ } else { - base->GENCS &= ~TSI_GENCS_TSIEN_MASK; /* Disable module */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_TSIEN_MASK); /* Disable module */ } } @@ -467,11 +465,11 @@ static inline void TSI_EnableLowPower(TSI_Type *base, bool enable) { if (enable) { - base->GENCS |= TSI_GENCS_STPE_MASK; /* Module enabled in low power stop modes */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_STPE_MASK; /* Module enabled in low power stop modes */ } else { - base->GENCS &= ~TSI_GENCS_STPE_MASK; /* Module disabled in low power stop modes */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_STPE_MASK); /* Module disabled in low power stop modes */ } } @@ -488,11 +486,11 @@ static inline void TSI_EnableHardwareTriggerScan(TSI_Type *base, bool enable) { if (enable) { - base->GENCS |= TSI_GENCS_STM_MASK; /* Enable hardware trigger scan */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_STM_MASK; /* Enable hardware trigger scan */ } else { - base->GENCS &= ~TSI_GENCS_STM_MASK; /* Enable software trigger scan */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_STM_MASK); /* Enable software trigger scan */ } } @@ -567,12 +565,12 @@ static inline void TSI_EnableEndOfScanDmaTransferOnly(TSI_Type *base, bool enabl { if (enable) { - base->GENCS |= TSI_GENCS_EOSDMEO_MASK; /* Enable End of Scan DMA transfer request only; */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_EOSDMEO_MASK; /* Enable End of Scan DMA transfer request only; */ } else { - base->GENCS &= - ~TSI_GENCS_EOSDMEO_MASK; /* Both End-of-Scan and Out-of-Range can generate DMA transfer request. */ + base->GENCS = + (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_EOSDMEO_MASK); /* Both End-of-Scan and Out-of-Range can generate DMA transfer request. */ } } #endif /* End of (FSL_FEATURE_TSI_HAS_END_OF_SCAN_DMA_ENABLE == 1)*/ @@ -625,7 +623,7 @@ static inline void TSI_SetHighThreshold(TSI_Type *base, uint16_t high_threshold) */ static inline void TSI_SetAnalogMode(TSI_Type *base, tsi_analog_mode_t mode) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_MODE_MASK) | (TSI_GENCS_MODE(mode)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_MODE_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_MODE(mode)); } /*! @@ -648,7 +646,7 @@ static inline uint8_t TSI_GetNoiseModeResult(TSI_Type *base) */ static inline void TSI_SetReferenceChargeCurrent(TSI_Type *base, tsi_reference_osc_charge_current_t current) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_REFCHRG_MASK) | (TSI_GENCS_REFCHRG(current)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_REFCHRG_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_REFCHRG(current)); } /*! @@ -660,7 +658,7 @@ static inline void TSI_SetReferenceChargeCurrent(TSI_Type *base, tsi_reference_o */ static inline void TSI_SetElectrodeChargeCurrent(TSI_Type *base, tsi_external_osc_charge_current_t current) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_EXTCHRG_MASK) | (TSI_GENCS_EXTCHRG(current)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_EXTCHRG_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_EXTCHRG(current)); } /*! @@ -672,7 +670,7 @@ static inline void TSI_SetElectrodeChargeCurrent(TSI_Type *base, tsi_external_os */ static inline void TSI_SetOscVoltageRails(TSI_Type *base, tsi_osc_voltage_rails_t dvolt) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_DVOLT_MASK) | (TSI_GENCS_DVOLT(dvolt)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_DVOLT_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_DVOLT(dvolt)); } /*! diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c index b0b92399db4..17d9260027b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,10 +37,12 @@ /* UART transfer state. */ enum _uart_tansfer_states { - kUART_TxIdle, /* TX idle. */ - kUART_TxBusy, /* TX busy. */ - kUART_RxIdle, /* RX idle. */ - kUART_RxBusy /* RX busy. */ + kUART_TxIdle, /* TX idle. */ + kUART_TxBusy, /* TX busy. */ + kUART_RxIdle, /* RX idle. */ + kUART_RxBusy, /* RX busy. */ + kUART_RxFramingError, /* Rx framing error */ + kUART_RxParityError /* Rx parity error */ }; /* Typedef for interrupt handler. */ @@ -138,8 +140,10 @@ static UART_Type *const s_uartBases[] = UART_BASE_PTRS; /* Array of UART IRQ number. */ static const IRQn_Type s_uartIRQ[] = UART_RX_TX_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of UART clock name. */ static const clock_ip_name_t s_uartClock[] = UART_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* UART ISR for transactional APIs. */ static uart_isr_t s_uartIsr; @@ -169,6 +173,8 @@ uint32_t UART_GetInstance(UART_Type *base) static size_t UART_TransferGetRxRingBufferLength(uart_handle_t *handle) { + assert(handle); + size_t size; if (handle->rxRingBufferTail > handle->rxRingBufferHead) @@ -185,6 +191,8 @@ static size_t UART_TransferGetRxRingBufferLength(uart_handle_t *handle) static bool UART_TransferIsRxRingBufferFull(uart_handle_t *handle) { + assert(handle); + bool full; if (UART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U)) @@ -199,36 +207,72 @@ static bool UART_TransferIsRxRingBufferFull(uart_handle_t *handle) return full; } -void UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz) +status_t UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz) { assert(config); + assert(config->baudRate_Bps); #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO assert(FSL_FEATURE_UART_FIFO_SIZEn(base) >= config->txFifoWatermark); assert(FSL_FEATURE_UART_FIFO_SIZEn(base) >= config->rxFifoWatermark); #endif - uint16_t sbr; - uint8_t temp; + uint16_t sbr = 0; + uint8_t temp = 0; + uint32_t baudDiff = 0; + + /* Calculate the baud rate modulo divisor, sbr*/ + sbr = srcClock_Hz / (config->baudRate_Bps * 16); + /* set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate */ + if (sbr == 0) + { + sbr = 1; + } +#if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT + /* Determine if a fractional divider is needed to fine tune closer to the + * desired baud, each value of brfa is in 1/32 increments, + * hence the multiply-by-32. */ + uint32_t tempBaud = 0; + + uint16_t brfa = (2 * srcClock_Hz / (config->baudRate_Bps)) - 32 * sbr; + + /* Calculate the baud rate based on the temporary SBR values and BRFA */ + tempBaud = (srcClock_Hz * 2 / ((sbr * 32 + brfa))); + baudDiff = + (tempBaud > config->baudRate_Bps) ? (tempBaud - config->baudRate_Bps) : (config->baudRate_Bps - tempBaud); +#else + /* Calculate the baud rate based on the temporary SBR values */ + baudDiff = (srcClock_Hz / (sbr * 16)) - config->baudRate_Bps; + + /* Select the better value between sbr and (sbr + 1) */ + if (baudDiff > (config->baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))))) + { + baudDiff = config->baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))); + sbr++; + } +#endif + + /* next, check to see if actual baud rate is within 3% of desired baud rate + * based on the calculate SBR value */ + if (baudDiff > ((config->baudRate_Bps / 100) * 3)) + { + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_UART_BaudrateNotSupport; + } + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable uart clock */ CLOCK_EnableClock(s_uartClock[UART_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Disable UART TX RX before setting. */ base->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); - /* Calculate the baud rate modulo divisor, sbr*/ - sbr = srcClock_Hz / (config->baudRate_Bps * 16); - /* Write the sbr value to the BDH and BDL registers*/ base->BDH = (base->BDH & ~UART_BDH_SBR_MASK) | (uint8_t)(sbr >> 8); base->BDL = (uint8_t)sbr; #if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT - /* Determine if a fractional divider is needed to fine tune closer to the - * desired baud, each value of brfa is in 1/32 increments, - * hence the multiply-by-32. */ - uint16_t brfa = (32 * srcClock_Hz / (config->baudRate_Bps * 16)) - 32 * sbr; - /* Write the brfa value to the register*/ base->C4 = (base->C4 & ~UART_C4_BRFA_MASK) | (brfa & UART_C4_BRFA_MASK); #endif @@ -274,6 +318,8 @@ void UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_H } base->C2 = temp; + + return kStatus_Success; } void UART_Deinit(UART_Type *base) @@ -292,8 +338,10 @@ void UART_Deinit(UART_Type *base) /* Disable the module. */ base->C2 = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable uart clock */ CLOCK_DisableClock(s_uartClock[UART_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void UART_GetDefaultConfig(uart_config_t *config) @@ -313,61 +361,101 @@ void UART_GetDefaultConfig(uart_config_t *config) config->enableRx = false; } -void UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) +status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) { - uint16_t sbr; - uint8_t oldCtrl; - - /* Store C2 before disable Tx and Rx */ - oldCtrl = base->C2; + assert(baudRate_Bps); - /* Disable UART TX RX before setting. */ - base->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); + uint16_t sbr = 0; + uint32_t baudDiff = 0; + uint8_t oldCtrl; /* Calculate the baud rate modulo divisor, sbr*/ sbr = srcClock_Hz / (baudRate_Bps * 16); - - /* Write the sbr value to the BDH and BDL registers*/ - base->BDH = (base->BDH & ~UART_BDH_SBR_MASK) | (uint8_t)(sbr >> 8); - base->BDL = (uint8_t)sbr; - + /* set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate */ + if (sbr == 0) + { + sbr = 1; + } #if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT /* Determine if a fractional divider is needed to fine tune closer to the * desired baud, each value of brfa is in 1/32 increments, * hence the multiply-by-32. */ - uint16_t brfa = (32 * srcClock_Hz / (baudRate_Bps * 16)) - 32 * sbr; + uint32_t tempBaud = 0; - /* Write the brfa value to the register*/ - base->C4 = (base->C4 & ~UART_C4_BRFA_MASK) | (brfa & UART_C4_BRFA_MASK); + uint16_t brfa = (2 * srcClock_Hz / (baudRate_Bps)) - 32 * sbr; + + /* Calculate the baud rate based on the temporary SBR values and BRFA */ + tempBaud = (srcClock_Hz * 2 / ((sbr * 32 + brfa))); + baudDiff = (tempBaud > baudRate_Bps) ? (tempBaud - baudRate_Bps) : (baudRate_Bps - tempBaud); +#else + /* Calculate the baud rate based on the temporary SBR values */ + baudDiff = (srcClock_Hz / (sbr * 16)) - baudRate_Bps; + + /* Select the better value between sbr and (sbr + 1) */ + if (baudDiff > (baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))))) + { + baudDiff = baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))); + sbr++; + } +#endif + + /* next, check to see if actual baud rate is within 3% of desired baud rate + * based on the calculate SBR value */ + if (baudDiff < ((baudRate_Bps / 100) * 3)) + { + /* Store C2 before disable Tx and Rx */ + oldCtrl = base->C2; + + /* Disable UART TX RX before setting. */ + base->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); + + /* Write the sbr value to the BDH and BDL registers*/ + base->BDH = (base->BDH & ~UART_BDH_SBR_MASK) | (uint8_t)(sbr >> 8); + base->BDL = (uint8_t)sbr; + +#if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT + /* Write the brfa value to the register*/ + base->C4 = (base->C4 & ~UART_C4_BRFA_MASK) | (brfa & UART_C4_BRFA_MASK); #endif + /* Restore C2. */ + base->C2 = oldCtrl; - /* Restore C2. */ - base->C2 = oldCtrl; + return kStatus_Success; + } + else + { + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_UART_BaudrateNotSupport; + } } void UART_EnableInterrupts(UART_Type *base, uint32_t mask) { + mask &= kUART_AllInterruptsEnable; + /* The interrupt mask is combined by control bits from several register: ((CFIFO<<24) | (C3<<16) | (C2<<8) |(BDH)) */ - base->BDH |= (mask & 0xFF); - base->C2 |= ((mask >> 8) & 0xFF); - base->C3 |= ((mask >> 16) & 0xFF); + base->BDH |= mask; + base->C2 |= (mask >> 8); + base->C3 |= (mask >> 16); #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO - base->CFIFO |= ((mask >> 24) & 0xFF); + base->CFIFO |= (mask >> 24); #endif } void UART_DisableInterrupts(UART_Type *base, uint32_t mask) { + mask &= kUART_AllInterruptsEnable; + /* The interrupt mask is combined by control bits from several register: ((CFIFO<<24) | (C3<<16) | (C2<<8) |(BDH)) */ - base->BDH &= ~(mask & 0xFF); - base->C2 &= ~((mask >> 8) & 0xFF); - base->C3 &= ~((mask >> 16) & 0xFF); + base->BDH &= ~mask; + base->C2 &= ~(mask >> 8); + base->C3 &= ~(mask >> 16); #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO - base->CFIFO &= ~((mask >> 24) & 0xFF); + base->CFIFO &= ~(mask >> 24); #endif } @@ -381,7 +469,7 @@ uint32_t UART_GetEnabledInterrupts(UART_Type *base) temp |= ((uint32_t)(base->CFIFO) << 24); #endif - return temp; + return temp & kUART_AllInterruptsEnable; } uint32_t UART_GetStatusFlags(UART_Type *base) @@ -418,14 +506,24 @@ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask) base->SFIFO = (uint8_t)(mask >> 24); #endif - if (mask & (kUART_IdleLineFlag | kUART_RxOverrunFlag | kUART_NoiseErrorFlag | kUART_FramingErrorFlag | - kUART_ParityErrorFlag)) + if (mask & (kUART_IdleLineFlag | kUART_NoiseErrorFlag | kUART_FramingErrorFlag | kUART_ParityErrorFlag)) { /* Read base->D to clear the flags. */ (void)base->S1; (void)base->D; } + if (mask & kUART_RxOverrunFlag) + { + /* Read base->D to clear the flags and Flush all data in FIFO. */ + (void)base->S1; + (void)base->D; +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + } + /* If some flags still pending. */ if (mask & UART_GetStatusFlags(base)) { @@ -457,6 +555,8 @@ void UART_WriteBlocking(UART_Type *base, const uint8_t *data, size_t length) static void UART_WriteNonBlocking(UART_Type *base, const uint8_t *data, size_t length) { + assert(data); + size_t i; /* The Non Blocking write data API assume user have ensured there is enough space in @@ -469,6 +569,8 @@ static void UART_WriteNonBlocking(UART_Type *base, const uint8_t *data, size_t l status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length) { + assert(data); + uint32_t statusFlag; while (length--) @@ -509,6 +611,8 @@ status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length) static void UART_ReadNonBlocking(UART_Type *base, uint8_t *data, size_t length) { + assert(data); + size_t i; /* The Non Blocking read data API assume user have ensured there is enough space in @@ -558,7 +662,6 @@ void UART_TransferCreateHandle(UART_Type *base, s_uartHandle[instance] = handle; s_uartIsr = UART_TransferHandleIRQ; - /* Enable interrupt in NVIC. */ EnableIRQ(s_uartIRQ[instance]); } @@ -566,17 +669,21 @@ void UART_TransferCreateHandle(UART_Type *base, void UART_TransferStartRingBuffer(UART_Type *base, uart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize) { assert(handle); + assert(ringBuffer); /* Setup the ringbuffer address */ - if (ringBuffer) - { - handle->rxRingBuffer = ringBuffer; - handle->rxRingBufferSize = ringBufferSize; - handle->rxRingBufferHead = 0U; - handle->rxRingBufferTail = 0U; + handle->rxRingBuffer = ringBuffer; + handle->rxRingBufferSize = ringBufferSize; + handle->rxRingBufferHead = 0U; + handle->rxRingBufferTail = 0U; - /* Enable the interrupt to accept the data when user need the ring buffer. */ - UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Enable the interrupt to accept the data when user need the ring buffer. */ + UART_EnableInterrupts( + base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | kUART_FramingErrorInterruptEnable); + /* Enable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_EnableInterrupts(base, kUART_ParityErrorInterruptEnable); } } @@ -586,7 +693,13 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle) if (handle->rxState == kUART_RxIdle) { - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } handle->rxRingBuffer = NULL; @@ -597,13 +710,12 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle) status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, uart_transfer_t *xfer) { - status_t status; + assert(handle); + assert(xfer); + assert(xfer->dataSize); + assert(xfer->data); - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } + status_t status; /* Return error if current TX busy. */ if (kUART_TxBusy == handle->txState) @@ -628,6 +740,8 @@ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, ua void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle) { + assert(handle); + UART_DisableInterrupts(base, kUART_TxDataRegEmptyInterruptEnable | kUART_TransmissionCompleteInterruptEnable); handle->txDataSize = 0; @@ -636,16 +750,14 @@ void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle) status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - *count = handle->txDataSizeAll - handle->txDataSize; return kStatus_Success; @@ -656,6 +768,11 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, uart_transfer_t *xfer, size_t *receivedBytes) { + assert(handle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); + uint32_t i; status_t status; /* How many bytes to copy from ring buffer to user memory. */ @@ -664,13 +781,6 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, size_t bytesToReceive; /* How many bytes currently have received. */ size_t bytesCurrentReceived; - uint32_t regPrimask = 0U; - - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } /* How to get data: 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize @@ -694,8 +804,8 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, /* If RX ring buffer is used. */ if (handle->rxRingBuffer) { - /* Disable IRQ, protect ring buffer. */ - regPrimask = DisableGlobalIRQ(); + /* Disable UART RX IRQ, protect ring buffer. */ + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable); /* How many bytes in RX ring buffer currently. */ bytesToCopy = UART_TransferGetRxRingBufferLength(handle); @@ -733,8 +843,8 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, handle->rxState = kUART_RxBusy; } - /* Enable IRQ if previously enabled. */ - EnableGlobalIRQ(regPrimask); + /* Enable UART RX IRQ if previously enabled. */ + UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable); /* Call user callback since all data are received. */ if (0 == bytesToReceive) @@ -753,8 +863,14 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, handle->rxDataSizeAll = bytesToReceive; handle->rxState = kUART_RxBusy; - /* Enable RX interrupt. */ - UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Enable RX/Rx overrun/framing error interrupt. */ + UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Enable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_EnableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } /* Return the how many bytes have read. */ @@ -771,11 +887,19 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle) { + assert(handle); + /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */ if (!handle->rxRingBuffer) { /* Disable RX interrupt. */ - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } handle->rxDataSize = 0U; @@ -784,6 +908,9 @@ void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle) status_t UART_TransferGetReceiveCount(UART_Type *base, uart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; @@ -801,17 +928,67 @@ status_t UART_TransferGetReceiveCount(UART_Type *base, uart_handle_t *handle, ui void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) { + assert(handle); + uint8_t count; uint8_t tempCount; - assert(handle); + /* If RX framing error */ + if (UART_S1_FE_MASK & base->S1) + { + /* Read base->D to clear framing error flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + + handle->rxState = kUART_RxFramingError; + handle->rxDataSize = 0U; + /* Trigger callback. */ + if (handle->callback) + { + handle->callback(base, handle, kStatus_UART_FramingError, handle->userData); + } + } + + /* If RX parity error */ + if (UART_S1_PF_MASK & base->S1) + { + /* Read base->D to clear parity error flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + + handle->rxState = kUART_RxParityError; + handle->rxDataSize = 0U; + /* Trigger callback. */ + if (handle->callback) + { + handle->callback(base, handle, kStatus_UART_ParityError, handle->userData); + } + } /* If RX overrun. */ if (UART_S1_OR_MASK & base->S1) { - /* Read base->D, otherwise the RX does not work. */ - (void)base->D; - + /* Read base->D to clear overrun flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif /* Trigger callback. */ if (handle->callback) { @@ -898,16 +1075,38 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) } } } - /* If no receive requst pending, stop RX interrupt. */ + else if (!handle->rxDataSize) { - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Disable RX interrupt/overrun interrupt/fram error interrupt */ + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } else { } } + /* If framing error or parity error happened, stop the RX interrupt when ues no ring buffer */ + if (((handle->rxState == kUART_RxFramingError) || (handle->rxState == kUART_RxParityError)) && + (!handle->rxRingBuffer)) + { + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } + } + /* Send data register empty and the interrupt is enabled. */ if ((base->S1 & UART_S1_TDRE_MASK) && (base->C2 & UART_C2_TIE_MASK)) { @@ -952,7 +1151,7 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) void UART_TransferHandleErrorIRQ(UART_Type *base, uart_handle_t *handle) { - /* TODO: To be implemented. */ + /* To be implemented by User. */ } #if defined(UART0) @@ -992,7 +1191,6 @@ void UART2_RX_TX_DriverIRQHandler(void) { UART2_DriverIRQHandler(); } - #endif #if defined(UART3) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h index 3eec4e66b58..451baa9ffd3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,16 +37,14 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief UART driver version 2.1.0. */ -#define FSL_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief UART driver version 2.1.4. */ +#define FSL_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 4)) /*@}*/ /*! @brief Error codes for the UART driver. */ @@ -66,6 +64,8 @@ enum _uart_status kStatus_UART_NoiseError = MAKE_STATUS(kStatusGroup_UART, 10), /*!< UART noise error. */ kStatus_UART_FramingError = MAKE_STATUS(kStatusGroup_UART, 11), /*!< UART framing error. */ kStatus_UART_ParityError = MAKE_STATUS(kStatusGroup_UART, 12), /*!< UART parity error. */ + kStatus_UART_BaudrateNotSupport = + MAKE_STATUS(kStatusGroup_UART, 13), /*!< Baudrate is not support in current clock source */ }; /*! @brief UART parity mode. */ @@ -103,10 +103,23 @@ enum _uart_interrupt_enable kUART_FramingErrorInterruptEnable = (UART_C3_FEIE_MASK << 16), /*!< Framing error flag interrupt. */ kUART_ParityErrorInterruptEnable = (UART_C3_PEIE_MASK << 16), /*!< Parity error flag interrupt. */ #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO - kUART_RxFifoOverflowInterruptEnable = (UART_CFIFO_TXOFE_MASK << 24), /*!< TX FIFO overflow interrupt. */ - kUART_TxFifoOverflowInterruptEnable = (UART_CFIFO_RXUFE_MASK << 24), /*!< RX FIFO underflow interrupt. */ + kUART_RxFifoOverflowInterruptEnable = (UART_CFIFO_RXOFE_MASK << 24), /*!< RX FIFO overflow interrupt. */ + kUART_TxFifoOverflowInterruptEnable = (UART_CFIFO_TXOFE_MASK << 24), /*!< TX FIFO overflow interrupt. */ kUART_RxFifoUnderflowInterruptEnable = (UART_CFIFO_RXUFE_MASK << 24), /*!< RX FIFO underflow interrupt. */ #endif + kUART_AllInterruptsEnable = +#if defined(FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT + kUART_LinBreakInterruptEnable | +#endif + kUART_RxActiveEdgeInterruptEnable | kUART_TxDataRegEmptyInterruptEnable | + kUART_TransmissionCompleteInterruptEnable | kUART_RxDataRegFullInterruptEnable | kUART_IdleLineInterruptEnable | + kUART_RxOverrunInterruptEnable | kUART_NoiseErrorInterruptEnable | kUART_FramingErrorInterruptEnable | + kUART_ParityErrorInterruptEnable +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + | + kUART_RxFifoOverflowInterruptEnable | kUART_TxFifoOverflowInterruptEnable | kUART_RxFifoUnderflowInterruptEnable +#endif + , }; /*! @@ -128,13 +141,16 @@ enum _uart_flags kUART_ParityErrorFlag = (UART_S1_PF_MASK), /*!< If parity enabled, sets upon parity error detection */ #if defined(FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT kUART_LinBreakFlag = - (UART_S2_LBKDIF_MASK << 8), /*!< LIN break detect interrupt flag, sets when - LIN break char detected and LIN circuit enabled */ + (UART_S2_LBKDIF_MASK + << 8), /*!< LIN break detect interrupt flag, sets when + LIN break char detected and LIN circuit enabled */ #endif - kUART_RxActiveEdgeFlag = (UART_S2_RXEDGIF_MASK << 8), /*!< RX pin active edge interrupt flag, - sets when active edge detected */ - kUART_RxActiveFlag = (UART_S2_RAF_MASK << 8), /*!< Receiver Active Flag (RAF), - sets at beginning of valid start bit */ + kUART_RxActiveEdgeFlag = + (UART_S2_RXEDGIF_MASK << 8), /*!< RX pin active edge interrupt flag, + sets when active edge detected */ + kUART_RxActiveFlag = + (UART_S2_RAF_MASK << 8), /*!< Receiver Active Flag (RAF), + sets at beginning of valid start bit */ #if defined(FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS kUART_NoiseErrorInRxDataRegFlag = (UART_ED_NOISY_MASK << 16), /*!< Noisy bit, sets if noise detected. */ kUART_ParityErrorInRxDataRegFlag = (UART_ED_PARITYE_MASK << 16), /*!< Paritye bit, sets if parity error detected. */ @@ -213,11 +229,11 @@ extern "C" { */ /*! - * @brief Initializes a UART instance with user configuration structure and peripheral clock. + * @brief Initializes a UART instance with a user configuration structure and peripheral clock. * * This function configures the UART module with the user-defined settings. The user can configure the configuration * structure and also get the default configuration by using the UART_GetDefaultConfig() function. - * Example below shows how to use this API to configure UART. + * The example below shows how to use this API to configure UART. * @code * uart_config_t uartConfig; * uartConfig.baudRate_Bps = 115200U; @@ -229,10 +245,12 @@ extern "C" { * @endcode * * @param base UART peripheral base address. - * @param config Pointer to user-defined configuration structure. + * @param config Pointer to the user-defined configuration structure. * @param srcClock_Hz UART clock source frequency in HZ. + * @retval kStatus_UART_BaudrateNotSupport Baudrate is not support in current clock source. + * @retval kStatus_Success Status UART initialize succeed */ -void UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz); +status_t UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz); /*! * @brief Deinitializes a UART instance. @@ -247,7 +265,7 @@ void UART_Deinit(UART_Type *base); * @brief Gets the default configuration structure. * * This function initializes the UART configuration structure to a default value. The default - * values are: + * values are as follows. * uartConfig->baudRate_Bps = 115200U; * uartConfig->bitCountPerChar = kUART_8BitsPerChar; * uartConfig->parityMode = kUART_ParityDisabled; @@ -272,9 +290,11 @@ void UART_GetDefaultConfig(uart_config_t *config); * * @param base UART peripheral base address. * @param baudRate_Bps UART baudrate to be set. - * @param srcClock_Hz UART clock source freqency in HZ. + * @param srcClock_Hz UART clock source freqency in Hz. + * @retval kStatus_UART_BaudrateNotSupport Baudrate is not support in the current clock source. + * @retval kStatus_Success Set baudrate succeeded. */ -void UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); +status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); /* @} */ @@ -284,12 +304,12 @@ void UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_ */ /*! - * @brief Get UART status flags. + * @brief Gets UART status flags. * - * This function get all UART status flags, the flags are returned as the logical - * OR value of the enumerators @ref _uart_flags. To check specific status, + * This function gets all UART status flags. The flags are returned as the logical + * OR value of the enumerators @ref _uart_flags. To check a specific status, * compare the return value with enumerators in @ref _uart_flags. - * For example, to check whether the TX is empty: + * For example, to check whether the TX is empty, do the following. * @code * if (kUART_TxDataRegEmptyFlag & UART_GetStatusFlags(UART1)) * { @@ -305,19 +325,19 @@ uint32_t UART_GetStatusFlags(UART_Type *base); /*! * @brief Clears status flags with the provided mask. * - * This function clears UART status flags with a provided mask. Automatically cleared flag + * This function clears UART status flags with a provided mask. An automatically cleared flag * can't be cleared by this function. - * Some flags can only be cleared or set by hardware itself. These flags are: + * These flags can only be cleared or set by hardware. * kUART_TxDataRegEmptyFlag, kUART_TransmissionCompleteFlag, kUART_RxDataRegFullFlag, * kUART_RxActiveFlag, kUART_NoiseErrorInRxDataRegFlag, kUART_ParityErrorInRxDataRegFlag, * kUART_TxFifoEmptyFlag,kUART_RxFifoEmptyFlag - * Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects. + * Note that this API should be called when the Tx/Rx is idle. Otherwise it has no effect. * * @param base UART peripheral base address. - * @param mask The status flags to be cleared, it is logical OR value of @ref _uart_flags. + * @param mask The status flags to be cleared; it is logical OR value of @ref _uart_flags. * @retval kStatus_UART_FlagCannotClearManually The flag can't be cleared by this function but * it is cleared automatically by hardware. - * @retval kStatus_Success Status in the mask are cleared. + * @retval kStatus_Success Status in the mask is cleared. */ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask); @@ -333,7 +353,7 @@ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask); * * This function enables the UART interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref _uart_interrupt_enable. - * For example, to enable TX empty interrupt and RX full interrupt: + * For example, to enable TX empty interrupt and RX full interrupt, do the following. * @code * UART_EnableInterrupts(UART1,kUART_TxDataRegEmptyInterruptEnable | kUART_RxDataRegFullInterruptEnable); * @endcode @@ -348,7 +368,7 @@ void UART_EnableInterrupts(UART_Type *base, uint32_t mask); * * This function disables the UART interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref _uart_interrupt_enable. - * For example, to disable TX empty interrupt and RX full interrupt: + * For example, to disable TX empty interrupt and RX full interrupt do the following. * @code * UART_DisableInterrupts(UART1,kUART_TxDataRegEmptyInterruptEnable | kUART_RxDataRegFullInterruptEnable); * @endcode @@ -363,9 +383,9 @@ void UART_DisableInterrupts(UART_Type *base, uint32_t mask); * * This function gets the enabled UART interrupts. The enabled interrupts are returned * as the logical OR value of the enumerators @ref _uart_interrupt_enable. To check - * specific interrupts enable status, compare the return value with enumerators + * a specific interrupts enable status, compare the return value with enumerators * in @ref _uart_interrupt_enable. - * For example, to check whether TX empty interrupt is enabled: + * For example, to check whether TX empty interrupt is enabled, do the following. * @code * uint32_t enabledInterrupts = UART_GetEnabledInterrupts(UART1); * @@ -394,7 +414,7 @@ uint32_t UART_GetEnabledInterrupts(UART_Type *base); * This function returns the UART data register address, which is mainly used by DMA/eDMA. * * @param base UART peripheral base address. - * @return UART data register address which are used both by transmitter and receiver. + * @return UART data register addresses which are used both by the transmitter and the receiver. */ static inline uint32_t UART_GetDataRegisterAddress(UART_Type *base) { @@ -526,7 +546,7 @@ static inline void UART_WriteByte(UART_Type *base, uint8_t data) /*! * @brief Reads the RX register directly. * - * This function reads data from the TX register directly. The upper layer must + * This function reads data from the RX register directly. The upper layer must * ensure that the RX register is full or that the TX FIFO has data before calling this function. * * @param base UART peripheral base address. @@ -543,7 +563,7 @@ static inline uint8_t UART_ReadByte(UART_Type *base) * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO * to have room and writes data to the TX buffer. * - * @note This function does not check whether all the data has been sent out to the bus. + * @note This function does not check whether all data is sent out to the bus. * Before disabling the TX, check kUART_TransmissionCompleteFlag to ensure that the TX is * finished. * @@ -557,15 +577,15 @@ void UART_WriteBlocking(UART_Type *base, const uint8_t *data, size_t length); * @brief Read RX data register using a blocking method. * * This function polls the RX register, waits for the RX register to be full or for RX FIFO to - * have data and read data from the TX register. + * have data, and reads data from the TX register. * * @param base UART peripheral base address. * @param data Start address of the buffer to store the received data. * @param length Size of the buffer. - * @retval kStatus_UART_RxHardwareOverrun Receiver overrun happened while receiving data. - * @retval kStatus_UART_NoiseError Noise error happened while receiving data. - * @retval kStatus_UART_FramingError Framing error happened while receiving data. - * @retval kStatus_UART_ParityError Parity error happened while receiving data. + * @retval kStatus_UART_RxHardwareOverrun Receiver overrun occurred while receiving data. + * @retval kStatus_UART_NoiseError A noise error occurred while receiving data. + * @retval kStatus_UART_FramingError A framing error occurred while receiving data. + * @retval kStatus_UART_ParityError A parity error occurred while receiving data. * @retval kStatus_Success Successfully received all data. */ status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length); @@ -600,16 +620,16 @@ void UART_TransferCreateHandle(UART_Type *base, * This function sets up the RX ring buffer to a specific UART handle. * * When the RX ring buffer is used, data received are stored into the ring buffer even when the - * user doesn't call the UART_TransferReceiveNonBlocking() API. If there is already data received + * user doesn't call the UART_TransferReceiveNonBlocking() API. If data is already received * in the ring buffer, the user can get the received data from the ring buffer directly. * * @note When using the RX ring buffer, one byte is reserved for internal use. In other - * words, if @p ringBufferSize is 32, then only 31 bytes are used for saving data. + * words, if @p ringBufferSize is 32, only 31 bytes are used for saving data. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer. - * @param ringBufferSize size of the ring buffer. + * @param ringBufferSize Size of the ring buffer. */ void UART_TransferStartRingBuffer(UART_Type *base, uart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize); @@ -632,23 +652,23 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle); * function and passes the @ref kStatus_UART_TxIdle as status parameter. * * @note The kStatus_UART_TxIdle is passed to the upper layer when all data is written - * to the TX register. However it does not ensure that all data are sent out. Before disabling the TX, + * to the TX register. However, it does not ensure that all data is sent out. Before disabling the TX, * check the kUART_TransmissionCompleteFlag to ensure that the TX is finished. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART transfer structure. See #uart_transfer_t. * @retval kStatus_Success Successfully start the data transmission. - * @retval kStatus_UART_TxBusy Previous transmission still not finished, data not all written to TX register yet. + * @retval kStatus_UART_TxBusy Previous transmission still not finished; data not all written to TX register yet. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Aborts the interrupt driven data transmit. + * @brief Aborts the interrupt-driven data transmit. * - * This function aborts the interrupt driven data sending. The user can get the remainBytes to find out - * how many bytes are still not sent out. + * This function aborts the interrupt-driven data sending. The user can get the remainBytes to find out + * how many bytes are not sent out. * * @param base UART peripheral base address. * @param handle UART handle pointer. @@ -656,16 +676,16 @@ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, ua void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes written to the UART TX register. * - * This function gets the number of bytes that have been written to UART TX - * register by interrupt method. + * This function gets the number of bytes written to the UART TX + * register by using the interrupt method. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param count Send bytes count. * @retval kStatus_NoTransferInProgress No send in progress. - * @retval kStatus_InvalidArgument Parameter is invalid. + * @retval kStatus_InvalidArgument The parameter is invalid. * @retval kStatus_Success Get successfully through the parameter \p count; */ status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint32_t *count); @@ -690,7 +710,7 @@ status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint3 * * @param base UART peripheral base address. * @param handle UART handle pointer. - * @param xfer UART transfer structure, refer to #uart_transfer_t. + * @param xfer UART transfer structure, see #uart_transfer_t. * @param receivedBytes Bytes received from the ring buffer directly. * @retval kStatus_Success Successfully queue the transfer into transmit queue. * @retval kStatus_UART_RxBusy Previous receive request is not finished. @@ -705,7 +725,7 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, * @brief Aborts the interrupt-driven data receiving. * * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to know - * how many bytes not received yet. + * how many bytes are not received yet. * * @param base UART peripheral base address. * @param handle UART handle pointer. @@ -713,7 +733,7 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of bytes that have been received. * * This function gets the number of bytes that have been received. * @@ -739,7 +759,7 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle); /*! * @brief UART Error IRQ handle function. * - * This function handle the UART error IRQ request. + * This function handles the UART error IRQ request. * * @param base UART peripheral base address. * @param handle UART handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c index 36734044860..c51e4934639 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -125,6 +125,8 @@ extern uint32_t UART_GetInstance(UART_Type *base); static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param; /* Avoid the warning for unused variables. */ @@ -145,6 +147,8 @@ static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool trans static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param; /* Avoid warning for unused parameters. */ @@ -165,11 +169,11 @@ static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool tr } void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle) + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle) { assert(handle); @@ -219,17 +223,15 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer) { + assert(handle); assert(handle->txEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous TX not finished. */ if (kUART_TxBusy == handle->txState) { @@ -244,6 +246,9 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -259,17 +264,15 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer) { + assert(handle); assert(handle->rxEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous RX not finished. */ if (kUART_RxBusy == handle->rxState) { @@ -284,6 +287,9 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran EDMA_PrepareTransfer(&xferConfig, (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -299,6 +305,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle) { + assert(handle); assert(handle->txEdmaHandle); /* Disable UART TX EDMA. */ @@ -312,6 +319,7 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle) void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle) { + assert(handle); assert(handle->rxEdmaHandle); /* Disable UART RX EDMA. */ @@ -325,38 +333,36 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle) status_t UART_TransferGetReceiveCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->rxEdmaHandle); + assert(count); if (kUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->rxDataSizeAll - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->txEdmaHandle); + assert(count); if (kUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->txDataSizeAll - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h index 52cc7373a9f..e411ffd7a44 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,8 +39,6 @@ * @{ */ -/*! @file*/ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -67,6 +65,8 @@ struct _uart_edma_handle edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -87,18 +87,18 @@ extern "C" { /*! * @brief Initializes the UART handle which is used in transactional functions. * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param callback UART callback, NULL means no callback. * @param userData User callback function data. - * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. - * @param txEdmaHandle User requested DMA handle for TX DMA transfer. + * @param rxEdmaHandle User-requested DMA handle for RX DMA transfer. + * @param txEdmaHandle User-requested DMA handle for TX DMA transfer. */ void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle); + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle); /*! * @brief Sends data using eDMA. @@ -109,23 +109,23 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_TxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_TxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Receive data using eDMA. + * @brief Receives data using eDMA. * * This function receives data using eDMA. This is a non-blocking function, which returns * right away. When all data is received, the receive callback function is called. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_RxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_RxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); @@ -136,7 +136,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran * This function aborts sent data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); @@ -146,12 +146,12 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); * This function aborts receive data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes that have been written to UART TX register. * * This function gets the number of bytes that have been written to UART TX * register by DMA. @@ -166,9 +166,9 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of received bytes. * - * This function gets the number of bytes that have been received. + * This function gets the number of received bytes. * * @param base UART peripheral base address. * @param handle UART handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c index 0854ca07577..24f2d1dc280 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -50,8 +50,10 @@ static uint32_t VREF_GetInstance(VREF_Type *base); /*! @brief Pointers to VREF bases for each instance. */ static VREF_Type *const s_vrefBases[] = VREF_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to VREF clocks for each instance. */ static const clock_ip_name_t s_vrefClocks[] = VREF_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -62,7 +64,7 @@ static uint32_t VREF_GetInstance(VREF_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_VREF_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_vrefBases); instance++) { if (s_vrefBases[instance] == base) { @@ -70,7 +72,7 @@ static uint32_t VREF_GetInstance(VREF_Type *base) } } - assert(instance < FSL_FEATURE_SOC_VREF_COUNT); + assert(instance < ARRAY_SIZE(s_vrefBases)); return instance; } @@ -81,15 +83,24 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config) uint8_t reg = 0U; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate clock for VREF */ CLOCK_EnableClock(s_vrefClocks[VREF_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure VREF to a known state */ #if defined(FSL_FEATURE_VREF_HAS_CHOP_OSC) && FSL_FEATURE_VREF_HAS_CHOP_OSC /* Set chop oscillator bit */ base->TRM |= VREF_TRM_CHOPEN_MASK; #endif /* FSL_FEATURE_VREF_HAS_CHOP_OSC */ + /* Get current SC register */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + reg = base->VREFH_SC; +#else reg = base->SC; +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ + /* Clear old buffer mode selection bits */ + reg &= ~VREF_SC_MODE_LV_MASK; /* Set buffer Mode selection and Regulator enable bit */ reg |= VREF_SC_MODE_LV(config->bufferMode) | VREF_SC_REGEN(1U); #if defined(FSL_FEATURE_VREF_HAS_COMPENSATION) && FSL_FEATURE_VREF_HAS_COMPENSATION @@ -99,30 +110,51 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config) /* Enable VREF module */ reg |= VREF_SC_VREFEN(1U); /* Update bit-field from value to Status and Control register */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + base->VREFH_SC = reg; +#else base->SC = reg; +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE reg = base->VREFL_TRM; - /* Clear old select external voltage reference and VREFL (0.4 V) reference buffer enable bits*/ + /* Clear old select external voltage reference and VREFL (0.4 V) reference buffer enable bits */ reg &= ~(VREF_VREFL_TRM_VREFL_EN_MASK | VREF_VREFL_TRM_VREFL_SEL_MASK); /* Select external voltage reference and set VREFL (0.4 V) reference buffer enable */ reg |= VREF_VREFL_TRM_VREFL_SEL(config->enableExternalVoltRef) | VREF_VREFL_TRM_VREFL_EN(config->enableLowRef); base->VREFL_TRM = reg; #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 + reg = base->TRM4; + /* Clear old select internal voltage reference bit (2.1V) */ + reg &= ~VREF_TRM4_VREF2V1_EN_MASK; + /* Select internal voltage reference (2.1V) */ + reg |= VREF_TRM4_VREF2V1_EN(config->enable2V1VoltRef); + base->TRM4 = reg; +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ + /* Wait until internal voltage stable */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0) +#else while ((base->SC & VREF_SC_VREFST_MASK) == 0) +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ { } } void VREF_Deinit(VREF_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate clock for VREF */ CLOCK_DisableClock(s_vrefClocks[VREF_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void VREF_GetDefaultConfig(vref_config_t *config) { + assert(config); + /* Set High power buffer mode in */ #if defined(FSL_FEATURE_VREF_MODE_LV_TYPE) && FSL_FEATURE_VREF_MODE_LV_TYPE config->bufferMode = kVREF_ModeHighPowerBuffer; @@ -136,6 +168,11 @@ void VREF_GetDefaultConfig(vref_config_t *config) /* Set VREFL (0.4 V) reference buffer disable */ config->enableLowRef = false; #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ + +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 + /* Disable internal voltage reference (2.1V) */ + config->enable2V1VoltRef = false; +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ } void VREF_SetTrimVal(VREF_Type *base, uint8_t trimValue) @@ -147,10 +184,30 @@ void VREF_SetTrimVal(VREF_Type *base, uint8_t trimValue) reg = ((reg & ~VREF_TRM_TRIM_MASK) | VREF_TRM_TRIM(trimValue)); base->TRM = reg; /* Wait until internal voltage stable */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0) +#else + while ((base->SC & VREF_SC_VREFST_MASK) == 0) +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ + { + } +} + +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 +void VREF_SetTrim2V1Val(VREF_Type *base, uint8_t trimValue) +{ + uint8_t reg = 0U; + + /* Set TRIM bits value in voltage reference (2V1) */ + reg = base->TRM4; + reg = ((reg & ~VREF_TRM4_TRIM2V1_MASK) | VREF_TRM4_TRIM2V1(trimValue)); + base->TRM4 = reg; + /* Wait until internal voltage stable */ while ((base->SC & VREF_SC_VREFST_MASK) == 0) { } } +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE void VREF_SetLowReferenceTrimVal(VREF_Type *base, uint8_t trimValue) @@ -165,7 +222,8 @@ void VREF_SetLowReferenceTrimVal(VREF_Type *base, uint8_t trimValue) reg = ((reg & ~VREF_VREFL_TRM_VREFL_TRIM_MASK) | VREF_VREFL_TRM_VREFL_TRIM(trimValue)); base->VREFL_TRM = reg; /* Wait until internal voltage stable */ - while ((base->SC & VREF_SC_VREFST_MASK) == 0) + + while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0) { } } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h index 79378863bb6..6c6c014b913 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /****************************************************************************** * Definitions @@ -46,12 +45,11 @@ /*! @name Driver version */ /*@{*/ -#define FSL_VREF_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ +#define FSL_VREF_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ /*@}*/ /* Those macros below defined to support SoC family which have VREFL (0.4V) reference */ #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE -#define SC VREFH_SC #define VREF_SC_MODE_LV VREF_VREFH_SC_MODE_LV #define VREF_SC_REGEN VREF_VREFH_SC_REGEN #define VREF_SC_VREFEN VREF_VREFH_SC_VREFEN @@ -80,8 +78,8 @@ typedef enum _vref_buffer_mode { kVREF_ModeBandgapOnly = 0U, /*!< Bandgap on only, for stabilization and startup */ #if defined(FSL_FEATURE_VREF_MODE_LV_TYPE) && FSL_FEATURE_VREF_MODE_LV_TYPE - kVREF_ModeHighPowerBuffer = 1U, /*!< High power buffer mode enabled */ - kVREF_ModeLowPowerBuffer = 2U /*!< Low power buffer mode enabled */ + kVREF_ModeHighPowerBuffer = 1U, /*!< High-power buffer mode enabled */ + kVREF_ModeLowPowerBuffer = 2U /*!< Low-power buffer mode enabled */ #else kVREF_ModeTightRegulationBuffer = 2U /*!< Tight regulation buffer enabled */ #endif /* FSL_FEATURE_VREF_MODE_LV_TYPE */ @@ -97,6 +95,9 @@ typedef struct _vref_config bool enableLowRef; /*!< Set VREFL (0.4 V) reference buffer enable or disable */ bool enableExternalVoltRef; /*!< Select external voltage reference or not (internal) */ #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 + bool enable2V1VoltRef; /*!< Enable Internal Voltage Reference (2.1V) */ +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ } vref_config_t; /****************************************************************************** @@ -115,11 +116,11 @@ extern "C" { /*! * @brief Enables the clock gate and configures the VREF module according to the configuration structure. * - * This function must be called before calling all the other VREF driver functions, + * This function must be called before calling all other VREF driver functions, * read/write registers, and configurations with user-defined settings. * The example below shows how to set up vref_config_t parameters and - * how to call the VREF_Init function by passing in these parameters: - * Example: + * how to call the VREF_Init function by passing in these parameters. + * This is an example. * @code * vref_config_t vrefConfig; * vrefConfig.bufferMode = kVREF_ModeHighPowerBuffer; @@ -137,7 +138,7 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config); * @brief Stops and disables the clock for the VREF module. * * This function should be called to shut down the module. - * Example: + * This is an example. * @code * vref_config_t vrefUserConfig; * VREF_Init(VREF); @@ -153,8 +154,8 @@ void VREF_Deinit(VREF_Type *base); /*! * @brief Initializes the VREF configuration structure. * - * This function initializes the VREF configuration structure to a default value. - * Example: + * This function initializes the VREF configuration structure to default values. + * This is an example. * @code * vrefConfig->bufferMode = kVREF_ModeHighPowerBuffer; * vrefConfig->enableExternalVoltRef = false; @@ -166,9 +167,9 @@ void VREF_Deinit(VREF_Type *base); void VREF_GetDefaultConfig(vref_config_t *config); /*! - * @brief Sets a TRIM value for reference voltage. + * @brief Sets a TRIM value for the reference voltage. * - * This function sets a TRIM value for reference voltage. + * This function sets a TRIM value for the reference voltage. * Note that the TRIM value maximum is 0x3F. * * @param base VREF peripheral address. @@ -188,13 +189,40 @@ static inline uint8_t VREF_GetTrimVal(VREF_Type *base) { return (base->TRM & VREF_TRM_TRIM_MASK); } + +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 +/*! + * @brief Sets a TRIM value for the reference voltage (2V1). + * + * This function sets a TRIM value for the reference voltage (2V1). + * Note that the TRIM value maximum is 0x3F. + * + * @param base VREF peripheral address. + * @param trimValue Value of the trim register to set the output reference voltage (maximum 0x3F (6-bit)). + */ +void VREF_SetTrim2V1Val(VREF_Type *base, uint8_t trimValue); + +/*! + * @brief Reads the value of the TRIM meaning output voltage (2V1). + * + * This function gets the TRIM value from the VREF_TRM4 register. + * + * @param base VREF peripheral address. + * @return Six-bit value of trim setting. + */ +static inline uint8_t VREF_GetTrim2V1Val(VREF_Type *base) +{ + return (base->TRM4 & VREF_TRM4_TRIM2V1_MASK); +} +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ + #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE /*! - * @brief Sets the TRIM value for low voltage reference. + * @brief Sets the TRIM value for the low voltage reference. * * This function sets the TRIM value for low reference voltage. - * NOTE: + * Note the following. * - The TRIM value maximum is 0x05U * - The values 111b and 110b are not valid/allowed. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c index 489798ca889..781ac133c1a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h index 949a9a8e046..580adb95a0f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup wdog_driver + * @addtogroup wdog * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -136,7 +135,7 @@ typedef struct _wdog_test_config */ enum _wdog_interrupt_enable_t { - kWDOG_InterruptEnable = WDOG_STCTRLH_IRQRSTEN_MASK, /*!< WDOG timeout will generate interrupt before reset*/ + kWDOG_InterruptEnable = WDOG_STCTRLH_IRQRSTEN_MASK, /*!< WDOG timeout generates an interrupt before reset*/ }; /*! @@ -164,10 +163,10 @@ extern "C" { */ /*! - * @brief Initializes WDOG configure sturcture. + * @brief Initializes the WDOG configuration sturcture. * - * This function initializes the WDOG configure structure to default value. The default - * value are: + * This function initializes the WDOG configuration structure to default values. The default + * values are as follows. * @code * wdogConfig->enableWdog = true; * wdogConfig->clockSource = kWDOG_LpoClockSource; @@ -182,7 +181,7 @@ extern "C" { * wdogConfig->timeoutValue = 0xFFFFU; * @endcode * - * @param config Pointer to WDOG config structure. + * @param config Pointer to the WDOG configuration structure. * @see wdog_config_t */ void WDOG_GetDefaultConfig(wdog_config_t *config); @@ -191,10 +190,10 @@ void WDOG_GetDefaultConfig(wdog_config_t *config); * @brief Initializes the WDOG. * * This function initializes the WDOG. When called, the WDOG runs according to the configuration. - * If user wants to reconfigure WDOG without forcing a reset first, enableUpdate must be set to true - * in configuration. + * To reconfigure WDOG without forcing a reset first, enableUpdate must be set to true + * in the configuration. * - * Example: + * This is an example. * @code * wdog_config_t config; * WDOG_GetDefaultConfig(&config); @@ -212,18 +211,18 @@ void WDOG_Init(WDOG_Type *base, const wdog_config_t *config); * @brief Shuts down the WDOG. * * This function shuts down the WDOG. - * Make sure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. + * Ensure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which indicates that the register update is enabled. */ void WDOG_Deinit(WDOG_Type *base); /*! - * @brief Configures WDOG functional test. + * @brief Configures the WDOG functional test. * * This function is used to configure the WDOG functional test. When called, the WDOG goes into test mode * and runs according to the configuration. - * Make sure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. + * Ensure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. * - * Example: + * This is an example. * @code * wdog_test_config_t test_config; * test_config.testMode = kWDOG_QuickTest; @@ -259,9 +258,9 @@ static inline void WDOG_Enable(WDOG_Type *base) /*! * @brief Disables the WDOG module. * - * This function write value into WDOG_STCTRLH register to disable the WDOG, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to disable the WDOG. It is a write-once register. + * Ensure that the WCT window is still open and that register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address */ @@ -271,15 +270,15 @@ static inline void WDOG_Disable(WDOG_Type *base) } /*! - * @brief Enable WDOG interrupt. + * @brief Enables the WDOG interrupt. * - * This function write value into WDOG_STCTRLH register to enable WDOG interrupt, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to enable the WDOG interrupt. It is a write-once register. + * Ensure that the WCT window is still open and the register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param mask The interrupts to enable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined. * @arg kWDOG_InterruptEnable */ static inline void WDOG_EnableInterrupts(WDOG_Type *base, uint32_t mask) @@ -288,15 +287,15 @@ static inline void WDOG_EnableInterrupts(WDOG_Type *base, uint32_t mask) } /*! - * @brief Disable WDOG interrupt. + * @brief Disables the WDOG interrupt. * - * This function write value into WDOG_STCTRLH register to disable WDOG interrupt, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to disable the WDOG interrupt. It is a write-once register. + * Ensure that the WCT window is still open and the register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param mask The interrupts to disable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined. * @arg kWDOG_InterruptEnable */ static inline void WDOG_DisableInterrupts(WDOG_Type *base, uint32_t mask) @@ -305,50 +304,50 @@ static inline void WDOG_DisableInterrupts(WDOG_Type *base, uint32_t mask) } /*! - * @brief Gets WDOG all status flags. + * @brief Gets the WDOG all status flags. * * This function gets all status flags. * - * Example for getting Running Flag: + * This is an example for getting the Running Flag. * @code * uint32_t status; - * status = WDOG_GetStatusFlags(wdog_base) & kWDOG_RunningFlag; + * status = WDOG_GetStatusFlags (wdog_base) & kWDOG_RunningFlag; * @endcode * @param base WDOG peripheral base address * @return State of the status flag: asserted (true) or not-asserted (false).@see _wdog_status_flags_t - * - true: related status flag has been set. - * - false: related status flag is not set. + * - true: a related status flag has been set. + * - false: a related status flag is not set. */ uint32_t WDOG_GetStatusFlags(WDOG_Type *base); /*! - * @brief Clear WDOG flag. + * @brief Clears the WDOG flag. * - * This function clears WDOG status flag. + * This function clears the WDOG status flag. * - * Example for clearing timeout(interrupt) flag: + * This is an example for clearing the timeout (interrupt) flag. * @code * WDOG_ClearStatusFlags(wdog_base,kWDOG_TimeoutFlag); * @endcode * @param base WDOG peripheral base address * @param mask The status flags to clear. - * The parameter could be any combination of the following values: + * The parameter could be any combination of the following values. * kWDOG_TimeoutFlag */ void WDOG_ClearStatusFlags(WDOG_Type *base, uint32_t mask); /*! - * @brief Set the WDOG timeout value. + * @brief Sets the WDOG timeout value. * * This function sets the timeout value. * It should be ensured that the time-out value for the WDOG is always greater than * 2xWCT time + 20 bus clock cycles. - * This function write value into WDOG_TOVALH and WDOG_TOVALL registers which are wirte-once. - * Make sure the WCT window is still open and these two registers have not been written in this WCT - * while this function is called. + * This function writes a value into WDOG_TOVALH and WDOG_TOVALL registers which are wirte-once. + * Ensure the WCT window is still open and the two registers have not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address - * @param timeoutCount WDOG timeout value, count of WDOG clock tick. + * @param timeoutCount WDOG timeout value; count of WDOG clock tick. */ static inline void WDOG_SetTimeoutValue(WDOG_Type *base, uint32_t timeoutCount) { @@ -360,9 +359,9 @@ static inline void WDOG_SetTimeoutValue(WDOG_Type *base, uint32_t timeoutCount) * @brief Sets the WDOG window value. * * This function sets the WDOG window value. - * This function write value into WDOG_WINH and WDOG_WINL registers which are wirte-once. - * Make sure the WCT window is still open and these two registers have not been written in this WCT - * while this function is called. + * This function writes a value into WDOG_WINH and WDOG_WINL registers which are wirte-once. + * Ensure the WCT window is still open and the two registers have not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param windowValue WDOG window value. @@ -378,7 +377,7 @@ static inline void WDOG_SetWindowValue(WDOG_Type *base, uint32_t windowValue) * * This function unlocks the WDOG register written. * Before starting the unlock sequence and following congfiguration, disable the global interrupts. - * Otherwise, an interrupt could effectively invalidate the unlock sequence and the WCT may expire, + * Otherwise, an interrupt may invalidate the unlocking sequence and the WCT may expire. * After the configuration finishes, re-enable the global interrupts. * * @param base WDOG peripheral base address @@ -393,7 +392,7 @@ static inline void WDOG_Unlock(WDOG_Type *base) * @brief Refreshes the WDOG timer. * * This function feeds the WDOG. - * This function should be called before WDOG timer is in timeout. Otherwise, a reset is asserted. + * This function should be called before the WDOG timer is in timeout. Otherwise, a reset is asserted. * * @param base WDOG peripheral base address */ @@ -405,7 +404,7 @@ void WDOG_Refresh(WDOG_Type *base); * This function gets the WDOG reset count value. * * @param base WDOG peripheral base address - * @return WDOG reset count value + * @return WDOG reset count value. */ static inline uint16_t WDOG_GetResetCount(WDOG_Type *base) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c index 8a65bd4f22a..2ca04b99c89 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c @@ -122,13 +122,17 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill) { int total = (tx_length > rx_length) ? tx_length : rx_length; - for (int i = 0; i < total; i++) { - char out = (i < tx_length) ? tx_buffer[i] : write_fill; - char in = spi_master_write(obj, out); - if (i < rx_length) { - rx_buffer[i] = in; - } - } + // Default write is done in each and every call, in future can create HAL API instead + DSPI_SetDummyData(spi_address[obj->instance], write_fill); + + DSPI_MasterTransferBlocking(spi_address[obj->instance], &(dspi_transfer_t){ + .txData = (uint8_t *)tx_buffer, + .rxData = (uint8_t *)rx_buffer, + .dataSize = total, + .configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous, + }); + + DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag); return total; } diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/cmsis_nvic.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/cmsis_nvic.h new file mode 100644 index 00000000000..584b9075a85 --- /dev/null +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/cmsis_nvic.h @@ -0,0 +1,46 @@ +/* mbed Microcontroller Library + * CMSIS-style functionality to support dynamic vectors + ******************************************************************************* + * Copyright (c) 2011 ARM Limited. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of ARM Limited nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + */ + +#ifndef MBED_CMSIS_NVIC_H +#define MBED_CMSIS_NVIC_H + +#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) +extern uint32_t Image$$VECTOR_RAM$$Base[]; +#define __VECTOR_RAM Image$$VECTOR_RAM$$Base +#else +extern uint32_t __VECTOR_RAM[]; +#endif + +/* Symbols defined by the linker script */ +#define NVIC_NUM_VECTORS (16 + 40) // CORE + MCU Peripherals +#define NVIC_RAM_VECTOR_ADDRESS (__VECTOR_RAM) // Vectors positioned at start of RAM + +#endif diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/cmsis_nvic.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54608/device/cmsis_nvic.h similarity index 100% rename from targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/cmsis_nvic.h rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54608/device/cmsis_nvic.h diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c index e80ad41e0fb..eee454211db 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c @@ -35,6 +35,7 @@ **/ #include "stm32f4xx.h" +#include "mbed_debug.h" /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ @@ -240,8 +241,6 @@ uint8_t SetSysClock_PLL_HSI(void) /******************************************************************************/ void HardFault_Handler(void) { -#if !defined(NDEBUG) || NDEBUG == 0 - printf("Hard Fault\n"); -#endif + debug("Hard Fault\n"); NVIC_SystemReset(); } diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c index cf1e3832b3d..f24a80bfdaf 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c @@ -35,7 +35,7 @@ **/ #include "stm32f4xx.h" - +#include "mbed_debug.h" /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ @@ -243,8 +243,6 @@ uint8_t SetSysClock_PLL_HSI(void) /******************************************************************************/ void HardFault_Handler(void) { -#if !defined(NDEBUG) || NDEBUG == 0 - printf("Hard Fault\n"); -#endif + debug("Hard Fault\n"); NVIC_SystemReset(); } diff --git a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c index 2cb8919f9ac..e5f39de4f74 100644 --- a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c @@ -37,6 +37,7 @@ #include "stm32l1xx.h" #include "stdio.h" +#include "mbed_debug.h" /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ @@ -253,9 +254,7 @@ uint8_t SetSysClock_PLL_HSI(void) /******************************************************************************/ void HardFault_Handler(void) { -#if !defined(NDEBUG) || NDEBUG == 0 - printf("Hard Fault\n"); -#endif + debug("Hard Fault\n"); NVIC_SystemReset(); } diff --git a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c index cec303bd953..437a576ecb1 100644 --- a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c +++ b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c @@ -30,12 +30,7 @@ #include "xdot_low_power.h" #include "stdio.h" - -#if defined(NDEBUG) && NDEBUG == 1 -#define xdot_lp_debug(...) do {} while(0) -#else -#define xdot_lp_debug(...) printf(__VA_ARGS__) -#endif +#include "mbed_debug.h" static uint32_t portA[6]; static uint32_t portB[6]; @@ -236,7 +231,7 @@ void xdot_enter_stop_mode() { HSERCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4; HSERCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3; if (HAL_RCC_OscConfig(&HSERCC_OscInitStruct) != HAL_OK) { - xdot_lp_debug("OSC initialization failed - initiating soft reset\r\n"); + debug("OSC initialization failed - initiating soft reset\r\n"); NVIC_SystemReset(); } @@ -247,7 +242,7 @@ void xdot_enter_stop_mode() { RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // 32 MHz RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 32 MHz if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { - xdot_lp_debug("PLL initialization failed - initiating soft reset\r\n"); + debug("PLL initialization failed - initiating soft reset\r\n"); NVIC_SystemReset(); } @@ -260,7 +255,7 @@ void xdot_enter_stop_mode() { HSIRCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; HAL_StatusTypeDef ret = HAL_RCC_OscConfig(&HSIRCC_OscInitStruct); if ( ret != HAL_OK ) { - xdot_lp_debug("HSI initialization failed - ADC will not function properly\r\n"); + debug("HSI initialization failed - ADC will not function properly\r\n"); } } diff --git a/targets/targets.json b/targets/targets.json index c9ae0ea0a0a..444399ceb13 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -1487,6 +1487,7 @@ } }, "detect_code": ["0788"], + "macros_add": ["USB_STM_HAL"], "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F469NI" diff --git a/tools/build_api.py b/tools/build_api.py index 7a267a04059..790b1bcb65b 100644 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -438,6 +438,18 @@ def scan_resources(src_paths, toolchain, dependencies_paths=None, # Set the toolchain's configuration data toolchain.set_config_data(toolchain.config.get_config_data()) + if (hasattr(toolchain.target, "release_versions") and + "5" not in toolchain.target.release_versions and + "rtos" in toolchain.config.lib_config_data): + if "Cortex-A" in toolchain.target.core: + raise NotSupportedException( + ("%s Will be supported in mbed OS 5.6. " + "To use the %s, please checkout the mbed OS 5.4 release branch. " + "See https://developer.mbed.org/platforms/Renesas-GR-PEACH/#important-notice " + "for more information") % (toolchain.target.name, toolchain.target.name)) + else: + raise NotSupportedException("Target does not support mbed OS 5") + return resources def build_project(src_paths, build_path, target, toolchain_name, @@ -519,17 +531,6 @@ def build_project(src_paths, build_path, target, toolchain_name, try: # Call unified scan_resources resources = scan_resources(src_paths, toolchain, inc_dirs=inc_dirs) - if (hasattr(toolchain.target, "release_versions") and - "5" not in toolchain.target.release_versions and - "rtos" in toolchain.config.lib_config_data): - if "Cortex-A" in toolchain.target.core: - raise NotSupportedException( - ("%s Will be supported in mbed OS 5.6. " - "To use the %s, please checkout the mbed OS 5.4 release branch. " - "See https://developer.mbed.org/platforms/Renesas-GR-PEACH/#important-notice " - "for more information") % (toolchain.target.name, toolchain.target.name)) - else: - raise NotSupportedException("Target does not support mbed OS 5") # Change linker script if specified if linker_script is not None: diff --git a/tools/project.py b/tools/project.py index 05f5c0a7d0f..ff59f5b9d40 100644 --- a/tools/project.py +++ b/tools/project.py @@ -20,6 +20,7 @@ from tools.utils import argparse_force_lowercase_type from tools.utils import argparse_force_uppercase_type from tools.utils import print_large_string +from tools.utils import NotSupportedException from tools.options import extract_profile, list_profiles, extract_mcus def setup_project(ide, target, program=None, source_dir=None, build=None, export_path=None): @@ -246,11 +247,13 @@ def main(): profile = extract_profile(parser, options, toolchain_name, fallback="debug") if options.clean: rmtree(BUILD_DIR) - export(mcu, options.ide, build=options.build, - src=options.source_dir, macros=options.macros, - project_id=options.program, zip_proj=zip_proj, - build_profile=profile, app_config=options.app_config) - + try: + export(mcu, options.ide, build=options.build, + src=options.source_dir, macros=options.macros, + project_id=options.program, zip_proj=zip_proj, + build_profile=profile, app_config=options.app_config) + except NotSupportedException as exc: + print "[ERROR] %s" % str(exc) if __name__ == "__main__": main()