1420 lines
44 KiB
C
1420 lines
44 KiB
C
|
|
/* -----------------------------------------------------------------------------
|
||
|
|
* Copyright (c) 2013-2015 ARM Ltd.
|
||
|
|
*
|
||
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
||
|
|
* In no event will the authors be held liable for any damages arising from
|
||
|
|
* the use of this software. Permission is granted to anyone to use this
|
||
|
|
* software for any purpose, including commercial applications, and to alter
|
||
|
|
* it and redistribute it freely, subject to the following restrictions:
|
||
|
|
*
|
||
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
||
|
|
* claim that you wrote the original software. If you use this software in
|
||
|
|
* a product, an acknowledgment in the product documentation would be
|
||
|
|
* appreciated but is not required.
|
||
|
|
*
|
||
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||
|
|
* misrepresented as being the original software.
|
||
|
|
*
|
||
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* $Date: 26. October 2015
|
||
|
|
* $Revision: V2.2
|
||
|
|
*
|
||
|
|
* Driver: Driver_SPI1, Driver_SPI2, Driver_SPI3
|
||
|
|
* Configured: via RTE_Device.h configuration file
|
||
|
|
* Project: SPI Driver for STMicroelectronics STM32F10x
|
||
|
|
* --------------------------------------------------------------------------
|
||
|
|
* Use the following configuration settings in the middleware component
|
||
|
|
* to connect to this driver.
|
||
|
|
*
|
||
|
|
* Configuration Setting Value SPI Interface
|
||
|
|
* --------------------- ----- -------------
|
||
|
|
* Connect to hardware via Driver_SPI# = 1 use SPI1
|
||
|
|
* Connect to hardware via Driver_SPI# = 2 use SPI2
|
||
|
|
* Connect to hardware via Driver_SPI# = 3 use SPI3
|
||
|
|
* -------------------------------------------------------------------------- */
|
||
|
|
|
||
|
|
/* History:
|
||
|
|
* Version 2.2
|
||
|
|
* Corrected SPI Peripheral Reset and Clock enable/disable
|
||
|
|
* - Added checking if peripheral is available on selected device
|
||
|
|
* Version 2.1
|
||
|
|
* Corrected Bus Speed configuration
|
||
|
|
* Corrected 8bit/16bit Data register access, regarding the Data frame size
|
||
|
|
* Version 2.0
|
||
|
|
* Updated to CMSIS Driver API V2.01
|
||
|
|
* Version 1.3
|
||
|
|
* Event send_data_event added to capabilities
|
||
|
|
* SPI IRQ handling corrected
|
||
|
|
* Version 1.2
|
||
|
|
* Based on API V1.10 (namespace prefix ARM_ added)
|
||
|
|
* Version 1.1
|
||
|
|
* Corrections for configuration without DMA
|
||
|
|
* Version 1.0
|
||
|
|
* Initial release
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "SPI_STM32F10x.h"
|
||
|
|
|
||
|
|
#define ARM_SPI_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,2)
|
||
|
|
|
||
|
|
// Driver Version
|
||
|
|
static const ARM_DRIVER_VERSION DriverVersion = { ARM_SPI_API_VERSION, ARM_SPI_DRV_VERSION };
|
||
|
|
|
||
|
|
// Driver Capabilities
|
||
|
|
static const ARM_SPI_CAPABILITIES DriverCapabilities = {
|
||
|
|
0, /* Simplex Mode (Master and Slave) */
|
||
|
|
0, /* TI Synchronous Serial Interface */
|
||
|
|
0, /* Microwire Interface */
|
||
|
|
1 /* Signal Mode Fault event: \ref ARM_SPI_EVENT_MODE_FAULT */
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef MX_SPI1
|
||
|
|
|
||
|
|
// SPI1 Run-Time Information
|
||
|
|
static SPI_INFO SPI1_Info = { 0U };
|
||
|
|
static SPI_TRANSFER_INFO SPI1_TransferInfo = { 0U };
|
||
|
|
|
||
|
|
#ifdef MX_SPI1_MOSI_Pin
|
||
|
|
static SPI_PIN SPI1_mosi = {MX_SPI1_MOSI_GPIOx, MX_SPI1_MOSI_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI1_MISO_Pin
|
||
|
|
static SPI_PIN SPI1_miso = {MX_SPI1_MISO_GPIOx, MX_SPI1_MISO_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI1_NSS_Pin
|
||
|
|
static SPI_PIN SPI1_nss = {MX_SPI1_NSS_GPIOx, MX_SPI1_NSS_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
static SPI_PIN SPI1_sck = {MX_SPI1_SCK_GPIOx, MX_SPI1_SCK_GPIO_Pin};
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef MX_SPI1_RX_DMA_Instance
|
||
|
|
static SPI_DMA SPI1_DMA_Rx = {
|
||
|
|
MX_SPI1_RX_DMA_Instance,
|
||
|
|
MX_SPI1_RX_DMA_Number,
|
||
|
|
MX_SPI1_RX_DMA_Channel,
|
||
|
|
MX_SPI1_RX_DMA_Priority
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef MX_SPI1_TX_DMA_Instance
|
||
|
|
static SPI_DMA SPI1_DMA_Tx = {
|
||
|
|
MX_SPI1_TX_DMA_Instance,
|
||
|
|
MX_SPI1_TX_DMA_Number,
|
||
|
|
MX_SPI1_TX_DMA_Channel,
|
||
|
|
MX_SPI1_TX_DMA_Priority
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// SPI1 Resources
|
||
|
|
static const SPI_RESOURCES SPI1_Resources = {
|
||
|
|
SPI1,
|
||
|
|
RTE_PCLK2,
|
||
|
|
// PINS
|
||
|
|
{
|
||
|
|
#ifdef MX_SPI1_MOSI_Pin
|
||
|
|
&SPI1_mosi,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI1_MISO_Pin
|
||
|
|
&SPI1_miso,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI1_NSS_Pin
|
||
|
|
&SPI1_nss,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
&SPI1_sck,
|
||
|
|
MX_SPI1_REMAP_DEF,
|
||
|
|
MX_SPI1_REMAP
|
||
|
|
},
|
||
|
|
|
||
|
|
SPI1_IRQn,
|
||
|
|
|
||
|
|
#ifdef MX_SPI1_RX_DMA_Instance
|
||
|
|
&SPI1_DMA_Rx,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef MX_SPI1_TX_DMA_Instance
|
||
|
|
&SPI1_DMA_Tx,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
|
||
|
|
&SPI1_Info,
|
||
|
|
&SPI1_TransferInfo
|
||
|
|
};
|
||
|
|
#endif /* MX_SPI1 */
|
||
|
|
|
||
|
|
#ifdef MX_SPI2
|
||
|
|
|
||
|
|
// SPI2 Run-Time Information
|
||
|
|
static SPI_INFO SPI2_Info = { 0U };
|
||
|
|
static SPI_TRANSFER_INFO SPI2_TransferInfo = { 0U };
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef MX_SPI2_MOSI_Pin
|
||
|
|
static SPI_PIN SPI2_mosi = {MX_SPI2_MOSI_GPIOx, MX_SPI2_MOSI_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI2_MISO_Pin
|
||
|
|
static SPI_PIN SPI2_miso = {MX_SPI2_MISO_GPIOx, MX_SPI2_MISO_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI2_NSS_Pin
|
||
|
|
static SPI_PIN SPI2_nss = {MX_SPI2_NSS_GPIOx, MX_SPI2_NSS_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
static SPI_PIN SPI2_sck = {MX_SPI2_SCK_GPIOx, MX_SPI2_SCK_GPIO_Pin};
|
||
|
|
|
||
|
|
#ifdef MX_SPI2_RX_DMA_Instance
|
||
|
|
static SPI_DMA SPI2_DMA_Rx = {
|
||
|
|
MX_SPI2_RX_DMA_Instance,
|
||
|
|
MX_SPI2_RX_DMA_Number,
|
||
|
|
MX_SPI2_RX_DMA_Channel,
|
||
|
|
MX_SPI2_RX_DMA_Priority
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI2_TX_DMA_Instance
|
||
|
|
static SPI_DMA SPI2_DMA_Tx = {
|
||
|
|
MX_SPI2_TX_DMA_Instance,
|
||
|
|
MX_SPI2_TX_DMA_Number,
|
||
|
|
MX_SPI2_TX_DMA_Channel,
|
||
|
|
MX_SPI2_TX_DMA_Priority
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// SPI2 Resources
|
||
|
|
static const SPI_RESOURCES SPI2_Resources = {
|
||
|
|
SPI2,
|
||
|
|
RTE_PCLK1,
|
||
|
|
// PINS
|
||
|
|
{
|
||
|
|
#ifdef MX_SPI2_MOSI_Pin
|
||
|
|
&SPI2_mosi,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI2_MISO_Pin
|
||
|
|
&SPI2_miso,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI2_NSS_Pin
|
||
|
|
&SPI2_nss,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
&SPI2_sck,
|
||
|
|
MX_SPI2_REMAP_DEF,
|
||
|
|
MX_SPI2_REMAP
|
||
|
|
},
|
||
|
|
|
||
|
|
SPI2_IRQn,
|
||
|
|
|
||
|
|
#ifdef MX_SPI2_RX_DMA_Instance
|
||
|
|
&SPI2_DMA_Rx,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef MX_SPI2_TX_DMA_Instance
|
||
|
|
&SPI2_DMA_Tx,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
|
||
|
|
&SPI2_Info,
|
||
|
|
&SPI2_TransferInfo
|
||
|
|
};
|
||
|
|
#endif /* MX_SPI2 */
|
||
|
|
|
||
|
|
#ifdef MX_SPI3
|
||
|
|
|
||
|
|
// SPI3 Run-Time Information
|
||
|
|
static SPI_INFO SPI3_Info = { 0U };
|
||
|
|
static SPI_TRANSFER_INFO SPI3_TransferInfo = { 0U };
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef MX_SPI3_MOSI_Pin
|
||
|
|
static SPI_PIN SPI3_mosi = {MX_SPI3_MOSI_GPIOx, MX_SPI3_MOSI_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI3_MISO_Pin
|
||
|
|
static SPI_PIN SPI3_miso = {MX_SPI3_MISO_GPIOx, MX_SPI3_MISO_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI3_NSS_Pin
|
||
|
|
static SPI_PIN SPI3_nss = {MX_SPI3_NSS_GPIOx, MX_SPI3_NSS_GPIO_Pin};
|
||
|
|
#endif
|
||
|
|
static SPI_PIN SPI3_sck = {MX_SPI3_SCK_GPIOx, MX_SPI3_SCK_GPIO_Pin};
|
||
|
|
|
||
|
|
#ifdef MX_SPI3_RX_DMA_Instance
|
||
|
|
static SPI_DMA SPI3_DMA_Rx = {
|
||
|
|
MX_SPI3_RX_DMA_Instance,
|
||
|
|
MX_SPI3_RX_DMA_Number,
|
||
|
|
MX_SPI3_RX_DMA_Channel,
|
||
|
|
MX_SPI3_RX_DMA_Priority
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI3_TX_DMA_Instance
|
||
|
|
static SPI_DMA SPI3_DMA_Tx = {
|
||
|
|
MX_SPI3_TX_DMA_Instance,
|
||
|
|
MX_SPI3_TX_DMA_Number,
|
||
|
|
MX_SPI3_TX_DMA_Channel,
|
||
|
|
MX_SPI3_TX_DMA_Priority
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// SPI3 Resources
|
||
|
|
static const SPI_RESOURCES SPI3_Resources = {
|
||
|
|
SPI3,
|
||
|
|
RTE_PCLK1,
|
||
|
|
// PINS
|
||
|
|
{
|
||
|
|
#ifdef MX_SPI3_MOSI_Pin
|
||
|
|
&SPI3_mosi,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI3_MISO_Pin
|
||
|
|
&SPI3_miso,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI3_NSS_Pin
|
||
|
|
&SPI3_nss,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
&SPI3_sck,
|
||
|
|
MX_SPI3_REMAP_DEF,
|
||
|
|
MX_SPI3_REMAP
|
||
|
|
},
|
||
|
|
|
||
|
|
SPI3_IRQn,
|
||
|
|
|
||
|
|
#ifdef MX_SPI3_RX_DMA_Instance
|
||
|
|
&SPI3_DMA_Rx,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef MX_SPI3_TX_DMA_Instance
|
||
|
|
&SPI3_DMA_Tx,
|
||
|
|
#else
|
||
|
|
NULL,
|
||
|
|
#endif
|
||
|
|
|
||
|
|
&SPI3_Info,
|
||
|
|
&SPI3_TransferInfo
|
||
|
|
};
|
||
|
|
#endif /* MX_SPI3 */
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn void SPI_PeripheralReset (const SPI_TypeDef *spi)
|
||
|
|
\brief SPI Reset
|
||
|
|
*/
|
||
|
|
static void SPI_PeripheralReset (const SPI_TypeDef *spi) {
|
||
|
|
|
||
|
|
if (spi == SPI1) { RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST; }
|
||
|
|
#if !defined(STM32F10X_LD) && !defined(STM32F10X_LD_VL)
|
||
|
|
if (spi == SPI2) { RCC->APB1RSTR |= RCC_APB1RSTR_SPI2RST; }
|
||
|
|
#endif
|
||
|
|
#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL)
|
||
|
|
if (spi == SPI3) { RCC->APB1RSTR |= RCC_APB1RSTR_SPI3RST; }
|
||
|
|
#endif
|
||
|
|
|
||
|
|
__NOP(); __NOP(); __NOP(); __NOP();
|
||
|
|
|
||
|
|
if (spi == SPI1) { RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1RST; }
|
||
|
|
#if !defined(STM32F10X_LD) && !defined(STM32F10X_LD_VL)
|
||
|
|
if (spi == SPI2) { RCC->APB1RSTR &= ~RCC_APB1RSTR_SPI2RST; }
|
||
|
|
#endif
|
||
|
|
#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL)
|
||
|
|
if (spi == SPI3) { RCC->APB1RSTR &= ~RCC_APB1RSTR_SPI3RST; }
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn ARM_DRIVER_VERSION SPIX_GetVersion (void)
|
||
|
|
\brief Get SPI driver version.
|
||
|
|
\return \ref ARM_DRV_VERSION
|
||
|
|
*/
|
||
|
|
static ARM_DRIVER_VERSION SPIX_GetVersion (void) {
|
||
|
|
return DriverVersion;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn ARM_SPI_CAPABILITIES SPI_GetCapabilities (void)
|
||
|
|
\brief Get driver capabilities.
|
||
|
|
\return \ref ARM_SPI_CAPABILITIES
|
||
|
|
*/
|
||
|
|
static ARM_SPI_CAPABILITIES SPIX_GetCapabilities (void) {
|
||
|
|
return DriverCapabilities;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn int32_t SPI_Initialize (ARM_SPI_SignalEvent_t cb_event, const SPI_RESOURCES *spi)
|
||
|
|
\brief Initialize SPI Interface.
|
||
|
|
\param[in] cb_event Pointer to \ref ARM_SPI_SignalEvent
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return \ref execution_status
|
||
|
|
*/
|
||
|
|
static int32_t SPI_Initialize (ARM_SPI_SignalEvent_t cb_event, const SPI_RESOURCES *spi) {
|
||
|
|
bool ok = true;
|
||
|
|
|
||
|
|
if (spi->info->state & SPI_INITIALIZED) { return ARM_DRIVER_OK; }
|
||
|
|
|
||
|
|
// Initialize SPI Run-Time Resources
|
||
|
|
spi->info->cb_event = cb_event;
|
||
|
|
spi->info->status.busy = 0U;
|
||
|
|
spi->info->status.data_lost = 0U;
|
||
|
|
spi->info->status.mode_fault = 0U;
|
||
|
|
|
||
|
|
// Clear transfer information
|
||
|
|
memset(spi->xfer, 0, sizeof(SPI_TRANSFER_INFO));
|
||
|
|
|
||
|
|
// Setup pin remap
|
||
|
|
GPIO_AFConfigure(spi->io.afio);
|
||
|
|
|
||
|
|
// Configure SPI SCK pin
|
||
|
|
GPIO_PortClock (spi->io.sck->port, true);
|
||
|
|
ok = GPIO_PinConfigure(spi->io.sck->port, spi->io.sck->pin, GPIO_AF_PUSHPULL,
|
||
|
|
GPIO_MODE_OUT50MHZ);
|
||
|
|
if (ok && (spi->io.mosi != NULL)) {
|
||
|
|
// Configure SPI MOSI pin
|
||
|
|
GPIO_PortClock (spi->io.mosi->port, true);
|
||
|
|
ok = GPIO_PinConfigure(spi->io.mosi->port, spi->io.mosi->pin, GPIO_AF_PUSHPULL,
|
||
|
|
GPIO_MODE_OUT50MHZ);
|
||
|
|
}
|
||
|
|
if (ok && (spi->io.miso != NULL)) {
|
||
|
|
// Configure SPI MISO pin
|
||
|
|
GPIO_PortClock (spi->io.miso->port, true);
|
||
|
|
ok = GPIO_PinConfigure(spi->io.miso->port, spi->io.miso->pin, GPIO_AF_PUSHPULL,
|
||
|
|
GPIO_MODE_INPUT);
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA
|
||
|
|
if ((spi->rx_dma != NULL) || (spi->tx_dma != NULL)) {
|
||
|
|
if (spi->rx_dma != NULL) {
|
||
|
|
DMA_ChannelInitialize (spi->rx_dma->dma_num, spi->rx_dma->ch_num);
|
||
|
|
}
|
||
|
|
if (spi->tx_dma != NULL) {
|
||
|
|
DMA_ChannelInitialize (spi->tx_dma->dma_num, spi->tx_dma->ch_num);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
spi->info->state = SPI_INITIALIZED;
|
||
|
|
|
||
|
|
return (ok) ? (ARM_DRIVER_OK) : (ARM_DRIVER_ERROR);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn int32_t SPI_Uninitialize (const SPI_RESOURCES *spi)
|
||
|
|
\brief De-initialize SPI Interface.
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return \ref execution_status
|
||
|
|
*/
|
||
|
|
static int32_t SPI_Uninitialize (const SPI_RESOURCES *spi) {
|
||
|
|
|
||
|
|
// Uninitialize SPI pins
|
||
|
|
GPIO_PinConfigure (spi->io.sck->port, spi->io.sck->pin, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
|
||
|
|
|
||
|
|
if (spi->io.miso != NULL) {
|
||
|
|
GPIO_PinConfigure (spi->io.miso->port, spi->io.miso->pin, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
|
||
|
|
}
|
||
|
|
if (spi->io.mosi != NULL) {
|
||
|
|
GPIO_PinConfigure (spi->io.mosi->port, spi->io.mosi->pin, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
|
||
|
|
}
|
||
|
|
if (spi->io.nss != NULL) {
|
||
|
|
GPIO_PinConfigure (spi->io.nss->port, spi->io.nss->pin, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uncofigure pin remapping
|
||
|
|
GPIO_AFConfigure(spi->io.afio_def);
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA
|
||
|
|
if ((spi->rx_dma != NULL) || (spi->tx_dma != NULL)) {
|
||
|
|
if (spi->rx_dma != NULL) {
|
||
|
|
DMA_ChannelUninitialize (spi->rx_dma->dma_num, spi->rx_dma->ch_num);
|
||
|
|
}
|
||
|
|
if (spi->tx_dma != NULL) {
|
||
|
|
DMA_ChannelUninitialize (spi->tx_dma->dma_num, spi->tx_dma->ch_num);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Clear SPI state
|
||
|
|
spi->info->state = 0U;
|
||
|
|
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn int32_t SPI_PowerControl (ARM_POWER_STATE state, const SPI_RESOURCES *spi)
|
||
|
|
\brief Control SPI Interface Power.
|
||
|
|
\param[in] state Power state
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return \ref execution_status
|
||
|
|
*/
|
||
|
|
static int32_t SPI_PowerControl (ARM_POWER_STATE state, const SPI_RESOURCES *spi) {
|
||
|
|
|
||
|
|
switch (state) {
|
||
|
|
case ARM_POWER_OFF:
|
||
|
|
// SPI peripheral reset
|
||
|
|
SPI_PeripheralReset (spi->reg);
|
||
|
|
|
||
|
|
NVIC_DisableIRQ (spi->irq_num);
|
||
|
|
|
||
|
|
// Disable SPI clock
|
||
|
|
if (spi->reg == SPI1) { RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN; }
|
||
|
|
#if !defined(STM32F10X_LD) && !defined(STM32F10X_LD_VL)
|
||
|
|
if (spi->reg == SPI2) { RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN; }
|
||
|
|
#endif
|
||
|
|
#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL)
|
||
|
|
if (spi->reg == SPI3) { RCC->APB1ENR &= ~RCC_APB1ENR_SPI3EN; }
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Clear status flags
|
||
|
|
spi->info->status.busy = 0U;
|
||
|
|
spi->info->status.data_lost = 0U;
|
||
|
|
spi->info->status.mode_fault = 0U;
|
||
|
|
|
||
|
|
// Clear powered flag
|
||
|
|
spi->info->state &= ~SPI_POWERED;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_POWER_FULL:
|
||
|
|
if ((spi->info->state & SPI_INITIALIZED) == 0U) {
|
||
|
|
return ARM_DRIVER_ERROR;
|
||
|
|
}
|
||
|
|
if ((spi->info->state & SPI_POWERED) != 0U) {
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Clear status flags
|
||
|
|
spi->info->status.busy = 0U;
|
||
|
|
spi->info->status.data_lost = 0U;
|
||
|
|
spi->info->status.mode_fault = 0U;
|
||
|
|
|
||
|
|
spi->xfer->def_val = 0U;
|
||
|
|
|
||
|
|
// Ready for operation - set powered flag
|
||
|
|
spi->info->state |= SPI_POWERED;
|
||
|
|
|
||
|
|
// Enable SPI clock
|
||
|
|
if (spi->reg == SPI1) { RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; }
|
||
|
|
#if !defined(STM32F10X_LD) && !defined(STM32F10X_LD_VL)
|
||
|
|
if (spi->reg == SPI2) { RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; }
|
||
|
|
#endif
|
||
|
|
#if defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F10X_XL) || defined(STM32F10X_HD_VL)
|
||
|
|
if (spi->reg == SPI3) { RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; }
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// SPI peripheral reset
|
||
|
|
SPI_PeripheralReset (spi->reg);
|
||
|
|
|
||
|
|
// Clear and Enable SPI IRQ
|
||
|
|
NVIC_ClearPendingIRQ(spi->irq_num);
|
||
|
|
NVIC_EnableIRQ(spi->irq_num);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_POWER_LOW:
|
||
|
|
default: return ARM_DRIVER_ERROR_UNSUPPORTED;
|
||
|
|
}
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn int32_t SPI_Send (const void *data, uint32_t num, const SPI_RESOURCES *spi)
|
||
|
|
\brief Start sending data to SPI transmitter.
|
||
|
|
\param[in] data Pointer to buffer with data to send to SPI transmitter
|
||
|
|
\param[in] num Number of data items to send
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return \ref execution_status
|
||
|
|
*/
|
||
|
|
static int32_t SPI_Send (const void *data, uint32_t num, const SPI_RESOURCES *spi) {
|
||
|
|
#ifdef __SPI_DMA
|
||
|
|
uint32_t cfg;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if ((data == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
|
||
|
|
if ((spi->info->state & SPI_CONFIGURED) == 0U) { return ARM_DRIVER_ERROR; }
|
||
|
|
if ( spi->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
|
||
|
|
|
||
|
|
// Check if transmit pin available
|
||
|
|
if ((((spi->io.mosi != NULL) && ((spi->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_MASTER)) ||
|
||
|
|
((spi->io.miso != NULL) && ((spi->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_SLAVE ))) == 0U) {
|
||
|
|
return ARM_DRIVER_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update SPI statuses
|
||
|
|
spi->info->status.busy = 1U;
|
||
|
|
spi->info->status.data_lost = 0U;
|
||
|
|
spi->info->status.mode_fault = 0U;
|
||
|
|
|
||
|
|
// Save transfer info
|
||
|
|
spi->xfer->rx_buf = NULL;
|
||
|
|
spi->xfer->tx_buf = (uint8_t *)data;
|
||
|
|
spi->xfer->num = num;
|
||
|
|
spi->xfer->rx_cnt = 0U;
|
||
|
|
spi->xfer->tx_cnt = 0U;
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA_RX
|
||
|
|
if (spi->rx_dma != NULL) {
|
||
|
|
// Configure and enable rx DMA channel
|
||
|
|
cfg = ((spi->rx_dma->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) |
|
||
|
|
DMA_PERIPHERAL_TO_MEMORY |
|
||
|
|
DMA_TRANSFER_COMPLETE_INTERRUPT;
|
||
|
|
|
||
|
|
if (spi->reg->CR1 & SPI_CR1_DFF) {
|
||
|
|
// 16 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_16BIT | DMA_MEMORY_DATA_16BIT;
|
||
|
|
} else {
|
||
|
|
// 8 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_8BIT | DMA_MEMORY_DATA_8BIT;
|
||
|
|
}
|
||
|
|
|
||
|
|
DMA_ChannelConfigure(spi->rx_dma->instance,
|
||
|
|
cfg,
|
||
|
|
(uint32_t)(&spi->reg->DR),
|
||
|
|
(uint32_t)(&spi->xfer->dump_val),
|
||
|
|
num);
|
||
|
|
DMA_ChannelEnable(spi->rx_dma->instance);
|
||
|
|
|
||
|
|
// RX Buffer DMA enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_RXDMAEN;
|
||
|
|
} else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
// Interrupt mode
|
||
|
|
// RX Buffer not empty interrupt enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_RXNEIE;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA_TX
|
||
|
|
if (spi->tx_dma != NULL) {
|
||
|
|
cfg = ((spi->tx_dma->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) |
|
||
|
|
DMA_READ_MEMORY |
|
||
|
|
DMA_MEMORY_INCREMENT |
|
||
|
|
DMA_TRANSFER_COMPLETE_INTERRUPT ;
|
||
|
|
|
||
|
|
if (spi->reg->CR1 & SPI_CR1_DFF) {
|
||
|
|
// 16 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_16BIT | DMA_MEMORY_DATA_16BIT;
|
||
|
|
} else {
|
||
|
|
// 8 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_8BIT | DMA_MEMORY_DATA_8BIT;
|
||
|
|
}
|
||
|
|
|
||
|
|
DMA_ChannelConfigure(spi->tx_dma->instance,
|
||
|
|
cfg,
|
||
|
|
(uint32_t)&spi->reg->DR,
|
||
|
|
(uint32_t)data,
|
||
|
|
num);
|
||
|
|
DMA_ChannelEnable(spi->tx_dma->instance);
|
||
|
|
|
||
|
|
// TX Buffer DMA enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_TXDMAEN;
|
||
|
|
} else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
// Interrupt mode
|
||
|
|
// TX Buffer empty interrupt enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_TXEIE;
|
||
|
|
}
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn int32_t SPI_Receive (void *data, uint32_t num, const SPI_RESOURCES *spi)
|
||
|
|
\brief Start receiving data from SPI receiver.
|
||
|
|
\param[out] data Pointer to buffer for data to receive from SPI receiver
|
||
|
|
\param[in] num Number of data items to receive
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return \ref execution_status
|
||
|
|
*/
|
||
|
|
static int32_t SPI_Receive (void *data, uint32_t num, const SPI_RESOURCES *spi) {
|
||
|
|
#ifdef __SPI_DMA
|
||
|
|
uint32_t cfg;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if ((data == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
|
||
|
|
if ((spi->info->state & SPI_CONFIGURED) == 0U) { return ARM_DRIVER_ERROR; }
|
||
|
|
if ( spi->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
|
||
|
|
|
||
|
|
// Check if receive pin available
|
||
|
|
if ((((spi->io.miso != NULL) && ((spi->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_MASTER)) ||
|
||
|
|
((spi->io.mosi != NULL) && ((spi->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_SLAVE ))) == 0U) {
|
||
|
|
return ARM_DRIVER_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update SPI statuses
|
||
|
|
spi->info->status.busy = 1U;
|
||
|
|
spi->info->status.data_lost = 0U;
|
||
|
|
spi->info->status.mode_fault = 0U;
|
||
|
|
|
||
|
|
// Save transfer info
|
||
|
|
spi->xfer->rx_buf = (uint8_t *)data;
|
||
|
|
spi->xfer->tx_buf = NULL;
|
||
|
|
spi->xfer->num = num;
|
||
|
|
spi->xfer->rx_cnt = 0U;
|
||
|
|
spi->xfer->tx_cnt = 0U;
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA_RX
|
||
|
|
// DMA mode
|
||
|
|
if (spi->rx_dma != NULL) {
|
||
|
|
cfg = ((spi->rx_dma->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) |
|
||
|
|
DMA_PERIPHERAL_TO_MEMORY |
|
||
|
|
DMA_MEMORY_INCREMENT |
|
||
|
|
DMA_TRANSFER_COMPLETE_INTERRUPT ;
|
||
|
|
|
||
|
|
if (spi->reg->CR1 & SPI_CR1_DFF) {
|
||
|
|
// 16 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_16BIT | DMA_MEMORY_DATA_16BIT;
|
||
|
|
} else {
|
||
|
|
// 8 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_8BIT | DMA_MEMORY_DATA_8BIT;
|
||
|
|
}
|
||
|
|
|
||
|
|
DMA_ChannelConfigure(spi->rx_dma->instance,
|
||
|
|
cfg,
|
||
|
|
(uint32_t)(&spi->reg->DR),
|
||
|
|
(uint32_t)data,
|
||
|
|
num);
|
||
|
|
DMA_ChannelEnable(spi->rx_dma->instance);
|
||
|
|
|
||
|
|
// RX Buffer DMA enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_RXDMAEN;
|
||
|
|
} else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
// Interrupt mode
|
||
|
|
// RX Buffer not empty interrupt enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_RXNEIE;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA_TX
|
||
|
|
// DMA mode
|
||
|
|
if (spi->tx_dma != NULL) {
|
||
|
|
cfg = ((spi->tx_dma->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) |
|
||
|
|
DMA_READ_MEMORY |
|
||
|
|
DMA_TRANSFER_COMPLETE_INTERRUPT;
|
||
|
|
|
||
|
|
if (spi->reg->CR1 & SPI_CR1_DFF) {
|
||
|
|
// 16 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_16BIT | DMA_MEMORY_DATA_16BIT;
|
||
|
|
} else {
|
||
|
|
// 8 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_8BIT | DMA_MEMORY_DATA_8BIT;
|
||
|
|
}
|
||
|
|
|
||
|
|
DMA_ChannelConfigure(spi->tx_dma->instance,
|
||
|
|
cfg,
|
||
|
|
(uint32_t)(&spi->reg->DR),
|
||
|
|
(uint32_t)(&spi->xfer->def_val),
|
||
|
|
num);
|
||
|
|
DMA_ChannelEnable(spi->tx_dma->instance);
|
||
|
|
|
||
|
|
// TX Buffer DMA enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_TXDMAEN;
|
||
|
|
} else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
// Interrupt mode
|
||
|
|
// TX buffer empty interrupt enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_TXEIE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn int32_t SPI_Transfer (const void *data_out, void *data_in, uint32_t num, const SPI_RESOURCES *spi)
|
||
|
|
\brief Start sending/receiving data to/from SPI transmitter/receiver.
|
||
|
|
\param[in] data_out Pointer to buffer with data to send to SPI transmitter
|
||
|
|
\param[out] data_in Pointer to buffer for data to receive from SPI receiver
|
||
|
|
\param[in] num Number of data items to transfer
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return \ref execution_status
|
||
|
|
*/
|
||
|
|
static int32_t SPI_Transfer (const void *data_out, void *data_in, uint32_t num, const SPI_RESOURCES *spi) {
|
||
|
|
#ifdef __SPI_DMA
|
||
|
|
uint32_t cfg;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if ((data_out == NULL) || (data_in == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
|
||
|
|
if ((spi->info->state & SPI_CONFIGURED) == 0U) { return ARM_DRIVER_ERROR; }
|
||
|
|
if ( spi->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
|
||
|
|
|
||
|
|
// Check if receive and transmit pins available
|
||
|
|
if ((spi->io.miso == NULL) || (spi->io.mosi == NULL)) {
|
||
|
|
return ARM_DRIVER_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update SPI statuses
|
||
|
|
spi->info->status.busy = 1U;
|
||
|
|
spi->info->status.data_lost = 0U;
|
||
|
|
spi->info->status.mode_fault = 0U;
|
||
|
|
|
||
|
|
// Save transfer info
|
||
|
|
spi->xfer->rx_buf = (uint8_t *)data_in;
|
||
|
|
spi->xfer->tx_buf = (uint8_t *)data_out;
|
||
|
|
spi->xfer->num = num;
|
||
|
|
spi->xfer->rx_cnt = 0U;
|
||
|
|
spi->xfer->tx_cnt = 0U;
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA
|
||
|
|
if ((spi->rx_dma != NULL) || (spi->tx_dma != NULL)) {
|
||
|
|
// DMA mode
|
||
|
|
|
||
|
|
if (spi->rx_dma != NULL) {
|
||
|
|
cfg = ((spi->rx_dma->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) |
|
||
|
|
DMA_PERIPHERAL_TO_MEMORY |
|
||
|
|
DMA_MEMORY_INCREMENT |
|
||
|
|
DMA_TRANSFER_COMPLETE_INTERRUPT;
|
||
|
|
|
||
|
|
if (spi->reg->CR1 & SPI_CR1_DFF) {
|
||
|
|
// 16 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_16BIT | DMA_MEMORY_DATA_16BIT;
|
||
|
|
} else {
|
||
|
|
// 8 - bit data frame
|
||
|
|
cfg |= DMA_PERIPHERAL_DATA_8BIT | DMA_MEMORY_DATA_8BIT;
|
||
|
|
}
|
||
|
|
|
||
|
|
DMA_ChannelConfigure(spi->rx_dma->instance,
|
||
|
|
cfg,
|
||
|
|
(uint32_t)(&spi->reg->DR),
|
||
|
|
(uint32_t)data_in,
|
||
|
|
num);
|
||
|
|
DMA_ChannelEnable(spi->rx_dma->instance);
|
||
|
|
|
||
|
|
// RX Buffer DMA enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_RXDMAEN;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (spi->tx_dma != NULL) {
|
||
|
|
cfg = ((spi->tx_dma->priority << DMA_PRIORITY_POS) & DMA_PRIORITY_MASK) |
|
||
|
|
DMA_READ_MEMORY |
|
||
|
|
DMA_MEMORY_INCREMENT |
|
||
|
|
DMA_TRANSFER_COMPLETE_INTERRUPT;
|
||
|
|
|
||
|
|
DMA_ChannelConfigure(spi->tx_dma->instance,
|
||
|
|
cfg,
|
||
|
|
(uint32_t)(&spi->reg->DR),
|
||
|
|
(uint32_t)data_out,
|
||
|
|
num);
|
||
|
|
DMA_ChannelEnable(spi->tx_dma->instance);
|
||
|
|
|
||
|
|
// TX Buffer DMA enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_TXDMAEN;
|
||
|
|
}
|
||
|
|
} else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
// Interrupt mode
|
||
|
|
// TX Buffer empty and RX Buffer not empty interrupt enable
|
||
|
|
spi->reg->CR2 |= SPI_CR2_RXNEIE | SPI_CR2_TXEIE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn uint32_t SPI_GetDataCount (const SPI_RESOURCES *spi)
|
||
|
|
\brief Get transferred data count.
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return number of data items transferred
|
||
|
|
*/
|
||
|
|
static uint32_t SPI_GetDataCount (const SPI_RESOURCES *spi) {
|
||
|
|
return (spi->xfer->rx_cnt);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn int32_t SPI_Control (uint32_t control, uint32_t arg, const SPI_RESOURCES *spi)
|
||
|
|
\brief Control SPI Interface.
|
||
|
|
\param[in] control operation
|
||
|
|
\param[in] arg argument of operation (optional)
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return \ref execution_status
|
||
|
|
*/
|
||
|
|
static int32_t SPI_Control (uint32_t control, uint32_t arg, const SPI_RESOURCES *spi) {
|
||
|
|
uint32_t mode, val, pclk;
|
||
|
|
uint32_t cr1, cr2;
|
||
|
|
|
||
|
|
mode = 0U;
|
||
|
|
val = 0U;
|
||
|
|
cr1 = 0U;
|
||
|
|
cr2 = 0U;
|
||
|
|
|
||
|
|
if ((spi->info->state & SPI_POWERED) == 0U) { return ARM_DRIVER_ERROR; }
|
||
|
|
|
||
|
|
if ((control & ARM_SPI_CONTROL_Msk) == ARM_SPI_ABORT_TRANSFER) {
|
||
|
|
// Send abort
|
||
|
|
if (spi->tx_dma != NULL) {
|
||
|
|
// DMA mode
|
||
|
|
// TX buffer DMA disable
|
||
|
|
spi->reg->CR2 &= ~SPI_CR2_TXDMAEN;
|
||
|
|
|
||
|
|
// Disable TX DMA transfer
|
||
|
|
DMA_ChannelDisable (spi->tx_dma->instance);
|
||
|
|
} else {
|
||
|
|
// Interrupt mode
|
||
|
|
// Disable TX buffer empty interrupt
|
||
|
|
spi->reg->CR2 &= ~SPI_CR2_TXEIE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Receive abort
|
||
|
|
if (spi->rx_dma != NULL) {
|
||
|
|
// DMA mode
|
||
|
|
// RX buffer DMA disable
|
||
|
|
spi->reg->CR2 &= ~SPI_CR2_RXDMAEN;
|
||
|
|
|
||
|
|
// Disable RX DMA transfer
|
||
|
|
DMA_ChannelDisable (spi->rx_dma->instance);
|
||
|
|
} else {
|
||
|
|
// Interrupt mode
|
||
|
|
// Disable RX buffer not empty interrupt
|
||
|
|
spi->reg->CR2 &= ~SPI_CR2_RXNEIE;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(spi->xfer, 0, sizeof(SPI_TRANSFER_INFO));
|
||
|
|
spi->info->status.busy = 0U;
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check for busy flag
|
||
|
|
if (spi->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
|
||
|
|
|
||
|
|
switch (control & ARM_SPI_CONTROL_Msk) {
|
||
|
|
case ARM_SPI_MODE_INACTIVE:
|
||
|
|
mode |= ARM_SPI_MODE_INACTIVE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_SPI_MODE_MASTER:
|
||
|
|
mode |= ARM_SPI_MODE_MASTER;
|
||
|
|
|
||
|
|
// Master enabled
|
||
|
|
cr1 |= SPI_CR1_MSTR;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_SPI_MODE_SLAVE:
|
||
|
|
mode |= ARM_SPI_MODE_SLAVE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_SPI_MODE_MASTER_SIMPLEX:
|
||
|
|
return ARM_SPI_ERROR_MODE;
|
||
|
|
|
||
|
|
case ARM_SPI_MODE_SLAVE_SIMPLEX:
|
||
|
|
return ARM_SPI_ERROR_MODE;
|
||
|
|
|
||
|
|
case ARM_SPI_SET_BUS_SPEED:
|
||
|
|
// Set SPI Bus Speed
|
||
|
|
pclk = spi->pclk;
|
||
|
|
for (val = 0U; val < 8U; val++) {
|
||
|
|
if (arg >= (pclk >> (val + 1U))) { break; }
|
||
|
|
}
|
||
|
|
if ((val == 8U) || (arg < (pclk >> (val + 1U)))) {
|
||
|
|
// Requested Bus Speed can not be configured
|
||
|
|
return ARM_DRIVER_ERROR;
|
||
|
|
}
|
||
|
|
// Disable SPI, update prescaler and enable SPI
|
||
|
|
spi->reg->CR1 &= ~SPI_CR1_SPE;
|
||
|
|
spi->reg->CR1 = (spi->reg->CR1 & ~SPI_CR1_BR) | (val << 3U);
|
||
|
|
spi->reg->CR1 |= SPI_CR1_SPE;
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
|
||
|
|
case ARM_SPI_GET_BUS_SPEED:
|
||
|
|
// Return current bus speed
|
||
|
|
return (spi->pclk >> (((spi->reg->CR1 & SPI_CR1_BR) >> 3U) + 1U));
|
||
|
|
|
||
|
|
case ARM_SPI_SET_DEFAULT_TX_VALUE:
|
||
|
|
spi->xfer->def_val = (uint16_t)(arg & 0xFFFFU);
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
|
||
|
|
case ARM_SPI_CONTROL_SS:
|
||
|
|
val = (spi->info->mode & ARM_SPI_CONTROL_Msk);
|
||
|
|
// Master modes
|
||
|
|
if (val == ARM_SPI_MODE_MASTER) {
|
||
|
|
val = spi->info->mode & ARM_SPI_SS_MASTER_MODE_Msk;
|
||
|
|
// Check if NSS pin is available and
|
||
|
|
// software slave select master is selected
|
||
|
|
if ((spi->io.nss != NULL) && (val == ARM_SPI_SS_MASTER_SW)) {
|
||
|
|
// Set/Clear NSS pin
|
||
|
|
if (arg == ARM_SPI_SS_INACTIVE)
|
||
|
|
GPIO_PinWrite (spi->io.nss->port, spi->io.nss->pin, 1);
|
||
|
|
else
|
||
|
|
GPIO_PinWrite (spi->io.nss->port, spi->io.nss->pin, 0);
|
||
|
|
} else return ARM_DRIVER_ERROR;
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
// Slave modes
|
||
|
|
else if (val == ARM_SPI_MODE_SLAVE) {
|
||
|
|
val = spi->info->mode & ARM_SPI_SS_SLAVE_MODE_Msk;
|
||
|
|
// Check if slave select slave mode is selected
|
||
|
|
if (val == ARM_SPI_SS_MASTER_SW) {
|
||
|
|
if (arg == ARM_SPI_SS_ACTIVE) {
|
||
|
|
spi->reg->CR1 |= SPI_CR1_SSI;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
spi->reg->CR1 &= ~SPI_CR1_SSI;
|
||
|
|
}
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
} else { return ARM_DRIVER_ERROR; }
|
||
|
|
} else { return ARM_DRIVER_ERROR; }
|
||
|
|
|
||
|
|
default:
|
||
|
|
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Frame format:
|
||
|
|
switch (control & ARM_SPI_FRAME_FORMAT_Msk) {
|
||
|
|
case ARM_SPI_CPOL0_CPHA0:
|
||
|
|
break;
|
||
|
|
case ARM_SPI_CPOL0_CPHA1:
|
||
|
|
cr1 |= SPI_CR1_CPHA;
|
||
|
|
break;
|
||
|
|
case ARM_SPI_CPOL1_CPHA0:
|
||
|
|
cr1 |= SPI_CR1_CPOL;
|
||
|
|
break;
|
||
|
|
case ARM_SPI_CPOL1_CPHA1:
|
||
|
|
cr1 |= SPI_CR1_CPHA | SPI_CR1_CPOL;
|
||
|
|
break;
|
||
|
|
case ARM_SPI_TI_SSI:
|
||
|
|
case ARM_SPI_MICROWIRE:
|
||
|
|
default:
|
||
|
|
return ARM_SPI_ERROR_FRAME_FORMAT;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Data Bits
|
||
|
|
switch (control & ARM_SPI_DATA_BITS_Msk) {
|
||
|
|
case ARM_SPI_DATA_BITS(8U):
|
||
|
|
break;
|
||
|
|
case ARM_SPI_DATA_BITS(16U):
|
||
|
|
cr1 |= SPI_CR1_DFF;
|
||
|
|
break;
|
||
|
|
default: return ARM_SPI_ERROR_DATA_BITS;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Bit order
|
||
|
|
if ((control & ARM_SPI_BIT_ORDER_Msk) == ARM_SPI_LSB_MSB) {
|
||
|
|
cr1 |= SPI_CR1_LSBFIRST;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Slave select master modes
|
||
|
|
if (mode == ARM_SPI_MODE_MASTER) {
|
||
|
|
switch (control & ARM_SPI_SS_MASTER_MODE_Msk) {
|
||
|
|
case ARM_SPI_SS_MASTER_UNUSED:
|
||
|
|
if (spi->io.nss != NULL) {
|
||
|
|
// Unconfigure NSS pin
|
||
|
|
GPIO_PinConfigure (spi->io.nss->port, spi->io.nss->pin, GPIO_IN_ANALOG,
|
||
|
|
GPIO_MODE_INPUT);
|
||
|
|
}
|
||
|
|
// Software slave management
|
||
|
|
// Internal NSS always active, IO value is ignored
|
||
|
|
cr1 |= SPI_CR1_SSM | SPI_CR1_SSI;
|
||
|
|
mode |= ARM_SPI_SS_MASTER_UNUSED;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_SPI_SS_MASTER_HW_INPUT:
|
||
|
|
if (spi->io.nss) {
|
||
|
|
// Configure NSS pin
|
||
|
|
GPIO_PortClock (spi->io.nss->port, true);
|
||
|
|
|
||
|
|
GPIO_PinConfigure (spi->io.nss->port, spi->io.nss->pin, GPIO_AF_PUSHPULL,
|
||
|
|
GPIO_MODE_OUT50MHZ);
|
||
|
|
} else {
|
||
|
|
// NSS pin is not available
|
||
|
|
return ARM_SPI_ERROR_SS_MODE;
|
||
|
|
}
|
||
|
|
mode |= ARM_SPI_SS_MASTER_HW_INPUT;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_SPI_SS_MASTER_SW:
|
||
|
|
if (spi->io.nss) {
|
||
|
|
// Configure NSS pin as GPIO output
|
||
|
|
GPIO_PortClock (spi->io.nss->port, true);
|
||
|
|
|
||
|
|
GPIO_PinConfigure (spi->io.nss->port, spi->io.nss->pin, GPIO_OUT_PUSH_PULL,
|
||
|
|
GPIO_MODE_OUT50MHZ);
|
||
|
|
// Software slave management
|
||
|
|
cr1 |= SPI_CR1_SSM | SPI_CR1_SSI;
|
||
|
|
|
||
|
|
mode |= ARM_SPI_SS_MASTER_SW;
|
||
|
|
} else {
|
||
|
|
// NSS pin is not available
|
||
|
|
return ARM_SPI_ERROR_SS_MODE;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_SPI_SS_MASTER_HW_OUTPUT:
|
||
|
|
if (spi->io.nss) {
|
||
|
|
// Configure NSS pin - SPI NSS alternative function
|
||
|
|
GPIO_PortClock (spi->io.nss->port, true);
|
||
|
|
|
||
|
|
GPIO_PinConfigure (spi->io.nss->port, spi->io.nss->pin, GPIO_AF_PUSHPULL,
|
||
|
|
GPIO_MODE_OUT50MHZ);
|
||
|
|
// Slave select output enable
|
||
|
|
cr2 |= SPI_CR2_SSOE;
|
||
|
|
|
||
|
|
mode |= ARM_SPI_SS_MASTER_HW_OUTPUT;
|
||
|
|
} else {
|
||
|
|
// NSS pin is not available
|
||
|
|
return ARM_SPI_ERROR_SS_MODE;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default: return ARM_SPI_ERROR_SS_MODE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Slave select slave modes
|
||
|
|
if (mode == ARM_SPI_MODE_SLAVE) {
|
||
|
|
switch (control & ARM_SPI_SS_SLAVE_MODE_Msk) {
|
||
|
|
case ARM_SPI_SS_SLAVE_HW:
|
||
|
|
if (spi->io.nss) {
|
||
|
|
// Configure NSS pin - SPI NSS alternative function
|
||
|
|
GPIO_PortClock (spi->io.nss->port, true);
|
||
|
|
|
||
|
|
GPIO_PinConfigure (spi->io.nss->port, spi->io.nss->pin, GPIO_AF_PUSHPULL,
|
||
|
|
GPIO_MODE_OUT50MHZ);
|
||
|
|
mode |= ARM_SPI_SS_SLAVE_HW;
|
||
|
|
} else {
|
||
|
|
// NSS pin is not available
|
||
|
|
return ARM_SPI_ERROR_SS_MODE;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ARM_SPI_SS_SLAVE_SW:
|
||
|
|
if (spi->io.nss) {
|
||
|
|
// Unconfigure NSS pin
|
||
|
|
GPIO_PinConfigure (spi->io.nss->port, spi->io.nss->pin, GPIO_IN_ANALOG,
|
||
|
|
GPIO_MODE_INPUT);
|
||
|
|
}
|
||
|
|
// Enable software slave management
|
||
|
|
cr1 |= SPI_CR1_SSM;
|
||
|
|
mode |= ARM_SPI_SS_SLAVE_SW;
|
||
|
|
break;
|
||
|
|
default: return ARM_SPI_ERROR_SS_MODE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set SPI Bus Speed
|
||
|
|
pclk = spi->pclk;
|
||
|
|
for (val = 0U; val < 8U; val++) {
|
||
|
|
if (arg >= (pclk >> (val + 1U))) break;
|
||
|
|
}
|
||
|
|
if ((val == 8U) || (arg < (pclk >> (val + 1U)))) {
|
||
|
|
// Requested Bus Speed can not be configured
|
||
|
|
return ARM_DRIVER_ERROR;
|
||
|
|
}
|
||
|
|
// Save prescaler value
|
||
|
|
cr1 |= (val << 3U);
|
||
|
|
|
||
|
|
spi->info->mode = mode;
|
||
|
|
|
||
|
|
// Configure registers
|
||
|
|
spi->reg->CR1 &= ~SPI_CR1_SPE;
|
||
|
|
spi->reg->CR2 = cr2 | SPI_CR2_ERRIE;
|
||
|
|
spi->reg->CR1 = cr1;
|
||
|
|
|
||
|
|
if ((mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_INACTIVE) {
|
||
|
|
spi->info->state &= ~SPI_CONFIGURED;
|
||
|
|
} else {
|
||
|
|
spi->info->state |= SPI_CONFIGURED;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Enable SPI
|
||
|
|
spi->reg->CR1 |= SPI_CR1_SPE;
|
||
|
|
|
||
|
|
return ARM_DRIVER_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
\fn ARM_SPI_STATUS SPI_GetStatus (const SPI_RESOURCES *spi)
|
||
|
|
\brief Get SPI status.
|
||
|
|
\param[in] spi Pointer to SPI resources
|
||
|
|
\return SPI status \ref ARM_SPI_STATUS
|
||
|
|
*/
|
||
|
|
static ARM_SPI_STATUS SPI_GetStatus (const SPI_RESOURCES *spi) {
|
||
|
|
ARM_SPI_STATUS status;
|
||
|
|
|
||
|
|
status.busy = spi->info->status.busy;
|
||
|
|
status.data_lost = spi->info->status.data_lost;
|
||
|
|
status.mode_fault = spi->info->status.mode_fault;
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*SPI IRQ Handler */
|
||
|
|
void SPI_IRQHandler (const SPI_RESOURCES *spi) {
|
||
|
|
uint8_t data_8bit;
|
||
|
|
uint16_t data_16bit, sr;
|
||
|
|
uint32_t event;
|
||
|
|
|
||
|
|
// Save status register
|
||
|
|
sr = spi->reg->SR;
|
||
|
|
|
||
|
|
event = 0U;
|
||
|
|
|
||
|
|
if ((sr & SPI_SR_OVR) != 0U) {
|
||
|
|
// Clear Overrun flag by reading data and status register
|
||
|
|
if ((spi->reg->CR1 & SPI_CR1_DFF) == 0U) {
|
||
|
|
// 8-bit data frame
|
||
|
|
data_8bit = *(volatile uint8_t *)(&spi->reg->DR);
|
||
|
|
if (spi->xfer->rx_cnt < spi->xfer->num) {
|
||
|
|
if (spi->xfer->rx_buf != NULL) {
|
||
|
|
*(spi->xfer->rx_buf++) = data_8bit;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// 16-bit data frame
|
||
|
|
data_16bit = *(volatile uint16_t *)(&spi->reg->DR);
|
||
|
|
if (spi->xfer->rx_cnt < spi->xfer->num) {
|
||
|
|
if (spi->xfer->rx_buf != NULL) {
|
||
|
|
*(spi->xfer->rx_buf++) = (uint8_t) data_16bit;
|
||
|
|
*(spi->xfer->rx_buf++) = (uint8_t)(data_16bit >> 8U);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
spi->xfer->rx_cnt++;
|
||
|
|
sr = spi->reg->SR;
|
||
|
|
|
||
|
|
spi->info->status.data_lost = 1U;
|
||
|
|
event |=ARM_SPI_EVENT_DATA_LOST;
|
||
|
|
}
|
||
|
|
if ((sr & SPI_SR_UDR) != 0U) {
|
||
|
|
// Underrun flag is set
|
||
|
|
spi->info->status.data_lost = 1U;
|
||
|
|
event |= ARM_SPI_EVENT_DATA_LOST;
|
||
|
|
}
|
||
|
|
if ((sr & SPI_SR_MODF) != 0U) {
|
||
|
|
// Mode fault flag is set
|
||
|
|
spi->info->status.mode_fault = 1U;
|
||
|
|
|
||
|
|
// Write CR1 register to clear MODF flag
|
||
|
|
spi->reg->CR1 = spi->reg->CR1;
|
||
|
|
event |= ARM_SPI_EVENT_MODE_FAULT;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (((sr & SPI_SR_RXNE) != 0U) && ((spi->reg->CR2 & SPI_CR2_RXNEIE) != 0U)) {
|
||
|
|
// Receive Buffer Not Empty
|
||
|
|
|
||
|
|
if (spi->xfer->rx_cnt < spi->xfer->num) {
|
||
|
|
if ((spi->reg->CR1 & SPI_CR1_DFF) == 0U) {
|
||
|
|
// 8-bit data frame
|
||
|
|
data_8bit = *(volatile uint8_t *)(&spi->reg->DR);
|
||
|
|
if (spi->xfer->rx_buf != NULL) {
|
||
|
|
*(spi->xfer->rx_buf++) = data_8bit;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// 16-bit data frame
|
||
|
|
data_16bit = *(volatile uint16_t *)(&spi->reg->DR);
|
||
|
|
if (spi->xfer->rx_buf != NULL) {
|
||
|
|
*(spi->xfer->rx_buf++) = (uint8_t) data_16bit;
|
||
|
|
*(spi->xfer->rx_buf++) = (uint8_t)(data_16bit >> 8U);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
spi->xfer->rx_cnt++;
|
||
|
|
|
||
|
|
if (spi->xfer->rx_cnt == spi->xfer->num) {
|
||
|
|
|
||
|
|
// Disable RX Buffer Not Empty Interrupt
|
||
|
|
spi->reg->CR2 &= ~SPI_CR2_RXNEIE;
|
||
|
|
|
||
|
|
// Clear busy flag
|
||
|
|
spi->info->status.busy = 0U;
|
||
|
|
|
||
|
|
// Transfer completed
|
||
|
|
event |= ARM_SPI_EVENT_TRANSFER_COMPLETE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// Unexpected transfer, data lost
|
||
|
|
event |= ARM_SPI_EVENT_DATA_LOST;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (((sr & SPI_SR_TXE) != 0U) && ((spi->reg->CR2 & SPI_CR2_TXEIE) != 0U)) {
|
||
|
|
if (spi->xfer->tx_cnt < spi->xfer->num) {
|
||
|
|
if ((spi->reg->CR1 & SPI_CR1_DFF) == 0U) {
|
||
|
|
if (spi->xfer->tx_buf != NULL) {
|
||
|
|
data_8bit = *(spi->xfer->tx_buf++);
|
||
|
|
} else {
|
||
|
|
data_8bit = (uint8_t)spi->xfer->def_val;
|
||
|
|
}
|
||
|
|
// Write data to data register
|
||
|
|
*(volatile uint8_t *)(&spi->reg->DR) = data_8bit;
|
||
|
|
} else {
|
||
|
|
if (spi->xfer->tx_buf != NULL) {
|
||
|
|
data_16bit = *(spi->xfer->tx_buf++);
|
||
|
|
data_16bit |= *(spi->xfer->tx_buf++) << 8U;
|
||
|
|
} else {
|
||
|
|
data_16bit = (uint16_t)spi->xfer->def_val;
|
||
|
|
}
|
||
|
|
// Write data to data register
|
||
|
|
*(volatile uint16_t *)(&spi->reg->DR) = data_16bit;
|
||
|
|
}
|
||
|
|
|
||
|
|
spi->xfer->tx_cnt++;
|
||
|
|
|
||
|
|
if (spi->xfer->tx_cnt == spi->xfer->num) {
|
||
|
|
// All data sent, disable TX Buffer Empty Interrupt
|
||
|
|
spi->reg->CR2 &= ~SPI_CR2_TXEIE;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// Unexpected transfer, data lost
|
||
|
|
event |= ARM_SPI_EVENT_DATA_LOST;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Send event
|
||
|
|
if ((event != 0U) && ((spi->info->cb_event != NULL))) {
|
||
|
|
spi->info->cb_event(event);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA_TX
|
||
|
|
void SPI_TX_DMA_Complete(uint32_t events, const SPI_RESOURCES *spi) {
|
||
|
|
|
||
|
|
DMA_ChannelDisable(spi->tx_dma->instance);
|
||
|
|
|
||
|
|
if ((DMA_ChannelTransferItemCount(spi->tx_dma->instance) != 0) && (spi->xfer->num != 0)) {
|
||
|
|
// TX DMA Complete caused by transfer abort
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
spi->xfer->tx_cnt = spi->xfer->num;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef __SPI_DMA_RX
|
||
|
|
void SPI_RX_DMA_Complete(uint32_t events, const SPI_RESOURCES *spi) {
|
||
|
|
|
||
|
|
DMA_ChannelDisable(spi->rx_dma->instance);
|
||
|
|
|
||
|
|
if ((DMA_ChannelTransferItemCount(spi->rx_dma->instance) != 0) && (spi->xfer->num != 0)) {
|
||
|
|
// RX DMA Complete caused by transfer abort
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
spi->xfer->rx_cnt = spi->xfer->num;
|
||
|
|
|
||
|
|
spi->info->status.busy = 0U;
|
||
|
|
if (spi->info->cb_event != NULL) {
|
||
|
|
spi->info->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// SPI1
|
||
|
|
#ifdef MX_SPI1
|
||
|
|
static int32_t SPI1_Initialize (ARM_SPI_SignalEvent_t pSignalEvent) { return SPI_Initialize (pSignalEvent, &SPI1_Resources); }
|
||
|
|
static int32_t SPI1_Uninitialize (void) { return SPI_Uninitialize (&SPI1_Resources); }
|
||
|
|
static int32_t SPI1_PowerControl (ARM_POWER_STATE state) { return SPI_PowerControl (state, &SPI1_Resources); }
|
||
|
|
static int32_t SPI1_Send (const void *data, uint32_t num) { return SPI_Send (data, num, &SPI1_Resources); }
|
||
|
|
static int32_t SPI1_Receive (void *data, uint32_t num) { return SPI_Receive (data, num, &SPI1_Resources); }
|
||
|
|
static int32_t SPI1_Transfer (const void *data_out, void *data_in, uint32_t num) { return SPI_Transfer (data_out, data_in, num, &SPI1_Resources); }
|
||
|
|
static uint32_t SPI1_GetDataCount (void) { return SPI_GetDataCount (&SPI1_Resources); }
|
||
|
|
static int32_t SPI1_Control (uint32_t control, uint32_t arg) { return SPI_Control (control, arg, &SPI1_Resources); }
|
||
|
|
static ARM_SPI_STATUS SPI1_GetStatus (void) { return SPI_GetStatus (&SPI1_Resources); }
|
||
|
|
void SPI1_IRQHandler (void) { SPI_IRQHandler (&SPI1_Resources); }
|
||
|
|
|
||
|
|
#ifdef MX_SPI1_TX_DMA_Instance
|
||
|
|
void SPI1_TX_DMA_Handler (uint32_t events) { SPI_TX_DMA_Complete (events, &SPI1_Resources); }
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI1_RX_DMA_Instance
|
||
|
|
void SPI1_RX_DMA_Handler (uint32_t events) { SPI_RX_DMA_Complete (events, &SPI1_Resources); }
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ARM_DRIVER_SPI Driver_SPI1 = {
|
||
|
|
SPIX_GetVersion,
|
||
|
|
SPIX_GetCapabilities,
|
||
|
|
SPI1_Initialize,
|
||
|
|
SPI1_Uninitialize,
|
||
|
|
SPI1_PowerControl,
|
||
|
|
SPI1_Send,
|
||
|
|
SPI1_Receive,
|
||
|
|
SPI1_Transfer,
|
||
|
|
SPI1_GetDataCount,
|
||
|
|
SPI1_Control,
|
||
|
|
SPI1_GetStatus
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// SPI2
|
||
|
|
#ifdef MX_SPI2
|
||
|
|
static int32_t SPI2_Initialize (ARM_SPI_SignalEvent_t pSignalEvent) { return SPI_Initialize (pSignalEvent, &SPI2_Resources); }
|
||
|
|
static int32_t SPI2_Uninitialize (void) { return SPI_Uninitialize (&SPI2_Resources); }
|
||
|
|
static int32_t SPI2_PowerControl (ARM_POWER_STATE state) { return SPI_PowerControl (state, &SPI2_Resources); }
|
||
|
|
static int32_t SPI2_Send (const void *data, uint32_t num) { return SPI_Send (data, num, &SPI2_Resources); }
|
||
|
|
static int32_t SPI2_Receive (void *data, uint32_t num) { return SPI_Receive (data, num, &SPI2_Resources); }
|
||
|
|
static int32_t SPI2_Transfer (const void *data_out, void *data_in, uint32_t num) { return SPI_Transfer (data_out, data_in, num, &SPI2_Resources); }
|
||
|
|
static uint32_t SPI2_GetDataCount (void) { return SPI_GetDataCount (&SPI2_Resources); }
|
||
|
|
static int32_t SPI2_Control (uint32_t control, uint32_t arg) { return SPI_Control (control, arg, &SPI2_Resources); }
|
||
|
|
static ARM_SPI_STATUS SPI2_GetStatus (void) { return SPI_GetStatus (&SPI2_Resources); }
|
||
|
|
void SPI2_IRQHandler (void) { SPI_IRQHandler (&SPI2_Resources); }
|
||
|
|
|
||
|
|
#ifdef MX_SPI2_TX_DMA_Instance
|
||
|
|
void SPI2_TX_DMA_Handler (uint32_t events) { SPI_TX_DMA_Complete (events, &SPI2_Resources); }
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI2_RX_DMA_Instance
|
||
|
|
void SPI2_RX_DMA_Handler (uint32_t events) { SPI_RX_DMA_Complete (events, &SPI2_Resources); }
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ARM_DRIVER_SPI Driver_SPI2 = {
|
||
|
|
SPIX_GetVersion,
|
||
|
|
SPIX_GetCapabilities,
|
||
|
|
SPI2_Initialize,
|
||
|
|
SPI2_Uninitialize,
|
||
|
|
SPI2_PowerControl,
|
||
|
|
SPI2_Send,
|
||
|
|
SPI2_Receive,
|
||
|
|
SPI2_Transfer,
|
||
|
|
SPI2_GetDataCount,
|
||
|
|
SPI2_Control,
|
||
|
|
SPI2_GetStatus
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// SPI3
|
||
|
|
#ifdef MX_SPI3
|
||
|
|
static int32_t SPI3_Initialize (ARM_SPI_SignalEvent_t pSignalEvent) { return SPI_Initialize (pSignalEvent, &SPI3_Resources); }
|
||
|
|
static int32_t SPI3_Uninitialize (void) { return SPI_Uninitialize (&SPI3_Resources); }
|
||
|
|
static int32_t SPI3_PowerControl (ARM_POWER_STATE state) { return SPI_PowerControl (state, &SPI3_Resources); }
|
||
|
|
static int32_t SPI3_Send (const void *data, uint32_t num) { return SPI_Send (data, num, &SPI3_Resources); }
|
||
|
|
static int32_t SPI3_Receive (void *data, uint32_t num) { return SPI_Receive (data, num, &SPI3_Resources); }
|
||
|
|
static int32_t SPI3_Transfer (const void *data_out, void *data_in, uint32_t num) { return SPI_Transfer (data_out, data_in, num, &SPI3_Resources); }
|
||
|
|
static uint32_t SPI3_GetDataCount (void) { return SPI_GetDataCount (&SPI3_Resources); }
|
||
|
|
static int32_t SPI3_Control (uint32_t control, uint32_t arg) { return SPI_Control (control, arg, &SPI3_Resources); }
|
||
|
|
static ARM_SPI_STATUS SPI3_GetStatus (void) { return SPI_GetStatus (&SPI3_Resources); }
|
||
|
|
void SPI3_IRQHandler (void) { SPI_IRQHandler (&SPI3_Resources); }
|
||
|
|
|
||
|
|
#ifdef MX_SPI3_TX_DMA_Instance
|
||
|
|
void SPI3_TX_DMA_Handler (uint32_t events) { SPI_TX_DMA_Complete (events, &SPI3_Resources); }
|
||
|
|
#endif
|
||
|
|
#ifdef MX_SPI3_RX_DMA_Instance
|
||
|
|
void SPI3_RX_DMA_Handler (uint32_t events) { SPI_RX_DMA_Complete (events, &SPI3_Resources); }
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ARM_DRIVER_SPI Driver_SPI3 = {
|
||
|
|
SPIX_GetVersion,
|
||
|
|
SPIX_GetCapabilities,
|
||
|
|
SPI3_Initialize,
|
||
|
|
SPI3_Uninitialize,
|
||
|
|
SPI3_PowerControl,
|
||
|
|
SPI3_Send,
|
||
|
|
SPI3_Receive,
|
||
|
|
SPI3_Transfer,
|
||
|
|
SPI3_GetDataCount,
|
||
|
|
SPI3_Control,
|
||
|
|
SPI3_GetStatus
|
||
|
|
};
|
||
|
|
#endif
|