Mateusz Kowalik / Application_danix

Fork of Application by Daniel Sygut

Committer:
Zaitsev
Date:
Tue Jan 10 20:42:26 2017 +0000
Revision:
10:41552d038a69
USB Serial bi-directional bridge

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Zaitsev 10:41552d038a69 1 /***************************************************************************//**
Zaitsev 10:41552d038a69 2 * @file dma_api.c
Zaitsev 10:41552d038a69 3 *******************************************************************************
Zaitsev 10:41552d038a69 4 * @section License
Zaitsev 10:41552d038a69 5 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
Zaitsev 10:41552d038a69 6 *******************************************************************************
Zaitsev 10:41552d038a69 7 *
Zaitsev 10:41552d038a69 8 * SPDX-License-Identifier: Apache-2.0
Zaitsev 10:41552d038a69 9 *
Zaitsev 10:41552d038a69 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Zaitsev 10:41552d038a69 11 * not use this file except in compliance with the License.
Zaitsev 10:41552d038a69 12 * You may obtain a copy of the License at
Zaitsev 10:41552d038a69 13 *
Zaitsev 10:41552d038a69 14 * http://www.apache.org/licenses/LICENSE-2.0
Zaitsev 10:41552d038a69 15 *
Zaitsev 10:41552d038a69 16 * Unless required by applicable law or agreed to in writing, software
Zaitsev 10:41552d038a69 17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Zaitsev 10:41552d038a69 18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Zaitsev 10:41552d038a69 19 * See the License for the specific language governing permissions and
Zaitsev 10:41552d038a69 20 * limitations under the License.
Zaitsev 10:41552d038a69 21 *
Zaitsev 10:41552d038a69 22 ******************************************************************************/
Zaitsev 10:41552d038a69 23
Zaitsev 10:41552d038a69 24 #include <stdint.h>
Zaitsev 10:41552d038a69 25 #include "dma_api_HAL.h"
Zaitsev 10:41552d038a69 26 #include "em_device.h"
Zaitsev 10:41552d038a69 27 #include "em_cmu.h"
Zaitsev 10:41552d038a69 28
Zaitsev 10:41552d038a69 29 #ifdef DMA_PRESENT
Zaitsev 10:41552d038a69 30 #include "em_dma.h"
Zaitsev 10:41552d038a69 31 #endif
Zaitsev 10:41552d038a69 32
Zaitsev 10:41552d038a69 33 #ifdef LDMA_PRESENT
Zaitsev 10:41552d038a69 34 #include "em_ldma.h"
Zaitsev 10:41552d038a69 35 #endif
Zaitsev 10:41552d038a69 36
Zaitsev 10:41552d038a69 37 /** DMA control block array, requires proper alignment. */
Zaitsev 10:41552d038a69 38 #ifdef DMA_PRESENT
Zaitsev 10:41552d038a69 39 #if defined (__ICCARM__)
Zaitsev 10:41552d038a69 40 #pragma data_alignment=DMACTRL_ALIGNMENT
Zaitsev 10:41552d038a69 41 DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT * 2];
Zaitsev 10:41552d038a69 42
Zaitsev 10:41552d038a69 43 #elif defined (__CC_ARM)
Zaitsev 10:41552d038a69 44 DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT * 2] __attribute__ ((aligned(DMACTRL_ALIGNMENT)));
Zaitsev 10:41552d038a69 45
Zaitsev 10:41552d038a69 46 #elif defined (__GNUC__)
Zaitsev 10:41552d038a69 47 DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT * 2] __attribute__ ((aligned(DMACTRL_ALIGNMENT), section("dma")));
Zaitsev 10:41552d038a69 48
Zaitsev 10:41552d038a69 49 #else
Zaitsev 10:41552d038a69 50 #error Undefined toolkit, need to define alignment
Zaitsev 10:41552d038a69 51 #endif
Zaitsev 10:41552d038a69 52 #endif /* DMA_PRESENT */
Zaitsev 10:41552d038a69 53
Zaitsev 10:41552d038a69 54 uint32_t channels = 0; // Bit vector of taken channels
Zaitsev 10:41552d038a69 55 bool enabled = false;
Zaitsev 10:41552d038a69 56
Zaitsev 10:41552d038a69 57 void dma_init(void)
Zaitsev 10:41552d038a69 58 {
Zaitsev 10:41552d038a69 59 if (enabled) return;
Zaitsev 10:41552d038a69 60
Zaitsev 10:41552d038a69 61 #if defined DMA_PRESENT
Zaitsev 10:41552d038a69 62 CMU_ClockEnable(cmuClock_DMA, true);
Zaitsev 10:41552d038a69 63 CMU_ClockEnable(cmuClock_HFPER, true); // FIXME: DMA is clocked via HFCORECLK, why HFPERCLK?
Zaitsev 10:41552d038a69 64
Zaitsev 10:41552d038a69 65 DMA_Init_TypeDef dmaInit;
Zaitsev 10:41552d038a69 66
Zaitsev 10:41552d038a69 67 dmaInit.hprot = 0;
Zaitsev 10:41552d038a69 68 dmaInit.controlBlock = dmaControlBlock;
Zaitsev 10:41552d038a69 69 DMA_Init(&dmaInit);
Zaitsev 10:41552d038a69 70
Zaitsev 10:41552d038a69 71 #elif defined LDMA_PRESENT
Zaitsev 10:41552d038a69 72 CMU_ClockEnable(cmuClock_LDMA, true);
Zaitsev 10:41552d038a69 73
Zaitsev 10:41552d038a69 74 LDMA_Init_t ldmaInit;
Zaitsev 10:41552d038a69 75
Zaitsev 10:41552d038a69 76 ldmaInit.ldmaInitCtrlNumFixed = 0; /* All channels round-robin */
Zaitsev 10:41552d038a69 77 ldmaInit.ldmaInitCtrlSyncPrsClrEn = 0; /* Do not allow PRS to clear SYNCTRIG */
Zaitsev 10:41552d038a69 78 ldmaInit.ldmaInitCtrlSyncPrsSetEn = 0; /* Do not allow PRS to set SYNCTRIG */
Zaitsev 10:41552d038a69 79 ldmaInit.ldmaInitIrqPriority = 2; /* IRQ Priority */
Zaitsev 10:41552d038a69 80
Zaitsev 10:41552d038a69 81 LDMA_Init(&ldmaInit);
Zaitsev 10:41552d038a69 82 #else
Zaitsev 10:41552d038a69 83 #error "Unrecognized DMA peripheral"
Zaitsev 10:41552d038a69 84 #endif
Zaitsev 10:41552d038a69 85
Zaitsev 10:41552d038a69 86 enabled = true;
Zaitsev 10:41552d038a69 87 }
Zaitsev 10:41552d038a69 88
Zaitsev 10:41552d038a69 89 int dma_channel_allocate(uint32_t capabilities)
Zaitsev 10:41552d038a69 90 {
Zaitsev 10:41552d038a69 91 int i;
Zaitsev 10:41552d038a69 92 // Check if 2d copy is required
Zaitsev 10:41552d038a69 93 if (DMA_CAP_2DCOPY & capabilities) {
Zaitsev 10:41552d038a69 94 if (channels & 1) {
Zaitsev 10:41552d038a69 95 // Channel already in use
Zaitsev 10:41552d038a69 96 return DMA_ERROR_OUT_OF_CHANNELS;
Zaitsev 10:41552d038a69 97 } else {
Zaitsev 10:41552d038a69 98 channels |= 1 << 0;
Zaitsev 10:41552d038a69 99 return 0;
Zaitsev 10:41552d038a69 100 }
Zaitsev 10:41552d038a69 101 }
Zaitsev 10:41552d038a69 102 for (i = 1; i < DMA_CHAN_COUNT; i++) {
Zaitsev 10:41552d038a69 103 if ((channels & (1 << i)) == 0) {
Zaitsev 10:41552d038a69 104 // Channel available
Zaitsev 10:41552d038a69 105 channels |= 1 << i;
Zaitsev 10:41552d038a69 106 return i;
Zaitsev 10:41552d038a69 107 }
Zaitsev 10:41552d038a69 108 }
Zaitsev 10:41552d038a69 109 // Check if channel 0 is available
Zaitsev 10:41552d038a69 110 if ((channels & 1 ) == 0) {
Zaitsev 10:41552d038a69 111 channels |= 1 << 0;
Zaitsev 10:41552d038a69 112 return 0;
Zaitsev 10:41552d038a69 113 }
Zaitsev 10:41552d038a69 114 // Couldn't find a channel.
Zaitsev 10:41552d038a69 115 return DMA_ERROR_OUT_OF_CHANNELS;
Zaitsev 10:41552d038a69 116 }
Zaitsev 10:41552d038a69 117
Zaitsev 10:41552d038a69 118 int dma_channel_free(int channelid)
Zaitsev 10:41552d038a69 119 {
Zaitsev 10:41552d038a69 120 if( channelid >= 0 ) {
Zaitsev 10:41552d038a69 121 channels &= ~(1 << channelid);
Zaitsev 10:41552d038a69 122 }
Zaitsev 10:41552d038a69 123
Zaitsev 10:41552d038a69 124 return 0;
Zaitsev 10:41552d038a69 125 }
Zaitsev 10:41552d038a69 126
Zaitsev 10:41552d038a69 127 #ifdef LDMA_PRESENT
Zaitsev 10:41552d038a69 128
Zaitsev 10:41552d038a69 129 /* LDMA emlib API extensions */
Zaitsev 10:41552d038a69 130
Zaitsev 10:41552d038a69 131 typedef struct {
Zaitsev 10:41552d038a69 132 LDMAx_CBFunc_t callback;
Zaitsev 10:41552d038a69 133 void *userdata;
Zaitsev 10:41552d038a69 134 } LDMA_InternCallback_t;
Zaitsev 10:41552d038a69 135
Zaitsev 10:41552d038a69 136 static LDMA_InternCallback_t ldmaCallback[DMA_CHAN_COUNT];
Zaitsev 10:41552d038a69 137
Zaitsev 10:41552d038a69 138 void LDMAx_StartTransfer( int ch,
Zaitsev 10:41552d038a69 139 LDMA_TransferCfg_t *transfer,
Zaitsev 10:41552d038a69 140 LDMA_Descriptor_t *descriptor,
Zaitsev 10:41552d038a69 141 LDMAx_CBFunc_t cbFunc,
Zaitsev 10:41552d038a69 142 void *userData )
Zaitsev 10:41552d038a69 143 {
Zaitsev 10:41552d038a69 144 ldmaCallback[ch].callback = cbFunc;
Zaitsev 10:41552d038a69 145 ldmaCallback[ch].userdata = userData;
Zaitsev 10:41552d038a69 146
Zaitsev 10:41552d038a69 147 LDMA_StartTransfer(ch, transfer, descriptor);
Zaitsev 10:41552d038a69 148 }
Zaitsev 10:41552d038a69 149
Zaitsev 10:41552d038a69 150 void LDMA_IRQHandler( void )
Zaitsev 10:41552d038a69 151 {
Zaitsev 10:41552d038a69 152 uint32_t pending, chnum, chmask;
Zaitsev 10:41552d038a69 153
Zaitsev 10:41552d038a69 154 /* Get all pending and enabled interrupts */
Zaitsev 10:41552d038a69 155 pending = LDMA->IF;
Zaitsev 10:41552d038a69 156 pending &= LDMA->IEN;
Zaitsev 10:41552d038a69 157
Zaitsev 10:41552d038a69 158 /* Check for LDMA error */
Zaitsev 10:41552d038a69 159 if ( pending & LDMA_IF_ERROR )
Zaitsev 10:41552d038a69 160 {
Zaitsev 10:41552d038a69 161 /* Loop here to enable the debugger to see what has happened */
Zaitsev 10:41552d038a69 162 while (1)
Zaitsev 10:41552d038a69 163 ;
Zaitsev 10:41552d038a69 164 }
Zaitsev 10:41552d038a69 165
Zaitsev 10:41552d038a69 166 /* Iterate over all LDMA channels. */
Zaitsev 10:41552d038a69 167 for ( chnum = 0, chmask = 1;
Zaitsev 10:41552d038a69 168 chnum < DMA_CHAN_COUNT;
Zaitsev 10:41552d038a69 169 chnum++, chmask <<= 1 )
Zaitsev 10:41552d038a69 170 {
Zaitsev 10:41552d038a69 171 if ( pending & chmask )
Zaitsev 10:41552d038a69 172 {
Zaitsev 10:41552d038a69 173 /* Clear interrupt flag. */
Zaitsev 10:41552d038a69 174 LDMA->IFC = chmask;
Zaitsev 10:41552d038a69 175
Zaitsev 10:41552d038a69 176 /* Do more stuff here, execute callbacks etc. */
Zaitsev 10:41552d038a69 177 if ( ldmaCallback[chnum].callback )
Zaitsev 10:41552d038a69 178 {
Zaitsev 10:41552d038a69 179 ldmaCallback[chnum].callback(chnum, false, ldmaCallback[chnum].userdata);
Zaitsev 10:41552d038a69 180 }
Zaitsev 10:41552d038a69 181 }
Zaitsev 10:41552d038a69 182 }
Zaitsev 10:41552d038a69 183 }
Zaitsev 10:41552d038a69 184
Zaitsev 10:41552d038a69 185 /***************************************************************************//**
Zaitsev 10:41552d038a69 186 * @brief
Zaitsev 10:41552d038a69 187 * Check if LDMA channel is enabled.
Zaitsev 10:41552d038a69 188 *
Zaitsev 10:41552d038a69 189 * @param[in] ch
Zaitsev 10:41552d038a69 190 * LDMA channel to check.
Zaitsev 10:41552d038a69 191 *
Zaitsev 10:41552d038a69 192 * @return
Zaitsev 10:41552d038a69 193 * true if channel is enabled, false if not.
Zaitsev 10:41552d038a69 194 ******************************************************************************/
Zaitsev 10:41552d038a69 195 bool LDMAx_ChannelEnabled( int ch )
Zaitsev 10:41552d038a69 196 {
Zaitsev 10:41552d038a69 197 EFM_ASSERT(ch < DMA_CHAN_COUNT);
Zaitsev 10:41552d038a69 198 uint32_t chMask = 1 << ch;
Zaitsev 10:41552d038a69 199 return (bool)(LDMA->CHEN & chMask);
Zaitsev 10:41552d038a69 200 }
Zaitsev 10:41552d038a69 201
Zaitsev 10:41552d038a69 202 #endif /* LDMA_PRESENT */