From 7e567dedc7a496257a00660a14cf3dfbc571a59c Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 8 Oct 2011 10:33:31 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3429 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/DMAv1/stm32_dma.c | 497 ------------------------------- os/hal/platforms/STM32/DMAv1/stm32_dma.h | 330 -------------------- os/hal/platforms/STM32F1xx/platform.mk | 4 +- os/hal/platforms/STM32F1xx/stm32_dma.c | 497 +++++++++++++++++++++++++++++++ os/hal/platforms/STM32F1xx/stm32_dma.h | 330 ++++++++++++++++++++ 5 files changed, 829 insertions(+), 829 deletions(-) delete mode 100644 os/hal/platforms/STM32/DMAv1/stm32_dma.c delete mode 100644 os/hal/platforms/STM32/DMAv1/stm32_dma.h create mode 100644 os/hal/platforms/STM32F1xx/stm32_dma.c create mode 100644 os/hal/platforms/STM32F1xx/stm32_dma.h (limited to 'os') diff --git a/os/hal/platforms/STM32/DMAv1/stm32_dma.c b/os/hal/platforms/STM32/DMAv1/stm32_dma.c deleted file mode 100644 index 84e372c26..000000000 --- a/os/hal/platforms/STM32/DMAv1/stm32_dma.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file DMAv1/stm32_dma.c - * @brief DMA helper driver code. - * - * @addtogroup STM32_DMA - * @details DMA sharing helper driver. In the STM32 the DMA streams are a - * shared resource, this driver allows to allocate and free DMA - * streams at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The DMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * IRSs when allocating streams. - * @{ - */ - -#include "ch.h" -#include "hal.h" - -/* The following macro is only defined if some driver requiring DMA services - has been enabled.*/ -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief Mask of the DMA1 streams in @p dma_streams_mask. - */ -#define STM32_DMA1_STREAMS_MASK 0x0000007F - -/** - * @brief Mask of the DMA2 streams in @p dma_streams_mask. - */ -#define STM32_DMA2_STREAMS_MASK 0x00000F80 - -/** - * @brief Post-reset value of the stream CCR register. - */ -#define STM32_DMA_CCR_RESET_VALUE 0x00000000 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief DMA streams descriptors. - * @details This table keeps the association between an unique stream - * identifier and the involved physical registers. - * @note Don't use this array directly, use the appropriate wrapper macros - * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. - */ -const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { - {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn}, - {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_IRQn}, - {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel3_IRQn}, - {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_IRQn}, - {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel5_IRQn}, - {DMA1_Channel6, &DMA1->IFCR, 20, 5, DMA1_Channel6_IRQn}, - {DMA1_Channel7, &DMA1->IFCR, 24, 6, DMA1_Channel7_IRQn}, -#if STM32_HAS_DMA2 || defined(__DOXYGEN__) - {DMA2_Channel1, &DMA2->IFCR, 0, 7, DMA2_Channel1_IRQn}, - {DMA2_Channel2, &DMA2->IFCR, 4, 8, DMA2_Channel2_IRQn}, - {DMA2_Channel3, &DMA2->IFCR, 8, 9, DMA2_Channel3_IRQn}, -#if defined(STM32F10X_CL) || defined(__DOXYGEN__) - {DMA2_Channel4, &DMA2->IFCR, 12, 10, DMA2_Channel4_IRQn}, - {DMA2_Channel5, &DMA2->IFCR, 16, 11, DMA2_Channel5_IRQn}, -#else /* !STM32F10X_CL */ - {DMA2_Channel4, &DMA2->IFCR, 12, 10, DMA2_Channel4_5_IRQn}, - {DMA2_Channel5, &DMA2->IFCR, 16, 11, DMA2_Channel4_5_IRQn}, -#endif /* !STM32F10X_CL */ -#endif /* STM32_HAS_DMA2 */ -}; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief DMA ISR redirector type. - */ -typedef struct { - stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ - void *dma_param; /**< @brief DMA callback parameter. */ -} dma_isr_redir_t; - -/** - * @brief Mask of the allocated streams. - */ -static uint32_t dma_streams_mask; - -/** - * @brief DMA IRQ redirectors. - */ -static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief DMA1 stream 1 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[0].dma_func) - dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 2 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 4; - if (dma_isr_redir[1].dma_func) - dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 3 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 8; - if (dma_isr_redir[2].dma_func) - dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 4 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 12; - if (dma_isr_redir[3].dma_func) - dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 5 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[4].dma_func) - dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 6 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 20) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 20; - if (dma_isr_redir[5].dma_func) - dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 7 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA1_Ch7_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 24) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 24; - if (dma_isr_redir[6].dma_func) - dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -#if STM32_HAS_DMA2 || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 1 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA2_Ch1_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 0) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[7].dma_func) - dma_isr_redir[7].dma_func(dma_isr_redir[7].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 2 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA2_Ch2_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 4) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 4; - if (dma_isr_redir[8].dma_func) - dma_isr_redir[8].dma_func(dma_isr_redir[8].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 3 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA2_Ch3_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 8) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 8; - if (dma_isr_redir[9].dma_func) - dma_isr_redir[9].dma_func(dma_isr_redir[9].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -#if defined(STM32F10X_CL) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 4 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA2_Ch4_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 12) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 12; - if (dma_isr_redir[10].dma_func) - dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 5 shared interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(DMA2_Ch5_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 16) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[11].dma_func) - dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); - - CH_IRQ_EPILOGUE(); -} -#else /* !STM32F10X_CL */ -/** - * @brief DMA2 streams 4 and 5 shared interrupt handler. - * @note This IRQ is shared between DMA2 channels 4 and 5 so it is a - * bit less efficient because an extra check. - * - * @isr - */ -CH_IRQ_HANDLER(DMA2_Ch4_5_IRQHandler) { - uint32_t flags; - - CH_IRQ_PROLOGUE(); - - /* Check on channel 4.*/ - flags = (DMA2->ISR >> 12) & STM32_DMA_ISR_MASK; - if (flags & STM32_DMA_ISR_MASK) { - DMA2->IFCR = STM32_DMA_ISR_MASK << 12; - if (dma_isr_redir[10].dma_func) - dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); - } - - /* Check on channel 5.*/ - flags = (DMA2->ISR >> 16) & STM32_DMA_ISR_MASK; - if (flags & STM32_DMA_ISR_MASK) { - DMA2->IFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[11].dma_func) - dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); - } - - CH_IRQ_EPILOGUE(); -} -#endif /* !STM32F10X_CL */ -#endif /* STM32_HAS_DMA2 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA helper initialization. - * - * @init - */ -void dmaInit(void) { - int i; - - dma_streams_mask = 0; - for (i = 0; i < STM32_DMA_STREAMS; i++) { - _stm32_dma_streams[i].channel->CCR = 0; - dma_isr_redir[i].dma_func = NULL; - } - DMA1->IFCR = 0xFFFFFFFF; -#if STM32_HAS_DMA2 - DMA2->IFCR = 0xFFFFFFFF; -#endif -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * @pre The stream must not be already in use or an error is returned. - * @post The stream is allocated and the default ISR handler redirected - * to the specified function. - * @post The stream ISR vector is enabled and its priority configured. - * @post The stream must be freed using @p dmaStreamRelease() before it can - * be reused with another peripheral. - * @post The stream is in its post-reset state. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] priority IRQ priority mask for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return The operation status. - * @retval FALSE no error, stream taken. - * @retval TRUE error, stream already taken. - * - * @special - */ -bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - - chDbgCheck(dmastp != NULL, "dmaAllocate"); - - /* Checks if the stream is already taken.*/ - if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) - return TRUE; - - /* Marks the stream as allocated.*/ - dma_isr_redir[dmastp->selfindex].dma_func = func; - dma_isr_redir[dmastp->selfindex].dma_param = param; - dma_streams_mask |= (1 << dmastp->selfindex); - - /* Enabling DMA clocks required by the current streams set.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) - rccEnableDMA1(FALSE); -#if STM32_HAS_DMA2 - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) - rccEnableDMA2(FALSE); -#endif - - /* Putting the stream in a safe state.*/ - dmaStreamDisable(dmastp); - dmaStreamClearInterrupt(dmastp); - dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; - - /* Enables the associated IRQ vector if a callback is defined.*/ - if (func != NULL) - NVICEnableVector(dmastp->vector, CORTEX_PRIORITY_MASK(priority)); - - return FALSE; -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post The stream is again available. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { - - chDbgCheck(dmastp != NULL, "dmaRelease"); - - /* Check if the streams is not taken.*/ - chDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, - "dmaRelease(), #1", "not allocated"); - - /* Disables the associated IRQ vector.*/ - NVICDisableVector(dmastp->vector); - - /* Marks the stream as not allocated.*/ - dma_streams_mask &= ~(1 << dmastp->selfindex); - - /* Shutting down clocks that are no more required, if any.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) - rccDisableDMA1(FALSE); -#if STM32_HAS_DMA2 - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) - rccDisableDMA2(FALSE); -#endif -} - -#endif /* STM32_DMA_REQUIRED */ - -/** @} */ diff --git a/os/hal/platforms/STM32/DMAv1/stm32_dma.h b/os/hal/platforms/STM32/DMAv1/stm32_dma.h deleted file mode 100644 index f209898d4..000000000 --- a/os/hal/platforms/STM32/DMAv1/stm32_dma.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file DMAv1/stm32_dma.h - * @brief DMA helper driver header. - * @note This file requires definitions from the ST header files - * stm32f10x.h or stm32l1xx.h. - * @note This driver uses the new naming convention used for the STM32F2xx - * so the "DMA channels" are referred as "DMA streams". - * - * @addtogroup STM32_DMA - * @{ - */ - -#ifndef _STM32_DMA_H_ -#define _STM32_DMA_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Total number of DMA streams. - * @note This is the total number of streams among all the DMA units. - */ -#if STM32_HAS_DMA2 || defined(__DOXYGEN__) -#define STM32_DMA_STREAMS 12 -#else -#define STM32_DMA_STREAMS 7 -#endif - -/** - * @brief Mask of the ISR bits passed to the DMA callback functions. - */ -#define STM32_DMA_ISR_MASK 0x0F - -/** - * @name DMA streams identifiers - * @{ - */ -#define STM32_DMA1_STREAM1 (&_stm32_dma_streams[0]) -#define STM32_DMA1_STREAM2 (&_stm32_dma_streams[1]) -#define STM32_DMA1_STREAM3 (&_stm32_dma_streams[2]) -#define STM32_DMA1_STREAM4 (&_stm32_dma_streams[3]) -#define STM32_DMA1_STREAM5 (&_stm32_dma_streams[4]) -#define STM32_DMA1_STREAM6 (&_stm32_dma_streams[5]) -#define STM32_DMA1_STREAM7 (&_stm32_dma_streams[6]) -#define STM32_DMA2_STREAM1 (&_stm32_dma_streams[7]) -#define STM32_DMA2_STREAM2 (&_stm32_dma_streams[8]) -#define STM32_DMA2_STREAM3 (&_stm32_dma_streams[9]) -#define STM32_DMA2_STREAM4 (&_stm32_dma_streams[10]) -#define STM32_DMA2_STREAM5 (&_stm32_dma_streams[11]) -/** @} */ - -/** - * @name CR register constants common to all DMA types - */ -#define STM32_DMA_CR_EN DMA_CCR1_EN -#define STM32_DMA_CR_TEIE DMA_CCR1_TEIE -#define STM32_DMA_CR_HTIE DMA_CCR1_HTIE -#define STM32_DMA_CR_TCIE DMA_CCR1_TCIE -#define STM32_DMA_CR_DIR_MASK (DMA_CCR1_DIR | DMA_CCR1_MEM2MEM) -#define STM32_DMA_CR_DIR_P2M 0 -#define STM32_DMA_CR_DIR_M2P DMA_CCR1_DIR -#define STM32_DMA_CR_DIR_M2M DMA_CCR1_MEM2MEM -#define STM32_DMA_CR_CIRC DMA_CCR1_CIRC -#define STM32_DMA_CR_PINC DMA_CCR1_PINC -#define STM32_DMA_CR_MINC DMA_CCR1_MINC -#define STM32_DMA_CR_PSIZE_MASK DMA_CCR1_PSIZE -#define STM32_DMA_CR_PSIZE_BYTE 0 -#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR1_PSIZE_0 -#define STM32_DMA_CR_PSIZE_WORD DMA_CCR1_PSIZE_1 -#define STM32_DMA_CR_MSIZE_MASK DMA_CCR1_MSIZE -#define STM32_DMA_CR_MSIZE_BYTE 0 -#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR1_MSIZE_0 -#define STM32_DMA_CR_MSIZE_WORD DMA_CCR1_MSIZE_1 -#define STM32_DMA_CR_PL_MASK DMA_CCR1_PL -#define STM32_DMA_CR_PL(n) ((n) << 12) -/** @} */ - -/** - * @name CR register constants only found in enhanced DMA - */ -#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */ -#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */ -/** @} */ - -/** - * @name Status flags passed to the ISR callbacks - */ -#define STM32_DMA_ISR_FEIF 0 -#define STM32_DMA_ISR_DMEIF 0 -#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 -#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 -#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA stream descriptor structure. - */ -typedef struct { - DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ - volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ - uint8_t ishift; /**< @brief Bits offset in xIFCR - register. */ - uint8_t selfindex; /**< @brief Index to self in array. */ - uint8_t vector; /**< @brief Associated IRQ vector. */ -} stm32_dma_stream_t; - -/** - * @brief STM32 DMA ISR function type. - * - * @param[in] p parameter for the registered function - * @param[in] flags pre-shifted content of the ISR register, the bits - * are aligned to bit zero - */ -typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Associates a peripheral data register to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CPAR register - * - * @special - */ -#define dmaStreamSetPeripheral(dmastp, addr) { \ - (dmastp)->channel->CPAR = (uint32_t)(addr); \ -} - -/** - * @brief Associates a memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CMAR register - * - * @special - */ -#define dmaStreamSetMemory0(dmastp, addr) { \ - (dmastp)->channel->CMAR = (uint32_t)(addr); \ -} - -/** - * @brief Sets the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] size value to be written in the CNDTR register - * - * @special - */ -#define dmaStreamSetTransactionSize(dmastp, size) { \ - (dmastp)->channel->CNDTR = (uint32_t)(size); \ -} - -/** - * @brief Returns the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @return The number of transfers to be performed. - * - * @special - */ -#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) - -/** - * @brief Programs the stream mode settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register - * - * @special - */ -#define dmaStreamSetMode(dmastp, mode) { \ - (dmastp)->channel->CCR = (uint32_t)(mode); \ -} - -/** - * @brief DMA stream enable. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamEnable(dmastp) { \ - (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ -} - -/** - * @brief DMA stream disable. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamDisable(dmastp) { \ - (dmastp)->channel->CCR &= ~STM32_DMA_CR_EN; \ -} - -/** - * @brief DMA stream interrupt sources clear. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamClearInterrupt(dmastp) { \ - *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ -} - -/** - * @brief Starts a memory to memory operation using the specified stream. - * @note The default transfer data mode is "byte to byte" but it can be - * changed by specifying extra options in the @p mode parameter. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register, this value - * is implicitly ORed with: - * - @p STM32_DMA_CR_MINC - * - @p STM32_DMA_CR_PINC - * - @p STM32_DMA_CR_DIR_M2M - * - @p STM32_DMA_CR_EN - * . - * @param[in] src source address - * @param[in] dst destination address - * @param[in] n number of data units to copy - */ -#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ - dmaStreamSetPeripheral(dmastp, src); \ - dmaStreamSetMemory0(dmastp, dst); \ - dmaStreamGetTransactionSize(dmastp, n); \ - dmaStreamSetMode(dmastp, (mode) | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ - STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ -} - -/** - * @brief Polled wait for DMA transfer end. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - */ -#define dmaWaitCompletion(dmastp) \ - while (((dmastp)->channel->CNDTR > 0) && \ - ((dmastp)->channel->CCR & STM32_DMA_CR_EN)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void dmaInit(void); - bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - void dmaStreamRelease(const stm32_dma_stream_t *dmastp); -#ifdef __cplusplus -} -#endif - -#endif /* _STM32_DMA_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F1xx/platform.mk b/os/hal/platforms/STM32F1xx/platform.mk index a73f1b4f3..5e42d1335 100644 --- a/os/hal/platforms/STM32F1xx/platform.mk +++ b/os/hal/platforms/STM32F1xx/platform.mk @@ -1,5 +1,6 @@ # List of all the STM32F1xx platform files. -PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F1xx/hal_lld.c \ +PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F1xx/stm32_dma.c \ + ${CHIBIOS}/os/hal/platforms/STM32F1xx/hal_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32F1xx/adc_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/can_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ @@ -13,7 +14,6 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F1xx/hal_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/GPIOv1/pal_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/DMAv1/stm32_dma.c \ ${CHIBIOS}/os/hal/platforms/STM32/USBv1/usb_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/RTCv1/rtc_lld.c diff --git a/os/hal/platforms/STM32F1xx/stm32_dma.c b/os/hal/platforms/STM32F1xx/stm32_dma.c new file mode 100644 index 000000000..84e372c26 --- /dev/null +++ b/os/hal/platforms/STM32F1xx/stm32_dma.c @@ -0,0 +1,497 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file DMAv1/stm32_dma.c + * @brief DMA helper driver code. + * + * @addtogroup STM32_DMA + * @details DMA sharing helper driver. In the STM32 the DMA streams are a + * shared resource, this driver allows to allocate and free DMA + * streams at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The DMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * IRSs when allocating streams. + * @{ + */ + +#include "ch.h" +#include "hal.h" + +/* The following macro is only defined if some driver requiring DMA services + has been enabled.*/ +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Mask of the DMA1 streams in @p dma_streams_mask. + */ +#define STM32_DMA1_STREAMS_MASK 0x0000007F + +/** + * @brief Mask of the DMA2 streams in @p dma_streams_mask. + */ +#define STM32_DMA2_STREAMS_MASK 0x00000F80 + +/** + * @brief Post-reset value of the stream CCR register. + */ +#define STM32_DMA_CCR_RESET_VALUE 0x00000000 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief DMA streams descriptors. + * @details This table keeps the association between an unique stream + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. + */ +const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { + {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn}, + {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_IRQn}, + {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel3_IRQn}, + {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_IRQn}, + {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel5_IRQn}, + {DMA1_Channel6, &DMA1->IFCR, 20, 5, DMA1_Channel6_IRQn}, + {DMA1_Channel7, &DMA1->IFCR, 24, 6, DMA1_Channel7_IRQn}, +#if STM32_HAS_DMA2 || defined(__DOXYGEN__) + {DMA2_Channel1, &DMA2->IFCR, 0, 7, DMA2_Channel1_IRQn}, + {DMA2_Channel2, &DMA2->IFCR, 4, 8, DMA2_Channel2_IRQn}, + {DMA2_Channel3, &DMA2->IFCR, 8, 9, DMA2_Channel3_IRQn}, +#if defined(STM32F10X_CL) || defined(__DOXYGEN__) + {DMA2_Channel4, &DMA2->IFCR, 12, 10, DMA2_Channel4_IRQn}, + {DMA2_Channel5, &DMA2->IFCR, 16, 11, DMA2_Channel5_IRQn}, +#else /* !STM32F10X_CL */ + {DMA2_Channel4, &DMA2->IFCR, 12, 10, DMA2_Channel4_5_IRQn}, + {DMA2_Channel5, &DMA2->IFCR, 16, 11, DMA2_Channel4_5_IRQn}, +#endif /* !STM32F10X_CL */ +#endif /* STM32_HAS_DMA2 */ +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief DMA ISR redirector type. + */ +typedef struct { + stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ + void *dma_param; /**< @brief DMA callback parameter. */ +} dma_isr_redir_t; + +/** + * @brief Mask of the allocated streams. + */ +static uint32_t dma_streams_mask; + +/** + * @brief DMA IRQ redirectors. + */ +static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief DMA1 stream 1 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[0].dma_func) + dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 2 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 4; + if (dma_isr_redir[1].dma_func) + dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 3 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 8; + if (dma_isr_redir[2].dma_func) + dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 4 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 12; + if (dma_isr_redir[3].dma_func) + dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 5 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[4].dma_func) + dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 6 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 20) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 20; + if (dma_isr_redir[5].dma_func) + dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 7 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA1_Ch7_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 24) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 24; + if (dma_isr_redir[6].dma_func) + dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +#if STM32_HAS_DMA2 || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 1 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA2_Ch1_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 0) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[7].dma_func) + dma_isr_redir[7].dma_func(dma_isr_redir[7].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 2 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA2_Ch2_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 4) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 4; + if (dma_isr_redir[8].dma_func) + dma_isr_redir[8].dma_func(dma_isr_redir[8].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 3 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA2_Ch3_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 8) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 8; + if (dma_isr_redir[9].dma_func) + dma_isr_redir[9].dma_func(dma_isr_redir[9].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +#if defined(STM32F10X_CL) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 4 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA2_Ch4_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 12) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 12; + if (dma_isr_redir[10].dma_func) + dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 5 shared interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(DMA2_Ch5_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 16) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[11].dma_func) + dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); + + CH_IRQ_EPILOGUE(); +} +#else /* !STM32F10X_CL */ +/** + * @brief DMA2 streams 4 and 5 shared interrupt handler. + * @note This IRQ is shared between DMA2 channels 4 and 5 so it is a + * bit less efficient because an extra check. + * + * @isr + */ +CH_IRQ_HANDLER(DMA2_Ch4_5_IRQHandler) { + uint32_t flags; + + CH_IRQ_PROLOGUE(); + + /* Check on channel 4.*/ + flags = (DMA2->ISR >> 12) & STM32_DMA_ISR_MASK; + if (flags & STM32_DMA_ISR_MASK) { + DMA2->IFCR = STM32_DMA_ISR_MASK << 12; + if (dma_isr_redir[10].dma_func) + dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); + } + + /* Check on channel 5.*/ + flags = (DMA2->ISR >> 16) & STM32_DMA_ISR_MASK; + if (flags & STM32_DMA_ISR_MASK) { + DMA2->IFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[11].dma_func) + dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); + } + + CH_IRQ_EPILOGUE(); +} +#endif /* !STM32F10X_CL */ +#endif /* STM32_HAS_DMA2 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA helper initialization. + * + * @init + */ +void dmaInit(void) { + int i; + + dma_streams_mask = 0; + for (i = 0; i < STM32_DMA_STREAMS; i++) { + _stm32_dma_streams[i].channel->CCR = 0; + dma_isr_redir[i].dma_func = NULL; + } + DMA1->IFCR = 0xFFFFFFFF; +#if STM32_HAS_DMA2 + DMA2->IFCR = 0xFFFFFFFF; +#endif +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * @pre The stream must not be already in use or an error is returned. + * @post The stream is allocated and the default ISR handler redirected + * to the specified function. + * @post The stream ISR vector is enabled and its priority configured. + * @post The stream must be freed using @p dmaStreamRelease() before it can + * be reused with another peripheral. + * @post The stream is in its post-reset state. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] priority IRQ priority mask for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return The operation status. + * @retval FALSE no error, stream taken. + * @retval TRUE error, stream already taken. + * + * @special + */ +bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + + chDbgCheck(dmastp != NULL, "dmaAllocate"); + + /* Checks if the stream is already taken.*/ + if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) + return TRUE; + + /* Marks the stream as allocated.*/ + dma_isr_redir[dmastp->selfindex].dma_func = func; + dma_isr_redir[dmastp->selfindex].dma_param = param; + dma_streams_mask |= (1 << dmastp->selfindex); + + /* Enabling DMA clocks required by the current streams set.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) + rccEnableDMA1(FALSE); +#if STM32_HAS_DMA2 + if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) + rccEnableDMA2(FALSE); +#endif + + /* Putting the stream in a safe state.*/ + dmaStreamDisable(dmastp); + dmaStreamClearInterrupt(dmastp); + dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; + + /* Enables the associated IRQ vector if a callback is defined.*/ + if (func != NULL) + NVICEnableVector(dmastp->vector, CORTEX_PRIORITY_MASK(priority)); + + return FALSE; +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post The stream is again available. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { + + chDbgCheck(dmastp != NULL, "dmaRelease"); + + /* Check if the streams is not taken.*/ + chDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, + "dmaRelease(), #1", "not allocated"); + + /* Disables the associated IRQ vector.*/ + NVICDisableVector(dmastp->vector); + + /* Marks the stream as not allocated.*/ + dma_streams_mask &= ~(1 << dmastp->selfindex); + + /* Shutting down clocks that are no more required, if any.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) + rccDisableDMA1(FALSE); +#if STM32_HAS_DMA2 + if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) + rccDisableDMA2(FALSE); +#endif +} + +#endif /* STM32_DMA_REQUIRED */ + +/** @} */ diff --git a/os/hal/platforms/STM32F1xx/stm32_dma.h b/os/hal/platforms/STM32F1xx/stm32_dma.h new file mode 100644 index 000000000..f209898d4 --- /dev/null +++ b/os/hal/platforms/STM32F1xx/stm32_dma.h @@ -0,0 +1,330 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file DMAv1/stm32_dma.h + * @brief DMA helper driver header. + * @note This file requires definitions from the ST header files + * stm32f10x.h or stm32l1xx.h. + * @note This driver uses the new naming convention used for the STM32F2xx + * so the "DMA channels" are referred as "DMA streams". + * + * @addtogroup STM32_DMA + * @{ + */ + +#ifndef _STM32_DMA_H_ +#define _STM32_DMA_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Total number of DMA streams. + * @note This is the total number of streams among all the DMA units. + */ +#if STM32_HAS_DMA2 || defined(__DOXYGEN__) +#define STM32_DMA_STREAMS 12 +#else +#define STM32_DMA_STREAMS 7 +#endif + +/** + * @brief Mask of the ISR bits passed to the DMA callback functions. + */ +#define STM32_DMA_ISR_MASK 0x0F + +/** + * @name DMA streams identifiers + * @{ + */ +#define STM32_DMA1_STREAM1 (&_stm32_dma_streams[0]) +#define STM32_DMA1_STREAM2 (&_stm32_dma_streams[1]) +#define STM32_DMA1_STREAM3 (&_stm32_dma_streams[2]) +#define STM32_DMA1_STREAM4 (&_stm32_dma_streams[3]) +#define STM32_DMA1_STREAM5 (&_stm32_dma_streams[4]) +#define STM32_DMA1_STREAM6 (&_stm32_dma_streams[5]) +#define STM32_DMA1_STREAM7 (&_stm32_dma_streams[6]) +#define STM32_DMA2_STREAM1 (&_stm32_dma_streams[7]) +#define STM32_DMA2_STREAM2 (&_stm32_dma_streams[8]) +#define STM32_DMA2_STREAM3 (&_stm32_dma_streams[9]) +#define STM32_DMA2_STREAM4 (&_stm32_dma_streams[10]) +#define STM32_DMA2_STREAM5 (&_stm32_dma_streams[11]) +/** @} */ + +/** + * @name CR register constants common to all DMA types + */ +#define STM32_DMA_CR_EN DMA_CCR1_EN +#define STM32_DMA_CR_TEIE DMA_CCR1_TEIE +#define STM32_DMA_CR_HTIE DMA_CCR1_HTIE +#define STM32_DMA_CR_TCIE DMA_CCR1_TCIE +#define STM32_DMA_CR_DIR_MASK (DMA_CCR1_DIR | DMA_CCR1_MEM2MEM) +#define STM32_DMA_CR_DIR_P2M 0 +#define STM32_DMA_CR_DIR_M2P DMA_CCR1_DIR +#define STM32_DMA_CR_DIR_M2M DMA_CCR1_MEM2MEM +#define STM32_DMA_CR_CIRC DMA_CCR1_CIRC +#define STM32_DMA_CR_PINC DMA_CCR1_PINC +#define STM32_DMA_CR_MINC DMA_CCR1_MINC +#define STM32_DMA_CR_PSIZE_MASK DMA_CCR1_PSIZE +#define STM32_DMA_CR_PSIZE_BYTE 0 +#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR1_PSIZE_0 +#define STM32_DMA_CR_PSIZE_WORD DMA_CCR1_PSIZE_1 +#define STM32_DMA_CR_MSIZE_MASK DMA_CCR1_MSIZE +#define STM32_DMA_CR_MSIZE_BYTE 0 +#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR1_MSIZE_0 +#define STM32_DMA_CR_MSIZE_WORD DMA_CCR1_MSIZE_1 +#define STM32_DMA_CR_PL_MASK DMA_CCR1_PL +#define STM32_DMA_CR_PL(n) ((n) << 12) +/** @} */ + +/** + * @name CR register constants only found in enhanced DMA + */ +#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */ +#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */ +/** @} */ + +/** + * @name Status flags passed to the ISR callbacks + */ +#define STM32_DMA_ISR_FEIF 0 +#define STM32_DMA_ISR_DMEIF 0 +#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 +#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 +#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA stream descriptor structure. + */ +typedef struct { + DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ + volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ + uint8_t ishift; /**< @brief Bits offset in xIFCR + register. */ + uint8_t selfindex; /**< @brief Index to self in array. */ + uint8_t vector; /**< @brief Associated IRQ vector. */ +} stm32_dma_stream_t; + +/** + * @brief STM32 DMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags pre-shifted content of the ISR register, the bits + * are aligned to bit zero + */ +typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Associates a peripheral data register to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CPAR register + * + * @special + */ +#define dmaStreamSetPeripheral(dmastp, addr) { \ + (dmastp)->channel->CPAR = (uint32_t)(addr); \ +} + +/** + * @brief Associates a memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CMAR register + * + * @special + */ +#define dmaStreamSetMemory0(dmastp, addr) { \ + (dmastp)->channel->CMAR = (uint32_t)(addr); \ +} + +/** + * @brief Sets the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] size value to be written in the CNDTR register + * + * @special + */ +#define dmaStreamSetTransactionSize(dmastp, size) { \ + (dmastp)->channel->CNDTR = (uint32_t)(size); \ +} + +/** + * @brief Returns the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @return The number of transfers to be performed. + * + * @special + */ +#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) + +/** + * @brief Programs the stream mode settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register + * + * @special + */ +#define dmaStreamSetMode(dmastp, mode) { \ + (dmastp)->channel->CCR = (uint32_t)(mode); \ +} + +/** + * @brief DMA stream enable. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamEnable(dmastp) { \ + (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ +} + +/** + * @brief DMA stream disable. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamDisable(dmastp) { \ + (dmastp)->channel->CCR &= ~STM32_DMA_CR_EN; \ +} + +/** + * @brief DMA stream interrupt sources clear. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamClearInterrupt(dmastp) { \ + *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ +} + +/** + * @brief Starts a memory to memory operation using the specified stream. + * @note The default transfer data mode is "byte to byte" but it can be + * changed by specifying extra options in the @p mode parameter. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register, this value + * is implicitly ORed with: + * - @p STM32_DMA_CR_MINC + * - @p STM32_DMA_CR_PINC + * - @p STM32_DMA_CR_DIR_M2M + * - @p STM32_DMA_CR_EN + * . + * @param[in] src source address + * @param[in] dst destination address + * @param[in] n number of data units to copy + */ +#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ + dmaStreamSetPeripheral(dmastp, src); \ + dmaStreamSetMemory0(dmastp, dst); \ + dmaStreamGetTransactionSize(dmastp, n); \ + dmaStreamSetMode(dmastp, (mode) | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ + STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ +} + +/** + * @brief Polled wait for DMA transfer end. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + */ +#define dmaWaitCompletion(dmastp) \ + while (((dmastp)->channel->CNDTR > 0) && \ + ((dmastp)->channel->CCR & STM32_DMA_CR_EN)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void dmaInit(void); + bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + void dmaStreamRelease(const stm32_dma_stream_t *dmastp); +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_DMA_H_ */ + +/** @} */ -- cgit v1.2.3