Lots of K64F SPI fixes (#315)

* Update DSPI driver to latest version from NXP

* Other updates to SDK files

* Fix double DMA transactions, improve dummy byte support

* Simplify dummy byte setting

* Also fix SPI driver bug

* Fix infinite hang with interrupt SPI

* Better fix for SPI hang

* Remove earlier fix
pull/15530/head
Jamie Smith 2024-07-28 13:32:42 -07:00 committed by GitHub
parent de0c404983
commit 5354079bfb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1462 additions and 518 deletions

View File

@ -480,7 +480,7 @@ public:
typename std::enable_if<std::is_integral<WordT>::value, int>::type
transfer(const WordT *tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
{
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(WordT)));
return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
}
@ -489,7 +489,7 @@ public:
typename std::enable_if<std::is_integral<WordT>::value, int>::type
transfer(const std::nullptr_t tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
{
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(WordT)));
return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
}
template<typename WordT>
@ -528,7 +528,7 @@ public:
typename std::enable_if<std::is_integral<WordT>::value, int>::type
transfer_and_wait(const WordT *tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
{
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(WordT)));
return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
}
@ -537,7 +537,7 @@ public:
typename std::enable_if<std::is_integral<WordT>::value, int>::type
transfer_and_wait(const std::nullptr_t tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
{
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(WordT)));
return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
}
template<typename WordT>
@ -549,6 +549,8 @@ public:
/**
* @brief Abort the on-going SPI transfer, if any, and continue with transfers in the queue, if any.
*
* @note If a transfer is aborted, its callback will not be called at all.
*/
void abort_transfer();

View File

@ -235,6 +235,9 @@ void spi_free(spi_t *obj);
*
* Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode.
* The default bit order is MSB.
*
* This function shall NOT modify the SPI frequency if the SPI frequency has previously been set.
*
* @param[in,out] obj The SPI object to configure
* @param[in] bits The number of bits per frame
* @param[in] mode The SPI mode (clock polarity, phase, and shift direction)

View File

@ -38,6 +38,7 @@ target_sources(mbed-mcu-k64f
drivers/fsl_cmp.c
drivers/fsl_cmt.c
drivers/fsl_crc.c
drivers/fsl_common_arm.c
drivers/fsl_dac.c
drivers/fsl_dmamux.c
drivers/fsl_dspi.c

View File

@ -1,31 +1,9 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021 NXP
* 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.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_COMMON_H_
@ -34,8 +12,13 @@
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#if defined(__ICCARM__) || (defined(__CC_ARM) || defined(__ARMCC_VERSION)) || defined(__GNUC__)
#include <stddef.h>
#endif
#include "fsl_device_registers.h"
/*!
@ -43,115 +26,210 @@
* @{
*/
/*******************************************************************************
* Configurations
******************************************************************************/
/*! @brief Macro to use the default weak IRQ handler in drivers. */
#ifndef FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
#define FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ 1
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
#define MAKE_STATUS(group, code) ((((group)*100L) + (code)))
/*! @brief Construct the version number for drivers. */
#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/*! @brief Construct the version number for drivers.
*
* The driver version is a 32-bit number, for both 32-bit platforms(such as Cortex M)
* and 16-bit platforms(such as DSC).
*
* @verbatim
| Unused || Major Version || Minor Version || Bug Fix |
31 25 24 17 16 9 8 0
@endverbatim
*/
#define MAKE_VERSION(major, minor, bugfix) (((major) * 65536L) + ((minor) * 256L) + (bugfix))
/*! @name Driver version */
/*@{*/
/*! @brief common driver version. */
#define FSL_COMMON_DRIVER_VERSION (MAKE_VERSION(2, 3, 1))
/*@}*/
/* 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_FLEXCOMM 5U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console based on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console based on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console based on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console based on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console based on FLEXCOMM. */
#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console based on i.MX UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console based on LPC_VUSART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_MINI_USART 8U /*!< Debug console based on LPC_USART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_SWO 9U /*!< Debug console based on SWO. */
#define DEBUG_CONSOLE_DEVICE_TYPE_QSCI 10U /*!< Debug console based on QSCI. */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
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_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_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. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
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_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. */
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
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_CSI = 29, /*!< Group number for CSI status codes */
kStatusGroup_MIPI_DSI = 30, /*!< Group number for MIPI DSI 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. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
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_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
kStatusGroup_DCP = 67, /*!< Group number for DCP status codes.*/
kStatusGroup_MSCAN = 68, /*!< Group number for MSCAN status codes.*/
kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
kStatusGroup_PDM = 72, /*!< Group number for MIC status codes. */
kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
kStatusGroup_ICS = 74, /*!< Group number for ICS status codes. */
kStatusGroup_SPDIF = 75, /*!< Group number for SPDIF status codes. */
kStatusGroup_LPC_MINISPI = 76, /*!< Group number for LPC_MINISPI status codes. */
kStatusGroup_HASHCRYPT = 77, /*!< Group number for Hashcrypt status codes */
kStatusGroup_LPC_SPI_SSP = 78, /*!< Group number for LPC_SPI_SSP status codes. */
kStatusGroup_I3C = 79, /*!< Group number for I3C status codes */
kStatusGroup_LPC_I2C_1 = 97, /*!< Group number for LPC_I2C_1 status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_SEMC = 100, /*!< Group number for SEMC status codes. */
kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */
kStatusGroup_IAP = 102, /*!< Group number for IAP status codes */
kStatusGroup_SFA = 103, /*!< Group number for SFA status codes*/
kStatusGroup_SPC = 104, /*!< Group number for SPC status codes. */
kStatusGroup_PUF = 105, /*!< Group number for PUF status codes. */
kStatusGroup_TOUCH_PANEL = 106, /*!< Group number for touch panel status codes */
kStatusGroup_HAL_GPIO = 121, /*!< Group number for HAL GPIO status codes. */
kStatusGroup_HAL_UART = 122, /*!< Group number for HAL UART status codes. */
kStatusGroup_HAL_TIMER = 123, /*!< Group number for HAL TIMER status codes. */
kStatusGroup_HAL_SPI = 124, /*!< Group number for HAL SPI status codes. */
kStatusGroup_HAL_I2C = 125, /*!< Group number for HAL I2C status codes. */
kStatusGroup_HAL_FLASH = 126, /*!< Group number for HAL FLASH status codes. */
kStatusGroup_HAL_PWM = 127, /*!< Group number for HAL PWM status codes. */
kStatusGroup_HAL_RNG = 128, /*!< Group number for HAL RNG status codes. */
kStatusGroup_HAL_I2S = 129, /*!< Group number for HAL I2S status codes. */
kStatusGroup_TIMERMANAGER = 135, /*!< Group number for TiMER MANAGER status codes. */
kStatusGroup_SERIALMANAGER = 136, /*!< Group number for SERIAL MANAGER status codes. */
kStatusGroup_LED = 137, /*!< Group number for LED status codes. */
kStatusGroup_BUTTON = 138, /*!< Group number for BUTTON status codes. */
kStatusGroup_EXTERN_EEPROM = 139, /*!< Group number for EXTERN EEPROM status codes. */
kStatusGroup_SHELL = 140, /*!< Group number for SHELL status codes. */
kStatusGroup_MEM_MANAGER = 141, /*!< Group number for MEM MANAGER status codes. */
kStatusGroup_LIST = 142, /*!< Group number for List status codes. */
kStatusGroup_OSA = 143, /*!< Group number for OSA status codes. */
kStatusGroup_COMMON_TASK = 144, /*!< Group number for Common task status codes. */
kStatusGroup_MSG = 145, /*!< Group number for messaging status codes. */
kStatusGroup_SDK_OCOTP = 146, /*!< Group number for OCOTP status codes. */
kStatusGroup_SDK_FLEXSPINOR = 147, /*!< Group number for FLEXSPINOR status codes.*/
kStatusGroup_CODEC = 148, /*!< Group number for codec status codes. */
kStatusGroup_ASRC = 149, /*!< Group number for codec status ASRC. */
kStatusGroup_OTFAD = 150, /*!< Group number for codec status codes. */
kStatusGroup_SDIOSLV = 151, /*!< Group number for SDIOSLV status codes. */
kStatusGroup_MECC = 152, /*!< Group number for MECC status codes. */
kStatusGroup_ENET_QOS = 153, /*!< Group number for ENET_QOS status codes. */
kStatusGroup_LOG = 154, /*!< Group number for LOG status codes. */
kStatusGroup_I3CBUS = 155, /*!< Group number for I3CBUS status codes. */
kStatusGroup_QSCI = 156, /*!< Group number for QSCI status codes. */
kStatusGroup_SNT = 157, /*!< Group number for SNT status codes. */
kStatusGroup_QUEUEDSPI = 158, /*!< Group number for QSPI status codes. */
kStatusGroup_POWER_MANAGER = 159, /*!< Group number for POWER_MANAGER status codes. */
};
/*! @brief Generic status return codes. */
enum _generic_status
/*! \public
* @brief Generic status return codes.
*/
enum
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0),
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1),
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2),
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3),
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4),
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5),
kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6),
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0), /*!< Generic status for Success. */
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1), /*!< Generic status for Fail. */
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2), /*!< Generic status for read only failure. */
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3), /*!< Generic status for out of range access. */
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4), /*!< Generic status for invalid argument check. */
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5), /*!< Generic status for timeout. */
kStatus_NoTransferInProgress =
MAKE_STATUS(kStatusGroup_Generic, 6), /*!< Generic status for no transfer in progress. */
kStatus_Busy = MAKE_STATUS(kStatusGroup_Generic, 7), /*!< Generic status for module is busy. */
kStatus_NoData =
MAKE_STATUS(kStatusGroup_Generic, 8), /*!< Generic status for no data is found for the operation. */
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
/*!
* @name Min/max macros
* @{
*/
#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)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#if !defined(MAX)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
/* @} */
/*! @brief Computes the number of elements in an array. */
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/*! @name UINT16_MAX/UINT32_MAX value */
/* @{ */
@ -164,17 +242,18 @@ typedef int32_t status_t;
#endif
/* @} */
/*! @name Timer utilities */
/*! @name Suppress fallthrough warning macro */
/* For switch case code block, if case section ends without "break;" statement, there wil be
fallthrough warning with compiler flag -Wextra or -Wimplicit-fallthrough=n when using armgcc.
To suppress this warning, "SUPPRESS_FALL_THROUGH_WARNING();" need to be added at the end of each
case section which misses "break;"statement.
*/
/* @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000000U / clockFreqInHz)
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)ms * clockFreqInHz / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000U / clockFreqInHz)
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
#define SUPPRESS_FALL_THROUGH_WARNING() __attribute__((fallthrough))
#else
#define SUPPRESS_FALL_THROUGH_WARNING()
#endif
/* @} */
/*******************************************************************************
@ -186,120 +265,32 @@ extern "C" {
#endif
/*!
* @brief Enable specific interrupt.
* @brief Allocate memory with given alignment and aligned size.
*
* Enable the interrupt not routed from intmux.
*
* @param interrupt The IRQ number.
* This is provided to support the dynamically allocated memory
* used in cache-able region.
* @param size The length required to malloc.
* @param alignbytes The alignment size.
* @retval The allocated memory.
*/
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
{
NVIC_EnableIRQ(interrupt);
}
}
void *SDK_Malloc(size_t size, size_t alignbytes);
/*!
* @brief Disable specific interrupt.
* @brief Free memory.
*
* Disable the interrupt not routed from intmux.
*
* @param interrupt The IRQ number.
* @param ptr The memory to be release.
*/
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
{
NVIC_DisableIRQ(interrupt);
}
}
void SDK_Free(void *ptr);
/*!
* @brief Disable the global IRQ
* @brief Delay at least for some time.
* Please note that, this API uses while loop for delay, different run-time environments make the time not precise,
* if precise delay count was needed, please implement a new delay function with hardware timer.
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
* @param delayTime_us Delay time in unit of microsecond.
* @param coreClock_Hz Core clock frequency with Hz.
*/
static inline uint32_t DisableGlobalIRQ(void)
{
uint32_t regPrimask = __get_PRIMASK();
__disable_irq();
return regPrimask;
}
/*!
* @brief Enaable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convinience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
static inline void EnableGlobalIRQ(uint32_t primask)
{
__set_PRIMASK(primask);
}
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler 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 */
void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz);
#if defined(__cplusplus)
}
@ -307,4 +298,12 @@ void DisableDeepSleepIRQ(IRQn_Type interrupt);
/*! @} */
#if (defined(__DSC__) && defined(__CW__))
#include "fsl_common_dsc.h"
#elif defined(__XCC__)
#include "fsl_common_dsp.h"
#else
#include "fsl_common_arm.h"
#endif
#endif /* _FSL_COMMON_H_ */

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.common_arm"
#endif
#ifndef __GIC_PRIO_BITS
#if defined(ENABLE_RAM_VECTOR_TABLE)
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
{
#ifdef __VECTOR_TABLE
#undef __VECTOR_TABLE
#endif
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
extern uint32_t Image$$VECTOR_ROM$$Base[];
extern uint32_t Image$$VECTOR_RAM$$Base[];
extern uint32_t Image$$RW_m_data$$Base[];
#define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
#define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
#elif defined(__ICCARM__)
extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
#elif defined(__GNUC__)
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
#endif /* defined(__CC_ARM) || defined(__ARMCC_VERSION) */
uint32_t n;
uint32_t ret;
uint32_t irqMaskValue;
irqMaskValue = DisableGlobalIRQ();
if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
{
/* Copy the vector table from ROM to RAM */
for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
{
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
}
/* Point the VTOR to the position of vector table */
SCB->VTOR = (uint32_t)__VECTOR_RAM;
}
ret = __VECTOR_RAM[(int32_t)irq + 16];
/* make sure the __VECTOR_RAM is noncachable */
__VECTOR_RAM[(int32_t)irq + 16] = irqHandler;
EnableGlobalIRQ(irqMaskValue);
return ret;
}
#endif /* ENABLE_RAM_VECTOR_TABLE. */
#endif /* __GIC_PRIO_BITS. */
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*
* When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
* powerlib should be used instead of these functions.
*/
#if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 0))
/*
* When the SYSCON STARTER registers are discontinuous, these functions are
* implemented in fsl_power.c.
*/
#if !(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS)
void EnableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t intNumber = (uint32_t)interrupt;
uint32_t index = 0;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERSET[index] = 1UL << intNumber;
(void)EnableIRQ(interrupt); /* also enable interrupt at NVIC */
}
void DisableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t intNumber = (uint32_t)interrupt;
(void)DisableIRQ(interrupt); /* also disable interrupt at NVIC */
uint32_t index = 0;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERCLR[index] = 1UL << intNumber;
}
#endif /* FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */
#endif /* FSL_FEATURE_POWERLIB_EXTEND */
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#if defined(SDK_DELAY_USE_DWT) && defined(DWT)
/* Use WDT. */
static void enableCpuCycleCounter(void)
{
/* Make sure the DWT trace fucntion is enabled. */
if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR))
{
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
}
/* CYCCNT not supported on this device. */
assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk));
/* Read CYCCNT directly if CYCCENT has already been enabled, otherwise enable CYCCENT first. */
if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL))
{
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
}
static uint32_t getCpuCycleCount(void)
{
return DWT->CYCCNT;
}
#else /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
/* Use software loop. */
#if defined(__CC_ARM) /* This macro is arm v5 specific */
/* clang-format off */
__ASM static void DelayLoop(uint32_t count)
{
loop
SUBS R0, R0, #1
CMP R0, #0
BNE loop
BX LR
}
/* clang-format on */
#elif defined(__ARMCC_VERSION) || defined(__ICCARM__) || defined(__GNUC__)
/* Cortex-M0 has a smaller instruction set, SUBS isn't supported in thumb-16 mode reported from __GNUC__ compiler,
* use SUB and CMP here for compatibility */
static void DelayLoop(uint32_t count)
{
__ASM volatile(" MOV R0, %0" : : "r"(count));
__ASM volatile(
"loop: \n"
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
" SUB R0, R0, #1 \n"
#else
" SUBS R0, R0, #1 \n"
#endif
" CMP R0, #0 \n"
" BNE loop \n"
:
:
: "r0");
}
#endif /* defined(__CC_ARM) */
#endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
/*!
* @brief Delay at least for some time.
* Please note that, if not uses DWT, this API will use while loop for delay, different run-time environments have
* effect on the delay time. If precise delay is needed, please enable DWT delay. The two parmeters delayTime_us and
* coreClock_Hz have limitation. For example, in the platform with 1GHz coreClock_Hz, the delayTime_us only supports
* up to 4294967 in current code. If long time delay is needed, please implement a new delay function.
*
* @param delayTime_us Delay time in unit of microsecond.
* @param coreClock_Hz Core clock frequency with Hz.
*/
void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz)
{
uint64_t count;
if (delayTime_us > 0U)
{
count = USEC_TO_COUNT(delayTime_us, coreClock_Hz);
assert(count <= UINT32_MAX);
#if defined(SDK_DELAY_USE_DWT) && defined(DWT) /* Use DWT for better accuracy */
enableCpuCycleCounter();
/* Calculate the count ticks. */
count += getCpuCycleCount();
if (count > UINT32_MAX)
{
count -= UINT32_MAX;
/* Wait for cyccnt overflow. */
while (count < getCpuCycleCount())
{
}
}
/* Wait for cyccnt reach count value. */
while (count > getCpuCycleCount())
{
}
#else
/* Divide value may be different in various environment to ensure delay is precise.
* Every loop count includes three instructions, due to Cortex-M7 sometimes executes
* two instructions in one period, through test here set divide 1.5. Other M cores use
* divide 4. By the way, divide 1.5 or 4 could let the count lose precision, but it does
* not matter because other instructions outside while loop is enough to fill the time.
*/
#if (__CORTEX_M == 7)
count = count / 3U * 2U;
#else
count = count / 4U;
#endif
DelayLoop((uint32_t)count);
#endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
}
}

View File

@ -0,0 +1,671 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_COMMON_ARM_H_
#define _FSL_COMMON_ARM_H_
/*
* For CMSIS pack RTE.
* CMSIS pack RTE generates "RTC_Components.h" which contains the statements
* of the related <RTE_Components_h> element for all selected software components.
*/
#ifdef _RTE_
#include "RTE_Components.h"
#endif
/*!
* @addtogroup ksdk_common
* @{
*/
/*! @name Atomic modification
*
* These macros are used for atomic access, such as read-modify-write
* to the peripheral registers.
*
* - SDK_ATOMIC_LOCAL_ADD
* - SDK_ATOMIC_LOCAL_SET
* - SDK_ATOMIC_LOCAL_CLEAR
* - SDK_ATOMIC_LOCAL_TOGGLE
* - SDK_ATOMIC_LOCAL_CLEAR_AND_SET
*
* Take SDK_ATOMIC_LOCAL_CLEAR_AND_SET as an example: the parameter @c addr
* means the address of the peripheral register or variable you want to modify
* atomically, the parameter @c clearBits is the bits to clear, the parameter
* @c setBits it the bits to set.
* For example, to set a 32-bit register bit1:bit0 to 0b10, use like this:
*
* @code
volatile uint32_t * reg = (volatile uint32_t *)REG_ADDR;
SDK_ATOMIC_LOCAL_CLEAR_AND_SET(reg, 0x03, 0x02);
@endcode
*
* In this example, the register bit1:bit0 are cleared and bit1 is set, as a result,
* register bit1:bit0 = 0b10.
*
* @note For the platforms don't support exclusive load and store, these macros
* disable the global interrupt to pretect the modification.
*
* @note These macros only guarantee the local processor atomic operations. For
* the multi-processor devices, use hardware semaphore such as SEMA42 to
* guarantee exclusive access if necessary.
*
* @{
*/
/* clang-format off */
#if ((defined(__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined(__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
(defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
(defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ == 1)))
/* clang-format on */
/* If the LDREX and STREX are supported, use them. */
#define _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, val, ops) \
do \
{ \
(val) = __LDREXB(addr); \
(ops); \
} while (0UL != __STREXB((val), (addr)))
#define _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, val, ops) \
do \
{ \
(val) = __LDREXH(addr); \
(ops); \
} while (0UL != __STREXH((val), (addr)))
#define _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, val, ops) \
do \
{ \
(val) = __LDREXW(addr); \
(ops); \
} while (0UL != __STREXW((val), (addr)))
static inline void _SDK_AtomicLocalAdd1Byte(volatile uint8_t *addr, uint8_t val)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val += val);
}
static inline void _SDK_AtomicLocalAdd2Byte(volatile uint16_t *addr, uint16_t val)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val += val);
}
static inline void _SDK_AtomicLocalAdd4Byte(volatile uint32_t *addr, uint32_t val)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val += val);
}
static inline void _SDK_AtomicLocalSub1Byte(volatile uint8_t *addr, uint8_t val)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val -= val);
}
static inline void _SDK_AtomicLocalSub2Byte(volatile uint16_t *addr, uint16_t val)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val -= val);
}
static inline void _SDK_AtomicLocalSub4Byte(volatile uint32_t *addr, uint32_t val)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val -= val);
}
static inline void _SDK_AtomicLocalSet1Byte(volatile uint8_t *addr, uint8_t bits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val |= bits);
}
static inline void _SDK_AtomicLocalSet2Byte(volatile uint16_t *addr, uint16_t bits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val |= bits);
}
static inline void _SDK_AtomicLocalSet4Byte(volatile uint32_t *addr, uint32_t bits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val |= bits);
}
static inline void _SDK_AtomicLocalClear1Byte(volatile uint8_t *addr, uint8_t bits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val &= ~bits);
}
static inline void _SDK_AtomicLocalClear2Byte(volatile uint16_t *addr, uint16_t bits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val &= ~bits);
}
static inline void _SDK_AtomicLocalClear4Byte(volatile uint32_t *addr, uint32_t bits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val &= ~bits);
}
static inline void _SDK_AtomicLocalToggle1Byte(volatile uint8_t *addr, uint8_t bits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val ^= bits);
}
static inline void _SDK_AtomicLocalToggle2Byte(volatile uint16_t *addr, uint16_t bits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val ^= bits);
}
static inline void _SDK_AtomicLocalToggle4Byte(volatile uint32_t *addr, uint32_t bits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val ^= bits);
}
static inline void _SDK_AtomicLocalClearAndSet1Byte(volatile uint8_t *addr, uint8_t clearBits, uint8_t setBits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
}
static inline void _SDK_AtomicLocalClearAndSet2Byte(volatile uint16_t *addr, uint16_t clearBits, uint16_t setBits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
}
static inline void _SDK_AtomicLocalClearAndSet4Byte(volatile uint32_t *addr, uint32_t clearBits, uint32_t setBits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
}
#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalAdd1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(val)) : \
((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalAdd2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(val)) : \
_SDK_AtomicLocalAdd4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(val))))
#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
_SDK_AtomicLocalSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClear1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
((2UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClear2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
_SDK_AtomicLocalClear4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalToggle1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
((2UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalToggle2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
_SDK_AtomicLocalToggle4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClearAndSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(clearBits), (uint8_t)(setBits)) : \
((2UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClearAndSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(clearBits), (uint16_t)(setBits)) : \
_SDK_AtomicLocalClearAndSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(clearBits), (uint32_t)(setBits))))
#else
#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) += (val); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (0)
#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) |= (bits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (0)
#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) &= ~(bits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (0)
#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) ^= (bits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (0)
#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) = (*(addr) & ~(clearBits)) | (setBits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (0)
#endif
/* @} */
/*! @name Timer utilities */
/* @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)(((uint64_t)(us) * (clockFreqInHz)) / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)(count)*1000000U / (clockFreqInHz))
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)(ms) * (clockFreqInHz) / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)(count)*1000U / (clockFreqInHz))
/* @} */
/*! @name ISR exit barrier
* @{
*
* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
* exception return operation might vector to incorrect interrupt.
* For Cortex-M7, if core speed much faster than peripheral register write speed,
* the peripheral interrupt flags may be still set after exiting ISR, this results to
* the same error similar with errata 83869.
*/
#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U))
#define SDK_ISR_EXIT_BARRIER __DSB()
#else
#define SDK_ISR_EXIT_BARRIER
#endif
/* @} */
/*! @name Alignment variable definition macros */
/* @{ */
#if (defined(__ICCARM__))
/*
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
* http:/ /supp.iar.com/Support/?note=24725
*/
_Pragma("diag_suppress=Pm120")
#define SDK_PRAGMA(x) _Pragma(#x)
_Pragma("diag_error=Pm120")
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var
#elif defined(__GNUC__)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
#else
#error Toolchain not supported
#endif
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) SDK_ALIGN(var, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) SDK_ALIGN(var, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#endif
/*! Macro to change a value to a given size aligned value */
#define SDK_SIZEALIGN(var, alignbytes) \
((unsigned int)((var) + ((alignbytes)-1U)) & (unsigned int)(~(unsigned int)((alignbytes)-1U)))
/* @} */
/*! @name Non-cacheable region definition macros */
/* For initialized non-zero non-cacheable variables, please using "AT_NONCACHEABLE_SECTION_INIT(var) ={xx};" or
* "AT_NONCACHEABLE_SECTION_ALIGN_INIT(var) ={xx};" in your projects to define them, for zero-inited non-cacheable
* variables, please using "AT_NONCACHEABLE_SECTION(var);" or "AT_NONCACHEABLE_SECTION_ALIGN(var);" to define them,
* these zero-inited variables will be initialized to zero in system startup.
*/
/* @{ */
#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && \
defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE))
#if (defined(__ICCARM__))
#define AT_NONCACHEABLE_SECTION(var) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_INIT(var) var @"NonCacheable.init"
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable.init"
#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) __attribute__((aligned(alignbytes))) var
#if (defined(__CC_ARM))
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"), zero_init)) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"), zero_init)) __attribute__((aligned(alignbytes))) var
#else
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section(".bss.NonCacheable"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section(".bss.NonCacheable"))) __attribute__((aligned(alignbytes))) var
#endif
#elif (defined(__GNUC__))
/* For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
* in your projects to make sure the non-cacheable section variables will be initialized in system startup.
*/
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) var __attribute__((aligned(alignbytes)))
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable,\"aw\",%nobits @"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable,\"aw\",%nobits @"))) var __attribute__((aligned(alignbytes)))
#else
#error Toolchain not supported.
#endif
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_ALIGN(var, alignbytes)
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_ALIGN(var, alignbytes)
#endif
/* @} */
/*!
* @name Time sensitive region
* @{
*/
#if (defined(__ICCARM__))
#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
#define AT_QUICKACCESS_SECTION_DATA(var) var @"DataQuickAccess"
#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
SDK_PRAGMA(data_alignment = alignbytes) var @"DataQuickAccess"
#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
__attribute__((section("DataQuickAccess"))) __attribute__((aligned(alignbytes))) var
#elif (defined(__GNUC__))
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
__attribute__((section("DataQuickAccess"))) var __attribute__((aligned(alignbytes)))
#else
#error Toolchain not supported.
#endif /* defined(__ICCARM__) */
/*! @name Ram Function */
#if (defined(__ICCARM__))
#define RAMFUNCTION_SECTION_CODE(func) func @"RamFunction"
#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#elif (defined(__GNUC__))
#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#else
#error Toolchain not supported.
#endif /* defined(__ICCARM__) */
/* @} */
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
void DefaultISR(void);
#endif
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
*/
#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
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @brief Enable specific interrupt.
*
* Enable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only enables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt enabled successfully
* @retval kStatus_Fail Failed to enable the interrupt
*/
static inline status_t EnableIRQ(IRQn_Type interrupt)
{
status_t status = kStatus_Success;
if (NotAvail_IRQn == interrupt)
{
status = kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
status = kStatus_Fail;
}
#endif
else
{
#if defined(__GIC_PRIO_BITS)
GIC_EnableIRQ(interrupt);
#else
NVIC_EnableIRQ(interrupt);
#endif
}
return status;
}
/*!
* @brief Disable specific interrupt.
*
* Disable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only disables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt disabled successfully
* @retval kStatus_Fail Failed to disable the interrupt
*/
static inline status_t DisableIRQ(IRQn_Type interrupt)
{
status_t status = kStatus_Success;
if (NotAvail_IRQn == interrupt)
{
status = kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
status = kStatus_Fail;
}
#endif
else
{
#if defined(__GIC_PRIO_BITS)
GIC_DisableIRQ(interrupt);
#else
NVIC_DisableIRQ(interrupt);
#endif
}
return status;
}
/*!
* @brief Disable the global IRQ
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
*/
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
}
/*!
* @brief Enable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convenience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
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
}
#if defined(ENABLE_RAM_VECTOR_TABLE)
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler IRQ handler address
* @return The old IRQ handler address
*/
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
#endif /* ENABLE_RAM_VECTOR_TABLE. */
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*
* When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
* powerlib should be used instead of these functions.
*/
#if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 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 internaly).
*
* @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 internaly).
*
* @param interrupt The IRQ number.
*/
void DisableDeepSleepIRQ(IRQn_Type interrupt);
#endif /* FSL_FEATURE_POWERLIB_EXTEND */
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @} */
#endif /* _FSL_COMMON_ARM_H_ */

View File

@ -88,11 +88,11 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han
/* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/
static const uint32_t s_baudratePrescaler[] = {2, 3, 5, 7};
static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128,
256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
static const uint32_t s_delayPrescaler[] = {1, 3, 5, 7};
static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256,
512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};
512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};
/*! @brief Pointers to dspi bases for each instance. */
static SPI_Type *const s_dspiBases[] = SPI_BASE_PTRS;
@ -115,7 +115,7 @@ static dspi_master_isr_t s_dspiMasterIsr;
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 g_dspiDummyData[ARRAY_SIZE(s_dspiBases)] = {0};
volatile uint16_t g_dspiDummyData[ARRAY_SIZE(s_dspiBases)] = {0};
/**********************************************************************************************************************
* Code
*********************************************************************************************************************/
@ -150,20 +150,20 @@ uint32_t DSPI_GetInstance(SPI_Type *base)
*
* param base DSPI peripheral base address.
*/
uint8_t DSPI_GetDummyDataInstance(SPI_Type *base)
uint16_t DSPI_GetDummyDataInstance(SPI_Type *base)
{
uint8_t instance = g_dspiDummyData[DSPI_GetInstance(base)];
uint16_t instance = g_dspiDummyData[DSPI_GetInstance(base)];
return instance;
}
/*!
* 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)
{
uint32_t instance = DSPI_GetInstance(base);
g_dspiDummyData[instance] = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
}
void DSPI_SetDummyData16Bit(SPI_Type *base, uint16_t dummyData)
{
uint32_t instance = DSPI_GetInstance(base);
g_dspiDummyData[instance] = dummyData;
@ -428,7 +428,7 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base,
/* for master mode configuration, if slave mode detected, return 0*/
if (!DSPI_IsMaster(base))
{
return 0;
return 0U;
}
uint32_t temp;
uint32_t prescaler, bestPrescaler;
@ -516,7 +516,7 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base,
* 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)
SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay)
{
/* these settings are only relevant in master mode */
if (DSPI_IsMaster(base))
@ -577,7 +577,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base,
/* for master mode configuration, if slave mode detected, return 0 */
if (!DSPI_IsMaster(base))
{
return 0;
return 0U;
}
uint32_t prescaler, bestPrescaler;
@ -670,8 +670,8 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command)
(void)memset(command, 0, sizeof(*command));
command->isPcsContinuous = false;
command->whichCtar = kDSPI_Ctar0;
command->whichPcs = kDSPI_Pcs0;
command->whichCtar = (uint8_t)kDSPI_Ctar0;
command->whichPcs = (uint8_t)kDSPI_Pcs0;
command->isEndOfQueue = false;
command->clearTransferCount = false;
}
@ -888,7 +888,7 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer)
uint16_t wordToSend = 0;
uint16_t wordReceived = 0;
uint8_t dummyData = DSPI_GetDummyDataInstance(base);
uint16_t dummyData = DSPI_GetDummyDataInstance(base);
uint8_t bitsPerFrame;
uint32_t command;
@ -916,19 +916,18 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer)
/*Calculate the command and lastCommand*/
commandStruct.whichPcs =
(dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
(uint8_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
commandStruct.isEndOfQueue = false;
commandStruct.clearTransferCount = false;
commandStruct.whichCtar =
(dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
commandStruct.whichCtar = (uint8_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
command = DSPI_MasterGetFormattedCommand(&(commandStruct));
commandStruct.isEndOfQueue = true;
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
/*Calculate the bitsPerFrame*/
@ -946,7 +945,7 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer)
}
else
{
fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base);
fifoSize = (uint32_t)FSL_FEATURE_DSPI_FIFO_SIZEn(base);
}
DSPI_StartTransfer(base);
@ -1156,25 +1155,24 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han
assert(NULL != transfer);
uint32_t tmpMCR = 0;
dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false};
dspi_command_data_config_t commandStruct = {false, (uint8_t)kDSPI_Ctar0, (uint8_t)kDSPI_Pcs0, false, false};
DSPI_StopTransfer(base);
DSPI_FlushFifo(base, true, true);
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
commandStruct.whichPcs =
(dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
(uint8_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
commandStruct.isEndOfQueue = false;
commandStruct.clearTransferCount = false;
commandStruct.whichCtar =
(dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
commandStruct.whichCtar = (uint8_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct));
commandStruct.isEndOfQueue = true;
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U;
@ -1182,11 +1180,11 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han
tmpMCR = base->MCR;
if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK)))
{
handle->fifoSize = 1;
handle->fifoSize = 1U;
}
else
{
handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base);
handle->fifoSize = (uint8_t)FSL_FEATURE_DSPI_FIFO_SIZEn(base);
}
handle->txData = transfer->txData;
handle->rxData = transfer->rxData;
@ -1418,7 +1416,7 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha
/* Disable interrupt requests*/
DSPI_DisableInterrupts(
base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable));
base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable));
status_t status = 0;
if (handle->state == (uint8_t)kDSPI_Error)
@ -1442,7 +1440,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t
assert(NULL != handle);
uint16_t wordToSend = 0;
uint8_t dummyData = DSPI_GetDummyDataInstance(base);
uint16_t dummyData = DSPI_GetDummyDataInstance(base);
size_t tmpRemainingSendByteCount = handle->remainingSendByteCount;
size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount;
uint8_t tmpFifoSize = handle->fifoSize;
@ -1484,14 +1482,14 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t
handle->remainingSendByteCount = 0;
base->PUSHR = handle->lastCommand | wordToSend;
}
/* For all words except the last word */
/* For all words except the last word */
else
{
if (NULL != handle->txData)
{
wordToSend = *(handle->txData);
++handle->txData; /* increment to next data byte */
wordToSend |= (unsigned)(*(handle->txData)) << 8U;
wordToSend |= (uint16_t)(*(handle->txData)) << 8U;
++handle->txData; /* increment to next data byte */
}
else
@ -1518,7 +1516,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t
tmpFifoSize = handle->fifoSize;
} /* End of TX FIFO fill while loop */
}
/* Optimized for bits/frame less than or equal to one byte. */
/* Optimized for bits/frame less than or equal to one byte. */
else
{
/* Fill the fifo until it is full or until the send word count is 0 or until the difference
@ -1584,7 +1582,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle)
/* Disable interrupt requests*/
DSPI_DisableInterrupts(
base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable));
base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable));
handle->state = (uint8_t)kDSPI_Idle;
}
@ -1658,7 +1656,7 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle)
}
} /* End of RX FIFO drain while loop */
}
/* Optimized for bits/frame less than or equal to one byte. */
/* Optimized for bits/frame less than or equal to one byte. */
else
{
while ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
@ -1785,7 +1783,7 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand
uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT);
handle->bitsPerFrame =
(((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U;
(((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U;
DSPI_StopTransfer(base);
@ -1851,7 +1849,7 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *
assert(NULL != handle);
uint16_t transmitData = 0;
uint8_t dummyPattern = DSPI_GetDummyDataInstance(base);
uint16_t dummyPattern = DSPI_GetDummyDataInstance(base);
/* Service the transmitter, if transmit buffer provided, transmit the data,
* else transmit dummy pattern
@ -1879,7 +1877,7 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *
/* Decrease remaining dataSize */
--handle->remainingSendByteCount;
}
/* bits/frame is 2 bytes */
/* bits/frame is 2 bytes */
else
{
/* With multibytes per frame transmission, the transmit frame contains data from
@ -1940,8 +1938,8 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand
/* Disable interrupt requests */
DSPI_DisableInterrupts(
base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable |
(uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable));
base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable |
(uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable));
/* The transfer is complete. */
handle->txData = NULL;
@ -1949,7 +1947,7 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand
handle->remainingReceiveByteCount = 0;
handle->remainingSendByteCount = 0;
status_t status = 0;
status_t status;
if (handle->state == (uint8_t)kDSPI_Error)
{
status = kStatus_DSPI_Error;
@ -1983,8 +1981,8 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle)
/* Disable interrupt requests */
DSPI_DisableInterrupts(
base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable |
(uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable));
base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable |
(uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable));
handle->state = (uint8_t)kDSPI_Idle;
handle->remainingSendByteCount = 0;
@ -2003,7 +2001,7 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle)
{
assert(NULL != handle);
uint8_t dummyPattern = DSPI_GetDummyDataInstance(base);
uint16_t dummyPattern = DSPI_GetDummyDataInstance(base);
uint32_t dataReceived;
uint32_t dataSend = 0;
uint32_t tmpRemainingReceiveByteCount = 0;
@ -2079,7 +2077,7 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle)
handle->remainingReceiveByteCount -= 2U;
}
}
/* If no handle->rxData*/
/* If no handle->rxData*/
else
{
if (handle->remainingReceiveByteCount == 1U)
@ -2112,7 +2110,7 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle)
handle->remainingSendByteCount -= 2U;
}
}
/* If no handle->txData*/
/* If no handle->txData*/
else
{
if (handle->remainingSendByteCount == 1U)
@ -2156,7 +2154,7 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle)
/* Change state to error and clear flag */
if (NULL != handle->txData)
{
handle->state = kDSPI_Error;
handle->state = (uint8_t)kDSPI_Error;
}
handle->errorCount++;
}
@ -2171,7 +2169,7 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle)
/* Change state to error and clear flag */
if (NULL != handle->txData)
{
handle->state = kDSPI_Error;
handle->state = (uint8_t)kDSPI_Error;
}
handle->errorCount++;
}
@ -2188,14 +2186,11 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param)
{
s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param);
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
SDK_ISR_EXIT_BARRIER;
}
#if defined(SPI0)
void SPI0_DriverIRQHandler(void);
void SPI0_DriverIRQHandler(void)
{
assert(NULL != g_dspiHandle[0]);
@ -2204,6 +2199,7 @@ void SPI0_DriverIRQHandler(void)
#endif
#if defined(SPI1)
void SPI1_DriverIRQHandler(void);
void SPI1_DriverIRQHandler(void)
{
assert(NULL != g_dspiHandle[1]);
@ -2212,6 +2208,7 @@ void SPI1_DriverIRQHandler(void)
#endif
#if defined(SPI2)
void SPI2_DriverIRQHandler(void);
void SPI2_DriverIRQHandler(void)
{
assert(NULL != g_dspiHandle[2]);
@ -2220,6 +2217,7 @@ void SPI2_DriverIRQHandler(void)
#endif
#if defined(SPI3)
void SPI3_DriverIRQHandler(void);
void SPI3_DriverIRQHandler(void)
{
assert(NULL != g_dspiHandle[3]);
@ -2228,6 +2226,7 @@ void SPI3_DriverIRQHandler(void)
#endif
#if defined(SPI4)
void SPI4_DriverIRQHandler(void);
void SPI4_DriverIRQHandler(void)
{
assert(NULL != g_dspiHandle[4]);
@ -2236,6 +2235,7 @@ void SPI4_DriverIRQHandler(void)
#endif
#if defined(SPI5)
void SPI5_DriverIRQHandler(void);
void SPI5_DriverIRQHandler(void)
{
assert(NULL != g_dspiHandle[5]);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@ -21,8 +21,8 @@
/*! @name Driver version */
/*@{*/
/*! @brief DSPI driver version 2.2.2. */
#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
/*! @brief DSPI driver version 2.2.4. */
#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 4))
/*@}*/
#ifndef DSPI_DUMMY_DATA
@ -30,8 +30,11 @@
#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */
#endif
/*! @brief Global variable for dummy data value setting. */
extern volatile uint16_t g_dspiDummyData[];
/*! @brief Status for the DSPI driver.*/
enum _dspi_status
enum
{
kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/
kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */
@ -50,7 +53,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 = (int)(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 statuses above.*/
SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/
};
/*! @brief DSPI interrupt source.*/
@ -85,8 +88,7 @@ typedef enum _dspi_master_slave_mode
/*!
* @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.
* valid only when the CPHA bit in the CTAR register is 0.
*/
typedef enum _dspi_master_sample_point
{
@ -171,10 +173,10 @@ typedef enum _dspi_ctar_selection
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; 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. */
#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
{
@ -194,18 +196,18 @@ 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, /*!< Indicates whether the PCS signal is continuous. */
kDSPI_MasterActiveAfterTransfer =
1U << 21, /*!< Indicates whether the PCS signal is active after the 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; used internally. */
#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */
#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. */
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 API state machine. */
@ -219,12 +221,12 @@ enum _dspi_transfer_state
/*! @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 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 the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/
bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/
uint8_t whichCtar; /*!< The desired Clock and Transfer Attributes
Register (CTAR) to use for CTAS.*/
uint8_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 the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/
} dspi_command_data_config_t;
/*! @brief DSPI master ctar configuration structure.*/
@ -241,8 +243,9 @@ typedef struct _dspi_master_ctar_config
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.*/
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.*/
@ -272,7 +275,7 @@ 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 and does not support LSB.*/
/*!< Slave only supports MSB and does not support LSB.*/
} dspi_slave_ctar_config_t;
/*! @brief DSPI slave configuration structure.*/
@ -293,14 +296,14 @@ typedef struct _dspi_slave_config
} dspi_slave_config_t;
/*!
* @brief Forward declaration of the _dspi_master_handle typedefs.
* @brief Forward declaration of the @ref _dspi_master_handle typedefs.
*/
typedef struct _dspi_master_handle dspi_master_handle_t;
typedef struct _dspi_master_handle dspi_master_handle_t; /*!< The master handle. */
/*!
* @brief Forward declaration of the _dspi_slave_handle typedefs.
* @brief Forward declaration of the @ref _dspi_slave_handle typedefs.
*/
typedef struct _dspi_slave_handle dspi_slave_handle_t;
typedef struct _dspi_slave_handle dspi_slave_handle_t; /*!< The slave handle. */
/*!
* @brief Completion callback function pointer type.
@ -334,21 +337,21 @@ typedef struct _dspi_transfer
uint8_t *rxData; /*!< Receive buffer. */
volatile size_t dataSize; /*!< Transfer bytes. */
uint32_t 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.*/
uint32_t configFlags; /*!< Transfer transfer configuration flags. Set from @ref
_dspi_transfer_config_flag_for_master if the transfer is used for master or @ref
_dspi_transfer_config_flag_for_slave enumeration if the transfer is used for slave.*/
} dspi_transfer_t;
/*! @brief DSPI half-duplex(master) transfer structure */
typedef struct _dspi_half_duplex_transfer
{
uint8_t *txData; /*!< Send buffer */
uint8_t *rxData; /*!< Receive buffer */
size_t txDataSize; /*!< Transfer bytes for transmit */
size_t rxDataSize; /*!< Transfer bytes */
uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */
uint8_t *txData; /*!< Send buffer */
uint8_t *rxData; /*!< Receive buffer */
size_t txDataSize; /*!< Transfer bytes for transmit */
size_t rxDataSize; /*!< Transfer bytes */
uint32_t configFlags; /*!< Transfer configuration flags; set from @ref _dspi_transfer_config_flag_for_master. */
bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for
deassert. */
de-assert. */
bool isTransmitFirst; /*!< True for transmit first and false for receive first. */
} dspi_half_duplex_transfer_t;
@ -362,7 +365,7 @@ struct _dspi_master_handle
uint8_t fifoSize; /*!< FIFO dataSize. */
volatile bool
isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/
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. */
@ -371,7 +374,7 @@ struct _dspi_master_handle
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, see _dspi_transfer_state.*/
volatile uint8_t state; /*!< DSPI transfer state, see @ref _dspi_transfer_state.*/
dspi_master_transfer_callback_t callback; /*!< Completion callback. */
void *userData; /*!< Callback user data. */
@ -434,13 +437,13 @@ extern "C" {
* @endcode
*
* @param base DSPI peripheral address.
* @param masterConfig Pointer to the structure dspi_master_config_t.
* @param masterConfig Pointer to the structure @ref 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);
/*!
* @brief Sets the dspi_master_config_t structure to default values.
* @brief Sets the @ref dspi_master_config_t structure to default values.
*
* The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit().
* Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure
@ -450,7 +453,7 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u
* dspi_master_config_t masterConfig;
* DSPI_MasterGetDefaultConfig(&masterConfig);
* @endcode
* @param masterConfig pointer to dspi_master_config_t structure
* @param masterConfig pointer to @ref dspi_master_config_t structure
*/
void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig);
@ -472,12 +475,12 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig);
* @endcode
*
* @param base DSPI peripheral address.
* @param slaveConfig Pointer to the structure dspi_master_config_t.
* @param slaveConfig Pointer to the structure @ref 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 a default value.
* @brief Sets the @ref 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().
* Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure
@ -487,7 +490,7 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig);
* dspi_slave_config_t slaveConfig;
* DSPI_SlaveGetDefaultConfig(&slaveConfig);
* @endcode
* @param slaveConfig Pointer to the dspi_slave_config_t structure.
* @param slaveConfig Pointer to the @ref dspi_slave_config_t structure.
*/
void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig);
@ -538,9 +541,8 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base)
* @brief Clears the DSPI status flag.
*
* 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.
* This is an example.
* desired status bit to clear. The list of status bits is defined in the <b>dspi_status_and_interrupt_request_t</b>.
* The function uses these bit positions in its algorithm to clear the desired flag state. This is an example.
* @code
* DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag);
* @endcode
@ -565,8 +567,8 @@ 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 a base and an interrupt mask.
* Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request.
* This function configures 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
@ -574,7 +576,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags)
* @endcode
*
* @param base DSPI peripheral address.
* @param mask The interrupt mask; use the enum _dspi_interrupt_enable.
* @param mask The interrupt mask; use the enum @ref _dspi_interrupt_enable.
*/
void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask);
@ -586,7 +588,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask);
* @endcode
*
* @param base DSPI peripheral address.
* @param mask The interrupt mask; use the enum _dspi_interrupt_enable.
* @param mask The interrupt mask; use the enum @ref _dspi_interrupt_enable.
*/
static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
{
@ -611,7 +613,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
* @endcode
*
* @param base DSPI peripheral address.
* @param mask The interrupt mask; use the enum dspi_dma_enable.
* @param mask The interrupt mask; use the enum @ref _dspi_dma_enable.
*/
static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask)
{
@ -627,7 +629,7 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask)
* @endcode
*
* @param base DSPI peripheral address.
* @param mask The interrupt mask; use the enum dspi_dma_enable.
* @param mask The interrupt mask; use the enum @ref _dspi_dma_enable.
*/
static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask)
{
@ -692,7 +694,7 @@ uint32_t DSPI_GetInstance(SPI_Type *base);
* @brief Configures the DSPI for master or slave.
*
* @param base DSPI peripheral address.
* @param mode Mode setting (master or slave) of type dspi_master_slave_mode_t.
* @param mode Mode setting (master or slave) of type @ref dspi_master_slave_mode_t.
*/
static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mode_t mode)
{
@ -707,14 +709,12 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod
*/
static inline bool DSPI_IsMaster(SPI_Type *base)
{
bool ismaster = false;
if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK))
{
return true;
}
else
{
return false;
ismaster = true;
}
return ismaster;
}
/*!
* @brief Starts the DSPI transfers and clears HALT bit in MCR.
@ -743,7 +743,7 @@ static inline void DSPI_StopTransfer(SPI_Type *base)
* @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, pass in a logic 0 (false) for the particular FIFO configuration. To enable,
* @note 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.
@ -777,7 +777,7 @@ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRx
* DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow);
@endcode
* @param base DSPI peripheral address.
* @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity.
* @param mask The PCS polarity mask; use the enum @ref _dspi_pcs_polarity.
*/
static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask)
{
@ -792,7 +792,7 @@ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask)
* caller also provide the frequency of the module source clock (in Hertz).
*
* @param base DSPI peripheral address.
* @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t
* @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type @ref dspi_ctar_selection_t
* @param baudRate_Bps The desired baud rate in bits per second
* @param srcClock_Hz Module source input clock in Hertz
* @return The actual calculated baud rate
@ -808,20 +808,20 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base,
* 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).
*
* These delay names are available in the type dspi_delay_type_t.
* These delay names are available in the type @ref dspi_delay_type_t.
*
* 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 whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type @ref 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 @ref 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);
SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay);
/*!
* @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds.
@ -831,7 +831,7 @@ void DSPI_MasterSetDelayScaler(
* After SCK delay pre-scalar (PASC) and scalar (ASC), or
* Delay after transfer pre-scalar (PDT) and scalar (DT).
*
* These delay names are available in the type dspi_delay_type_t.
* These delay names are available in the type @ref dspi_delay_type_t.
*
* 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
@ -842,8 +842,8 @@ void DSPI_MasterSetDelayScaler(
* input.
*
* @param base DSPI peripheral address.
* @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t.
* @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t
* @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type @ref dspi_ctar_selection_t.
* @param whichDelay The desired delay to configure, must be of type @ref dspi_delay_type_t
* @param srcClock_Hz Module source input clock in Hertz
* @param delayTimeInNanoSec The desired delay value in nanoseconds.
* @return The actual calculated delay value.
@ -885,17 +885,16 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config
}
/*!
* @brief Sets the dspi_command_data_config_t structure to default values.
* @brief Sets the @ref 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().
* 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.
* The purpose of this API is to get the configuration structure initialized for use in the
* <b>DSPI_MasterWrite_xx()</b>. 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 the dspi_command_data_config_t structure.
* @param command Pointer to the @ref dspi_command_data_config_t structure.
*/
void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command);
@ -918,7 +917,7 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command);
* DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord);
* @endcode
*
* Note that this function does not return until after the transmit is complete. Also note that the DSPI must be
* @note 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 received data is available when the transmit completes.
*
@ -933,13 +932,13 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co
*
* This function allows the caller to pass in the data command structure and returns the command word formatted
* according to the DSPI PUSHR register bit field placement. The user can then "OR" the returned command word with the
* desired data to send and use the function DSPI_HAL_WriteCommandDataMastermode or
* DSPI_HAL_WriteCommandDataMastermodeBlocking to write the entire 32-bit command data word to the PUSHR. This helps
* improve performance in cases where the command structure is constant. For example, the user calls this function
* desired data to send and use the function <b>DSPI_HAL_WriteCommandDataMastermode</b> or
* <b>DSPI_HAL_WriteCommandDataMastermodeBlocking</b> to write the entire 32-bit command data word to the PUSHR. This
* helps 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
* data word is to be sent.
* compared to calling send functions, such as <b>DSPI_HAL_WriteDataMastermode</b>, which format the command word each
* time a data word is to be sent.
*
* @param command Pointer to the command structure.
* @return The command word formatted to the PUSHR data register bit field.
@ -970,25 +969,29 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t
* 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
* @note 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 received data is available when the transmit completes.
*
* For a blocking polling transfer, see methods below.
* Option 1:
* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command);
* uint32_t data0 = command_to_send | data_need_to_send_0;
* uint32_t data1 = command_to_send | data_need_to_send_1;
* uint32_t data2 = command_to_send | data_need_to_send_2;
* <table>
* <tr><th>Option 1
* <tr><td>uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command);
* <tr><td>uint32_t data0 = command_to_send | data_need_to_send_0;
* <tr><td>uint32_t data1 = command_to_send | data_need_to_send_1;
* <tr><td>uint32_t data2 = command_to_send | data_need_to_send_2;
* <tr><td>
* <tr><td>DSPI_MasterWriteCommandDataBlocking(base,data0);
* <tr><td>DSPI_MasterWriteCommandDataBlocking(base,data1);
* <tr><td>DSPI_MasterWriteCommandDataBlocking(base,data2);
* </table>
*
* DSPI_MasterWriteCommandDataBlocking(base,data0);
* DSPI_MasterWriteCommandDataBlocking(base,data1);
* DSPI_MasterWriteCommandDataBlocking(base,data2);
*
* Option 2:
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0);
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1);
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2);
* <table>
* <tr><th>Option 2
* <tr><td>DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0);
* <tr><td>DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1);
* <tr><td>DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2);
* </table>
*
* @param base DSPI peripheral address.
* @param data The data word (command and data combined) to be sent.
@ -1035,18 +1038,28 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base)
*
* @param base DSPI peripheral address.
* @param dummyData Data to be transferred when tx buffer is NULL.
*
* @note This version of the dummy data setter will construct the upper 8 bits of the dummy data
* to be the same as the lower 8 bits.
*/
void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
/*!
* @brief Set up the dummy data as a 16-bit value.
*
* @param base DSPI peripheral address.
* @param dummyData Data to be transferred when tx buffer is NULL.
*/
void DSPI_SetDummyData16Bit(SPI_Type *base, uint16_t dummyData);
/*!
*@}
*/
/*!
* @name Transactional
* @name Transactional APIs
* @{
*/
/*Transactional APIs*/
/*!
* @brief Initializes the DSPI master handle.
@ -1055,7 +1068,7 @@ void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
* 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 handle DSPI handle pointer to @ref _dspi_master_handle.
* @param callback DSPI callback.
* @param userData Callback function parameter.
*/
@ -1071,7 +1084,7 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base,
* have been completed.
*
* @param base DSPI peripheral base address.
* @param transfer Pointer to the dspi_transfer_t structure.
* @param transfer Pointer to the @ref dspi_transfer_t structure.
* @return status of status_t.
*/
status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer);
@ -1083,8 +1096,8 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer);
* data is transferred, the callback function is called.
* @param base DSPI peripheral base address.
* @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
* @param transfer Pointer to the dspi_transfer_t structure.
* @param handle Pointer to the @ref _dspi_master_handle structure which stores the transfer state.
* @param transfer Pointer to the @ref 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);
@ -1097,7 +1110,7 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha
* users can set transmit first or receive first.
*
* @param base DSPI base pointer
* @param xfer pointer to dspi_half_duplex_transfer_t structure
* @param xfer pointer to @ref dspi_half_duplex_transfer_t structure
* @return status of status_t.
*/
status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer);
@ -1110,8 +1123,8 @@ status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_
* which returns right away. When all 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 xfer pointer to dspi_half_duplex_transfer_t structure
* @param handle pointer to @ref _dspi_master_handle structure which stores the transfer state
* @param xfer pointer to @ref dspi_half_duplex_transfer_t structure
* @return status of status_t.
*/
status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base,
@ -1124,7 +1137,7 @@ status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base,
* This function gets the master transfer count.
*
* @param base DSPI peripheral base address.
* @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
* @param handle Pointer to the @ref _dspi_master_handle structure which stores the transfer state.
* @param count The number of bytes transferred by using the non-blocking transaction.
* @return status of status_t.
*/
@ -1136,7 +1149,7 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl
* This function aborts a transfer using an interrupt.
*
* @param base DSPI peripheral base address.
* @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
* @param handle Pointer to the @ref _dspi_master_handle structure which stores the transfer state.
*/
void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle);
@ -1146,7 +1159,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 the dspi_master_handle_t structure which stores the transfer state.
* @param handle Pointer to the @ref _dspi_master_handle structure which stores the transfer state.
*/
void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle);
@ -1156,7 +1169,7 @@ 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 the dspi_slave_handle_t.
* @param handle DSPI handle pointer to the @ref _dspi_slave_handle.
* @param base DSPI peripheral base address.
* @param callback DSPI callback.
* @param userData Callback function parameter.
@ -1173,8 +1186,8 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base,
* data is transferred, the callback function is called.
*
* @param base DSPI peripheral base address.
* @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state.
* @param transfer Pointer to the dspi_transfer_t structure.
* @param handle Pointer to the @ref _dspi_slave_handle structure which stores the transfer state.
* @param transfer Pointer to the @ref 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);
@ -1185,7 +1198,7 @@ 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 the dspi_master_handle_t structure which stores the transfer state.
* @param handle Pointer to the @ref _dspi_master_handle structure which stores the transfer state.
* @param count The number of bytes transferred by using the non-blocking transaction.
* @return status of status_t.
*/
@ -1197,7 +1210,7 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle,
* This function aborts a transfer using an interrupt.
*
* @param base DSPI peripheral base address.
* @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state.
* @param handle Pointer to the @ref _dspi_slave_handle structure which stores the transfer state.
*/
void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle);
@ -1207,7 +1220,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 the dspi_slave_handle_t structure which stores the transfer state.
* @param handle Pointer to the @ref _dspi_slave_handle structure which stores the transfer state.
*/
void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle);
@ -1215,11 +1228,11 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle);
* brief Dummy data for each instance.
*
* The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of
* externally-linked object or function g_dspiDummyData.
* externally-linked object or function @ref g_dspiDummyData.
*
* param base DSPI peripheral base address.
*/
uint8_t DSPI_GetDummyDataInstance(SPI_Type *base);
uint16_t DSPI_GetDummyDataInstance(SPI_Type *base);
/*!
*@}
@ -1228,8 +1241,8 @@ uint8_t DSPI_GetDummyDataInstance(SPI_Type *base);
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*!
*@}
*/
/*!
*@}
*/
#endif /*_FSL_DSPI_H_*/

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@ -125,6 +125,10 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
* This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
* is transferred, the callback function is called.
*
* note The max transfer size of each transfer depends on whether the instance's Tx/Rx shares the same DMA request. If
* FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) is true, then the max transfer size is 32767 datawidth of data,
* otherwise is 511.
*
* param base DSPI peripheral base address.
* param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
* param transfer A pointer to the dspi_transfer_t structure.
@ -157,7 +161,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
uint32_t instance = DSPI_GetInstance(base);
uint16_t wordToSend = 0;
uint8_t dummyData = DSPI_GetDummyDataInstance(base);
uint16_t dummyData = DSPI_GetDummyDataInstance(base);
uint8_t dataAlreadyFed = 0;
uint8_t dataFedMax = 2;
uint32_t tmpMCR = 0;
@ -171,7 +175,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
edma_transfer_config_t transferConfigA;
edma_transfer_config_t transferConfigB;
handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData;
handle->txBuffIfNull = dummyData;
dspi_command_data_config_t commandStruct;
DSPI_StopTransfer(base);
@ -179,18 +183,17 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
commandStruct.whichPcs =
(dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
(uint8_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
commandStruct.isEndOfQueue = false;
commandStruct.clearTransferCount = false;
commandStruct.whichCtar =
(dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
commandStruct.whichCtar = (uint8_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct));
commandStruct.isEndOfQueue = true;
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U;
@ -198,11 +201,11 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
tmpMCR = base->MCR;
if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK)))
{
handle->fifoSize = 1;
handle->fifoSize = 1U;
}
else
{
handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base);
handle->fifoSize = (uint8_t)FSL_FEATURE_DSPI_FIFO_SIZEn(base);
}
handle->txData = transfer->txData;
handle->rxData = transfer->rxData;
@ -213,31 +216,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
/* 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))
if (transfer->dataSize > DSPI_EDMA_MAX_TRANSFER_SIZE(base, (handle->bitsPerFrame)))
{
limited_size = 32767u;
}
else
{
limited_size = 511u;
}
if (handle->bitsPerFrame > 8U)
{
if (transfer->dataSize > (limited_size << 1u))
{
handle->state = (uint8_t)kDSPI_Idle;
return kStatus_DSPI_OutOfRange;
}
}
else
{
if (transfer->dataSize > limited_size)
{
handle->state = (uint8_t)kDSPI_Idle;
return kStatus_DSPI_OutOfRange;
}
handle->state = (uint8_t)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) */
@ -297,7 +279,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
}
else
{
wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
wordToSend = dummyData;
}
handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
handle->command = handle->lastCommand;
@ -313,7 +295,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
}
else
{
wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
wordToSend = dummyData;
}
handle->command = (handle->command & 0xffff0000U) | wordToSend;
}
@ -364,12 +346,12 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
}
else
{
wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
wordToSend = dummyData;
}
handle->remainingSendByteCount = 0;
base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend;
}
/* For all words except the last word */
/* For all words except the last word */
else
{
if (NULL != handle->txData)
@ -381,7 +363,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
}
else
{
wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
wordToSend = dummyData;
}
handle->remainingSendByteCount -= 2U;
base->PUSHR = (handle->command & 0xffff0000U) | wordToSend;
@ -479,6 +461,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
(uint32_t)kEDMA_MajorInterruptEnable);
if (handle->remainingSendByteCount == 0U)
{
EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable);
DSPI_StartTransfer(base);
return kStatus_Success;
}
tmpRemainingSendByteCount = handle->remainingSendByteCount;
/*Calculate the last data : handle->lastCommand*/
if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) ||
@ -523,14 +513,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
}
else
{
if (handle->bitsPerFrame <= 8U)
{
wordToSend = dummyData;
}
else
{
wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
}
wordToSend = dummyData;
handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
}
}
@ -1147,7 +1130,11 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base,
* is transferred, the callback function is called.
* Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater
* than eight.
*
* note The max transfer size of each transfer depends on whether the instance's Tx/Rx shares the same DMA request. If
* FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) is true, then the max transfer size is 32767 datawidth of data,
* otherwise is 511.
*
* param base DSPI peripheral base address.
* param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
* param transfer A pointer to the dspi_transfer_t structure.
@ -1181,36 +1168,15 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle
uint32_t instance = DSPI_GetInstance(base);
uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT);
handle->bitsPerFrame =
(((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U;
(((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U;
/* 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))
if (transfer->dataSize > DSPI_EDMA_MAX_TRANSFER_SIZE(base, (handle->bitsPerFrame)))
{
limited_size = 32767u;
}
else
{
limited_size = 511u;
}
if (handle->bitsPerFrame > 8U)
{
if (transfer->dataSize > (limited_size << 1u))
{
handle->state = (uint8_t)kDSPI_Idle;
return kStatus_DSPI_OutOfRange;
}
}
else
{
if (transfer->dataSize > limited_size)
{
handle->state = (uint8_t)kDSPI_Idle;
return kStatus_DSPI_OutOfRange;
}
handle->state = (uint8_t)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) */
@ -1230,7 +1196,7 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle
handle->totalByteCount = transfer->dataSize;
uint32_t wordToSend = 0;
uint8_t dummyData = DSPI_GetDummyDataInstance(base);
uint16_t dummyData = DSPI_GetDummyDataInstance(base);
uint8_t dataAlreadyFed = 0;
uint8_t dataFedMax = 2;
@ -1273,7 +1239,7 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle
}
else
{
wordToSend = ((uint32_t)dummyData << 8U) | dummyData;
wordToSend = dummyData;
}
handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */
base->PUSHR_SLAVE = wordToSend;
@ -1384,14 +1350,7 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle
{
transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull);
transferConfigC.srcOffset = 0;
if (handle->bitsPerFrame <= 8U)
{
handle->txBuffIfNull = dummyData;
}
else
{
handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData;
}
handle->txBuffIfNull = dummyData;
}
transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@ -21,10 +21,18 @@
/*! @name Driver version */
/*@{*/
/*! @brief DSPI EDMA driver version 2.2.2. */
#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
/*! @brief DSPI EDMA driver version 2.2.4 */
#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 4))
/*@}*/
/*! @brief DSPI EDMA max transfer data size calculate
* @param base DSPI peripheral base address.
* @param width Transfer width
*/
#define DSPI_EDMA_MAX_TRANSFER_SIZE(base, width) \
((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) ? ((width > 8U) ? 65534U : 32767U) : \
((width > 8U) ? 1022U : 511U))
/*!
* @brief Forward declaration of the DSPI eDMA master handle typedefs.
*/
@ -70,10 +78,10 @@ struct _dspi_master_edma_handle
uint8_t fifoSize; /*!< FIFO dataSize. */
volatile bool
isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/
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.*/
volatile uint8_t state; /*!< DSPI transfer state, see @ref _dspi_transfer_state.*/
uint8_t *volatile txData; /*!< Send buffer. */
uint8_t *volatile rxData; /*!< Receive buffer. */
@ -127,7 +135,9 @@ struct _dspi_slave_edma_handle
extern "C" {
#endif /*_cplusplus*/
/*Transactional APIs*/
/*! @name Transactional APIs
* @{
*/
/*!
* @brief Initializes the DSPI master eDMA handle.
@ -135,14 +145,14 @@ extern "C" {
* This function initializes the DSPI eDMA 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.
*
* Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request
* @note DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request
* source.
* (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
* TX DMAMUX source for edmaIntermediaryToTxRegHandle.
* (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
* - For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
* TX DMAMUX source for edmaIntermediaryToTxRegHandle.
* - For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
*
* @param base DSPI peripheral base address.
* @param handle DSPI handle pointer to dspi_master_edma_handle_t.
* @param handle DSPI handle pointer to @ref _dspi_master_edma_handle.
* @param callback DSPI callback.
* @param userData A callback function parameter.
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
@ -163,9 +173,13 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
* This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
* is transferred, the callback function is called.
*
* @note The max transfer size of each transfer depends on whether the instance's Tx/Rx shares the same DMA request. If
* <b>FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x)</b> is true, then the max transfer size is 32767 datawidth of
* data, otherwise is 511.
*
* @param base DSPI peripheral base address.
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
* @param transfer A pointer to the dspi_transfer_t structure.
* @param handle A pointer to the @ref _dspi_master_edma_handle structure which stores the transfer state.
* @param transfer A pointer to the @ref dspi_transfer_t structure.
* @return status of status_t.
*/
status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer);
@ -177,8 +191,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand
* which returns right away. When all data is transferred, the callback function is called.
*
* @param base DSPI base pointer
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
* @param transfer A pointer to the dspi_half_duplex_transfer_t structure.
* @param handle A pointer to the @ref _dspi_master_edma_handle structure which stores the transfer state.
* @param xfer A pointer to the @ref dspi_half_duplex_transfer_t structure.
* @return status of status_t.
*/
status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base,
@ -191,7 +205,7 @@ status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base,
* This function aborts a transfer which is using eDMA.
*
* @param base DSPI peripheral base address.
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
* @param handle A pointer to the @ref _dspi_master_edma_handle structure which stores the transfer state.
*/
void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle);
@ -201,7 +215,7 @@ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *han
* This function gets the master eDMA transfer count.
*
* @param base DSPI peripheral base address.
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
* @param handle A pointer to the @ref _dspi_master_edma_handle structure which stores the transfer state.
* @param count A number of bytes transferred by the non-blocking transaction.
* @return status of status_t.
*/
@ -213,14 +227,14 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle
* This function initializes the DSPI eDMA 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.
*
* Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request
* @note DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request
* source.
* (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
* TX DMAMUX source for edmaTxDataToTxRegHandle.
* (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
* - For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
* TX DMAMUX source for edmaTxDataToTxRegHandle.
* - For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
*
* @param base DSPI peripheral base address.
* @param handle DSPI handle pointer to dspi_slave_edma_handle_t.
* @param handle DSPI handle pointer to @ref _dspi_slave_edma_handle.
* @param callback DSPI callback.
* @param userData A callback function parameter.
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
@ -240,10 +254,14 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base,
* is transferred, the callback function is called.
* Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater
* than eight.
*
* @note The max transfer size of each transfer depends on whether the instance's Tx/Rx shares the same DMA request. If
* <b>FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x)</b> is true, then the max transfer size is 32767 datawidth of
* data, otherwise is 511.
*
* @param base DSPI peripheral base address.
* @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
* @param transfer A pointer to the dspi_transfer_t structure.
* @param handle A pointer to the @ref _dspi_slave_edma_handle structure which stores the transfer state.
* @param transfer A pointer to the @ref dspi_transfer_t structure.
* @return status of status_t.
*/
status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer);
@ -254,7 +272,7 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle
* This function aborts a transfer which is using eDMA.
*
* @param base DSPI peripheral base address.
* @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
* @param handle A pointer to the @ref _dspi_slave_edma_handle structure which stores the transfer state.
*/
void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle);
@ -264,17 +282,19 @@ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handl
* This function gets the slave eDMA transfer count.
*
* @param base DSPI peripheral base address.
* @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
* @param handle A pointer to the @ref _dspi_slave_edma_handle structure which stores the transfer state.
* @param count A number of bytes transferred so far by the non-blocking transaction.
* @return status of status_t.
*/
status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count);
/*!@}*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*!
*@}
*/
/*!
*@}
*/
#endif /*_FSL_DSPI_EDMA_H_*/

View File

@ -79,6 +79,7 @@ void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
/* Set the transfer status to idle */
obj->spi.status = kDSPI_Idle;
obj->spi.last_set_frequency_hz = 500000; // Match FSL HAL default, though this can really be any value
obj->spi.spiDmaMasterRx.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
}
@ -108,6 +109,13 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
void spi_free(spi_t *obj)
{
if(obj->spi.spiDmaMasterRx.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.spiDmaMasterRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED)
{
dma_channel_free(obj->spi.spiDmaMasterRx.dmaChannel);
dma_channel_free(obj->spi.spiDmaMasterTx.dmaChannel);
dma_channel_free(obj->spi.spiDmaMasterIntermediary.dmaChannel);
}
DSPI_Deinit(spi_address[obj->spi.instance]);
}
@ -136,7 +144,12 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
master_config.ctarConfig.cpol = (mode & 0x2) ? kDSPI_ClockPolarityActiveLow : kDSPI_ClockPolarityActiveHigh;
master_config.ctarConfig.cpha = (mode & 0x1) ? kDSPI_ClockPhaseSecondEdge : kDSPI_ClockPhaseFirstEdge;
master_config.ctarConfig.direction = kDSPI_MsbFirst;
master_config.ctarConfig.pcsToSckDelayInNanoSec = 100;
master_config.ctarConfig.baudRate = obj->spi.last_set_frequency_hz;
// Half clock period delay before and after SPI transfer, 1 clock period between transfers
master_config.ctarConfig.pcsToSckDelayInNanoSec = 500000000 / obj->spi.last_set_frequency_hz;
master_config.ctarConfig.lastSckToPcsDelayInNanoSec = 500000000 / obj->spi.last_set_frequency_hz;
master_config.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / obj->spi.last_set_frequency_hz;
DSPI_MasterInit(spi_address[obj->spi.instance], &master_config, CLOCK_GetFreq(spi_clocks[obj->spi.instance]));
}
@ -146,8 +159,13 @@ void spi_frequency(spi_t *obj, int hz)
{
uint32_t busClock = CLOCK_GetFreq(spi_clocks[obj->spi.instance]);
DSPI_MasterSetBaudRate(spi_address[obj->spi.instance], kDSPI_Ctar0, (uint32_t)hz, busClock);
//Half clock period delay after SPI transfer
// Half clock period delay before and after SPI transfer, 1 clock period between transfers
DSPI_MasterSetDelayTimes(spi_address[obj->spi.instance], kDSPI_Ctar0, kDSPI_LastSckToPcs, busClock, 500000000 / hz);
DSPI_MasterSetDelayTimes(spi_address[obj->spi.instance], kDSPI_Ctar0, kDSPI_PcsToSck, busClock, 500000000 / hz);
DSPI_MasterSetDelayTimes(spi_address[obj->spi.instance], kDSPI_Ctar0, kDSPI_BetweenTransfer, busClock, 1000000000 / obj->spi.last_set_frequency_hz);
obj->spi.last_set_frequency_hz = hz;
}
static inline int spi_readable(spi_t *obj)
@ -162,6 +180,12 @@ int spi_master_write(spi_t *obj, int value)
DSPI_GetDefaultDataCommandConfig(&command);
command.isEndOfQueue = true;
// Some other FSL HAL SPI functions (notably, interrupt and DMA based transfers) can leave junk in the FIFO
// and/or leave the end of queue flag set, which blocks bytes from being transferred.
// Clear that stuff out now, because if we don't, we will hang forever in the SPI write function!
DSPI_FlushFifo(spi_address[obj->spi.instance], true, true);
DSPI_ClearStatusFlags(spi_address[obj->spi.instance], kDSPI_EndOfQueueFlag);
DSPI_MasterWriteDataBlocking(spi_address[obj->spi.instance], &command, (uint16_t)value);
DSPI_ClearStatusFlags(spi_address[obj->spi.instance], kDSPI_TxFifoFillRequestFlag);
@ -178,9 +202,7 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
{
int total = (tx_length > rx_length) ? tx_length : rx_length;
// Default write is done in each and every call, in future can create HAL API instead
DSPI_SetDummyData(spi_address[obj->spi.instance], write_fill);
DSPI_MasterTransferBlocking(spi_address[obj->spi.instance], &(dspi_transfer_t) {
.txData = (uint8_t *)tx_buffer,
.rxData = (uint8_t *)rx_buffer,
@ -230,7 +252,13 @@ static int32_t spi_master_transfer_asynch(spi_t *obj)
if (obj->spi.spiDmaMasterRx.dmaUsageState == DMA_USAGE_ALLOCATED ||
obj->spi.spiDmaMasterRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
status = DSPI_MasterTransferEDMA(spi_address[obj->spi.instance], &obj->spi.spi_dma_master_handle, &masterXfer);
if (status == kStatus_DSPI_OutOfRange) {
if (status == kStatus_Success)
{
/* Save amount of TX done by DMA */
obj->tx_buff.pos += masterXfer.dataSize;
obj->rx_buff.pos += masterXfer.dataSize;
}
else if (status == kStatus_DSPI_OutOfRange) {
if (obj->spi.bits > 8) {
transferSize = 1022;
} else {
@ -411,6 +439,7 @@ uint32_t spi_irq_handler_asynch(spi_t *obj)
/* Determine whether the current scenario is DMA or IRQ, and act accordingly */
if (obj->spi.spiDmaMasterRx.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.spiDmaMasterRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
/* DMA implementation */
/* Check If there is still data in the TX buffer */
if (obj->tx_buff.pos < obj->tx_buff.length) {

View File

@ -74,6 +74,7 @@ struct i2c_s {
struct spi_s {
uint32_t instance;
uint8_t bits;
uint32_t last_set_frequency_hz; ///< Last frequency passed to spi_frequency()
#if DEVICE_SPI_ASYNCH
status_t status;
dspi_master_handle_t spi_master_handle;

View File

@ -5,6 +5,19 @@
# Notes:
# 1. PyOCD did not actually work in my testing as of Apr 2024, though this device is supposed to be supported
# 2. Be sure to update the DAPLink firmware on the board via these instructions: https://os.mbed.com/blog/entry/DAPLink-bootloader-update/
# 3. OpenOCD 0.12 flashes this device perfectly and can enter a debug session, but cannot hit breakpoints
# 4. LinkServer can both flash and debug, so it's the recommended upload method for this device.
# 5. LinkServer does appear to have a bug where it doesn't map the peripheral registers as valid memory, so you can't
# inspect them. I was able to work around this by inserting a block like this into <LinkServer install dir>/devices/FRDM-K64F.json:
#
# "name": "MK64FN1M0xxx12",
# "family": "K6x",
# "memory": [
# + {
# + "location": "0x40000000",
# + "size": "0x000f0000",
# + "type": "RAM"
# + },
# General config parameters
# -------------------------------------------------------------