aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports
diff options
context:
space:
mode:
authorisiora <none@example.com>2018-02-20 18:22:05 +0000
committerisiora <none@example.com>2018-02-20 18:22:05 +0000
commit4be6636fd080e4d4d37d4b8e6e2449dd912663b6 (patch)
treecbb90941a01c388fbb98e21cc97cbb1badce6c33 /os/hal/ports
parenta6d67787e4730a1d925524494d5a0c1b580cc7be (diff)
downloadChibiOS-4be6636fd080e4d4d37d4b8e6e2449dd912663b6.tar.gz
ChibiOS-4be6636fd080e4d4d37d4b8e6e2449dd912663b6.tar.bz2
ChibiOS-4be6636fd080e4d4d37d4b8e6e2449dd912663b6.zip
Added WDRBT flag in MR register as default to avoid overrun using dma.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11520 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports')
-rw-r--r--os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c1554
1 files changed, 779 insertions, 775 deletions
diff --git a/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c b/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c
index 6a8b5ec0f..9d2378e7a 100644
--- a/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c
+++ b/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c
@@ -1,775 +1,779 @@
-/*
- ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-/**
- * @file hal_spi_lld.c
- * @brief SAMA SPI subsystem low level driver source.
- *
- * @addtogroup SPI
- * @{
- */
-
-#include "hal.h"
-
-#if HAL_USE_SPI || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver local definitions. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local macros. */
-/*===========================================================================*/
-
-/**
- * @brief Enable write protection on SPI registers block.
- *
- * @param[in] spip pointer to a SPI register block
- *
- * @notapi
- */
-#define spiEnableWP(spip) { \
- spip->SPI_WPMR = SPI_WPMR_WPKEY_PASSWD | SPI_WPMR_WPEN; \
-}
-
-/**
- * @brief Disable write protection on SPI registers block.
- *
- * @param[in] spip pointer to a SPI register block
- *
- * @notapi
- */
-#define spiDisableWP(spip) { \
- spip->SPI_WPMR = SPI_WPMR_WPKEY_PASSWD; \
-}
-
-
-/*===========================================================================*/
-/* Driver exported variables. */
-/*===========================================================================*/
-
-/**
- * @brief SPI0 driver identifier.
- */
-#if SAMA_SPI_USE_SPI0 || defined(__DOXYGEN__)
-SPIDriver SPID0;
-#endif
-
-/**
- * @brief SPI1 driver identifier.
- */
-#if SAMA_SPI_USE_SPI1 || defined(__DOXYGEN__)
-SPIDriver SPID1;
-#endif
-
-/**
- * @brief SPI FLEXCOM0 driver identifier.
- */
-#if SAMA_SPI_USE_FLEXCOM0 || defined(__DOXYGEN__)
-SPIDriver FSPID0;
-#endif
-
-/**
- * @brief SPI FLEXCOM1 driver identifier.
- */
-#if SAMA_SPI_USE_FLEXCOM1 || defined(__DOXYGEN__)
-SPIDriver FSPID1;
-#endif
-
-/**
- * @brief SPI FLEXCOM2 driver identifier.
- */
-#if SAMA_SPI_USE_FLEXCOM2 || defined(__DOXYGEN__)
-SPIDriver FSPID2;
-#endif
-
-/**
- * @brief SPI FLEXCOM3 driver identifier.
- */
-#if SAMA_SPI_USE_FLEXCOM3 || defined(__DOXYGEN__)
-SPIDriver FSPID3;
-#endif
-
-/**
- * @brief SPI FLEXCOM4 driver identifier.
- */
-#if SAMA_SPI_USE_FLEXCOM4 || defined(__DOXYGEN__)
-SPIDriver FSPID4;
-#endif
-
-/*===========================================================================*/
-/* Driver local variables and types. */
-/*===========================================================================*/
-
-static const uint8_t dummytx = 0xFFU;
-static uint8_t dummyrx;
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-
-/**
- * @brief Shared end-of-rx service routine.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] flags pre-shifted content of the ISR register
- */
-static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
-
- /* DMA errors handling.*/
-#if defined(SAMA_SPI_DMA_ERROR_HOOK)
- if ((flags & (XDMAC_CIS_RBEIS | XDMAC_CIS_ROIS)) != 0) {
- SAMA_SPI_DMA_ERROR_HOOK(spip);
- }
-#else
- (void)flags;
-#endif
-
- /* Stop everything.*/
- dmaChannelDisable(spip->dmatx);
- dmaChannelDisable(spip->dmarx);
-
- /* Portable SPI ISR code defined in the high level driver, note, it is
- a macro.*/
- _spi_isr_code(spip);
-}
-
-/**
- * @brief Shared end-of-tx service routine.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] flags pre-shifted content of the ISR register
- */
-static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
-
- /* DMA errors handling.*/
-
-#if defined(SAMA_SPI_DMA_ERROR_HOOK)
- (void)spip;
- if ((flags & (XDMAC_CIS_WBEIS | XDMAC_CIS_ROIS)) != 0) {
- SAMA_SPI_DMA_ERROR_HOOK(spip);
- }
-#else
- (void)spip;
- (void)flags;
-#endif
-}
-/*===========================================================================*/
-/* Driver interrupt handlers. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-/**
- * @brief Low level SPI driver initialization.
- *
- * @notapi
- */
-void spi_lld_init(void) {
-
-#if SAMA_SPI_USE_SPI0
-#if SAMA_HAL_IS_SECURE
- mtxConfigPeriphSecurity(MATRIX1, ID_SPI0, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
- /* Driver initialization.*/
- spiObjectInit(&SPID0);
- SPID0.spi = SPI0;
- SPID0.dmarx = NULL;
- SPID0.dmatx = NULL;
- SPID0.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_PER2MEM |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF1 |
- XDMAC_CC_DIF_AHB_IF0 |
- XDMAC_CC_SAM_FIXED_AM |
- XDMAC_CC_DAM_INCREMENTED_AM |
- XDMAC_CC_PERID(PERID_SPI0_RX);
- SPID0.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_MEM2PER |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF0 |
- XDMAC_CC_DIF_AHB_IF1 |
- XDMAC_CC_SAM_INCREMENTED_AM |
- XDMAC_CC_DAM_FIXED_AM |
- XDMAC_CC_PERID(PERID_SPI0_TX);
-#endif /* SAMA_SPI_USE_SPI0 */
-
-#if SAMA_SPI_USE_SPI1
-#if SAMA_HAL_IS_SECURE
- mtxConfigPeriphSecurity(MATRIX1, ID_SPI1, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
- /* Driver initialization.*/
- spiObjectInit(&SPID1);
- SPID1.spi = SPI1;
- SPID1.dmarx = NULL;
- SPID1.dmatx = NULL;
- SPID1.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_PER2MEM |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF1 |
- XDMAC_CC_DIF_AHB_IF0 |
- XDMAC_CC_SAM_FIXED_AM |
- XDMAC_CC_DAM_INCREMENTED_AM |
- XDMAC_CC_PERID(PERID_SPI1_RX);
- SPID1.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_MEM2PER |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF0 |
- XDMAC_CC_DIF_AHB_IF1 |
- XDMAC_CC_SAM_INCREMENTED_AM |
- XDMAC_CC_DAM_FIXED_AM |
- XDMAC_CC_PERID(PERID_SPI1_TX);
-#endif /* SAMA_SPI_USE_SPI1 */
-
-#if SAMA_SPI_USE_FLEXCOM0
-#if SAMA_HAL_IS_SECURE
- mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM0, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
- /* Driver initialization.*/
- spiObjectInit(&FSPID0);
- FSPID0.spi = FCOMSPI0;
- FSPID0.flexcom = FLEXCOM0;
- FSPID0.dmarx = NULL;
- FSPID0.dmatx = NULL;
- FSPID0.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_PER2MEM |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF1 |
- XDMAC_CC_DIF_AHB_IF0 |
- XDMAC_CC_SAM_FIXED_AM |
- XDMAC_CC_DAM_INCREMENTED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM0_RX);
- FSPID0.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_MEM2PER |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF0 |
- XDMAC_CC_DIF_AHB_IF1 |
- XDMAC_CC_SAM_INCREMENTED_AM |
- XDMAC_CC_DAM_FIXED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM0_TX);
-#endif /* SAMA_SPI_USE_FLEXCOM0 */
-
-#if SAMA_SPI_USE_FLEXCOM1
-#if SAMA_HAL_IS_SECURE
- mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM1, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
- /* Driver initialization.*/
- spiObjectInit(&FSPID1);
- FSPID1.spi = FCOMSPI1;
- FSPID1.flexcom = FLEXCOM1;
- FSPID1.dmarx = NULL;
- FSPID1.dmatx = NULL;
- FSPID1.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_PER2MEM |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF1 |
- XDMAC_CC_DIF_AHB_IF0 |
- XDMAC_CC_SAM_FIXED_AM |
- XDMAC_CC_DAM_INCREMENTED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM1_RX);
- FSPID1.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_MEM2PER |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF0 |
- XDMAC_CC_DIF_AHB_IF1 |
- XDMAC_CC_SAM_INCREMENTED_AM |
- XDMAC_CC_DAM_FIXED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM1_TX);
-#endif /* SAMA_SPI_USE_FLEXCOM1 */
-
-#if SAMA_SPI_USE_FLEXCOM2
-#if SAMA_HAL_IS_SECURE
- mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM2, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
- /* Driver initialization.*/
- spiObjectInit(&FSPID2);
- FSPID2.spi = FCOMSPI2;
- FSPID2.flexcom = FLEXCOM2;
- FSPID2.dmarx = NULL;
- FSPID2.dmatx = NULL;
- FSPID2.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_PER2MEM |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF1 |
- XDMAC_CC_DIF_AHB_IF0 |
- XDMAC_CC_SAM_FIXED_AM |
- XDMAC_CC_DAM_INCREMENTED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM2_RX);
- FSPID2.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_MEM2PER |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF0 |
- XDMAC_CC_DIF_AHB_IF1 |
- XDMAC_CC_SAM_INCREMENTED_AM |
- XDMAC_CC_DAM_FIXED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM2_TX);
-#endif /* SAMA_SPI_USE_FLEXCOM2 */
-
-#if SAMA_SPI_USE_FLEXCOM3
-#if SAMA_HAL_IS_SECURE
- mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM3, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
- /* Driver initialization.*/
- spiObjectInit(&FSPID3);
- FSPID3.spi = FCOMSPI3;
- FSPID3.flexcom = FLEXCOM3;
- FSPID3.dmarx = NULL;
- FSPID3.dmatx = NULL;
- FSPID3.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_PER2MEM |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF1 |
- XDMAC_CC_DIF_AHB_IF0 |
- XDMAC_CC_SAM_FIXED_AM |
- XDMAC_CC_DAM_INCREMENTED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM3_RX);
- FSPID3.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_MEM2PER |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF0 |
- XDMAC_CC_DIF_AHB_IF1 |
- XDMAC_CC_SAM_INCREMENTED_AM |
- XDMAC_CC_DAM_FIXED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM3_TX);
-#endif /* SAMA_SPI_USE_FLEXCOM3 */
-
-#if SAMA_SPI_USE_FLEXCOM4
-#if SAMA_HAL_IS_SECURE
- mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM4, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
- /* Driver initialization.*/
- spiObjectInit(&FSPID4);
- FSPID4.spi = FCOMSPI4;
- FSPID4.flexcom = FLEXCOM4;
- FSPID4.dmarx = NULL;
- FSPID4.dmatx = NULL;
- FSPID4.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_PER2MEM |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF1 |
- XDMAC_CC_DIF_AHB_IF0 |
- XDMAC_CC_SAM_FIXED_AM |
- XDMAC_CC_DAM_INCREMENTED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM4_RX);
- FSPID4.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
- XDMAC_CC_MBSIZE_SINGLE |
- XDMAC_CC_DSYNC_MEM2PER |
- XDMAC_CC_PROT_SEC |
- XDMAC_CC_CSIZE_CHK_1 |
- XDMAC_CC_DWIDTH_BYTE |
- XDMAC_CC_SIF_AHB_IF0 |
- XDMAC_CC_DIF_AHB_IF1 |
- XDMAC_CC_SAM_INCREMENTED_AM |
- XDMAC_CC_DAM_FIXED_AM |
- XDMAC_CC_PERID(PERID_FLEXCOM4_TX);
-#endif /* SAMA_SPI_USE_FLEXCOM4 */
-}
-
-/**
- * @brief Configures and activates the SPI peripheral.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- *
- * @notapi
- */
-void spi_lld_start(SPIDriver *spip) {
-
- /* Configures the peripheral.*/
-
- if (spip->state == SPI_STOP) {
-
-#if SAMA_SPI_USE_SPI0
- if (&SPID0 == spip) {
- spip->dmarx = dmaChannelAllocate(SAMA_SPI_SPI0_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
-
- spip->dmatx = dmaChannelAllocate(SAMA_SPI_SPI0_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
- /* Enable SPI0 clock */
- pmcEnableSPI0();
- }
-#endif /* SAMA_SPI_USE_SPI0 */
-#if SAMA_SPI_USE_SPI1
- if (&SPID1 == spip) {
- spip->dmarx = dmaChannelAllocate(SAMA_SPI_SPI1_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
-
- spip->dmatx = dmaChannelAllocate(SAMA_SPI_SPI1_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
- /* Enable SPI1 clock */
- pmcEnableSPI1();
- }
-#endif /* SAMA_SPI_USE_SPI1 */
-#if SAMA_SPI_USE_FLEXCOM0
- if (&FSPID0 == spip) {
- spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM0_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
-
- spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM0_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
- /* Enabling SPI on FLEXCOM */
- spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
- /* Enable FLEXCOM0 clock */
- pmcEnableFLEXCOM0();
- }
-#endif /* SAMA_SPI_USE_FLEXCOM0 */
-#if SAMA_SPI_USE_FLEXCOM1
- if (&FSPID1 == spip) {
- spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM1_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
-
- spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM1_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
- /* Enabling SPI on FLEXCOM */
- spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
- /* Enable FLEXCOM1 clock */
- pmcEnableFLEXCOM1();
- }
-#endif /* SAMA_SPI_USE_FLEXCOM1 */
-#if SAMA_SPI_USE_FLEXCOM2
- if (&FSPID2 == spip) {
- spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM2_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
-
- spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM2_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
- /* Enabling SPI on FLEXCOM */
- spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
- /* Enable FLEXCOM2 clock */
- pmcEnableFLEXCOM2();
- }
-#endif /* SAMA_SPI_USE_FLEXCOM2 */
-#if SAMA_SPI_USE_FLEXCOM3
- if (&FSPID3 == spip) {
- spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM3_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
-
- spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM3_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
- /* Enabling SPI on FLEXCOM */
- spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
- /* Enable FLEXCOM3 clock */
- pmcEnableFLEXCOM3();
- }
-#endif /* SAMA_SPI_USE_FLEXCOM3 */
-#if SAMA_SPI_USE_FLEXCOM4
- if (&FSPID4 == spip) {
- spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM4_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
-
- spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM4_DMA_IRQ_PRIORITY,
- (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
- (void *)spip);
- osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
- /* Enabling SPI on FLEXCOM */
- spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
- /* Enable FLEXCOM4 clock */
- pmcEnableFLEXCOM4();
- }
-#endif /* SAMA_SPI_USE_FLEXCOM4 */
- }
-
- /* Set mode */
- dmaChannelSetMode(spip->dmarx, spip->rxdmamode);
- dmaChannelSetMode(spip->dmatx, spip->txdmamode);
-
- /* Disable write protection */
- spiDisableWP(spip->spi);
-
- /* Execute a software reset of the SPI twice */
- spip->spi->SPI_CR = SPI_CR_SWRST;
- spip->spi->SPI_CR = SPI_CR_SWRST;
-
- /* SPI configuration */
- spip->spi->SPI_MR = SPI_MR_MSTR | spip->config->mr;
- spip->spi->SPI_MR &= ~SPI_MR_PCS_Msk;
- spip->spi->SPI_MR |= SPI_PCS(spip->config->npcs);
- spip->spi->SPI_CSR[spip->config->npcs] = spip->config->csr;
-
- /* if SPI_CSRx_BITS > 8, dma is set to 16 bits */
- if (((spip->spi->SPI_CSR[spip->config->npcs] >> 4) & 0xF) > 0) {
- dmaChannelSetMode(spip->dmatx, spip->txdmamode | XDMAC_CC_DWIDTH_HALFWORD);
- dmaChannelSetMode(spip->dmarx, spip->rxdmamode | XDMAC_CC_DWIDTH_HALFWORD);
- }
-
- /* Enable SPI */
- spip->spi->SPI_CR |= SPI_CR_SPIEN;
- /* Enable write protection. */
- spiEnableWP(spip->spi);
-}
-
-/**
- * @brief Deactivates the SPI peripheral.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- *
- * @notapi
- */
-void spi_lld_stop(SPIDriver *spip) {
-
- if (spip->state == SPI_READY) {
- /* Disable write protection */
- spiDisableWP(spip->spi);
- /* Reset SPI */
- spip->spi->SPI_MR = 0;
- spip->spi->SPI_CSR[spip->config->npcs] = 0;
- /* Disable SPI */
- spip->spi->SPI_CR |= SPI_CR_SPIDIS;
- /* Enable write protection */
- spiEnableWP(spip->spi);
-
-#if SAMA_SPI_USE_SPI0
- if (&SPID0 == spip)
- /* Disable SPI0 clock */
- pmcDisableSPI0();
-
-#endif /* SAMA_SPI_USE_SPI1 */
-#if SAMA_SPI_USE_SPI1
- if (&SPID1 == spip)
- /* Disable SPI1 clock */
- pmcDisableSPI1();
-
-#endif /* SAMA_SPI_USE_FLEXCOM0 */
-
-#if SAMA_SPI_USE_FLEXCOM0
- if (&FSPID0 == spip)
- /* Disable FLEXCOM0 clock */
- pmcDisableFLEXCOM0();
-
-#endif /* SAMA_SPI_USE_FLEXCOM0 */
-
-#if SAMA_SPI_USE_FLEXCOM1
- if (&FSPID1 == spip)
- /* Disable FLEXCOM1 clock */
- pmcDisableFLEXCOM1();
-
-#endif /* SAMA_SPI_USE_FLEXCOM1 */
-
-#if SAMA_SPI_USE_FLEXCOM2
- if (&FSPID2 == spip)
- /* Disable FLEXCOM2 clock */
- pmcDisableFLEXCOM2();
-
-#endif /* SAMA_SPI_USE_FLEXCOM2 */
-
-#if SAMA_SPI_USE_FLEXCOM3
- if (&FSPID3 == spip)
- /* Disable FLEXCOM3 clock */
- pmcDisableFLEXCOM3();
-
-#endif /* SAMA_SPI_USE_FLEXCOM3 */
-
-#if SAMA_SPI_USE_FLEXCOM4
- if (&FSPID4 == spip)
- /* Disable FLEXCOM4 clock */
- pmcDisableFLEXCOM4();
-
-#endif /* SAMA_SPI_USE_FLEXCOM4 */
- }
-}
-
-#if (SPI_SELECT_MODE == (SPI_SELECT_MODE_LLD || SPI_SELECT_MODE_PAD || \
- SPI_SELECT_MODE_PORT || SPI_SELECT_MODE_LINE)) || defined(__DOXYGEN__)
-/**
- * @brief Asserts the slave select signal and prepares for transfers.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- *
- * @notapi
- */
-void spi_lld_select(SPIDriver *spip) {
- /* No implementation on SAMA.*/
-}
-
-/**
- * @brief Deasserts the slave select signal.
- * @details The previously selected peripheral is unselected.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- *
- * @notapi
- */
-void spi_lld_unselect(SPIDriver *spip) {
- /* No implementation on SAMA.*/
-}
-#endif
-
-/**
- * @brief Exchanges data on the SPI bus.
- * @details This asynchronous function starts a simultaneous transmit/receive
- * operation.
- * @post At the end of the operation the configured callback is invoked.
- * @note The buffers are organized as uint8_t arrays for data sizes below or
- * equal to 8 bits else it is organized as uint16_t arrays.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] n number of words to be exchanged
- * @param[in] txbuf the pointer to the transmit buffer
- * @param[out]rxbuf the pointer to the receive buffer
- *
- * @notapi
- */
-void spi_lld_exchange(SPIDriver *spip, size_t n,
- const void *txbuf, void *rxbuf) {
-
- /* Writing channel */
- dmaChannelSetSource(spip->dmatx, txbuf);
- dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
- dmaChannelSetTransactionSize(spip->dmatx, n);
-
- /* Reading channel */
- dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
- dmaChannelSetDestination(spip->dmarx, rxbuf);
- dmaChannelSetTransactionSize(spip->dmarx, n);
-
- dmaChannelEnable(spip->dmarx);
- dmaChannelEnable(spip->dmatx);
-}
-
-/**
- * @brief Sends data over the SPI bus.
- * @details This asynchronous function starts a transmit operation.
- * @post At the end of the operation the configured callback is invoked.
- * @note The buffers are organized as uint8_t arrays for data sizes below or
- * equal to 8 bits else it is organized as uint16_t arrays.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] n number of words to send
- * @param[in] txbuf the pointer to the transmit buffer
- *
- * @notapi
- */
-void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
-
- /* Writing channel */
- dmaChannelSetSource(spip->dmatx, txbuf);
- dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
- dmaChannelSetTransactionSize(spip->dmatx, n);
-
- /* Reading channel */
- dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
- dmaChannelSetDestination(spip->dmarx, &dummyrx);
- dmaChannelSetTransactionSize(spip->dmarx, n);
- /* Enable write protection. */
-
- dmaChannelEnable(spip->dmarx);
- dmaChannelEnable(spip->dmatx);
-
- /* Waiting TXEMPTY flag */
- while (!(spip->spi->SPI_SR & SPI_SR_TXEMPTY)) {
- ;
- }
-}
-
-/**
- * @brief Receives data from the SPI bus.
- * @details This asynchronous function starts a receive operation.
- * @post At the end of the operation the configured callback is invoked.
- * @note The buffers are organized as uint8_t arrays for data sizes below or
- * equal to 8 bits else it is organized as uint16_t arrays.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] n number of words to receive
- * @param[out]rxbuf the pointer to the receive buffer
- *
- * @notapi
- */
-void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
-
- /* Writing channel */
- dmaChannelSetSource(spip->dmatx, &dummytx);
- dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
- dmaChannelSetTransactionSize(spip->dmatx, n);
-
- /* Reading channel */
- dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
- dmaChannelSetDestination(spip->dmarx, rxbuf);
- dmaChannelSetTransactionSize(spip->dmarx, n);
-
- dmaChannelEnable(spip->dmarx);
- dmaChannelEnable(spip->dmatx);
-}
-
-#endif /* HAL_USE_SPI */
-
-/** @} */
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_spi_lld.c
+ * @brief SAMA SPI subsystem low level driver source.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Enable write protection on SPI registers block.
+ *
+ * @param[in] spip pointer to a SPI register block
+ *
+ * @notapi
+ */
+#define spiEnableWP(spip) { \
+ spip->SPI_WPMR = SPI_WPMR_WPKEY_PASSWD | SPI_WPMR_WPEN; \
+}
+
+/**
+ * @brief Disable write protection on SPI registers block.
+ *
+ * @param[in] spip pointer to a SPI register block
+ *
+ * @notapi
+ */
+#define spiDisableWP(spip) { \
+ spip->SPI_WPMR = SPI_WPMR_WPKEY_PASSWD; \
+}
+
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief SPI0 driver identifier.
+ */
+#if SAMA_SPI_USE_SPI0 || defined(__DOXYGEN__)
+SPIDriver SPID0;
+#endif
+
+/**
+ * @brief SPI1 driver identifier.
+ */
+#if SAMA_SPI_USE_SPI1 || defined(__DOXYGEN__)
+SPIDriver SPID1;
+#endif
+
+/**
+ * @brief SPI FLEXCOM0 driver identifier.
+ */
+#if SAMA_SPI_USE_FLEXCOM0 || defined(__DOXYGEN__)
+SPIDriver FSPID0;
+#endif
+
+/**
+ * @brief SPI FLEXCOM1 driver identifier.
+ */
+#if SAMA_SPI_USE_FLEXCOM1 || defined(__DOXYGEN__)
+SPIDriver FSPID1;
+#endif
+
+/**
+ * @brief SPI FLEXCOM2 driver identifier.
+ */
+#if SAMA_SPI_USE_FLEXCOM2 || defined(__DOXYGEN__)
+SPIDriver FSPID2;
+#endif
+
+/**
+ * @brief SPI FLEXCOM3 driver identifier.
+ */
+#if SAMA_SPI_USE_FLEXCOM3 || defined(__DOXYGEN__)
+SPIDriver FSPID3;
+#endif
+
+/**
+ * @brief SPI FLEXCOM4 driver identifier.
+ */
+#if SAMA_SPI_USE_FLEXCOM4 || defined(__DOXYGEN__)
+SPIDriver FSPID4;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint8_t dummytx = 0xFFU;
+static uint8_t dummyrx;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(SAMA_SPI_DMA_ERROR_HOOK)
+ if ((flags & (XDMAC_CIS_RBEIS | XDMAC_CIS_ROIS)) != 0) {
+ SAMA_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)flags;
+#endif
+
+ /* Stop everything.*/
+ dmaChannelDisable(spip->dmatx);
+ dmaChannelDisable(spip->dmarx);
+
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+}
+
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+
+#if defined(SAMA_SPI_DMA_ERROR_HOOK)
+ (void)spip;
+ if ((flags & (XDMAC_CIS_WBEIS | XDMAC_CIS_ROIS)) != 0) {
+ SAMA_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)spip;
+ (void)flags;
+#endif
+}
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SPI driver initialization.
+ *
+ * @notapi
+ */
+void spi_lld_init(void) {
+
+#if SAMA_SPI_USE_SPI0
+#if SAMA_HAL_IS_SECURE
+ mtxConfigPeriphSecurity(MATRIX1, ID_SPI0, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+ /* Driver initialization.*/
+ spiObjectInit(&SPID0);
+ SPID0.spi = SPI0;
+ SPID0.dmarx = NULL;
+ SPID0.dmatx = NULL;
+ SPID0.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_SPI0_RX);
+ SPID0.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_SPI0_TX);
+#endif /* SAMA_SPI_USE_SPI0 */
+
+#if SAMA_SPI_USE_SPI1
+#if SAMA_HAL_IS_SECURE
+ mtxConfigPeriphSecurity(MATRIX1, ID_SPI1, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+ /* Driver initialization.*/
+ spiObjectInit(&SPID1);
+ SPID1.spi = SPI1;
+ SPID1.dmarx = NULL;
+ SPID1.dmatx = NULL;
+ SPID1.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_SPI1_RX);
+ SPID1.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_SPI1_TX);
+#endif /* SAMA_SPI_USE_SPI1 */
+
+#if SAMA_SPI_USE_FLEXCOM0
+#if SAMA_HAL_IS_SECURE
+ mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM0, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+ /* Driver initialization.*/
+ spiObjectInit(&FSPID0);
+ FSPID0.spi = FCOMSPI0;
+ FSPID0.flexcom = FLEXCOM0;
+ FSPID0.dmarx = NULL;
+ FSPID0.dmatx = NULL;
+ FSPID0.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM0_RX);
+ FSPID0.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM0_TX);
+#endif /* SAMA_SPI_USE_FLEXCOM0 */
+
+#if SAMA_SPI_USE_FLEXCOM1
+#if SAMA_HAL_IS_SECURE
+ mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM1, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+ /* Driver initialization.*/
+ spiObjectInit(&FSPID1);
+ FSPID1.spi = FCOMSPI1;
+ FSPID1.flexcom = FLEXCOM1;
+ FSPID1.dmarx = NULL;
+ FSPID1.dmatx = NULL;
+ FSPID1.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM1_RX);
+ FSPID1.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM1_TX);
+#endif /* SAMA_SPI_USE_FLEXCOM1 */
+
+#if SAMA_SPI_USE_FLEXCOM2
+#if SAMA_HAL_IS_SECURE
+ mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM2, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+ /* Driver initialization.*/
+ spiObjectInit(&FSPID2);
+ FSPID2.spi = FCOMSPI2;
+ FSPID2.flexcom = FLEXCOM2;
+ FSPID2.dmarx = NULL;
+ FSPID2.dmatx = NULL;
+ FSPID2.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM2_RX);
+ FSPID2.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM2_TX);
+#endif /* SAMA_SPI_USE_FLEXCOM2 */
+
+#if SAMA_SPI_USE_FLEXCOM3
+#if SAMA_HAL_IS_SECURE
+ mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM3, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+ /* Driver initialization.*/
+ spiObjectInit(&FSPID3);
+ FSPID3.spi = FCOMSPI3;
+ FSPID3.flexcom = FLEXCOM3;
+ FSPID3.dmarx = NULL;
+ FSPID3.dmatx = NULL;
+ FSPID3.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM3_RX);
+ FSPID3.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM3_TX);
+#endif /* SAMA_SPI_USE_FLEXCOM3 */
+
+#if SAMA_SPI_USE_FLEXCOM4
+#if SAMA_HAL_IS_SECURE
+ mtxConfigPeriphSecurity(MATRIX1, ID_FLEXCOM4, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+ /* Driver initialization.*/
+ spiObjectInit(&FSPID4);
+ FSPID4.spi = FCOMSPI4;
+ FSPID4.flexcom = FLEXCOM4;
+ FSPID4.dmarx = NULL;
+ FSPID4.dmatx = NULL;
+ FSPID4.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM4_RX);
+ FSPID4.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_FLEXCOM4_TX);
+#endif /* SAMA_SPI_USE_FLEXCOM4 */
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_start(SPIDriver *spip) {
+
+ /* Configures the peripheral.*/
+
+ if (spip->state == SPI_STOP) {
+
+#if SAMA_SPI_USE_SPI0
+ if (&SPID0 == spip) {
+ spip->dmarx = dmaChannelAllocate(SAMA_SPI_SPI0_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
+
+ spip->dmatx = dmaChannelAllocate(SAMA_SPI_SPI0_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+ /* Enable SPI0 clock */
+ pmcEnableSPI0();
+ }
+#endif /* SAMA_SPI_USE_SPI0 */
+#if SAMA_SPI_USE_SPI1
+ if (&SPID1 == spip) {
+ spip->dmarx = dmaChannelAllocate(SAMA_SPI_SPI1_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
+
+ spip->dmatx = dmaChannelAllocate(SAMA_SPI_SPI1_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+ /* Enable SPI1 clock */
+ pmcEnableSPI1();
+ }
+#endif /* SAMA_SPI_USE_SPI1 */
+#if SAMA_SPI_USE_FLEXCOM0
+ if (&FSPID0 == spip) {
+ spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM0_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
+
+ spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM0_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+ /* Enabling SPI on FLEXCOM */
+ spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+ /* Enable FLEXCOM0 clock */
+ pmcEnableFLEXCOM0();
+ }
+#endif /* SAMA_SPI_USE_FLEXCOM0 */
+#if SAMA_SPI_USE_FLEXCOM1
+ if (&FSPID1 == spip) {
+ spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM1_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
+
+ spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM1_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+ /* Enabling SPI on FLEXCOM */
+ spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+ /* Enable FLEXCOM1 clock */
+ pmcEnableFLEXCOM1();
+ }
+#endif /* SAMA_SPI_USE_FLEXCOM1 */
+#if SAMA_SPI_USE_FLEXCOM2
+ if (&FSPID2 == spip) {
+ spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM2_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
+
+ spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM2_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+ /* Enabling SPI on FLEXCOM */
+ spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+ /* Enable FLEXCOM2 clock */
+ pmcEnableFLEXCOM2();
+ }
+#endif /* SAMA_SPI_USE_FLEXCOM2 */
+#if SAMA_SPI_USE_FLEXCOM3
+ if (&FSPID3 == spip) {
+ spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM3_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
+
+ spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM3_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+ /* Enabling SPI on FLEXCOM */
+ spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+ /* Enable FLEXCOM3 clock */
+ pmcEnableFLEXCOM3();
+ }
+#endif /* SAMA_SPI_USE_FLEXCOM3 */
+#if SAMA_SPI_USE_FLEXCOM4
+ if (&FSPID4 == spip) {
+ spip->dmarx = dmaChannelAllocate(SAMA_SPI_FLEXCOM4_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "no channel allocated");
+
+ spip->dmatx = dmaChannelAllocate(SAMA_SPI_FLEXCOM4_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+ /* Enabling SPI on FLEXCOM */
+ spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+ /* Enable FLEXCOM4 clock */
+ pmcEnableFLEXCOM4();
+ }
+#endif /* SAMA_SPI_USE_FLEXCOM4 */
+ }
+
+ /* Set mode */
+ dmaChannelSetMode(spip->dmarx, spip->rxdmamode);
+ dmaChannelSetMode(spip->dmatx, spip->txdmamode);
+
+ /* Disable write protection */
+ spiDisableWP(spip->spi);
+
+ /* Execute a software reset of the SPI twice */
+ spip->spi->SPI_CR = SPI_CR_SWRST;
+ spip->spi->SPI_CR = SPI_CR_SWRST;
+
+ /* SPI configuration */
+ spip->spi->SPI_MR = SPI_MR_MSTR | SPI_MR_WDRBT | spip->config->mr;
+ spip->spi->SPI_MR &= ~SPI_MR_PCS_Msk;
+ spip->spi->SPI_MR |= SPI_PCS(spip->config->npcs);
+ spip->spi->SPI_CSR[spip->config->npcs] = spip->config->csr;
+
+ /* if SPI_CSRx_BITS > 8, dma is set to 16 bits */
+ if (((spip->spi->SPI_CSR[spip->config->npcs] >> 4) & 0xF) > 0) {
+ dmaChannelSetMode(spip->dmatx, spip->txdmamode | XDMAC_CC_DWIDTH_HALFWORD);
+ dmaChannelSetMode(spip->dmarx, spip->rxdmamode | XDMAC_CC_DWIDTH_HALFWORD);
+ }
+
+ /* Enable SPI */
+ spip->spi->SPI_CR |= SPI_CR_SPIEN;
+ /* Enable write protection. */
+ spiEnableWP(spip->spi);
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ if (spip->state == SPI_READY) {
+ /* Disable write protection */
+ spiDisableWP(spip->spi);
+ /* Reset SPI */
+ spip->spi->SPI_MR = 0;
+ spip->spi->SPI_CSR[spip->config->npcs] = 0;
+ /* Disable SPI */
+ spip->spi->SPI_CR |= SPI_CR_SPIDIS;
+ /* Enable write protection */
+ spiEnableWP(spip->spi);
+
+ dmaChannelRelease(spip->dmarx);
+ dmaChannelRelease(spip->dmatx);
+
+#if SAMA_SPI_USE_SPI0
+ if (&SPID0 == spip)
+ /* Disable SPI0 clock */
+ pmcDisableSPI0();
+
+#endif /* SAMA_SPI_USE_SPI1 */
+#if SAMA_SPI_USE_SPI1
+ if (&SPID1 == spip)
+ /* Disable SPI1 clock */
+ pmcDisableSPI1();
+
+#endif /* SAMA_SPI_USE_FLEXCOM0 */
+
+#if SAMA_SPI_USE_FLEXCOM0
+ if (&FSPID0 == spip)
+ /* Disable FLEXCOM0 clock */
+ pmcDisableFLEXCOM0();
+
+#endif /* SAMA_SPI_USE_FLEXCOM0 */
+
+#if SAMA_SPI_USE_FLEXCOM1
+ if (&FSPID1 == spip)
+ /* Disable FLEXCOM1 clock */
+ pmcDisableFLEXCOM1();
+
+#endif /* SAMA_SPI_USE_FLEXCOM1 */
+
+#if SAMA_SPI_USE_FLEXCOM2
+ if (&FSPID2 == spip)
+ /* Disable FLEXCOM2 clock */
+ pmcDisableFLEXCOM2();
+
+#endif /* SAMA_SPI_USE_FLEXCOM2 */
+
+#if SAMA_SPI_USE_FLEXCOM3
+ if (&FSPID3 == spip)
+ /* Disable FLEXCOM3 clock */
+ pmcDisableFLEXCOM3();
+
+#endif /* SAMA_SPI_USE_FLEXCOM3 */
+
+#if SAMA_SPI_USE_FLEXCOM4
+ if (&FSPID4 == spip)
+ /* Disable FLEXCOM4 clock */
+ pmcDisableFLEXCOM4();
+
+#endif /* SAMA_SPI_USE_FLEXCOM4 */
+ }
+}
+
+#if (SPI_SELECT_MODE == (SPI_SELECT_MODE_LLD || SPI_SELECT_MODE_PAD || \
+ SPI_SELECT_MODE_PORT || SPI_SELECT_MODE_LINE)) || defined(__DOXYGEN__)
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_select(SPIDriver *spip) {
+ /* No implementation on SAMA.*/
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_unselect(SPIDriver *spip) {
+ /* No implementation on SAMA.*/
+}
+#endif
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out]rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ /* Writing channel */
+ dmaChannelSetSource(spip->dmatx, txbuf);
+ dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
+ dmaChannelSetTransactionSize(spip->dmatx, n);
+
+ /* Reading channel */
+ dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
+ dmaChannelSetDestination(spip->dmarx, rxbuf);
+ dmaChannelSetTransactionSize(spip->dmarx, n);
+
+ dmaChannelEnable(spip->dmarx);
+ dmaChannelEnable(spip->dmatx);
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ /* Writing channel */
+ dmaChannelSetSource(spip->dmatx, txbuf);
+ dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
+ dmaChannelSetTransactionSize(spip->dmatx, n);
+
+ /* Reading channel */
+ dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
+ dmaChannelSetDestination(spip->dmarx, &dummyrx);
+ dmaChannelSetTransactionSize(spip->dmarx, n);
+ /* Enable write protection. */
+
+ dmaChannelEnable(spip->dmarx);
+ dmaChannelEnable(spip->dmatx);
+
+ /* Waiting TXEMPTY flag */
+ while (!(spip->spi->SPI_SR & SPI_SR_TXEMPTY)) {
+ ;
+ }
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out]rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ /* Writing channel */
+ dmaChannelSetSource(spip->dmatx, &dummytx);
+ dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
+ dmaChannelSetTransactionSize(spip->dmatx, n);
+
+ /* Reading channel */
+ dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
+ dmaChannelSetDestination(spip->dmarx, rxbuf);
+ dmaChannelSetTransactionSize(spip->dmarx, n);
+
+ dmaChannelEnable(spip->dmarx);
+ dmaChannelEnable(spip->dmatx);
+}
+
+#endif /* HAL_USE_SPI */
+
+/** @} */
+