| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- /*
- * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
- * Copyright (C) 2010 by Nikolaj Zamotaev. All rights reserved.
- * Copyright (C) 2012 by Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
- * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- *
- */
- /*
- * \verbatim
- * $Id$
- * \endverbatim
- */
- /* Both F2 and F4 have 8 DMA streams with 8 requests per stream
- Only DMA2 can do Memory to memory transfers
- DMA/Controller(D), Stream(S) and Request(R) are encoded in one byte
- Byte 7 6 5 4 3 2 1 0
- D S2 S1 S0 0 R2 R1 R0
- */
- #include <cfg/arch.h>
- #include <arch/cm3.h>
- #include <dev/irqreg.h>
- #include <dev/gpio.h>
- #include <arch/cm3/stm/stm32xxxx.h>
- #include <arch/cm3/stm/stm32_dma.h>
- #define CH2NR(ch) ((ch & 0x70)>>4)
- #define CH2STREAM(base, ch) (base + 0x10 + ( CH2NR(ch) * 0x18))
- /*
- * \brief DMA Transfer Setup Function.
- *
- * This function sets up a DMA transfer. This function automatically
- * detects the transfer direction and if sources or targets are memory
- * or peripherals and sets up the right flags.
- *
- * \param channel One of the available channes of the STM32. If used
- * with peripherals, check to use the correct channel for the
- * desired peripheral unit.
- * \param dst Destination where to send the data to. Can be memory or peripheral.
- * \param src Source to take the data from. Can be memory or peripheral.
- * \param flags Option flags for priority and autoincrement of memory or peripheral.
- *
- */
- void DMA_Setup( uint8_t ch, void* dst, void* src, uint16_t length, uint32_t flags)
- {
- uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
- uint32_t stream_base = CH2STREAM(dma_base, ch);
- uint32_t cc = flags & ~(DMA_SxCR_CHSEL||DMA_SxCR_DIR|DMA_SxCR_EN);
- uint32_t cp;
- uint32_t cm;
- /* Clear all stream related flags */
- DMA_ClearFlag( ch, DMA_TEIF| DMA_HTIF| DMA_TCIF);
- cc |= (ch & 0x7)<<_BI32(DMA_SxCR_CHSEL_0);
- /* if DMA stream running, Stop DMA stream */
- if (CM3BBGET(stream_base, DMA_Stream_TypeDef,
- CR, _BI32(DMA_SxCR_EN)))
- {
- /* Disable stream */
- CM3BBCLR(stream_base, DMA_Stream_TypeDef, CR, _BI32(DMA_SxCR_EN));
- while(CM3BBGET(stream_base, DMA_Stream_TypeDef,
- CR, _BI32(DMA_SxCR_EN)));
- }
- /* Detect transfer type and set Registers accordingly */
- if ((uint32_t)src & PERIPH_BASE) {
- /* Peripheral to Memory */
- cp=(uint32_t)src;
- cm=(uint32_t)dst;
- }
- else if ((uint32_t)dst & PERIPH_BASE) {
- /* Memory to Peripheral */
- cc |= DMA_SxCR_DIR_0;
- cp=(uint32_t)dst;
- cm=(uint32_t)src;
- }
- else {
- /* Memory to Memory Transfer */
- cc |= DMA_SxCR_DIR_1;
- cp =(uint32_t)dst;
- cm =(uint32_t)dst;
- }
- CM3REG(stream_base, DMA_Stream_TypeDef, CR)=cc;
- CM3REG(stream_base, DMA_Stream_TypeDef, NDTR)=length;
- CM3REG(stream_base, DMA_Stream_TypeDef, PAR)=cp;
- CM3REG(stream_base, DMA_Stream_TypeDef, M0AR)=cm;
- };
- /*
- * \brief Enable DMA Transfer.
- */
- void DMA_Enable(uint8_t ch)
- {
- uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
- uint32_t stream_base = CH2STREAM(dma_base, ch);
- CM3BBSET(stream_base, DMA_Stream_TypeDef, CR, _BI32(DMA_SxCR_EN));
- }
- /*
- * \brief Disable DMA Transfer.
- */
- void DMA_Disable(uint8_t ch)
- {
- uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
- uint32_t stream_base = CH2STREAM(dma_base, ch);
- CM3BBCLR(stream_base, DMA_Stream_TypeDef, CR, _BI32(DMA_SxCR_EN));
- }
- /*!
- * \brief DMA System Initialization
- *
- * Register all DMA interrupt handlers.
- * Both DMA controllers are initialized separate
- */
- #if 0
- void DMA_Init(uint8_t ch)
- {
- uint8_t stream_nr = CH2NR(ch);
- uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
- if (ch < 0x80)
- {
- if (!(CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR,
- _BI32(RCC_AHB1ENR_DMA1EN ))))
- {
- /* Enable DMA1 Clock */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA1EN ));
- /* Reset DMA1 */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
- CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
- return;
- }
- }
- else if (!(CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ))))
- {
- /* Enable DMA2 Clock */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ));
- /* Reset DMA2 */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
- CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
- return;
- }
- switch (stream_nr)
- {
- case 0: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF0|DMA_LIFCR_CDMEIF0|DMA_LIFCR_CTEIF0 |DMA_LIFCR_CHTIF0 |DMA_LIFCR_CTCIF0);
- break;
- case 1: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF1|DMA_LIFCR_CDMEIF1|DMA_LIFCR_CTEIF1 |DMA_LIFCR_CHTIF1 |DMA_LIFCR_CTCIF1);
- break;
- case 2: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF2|DMA_LIFCR_CDMEIF2|DMA_LIFCR_CTEIF2 |DMA_LIFCR_CHTIF2 |DMA_LIFCR_CTCIF2);
- break;
- case 3: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF3|DMA_LIFCR_CDMEIF3|DMA_LIFCR_CTEIF3 |DMA_LIFCR_CHTIF3 |DMA_LIFCR_CTCIF3);
- break;
- case 4: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
- break;
- case 5: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
- break;
- case 6: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
- break;
- case 7: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
- break;
- }
- #else
- void DMA_Init(void)
- {
- if (!CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA1EN ))) {
- /* Enable DMA1 Clock */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA1EN ));
- /* Reset DMA1 */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
- CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
- }
- if (!CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ))) {
- /* Enable DMA2 Clock */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ));
- /* Reset DMA2 */
- CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
- CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
- }
- return;
- }
- #endif
- /*!
- * \brief Control DMA channel interrupt masks
- *
- * Setup interrupt mask on given channel. Channel numbers are
- * from 0..n while documentation numbers them from 1..n.
- * For that please use the defines DMAx_Cn.
- *
- * \param ch Channel number to set interrupt mask.
- * \param mask Mask to set on the designated channel interrupts.
- * \param ena Enable (1) or Disable (0) the bits in the mask.
- *
- * On F2/F4, Interrupt enable bits and interrupt clear flags don't correspond!
- * The Clear flags are arranged with sffereing spacing!
- */
- void DMA_IrqMask( uint8_t ch, uint32_t mask, uint8_t ena)
- {
- uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
- uint32_t stream_base = CH2STREAM(dma_base, ch);
- uint32_t en_dis_msk = 0, clr_msk = DMA_LIFCR_CFEIF0|DMA_LIFCR_CDMEIF0;
- if (mask & DMA_TCIF)
- {
- en_dis_msk |= DMA_SxCR_TCIE;
- clr_msk |= DMA_LIFCR_CTCIF0;
- }
- if (mask & DMA_HTIF)
- {
- en_dis_msk |= DMA_SxCR_HTIE;
- clr_msk |= DMA_LIFCR_CHTIF0;
- }
- if (mask & DMA_TEIF)
- {
- en_dis_msk |= DMA_SxCR_TEIE;
- clr_msk |= DMA_LIFCR_CTEIF0;
- }
- if (ena)
- CM3REG(stream_base, DMA_Stream_TypeDef, CR) |= en_dis_msk;
- else
- CM3REG(stream_base, DMA_Stream_TypeDef, CR) &= ~en_dis_msk;
- switch (CH2NR(ch))
- {
- case 0: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk; break;
- case 1: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<6; break;
- case 2: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<16; break;
- case 3: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<22; break;
- case 4: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk; break;
- case 5: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<6; break;
- case 6: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<16; break;
- case 7: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<22; break;
- }
- };
- /*!
- * \brief Clear DMA channel flags.
- *
- * \param ch Channel number.
- * \param flags Mask of flags to clear.
- */
- void DMA_ClearFlag( uint8_t ch, uint32_t flags)
- {
- uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
- uint32_t clr_msk = DMA_LIFCR_CFEIF0|DMA_LIFCR_CDMEIF0|DMA_LIFCR_CTEIF0;
- if (flags & DMA_TCIF) clr_msk |= DMA_LIFCR_CTCIF0;
- if (flags & DMA_HTIF) clr_msk |= DMA_LIFCR_CHTIF0;
- if (flags & DMA_TEIF) clr_msk |= DMA_LIFCR_CTEIF0;
- switch (CH2NR(ch))
- {
- case 0: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk; break;
- case 1: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<6; break;
- case 2: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<16; break;
- case 3: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<22; break;
- case 4: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk; break;
- case 5: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<6; break;
- case 6: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<16; break;
- case 7: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<22; break;
- }
- }
- /*!
- * \brief Get DMA channel flags.
- *
- * Get interrupt / status flags of given channel.
- *
- * \param ch Channel number to set interrupt mask.
- *
- * \return flags Mask of flags to clear.
- */
- uint32_t DMA_GetFlag( uint8_t ch)
- {
- uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
- uint32_t flags = 0, ret = 0;
- switch (CH2NR(ch))
- {
- case 0: flags = (CM3REG(dma_base, DMA_TypeDef, LISR) ) & 0x3d; break;
- case 1: flags = (CM3REG(dma_base, DMA_TypeDef, LISR)>> 6) & 0x3d; break;
- case 2: flags = (CM3REG(dma_base, DMA_TypeDef, LISR)>>16) & 0x3d; break;
- case 3: flags = (CM3REG(dma_base, DMA_TypeDef, LISR)>>22) & 0x3d; break;
- case 4: flags = (CM3REG(dma_base, DMA_TypeDef, HISR) ) & 0x3d; break;
- case 5: flags = (CM3REG(dma_base, DMA_TypeDef, HISR)>> 6) & 0x3d; break;
- case 6: flags = (CM3REG(dma_base, DMA_TypeDef, HISR)>>16) & 0x3d; break;
- case 7: flags = (CM3REG(dma_base, DMA_TypeDef, HISR)>>22) & 0x3d; break;
- }
- if (flags & DMA_LISR_TCIF0) ret |= DMA_TCIF;
- if (flags & DMA_LISR_HTIF0) ret |= DMA_HTIF;
- if (flags & DMA_LISR_TEIF0) ret |= DMA_TEIF;
- return ret;
- }
|