t

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Oct 28 11:17:30 2016 +0100
Revision:
149:156823d33999
Parent:
targets/hal/TARGET_Atmel/TARGET_SAM_CortexM0P/drivers/dma/dma.c@15:a81a8d6c1dfe
This updates the lib to the mbed lib v128

NOTE: This release includes a restructuring of the file and directory locations and thus some
include paths in your code may need updating accordingly.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 15:a81a8d6c1dfe 1 /*
mbed_official 15:a81a8d6c1dfe 2 * \file
mbed_official 15:a81a8d6c1dfe 3 *
mbed_official 15:a81a8d6c1dfe 4 * \brief SAM Direct Memory Access Controller Driver
mbed_official 15:a81a8d6c1dfe 5 *
mbed_official 15:a81a8d6c1dfe 6 * Copyright (C) 2014-2015 Atmel Corporation. All rights reserved.
mbed_official 15:a81a8d6c1dfe 7 *
mbed_official 15:a81a8d6c1dfe 8 * \asf_license_start
mbed_official 15:a81a8d6c1dfe 9 *
mbed_official 15:a81a8d6c1dfe 10 * \page License
mbed_official 15:a81a8d6c1dfe 11 *
mbed_official 15:a81a8d6c1dfe 12 * Redistribution and use in source and binary forms, with or without
mbed_official 15:a81a8d6c1dfe 13 * modification, are permitted provided that the following conditions are met:
mbed_official 15:a81a8d6c1dfe 14 *
mbed_official 15:a81a8d6c1dfe 15 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 15:a81a8d6c1dfe 16 * this list of conditions and the following disclaimer.
mbed_official 15:a81a8d6c1dfe 17 *
mbed_official 15:a81a8d6c1dfe 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 15:a81a8d6c1dfe 19 * this list of conditions and the following disclaimer in the documentation
mbed_official 15:a81a8d6c1dfe 20 * and/or other materials provided with the distribution.
mbed_official 15:a81a8d6c1dfe 21 *
mbed_official 15:a81a8d6c1dfe 22 * 3. The name of Atmel may not be used to endorse or promote products derived
mbed_official 15:a81a8d6c1dfe 23 * from this software without specific prior written permission.
mbed_official 15:a81a8d6c1dfe 24 *
mbed_official 15:a81a8d6c1dfe 25 * 4. This software may only be redistributed and used in connection with an
mbed_official 15:a81a8d6c1dfe 26 * Atmel microcontroller product.
mbed_official 15:a81a8d6c1dfe 27 *
mbed_official 15:a81a8d6c1dfe 28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
mbed_official 15:a81a8d6c1dfe 29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
mbed_official 15:a81a8d6c1dfe 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
mbed_official 15:a81a8d6c1dfe 31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
mbed_official 15:a81a8d6c1dfe 32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
mbed_official 15:a81a8d6c1dfe 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
mbed_official 15:a81a8d6c1dfe 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
mbed_official 15:a81a8d6c1dfe 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
mbed_official 15:a81a8d6c1dfe 36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
mbed_official 15:a81a8d6c1dfe 37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
mbed_official 15:a81a8d6c1dfe 38 * POSSIBILITY OF SUCH DAMAGE.
mbed_official 15:a81a8d6c1dfe 39 *
mbed_official 15:a81a8d6c1dfe 40 * \asf_license_stop
mbed_official 15:a81a8d6c1dfe 41 *
mbed_official 15:a81a8d6c1dfe 42 */
mbed_official 15:a81a8d6c1dfe 43 /*
mbed_official 15:a81a8d6c1dfe 44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
mbed_official 15:a81a8d6c1dfe 45 */
mbed_official 15:a81a8d6c1dfe 46
mbed_official 15:a81a8d6c1dfe 47 #include <string.h>
mbed_official 15:a81a8d6c1dfe 48 #include "dma.h"
mbed_official 15:a81a8d6c1dfe 49 #include "clock.h"
mbed_official 15:a81a8d6c1dfe 50 #include "system_interrupt.h"
mbed_official 15:a81a8d6c1dfe 51
mbed_official 15:a81a8d6c1dfe 52 struct _dma_module {
mbed_official 15:a81a8d6c1dfe 53 volatile bool _dma_init;
mbed_official 15:a81a8d6c1dfe 54 volatile uint32_t allocated_channels;
mbed_official 15:a81a8d6c1dfe 55 uint8_t free_channels;
mbed_official 15:a81a8d6c1dfe 56 };
mbed_official 15:a81a8d6c1dfe 57
mbed_official 15:a81a8d6c1dfe 58 struct _dma_module _dma_inst = {
mbed_official 15:a81a8d6c1dfe 59 ._dma_init = false,
mbed_official 15:a81a8d6c1dfe 60 .allocated_channels = 0,
mbed_official 15:a81a8d6c1dfe 61 .free_channels = CONF_MAX_USED_CHANNEL_NUM,
mbed_official 15:a81a8d6c1dfe 62 };
mbed_official 15:a81a8d6c1dfe 63
mbed_official 15:a81a8d6c1dfe 64 /** Maximum retry counter for resuming a job transfer. */
mbed_official 15:a81a8d6c1dfe 65 #define MAX_JOB_RESUME_COUNT 10000
mbed_official 15:a81a8d6c1dfe 66
mbed_official 15:a81a8d6c1dfe 67 /** DMA channel mask. */
mbed_official 15:a81a8d6c1dfe 68 #define DMA_CHANNEL_MASK (0x1f)
mbed_official 15:a81a8d6c1dfe 69
mbed_official 15:a81a8d6c1dfe 70 COMPILER_ALIGNED(16)
mbed_official 15:a81a8d6c1dfe 71 DmacDescriptor descriptor_section[CONF_MAX_USED_CHANNEL_NUM] SECTION_DMAC_DESCRIPTOR;
mbed_official 15:a81a8d6c1dfe 72
mbed_official 15:a81a8d6c1dfe 73 /** Initial write back memory section. */
mbed_official 15:a81a8d6c1dfe 74 COMPILER_ALIGNED(16)
mbed_official 15:a81a8d6c1dfe 75 static DmacDescriptor _write_back_section[CONF_MAX_USED_CHANNEL_NUM] SECTION_DMAC_DESCRIPTOR;
mbed_official 15:a81a8d6c1dfe 76
mbed_official 15:a81a8d6c1dfe 77 /** Internal DMA resource pool. */
mbed_official 15:a81a8d6c1dfe 78 static struct dma_resource* _dma_active_resource[CONF_MAX_USED_CHANNEL_NUM];
mbed_official 15:a81a8d6c1dfe 79
mbed_official 15:a81a8d6c1dfe 80 /* DMA channel interrup flag. */
mbed_official 15:a81a8d6c1dfe 81 uint8_t g_chan_interrupt_flag[CONF_MAX_USED_CHANNEL_NUM]= {0};
mbed_official 15:a81a8d6c1dfe 82
mbed_official 15:a81a8d6c1dfe 83 /**
mbed_official 15:a81a8d6c1dfe 84 * \brief Find a free channel for a DMA resource.
mbed_official 15:a81a8d6c1dfe 85 *
mbed_official 15:a81a8d6c1dfe 86 * Find a channel for the requested DMA resource.
mbed_official 15:a81a8d6c1dfe 87 *
mbed_official 15:a81a8d6c1dfe 88 * \return Status of channel allocation.
mbed_official 15:a81a8d6c1dfe 89 * \retval DMA_INVALID_CHANNEL No channel available
mbed_official 15:a81a8d6c1dfe 90 * \retval count Allocated channel for the DMA resource
mbed_official 15:a81a8d6c1dfe 91 */
mbed_official 15:a81a8d6c1dfe 92 static uint8_t _dma_find_first_free_channel_and_allocate(void)
mbed_official 15:a81a8d6c1dfe 93 {
mbed_official 15:a81a8d6c1dfe 94 uint8_t count;
mbed_official 15:a81a8d6c1dfe 95 uint32_t tmp;
mbed_official 15:a81a8d6c1dfe 96 bool allocated = false;
mbed_official 15:a81a8d6c1dfe 97
mbed_official 15:a81a8d6c1dfe 98 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 99
mbed_official 15:a81a8d6c1dfe 100 tmp = _dma_inst.allocated_channels;
mbed_official 15:a81a8d6c1dfe 101
mbed_official 15:a81a8d6c1dfe 102 for (count = 0; count < CONF_MAX_USED_CHANNEL_NUM; ++count) {
mbed_official 15:a81a8d6c1dfe 103 if (!(tmp & 0x00000001)) {
mbed_official 15:a81a8d6c1dfe 104 /* If free channel found, set as allocated and return
mbed_official 15:a81a8d6c1dfe 105 *number */
mbed_official 15:a81a8d6c1dfe 106
mbed_official 15:a81a8d6c1dfe 107 _dma_inst.allocated_channels |= 1 << count;
mbed_official 15:a81a8d6c1dfe 108 _dma_inst.free_channels--;
mbed_official 15:a81a8d6c1dfe 109 allocated = true;
mbed_official 15:a81a8d6c1dfe 110
mbed_official 15:a81a8d6c1dfe 111 break;
mbed_official 15:a81a8d6c1dfe 112 }
mbed_official 15:a81a8d6c1dfe 113
mbed_official 15:a81a8d6c1dfe 114 tmp = tmp >> 1;
mbed_official 15:a81a8d6c1dfe 115 }
mbed_official 15:a81a8d6c1dfe 116
mbed_official 15:a81a8d6c1dfe 117 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 118
mbed_official 15:a81a8d6c1dfe 119 if (!allocated) {
mbed_official 15:a81a8d6c1dfe 120 return DMA_INVALID_CHANNEL;
mbed_official 15:a81a8d6c1dfe 121 } else {
mbed_official 15:a81a8d6c1dfe 122 return count;
mbed_official 15:a81a8d6c1dfe 123 }
mbed_official 15:a81a8d6c1dfe 124 }
mbed_official 15:a81a8d6c1dfe 125
mbed_official 15:a81a8d6c1dfe 126 /**
mbed_official 15:a81a8d6c1dfe 127 * \brief Release an allocated DMA channel.
mbed_official 15:a81a8d6c1dfe 128 *
mbed_official 15:a81a8d6c1dfe 129 * \param[in] channel Channel id to be released
mbed_official 15:a81a8d6c1dfe 130 *
mbed_official 15:a81a8d6c1dfe 131 */
mbed_official 15:a81a8d6c1dfe 132 static void _dma_release_channel(uint8_t channel)
mbed_official 15:a81a8d6c1dfe 133 {
mbed_official 15:a81a8d6c1dfe 134 _dma_inst.allocated_channels &= ~(1 << channel);
mbed_official 15:a81a8d6c1dfe 135 _dma_inst.free_channels++;
mbed_official 15:a81a8d6c1dfe 136 }
mbed_official 15:a81a8d6c1dfe 137
mbed_official 15:a81a8d6c1dfe 138 /**
mbed_official 15:a81a8d6c1dfe 139 * \brief Configure the DMA resource.
mbed_official 15:a81a8d6c1dfe 140 *
mbed_official 15:a81a8d6c1dfe 141 * \param[in] dma_resource Pointer to a DMA resource instance
mbed_official 15:a81a8d6c1dfe 142 * \param[out] resource_config Configurations of the DMA resource
mbed_official 15:a81a8d6c1dfe 143 *
mbed_official 15:a81a8d6c1dfe 144 */
mbed_official 15:a81a8d6c1dfe 145 static void _dma_set_config(struct dma_resource *resource,
mbed_official 15:a81a8d6c1dfe 146 struct dma_resource_config *resource_config)
mbed_official 15:a81a8d6c1dfe 147 {
mbed_official 15:a81a8d6c1dfe 148 Assert(resource);
mbed_official 15:a81a8d6c1dfe 149 Assert(resource_config);
mbed_official 15:a81a8d6c1dfe 150 uint32_t temp_CHCTRLB_reg;
mbed_official 15:a81a8d6c1dfe 151 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 152
mbed_official 15:a81a8d6c1dfe 153 /** Select the DMA channel and clear software trigger */
mbed_official 15:a81a8d6c1dfe 154 DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 155 DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << resource->channel_id));
mbed_official 15:a81a8d6c1dfe 156
mbed_official 15:a81a8d6c1dfe 157 temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL(resource_config->priority) | \
mbed_official 15:a81a8d6c1dfe 158 DMAC_CHCTRLB_TRIGSRC(resource_config->peripheral_trigger) | \
mbed_official 15:a81a8d6c1dfe 159 DMAC_CHCTRLB_TRIGACT(resource_config->trigger_action);
mbed_official 15:a81a8d6c1dfe 160
mbed_official 15:a81a8d6c1dfe 161
mbed_official 15:a81a8d6c1dfe 162 if(resource_config->event_config.input_action) {
mbed_official 15:a81a8d6c1dfe 163 temp_CHCTRLB_reg |= DMAC_CHCTRLB_EVIE | DMAC_CHCTRLB_EVACT(
mbed_official 15:a81a8d6c1dfe 164 resource_config->event_config.input_action);
mbed_official 15:a81a8d6c1dfe 165 }
mbed_official 15:a81a8d6c1dfe 166
mbed_official 15:a81a8d6c1dfe 167 /** Enable event output, the event output selection is configured in
mbed_official 15:a81a8d6c1dfe 168 * each transfer descriptor */
mbed_official 15:a81a8d6c1dfe 169 if (resource_config->event_config.event_output_enable) {
mbed_official 15:a81a8d6c1dfe 170 temp_CHCTRLB_reg |= DMAC_CHCTRLB_EVOE;
mbed_official 15:a81a8d6c1dfe 171 }
mbed_official 15:a81a8d6c1dfe 172
mbed_official 15:a81a8d6c1dfe 173 /* Write config to CTRLB register */
mbed_official 15:a81a8d6c1dfe 174 DMAC->CHCTRLB.reg = temp_CHCTRLB_reg;
mbed_official 15:a81a8d6c1dfe 175
mbed_official 15:a81a8d6c1dfe 176
mbed_official 15:a81a8d6c1dfe 177
mbed_official 15:a81a8d6c1dfe 178 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 179 }
mbed_official 15:a81a8d6c1dfe 180
mbed_official 15:a81a8d6c1dfe 181 /**
mbed_official 15:a81a8d6c1dfe 182 * \brief DMA interrupt service routine.
mbed_official 15:a81a8d6c1dfe 183 *
mbed_official 15:a81a8d6c1dfe 184 */
mbed_official 15:a81a8d6c1dfe 185 void DMAC_Handler( void )
mbed_official 15:a81a8d6c1dfe 186 {
mbed_official 15:a81a8d6c1dfe 187 uint8_t active_channel;
mbed_official 15:a81a8d6c1dfe 188 struct dma_resource *resource;
mbed_official 15:a81a8d6c1dfe 189 uint8_t isr;
mbed_official 15:a81a8d6c1dfe 190 uint32_t write_size;
mbed_official 15:a81a8d6c1dfe 191 uint32_t total_size;
mbed_official 15:a81a8d6c1dfe 192
mbed_official 15:a81a8d6c1dfe 193 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 194
mbed_official 15:a81a8d6c1dfe 195 /* Get Pending channel */
mbed_official 15:a81a8d6c1dfe 196 active_channel = DMAC->INTPEND.reg & DMAC_INTPEND_ID_Msk;
mbed_official 15:a81a8d6c1dfe 197
mbed_official 15:a81a8d6c1dfe 198 Assert(_dma_active_resource[active_channel]);
mbed_official 15:a81a8d6c1dfe 199
mbed_official 15:a81a8d6c1dfe 200 /* Get active DMA resource based on channel */
mbed_official 15:a81a8d6c1dfe 201 resource = _dma_active_resource[active_channel];
mbed_official 15:a81a8d6c1dfe 202
mbed_official 15:a81a8d6c1dfe 203 /* Select the active channel */
mbed_official 15:a81a8d6c1dfe 204 DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 205 isr = DMAC->CHINTFLAG.reg;
mbed_official 15:a81a8d6c1dfe 206
mbed_official 15:a81a8d6c1dfe 207 /* Calculate block transfer size of the DMA transfer */
mbed_official 15:a81a8d6c1dfe 208 total_size = descriptor_section[resource->channel_id].BTCNT.reg;
mbed_official 15:a81a8d6c1dfe 209 write_size = _write_back_section[resource->channel_id].BTCNT.reg;
mbed_official 15:a81a8d6c1dfe 210 resource->transfered_size = total_size - write_size;
mbed_official 15:a81a8d6c1dfe 211
mbed_official 15:a81a8d6c1dfe 212 /* DMA channel interrupt handler */
mbed_official 15:a81a8d6c1dfe 213 if (isr & DMAC_CHINTENCLR_TERR) {
mbed_official 15:a81a8d6c1dfe 214 /* Clear transfer error flag */
mbed_official 15:a81a8d6c1dfe 215 DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
mbed_official 15:a81a8d6c1dfe 216
mbed_official 15:a81a8d6c1dfe 217 /* Set I/O ERROR status */
mbed_official 15:a81a8d6c1dfe 218 resource->job_status = STATUS_ERR_IO;
mbed_official 15:a81a8d6c1dfe 219
mbed_official 15:a81a8d6c1dfe 220 /* Execute the callback function */
mbed_official 15:a81a8d6c1dfe 221 if ((resource->callback_enable & (1<<DMA_CALLBACK_TRANSFER_ERROR)) &&
mbed_official 15:a81a8d6c1dfe 222 (resource->callback[DMA_CALLBACK_TRANSFER_ERROR])) {
mbed_official 15:a81a8d6c1dfe 223 resource->callback[DMA_CALLBACK_TRANSFER_ERROR](resource);
mbed_official 15:a81a8d6c1dfe 224 }
mbed_official 15:a81a8d6c1dfe 225 } else if (isr & DMAC_CHINTENCLR_TCMPL) {
mbed_official 15:a81a8d6c1dfe 226 /* Clear the transfer complete flag */
mbed_official 15:a81a8d6c1dfe 227 DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
mbed_official 15:a81a8d6c1dfe 228
mbed_official 15:a81a8d6c1dfe 229 /* Set job status */
mbed_official 15:a81a8d6c1dfe 230 resource->job_status = STATUS_OK;
mbed_official 15:a81a8d6c1dfe 231
mbed_official 15:a81a8d6c1dfe 232 /* Execute the callback function */
mbed_official 15:a81a8d6c1dfe 233 if ((resource->callback_enable & (1 << DMA_CALLBACK_TRANSFER_DONE)) &&
mbed_official 15:a81a8d6c1dfe 234 (resource->callback[DMA_CALLBACK_TRANSFER_DONE])) {
mbed_official 15:a81a8d6c1dfe 235 resource->callback[DMA_CALLBACK_TRANSFER_DONE](resource);
mbed_official 15:a81a8d6c1dfe 236 }
mbed_official 15:a81a8d6c1dfe 237 } else if (isr & DMAC_CHINTENCLR_SUSP) {
mbed_official 15:a81a8d6c1dfe 238 /* Clear channel suspend flag */
mbed_official 15:a81a8d6c1dfe 239 DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP;
mbed_official 15:a81a8d6c1dfe 240
mbed_official 15:a81a8d6c1dfe 241 /* Set job status */
mbed_official 15:a81a8d6c1dfe 242 resource->job_status = STATUS_SUSPEND;
mbed_official 15:a81a8d6c1dfe 243
mbed_official 15:a81a8d6c1dfe 244 /* Execute the callback function */
mbed_official 15:a81a8d6c1dfe 245 if ((resource->callback_enable & (1 << DMA_CALLBACK_CHANNEL_SUSPEND)) &&
mbed_official 15:a81a8d6c1dfe 246 (resource->callback[DMA_CALLBACK_CHANNEL_SUSPEND])) {
mbed_official 15:a81a8d6c1dfe 247 resource->callback[DMA_CALLBACK_CHANNEL_SUSPEND](resource);
mbed_official 15:a81a8d6c1dfe 248 }
mbed_official 15:a81a8d6c1dfe 249 }
mbed_official 15:a81a8d6c1dfe 250
mbed_official 15:a81a8d6c1dfe 251 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 252 }
mbed_official 15:a81a8d6c1dfe 253
mbed_official 15:a81a8d6c1dfe 254 /**
mbed_official 15:a81a8d6c1dfe 255 * \brief Initializes config with predefined default values.
mbed_official 15:a81a8d6c1dfe 256 *
mbed_official 15:a81a8d6c1dfe 257 * This function will initialize a given DMA configuration structure to
mbed_official 15:a81a8d6c1dfe 258 * a set of known default values. This function should be called on
mbed_official 15:a81a8d6c1dfe 259 * any new instance of the configuration structure before being
mbed_official 15:a81a8d6c1dfe 260 * modified by the user application.
mbed_official 15:a81a8d6c1dfe 261 *
mbed_official 15:a81a8d6c1dfe 262 * The default configuration is as follows:
mbed_official 15:a81a8d6c1dfe 263 * \li Software trigger is used as the transfer trigger
mbed_official 15:a81a8d6c1dfe 264 * \li Priority level 0
mbed_official 15:a81a8d6c1dfe 265 * \li Only software/event trigger
mbed_official 15:a81a8d6c1dfe 266 * \li Requires a trigger for each transaction
mbed_official 15:a81a8d6c1dfe 267 * \li No event input /output
mbed_official 15:a81a8d6c1dfe 268 * \li DMA channel is disabled during sleep mode (if has the feature)
mbed_official 15:a81a8d6c1dfe 269 * \param[out] config Pointer to the configuration
mbed_official 15:a81a8d6c1dfe 270 *
mbed_official 15:a81a8d6c1dfe 271 */
mbed_official 15:a81a8d6c1dfe 272 void dma_get_config_defaults(struct dma_resource_config *config)
mbed_official 15:a81a8d6c1dfe 273 {
mbed_official 15:a81a8d6c1dfe 274 Assert(config);
mbed_official 15:a81a8d6c1dfe 275 /* Set as priority 0 */
mbed_official 15:a81a8d6c1dfe 276 config->priority = DMA_PRIORITY_LEVEL_0;
mbed_official 15:a81a8d6c1dfe 277 /* Only software/event trigger */
mbed_official 15:a81a8d6c1dfe 278 config->peripheral_trigger = 0;
mbed_official 15:a81a8d6c1dfe 279 /* Transaction trigger */
mbed_official 15:a81a8d6c1dfe 280 config->trigger_action = DMA_TRIGGER_ACTON_TRANSACTION;
mbed_official 15:a81a8d6c1dfe 281
mbed_official 15:a81a8d6c1dfe 282 /* Event configurations, no event input/output */
mbed_official 15:a81a8d6c1dfe 283 config->event_config.input_action = DMA_EVENT_INPUT_NOACT;
mbed_official 15:a81a8d6c1dfe 284 config->event_config.event_output_enable = false;
mbed_official 15:a81a8d6c1dfe 285 #ifdef FEATURE_DMA_CHANNEL_STANDBY
mbed_official 15:a81a8d6c1dfe 286 config->run_in_standby = false;
mbed_official 15:a81a8d6c1dfe 287 #endif
mbed_official 15:a81a8d6c1dfe 288 }
mbed_official 15:a81a8d6c1dfe 289
mbed_official 15:a81a8d6c1dfe 290 /**
mbed_official 15:a81a8d6c1dfe 291 * \brief Allocate a DMA with configurations.
mbed_official 15:a81a8d6c1dfe 292 *
mbed_official 15:a81a8d6c1dfe 293 * This function will allocate a proper channel for a DMA transfer request.
mbed_official 15:a81a8d6c1dfe 294 *
mbed_official 15:a81a8d6c1dfe 295 * \param[in,out] dma_resource Pointer to a DMA resource instance
mbed_official 15:a81a8d6c1dfe 296 * \param[in] transfer_config Configurations of the DMA transfer
mbed_official 15:a81a8d6c1dfe 297 *
mbed_official 15:a81a8d6c1dfe 298 * \return Status of the allocation procedure.
mbed_official 15:a81a8d6c1dfe 299 *
mbed_official 15:a81a8d6c1dfe 300 * \retval STATUS_OK The DMA resource was allocated successfully
mbed_official 15:a81a8d6c1dfe 301 * \retval STATUS_ERR_NOT_FOUND DMA resource allocation failed
mbed_official 15:a81a8d6c1dfe 302 */
mbed_official 15:a81a8d6c1dfe 303 enum status_code dma_allocate(struct dma_resource *resource,
mbed_official 15:a81a8d6c1dfe 304 struct dma_resource_config *config)
mbed_official 15:a81a8d6c1dfe 305 {
mbed_official 15:a81a8d6c1dfe 306 uint8_t new_channel;
mbed_official 15:a81a8d6c1dfe 307
mbed_official 15:a81a8d6c1dfe 308 Assert(resource);
mbed_official 15:a81a8d6c1dfe 309
mbed_official 15:a81a8d6c1dfe 310 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 311
mbed_official 15:a81a8d6c1dfe 312 if (!_dma_inst._dma_init) {
mbed_official 15:a81a8d6c1dfe 313 /* Initialize clocks for DMA */
mbed_official 15:a81a8d6c1dfe 314 #if (SAML21) || (SAMC20) || (SAMC21)
mbed_official 15:a81a8d6c1dfe 315 system_ahb_clock_set_mask(MCLK_AHBMASK_DMAC);
mbed_official 15:a81a8d6c1dfe 316 #else
mbed_official 15:a81a8d6c1dfe 317 system_ahb_clock_set_mask(PM_AHBMASK_DMAC);
mbed_official 15:a81a8d6c1dfe 318 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBB,
mbed_official 15:a81a8d6c1dfe 319 PM_APBBMASK_DMAC);
mbed_official 15:a81a8d6c1dfe 320 #endif
mbed_official 15:a81a8d6c1dfe 321
mbed_official 15:a81a8d6c1dfe 322 /* Perform a software reset before enable DMA controller */
mbed_official 15:a81a8d6c1dfe 323 DMAC->CTRL.reg &= ~DMAC_CTRL_DMAENABLE;
mbed_official 15:a81a8d6c1dfe 324 DMAC->CTRL.reg = DMAC_CTRL_SWRST;
mbed_official 15:a81a8d6c1dfe 325
mbed_official 15:a81a8d6c1dfe 326 /* Setup descriptor base address and write back section base
mbed_official 15:a81a8d6c1dfe 327 * address */
mbed_official 15:a81a8d6c1dfe 328 DMAC->BASEADDR.reg = (uint32_t)descriptor_section;
mbed_official 15:a81a8d6c1dfe 329 DMAC->WRBADDR.reg = (uint32_t)_write_back_section;
mbed_official 15:a81a8d6c1dfe 330
mbed_official 15:a81a8d6c1dfe 331 /* Enable all priority level at the same time */
mbed_official 15:a81a8d6c1dfe 332 DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf);
mbed_official 15:a81a8d6c1dfe 333
mbed_official 15:a81a8d6c1dfe 334 _dma_inst._dma_init = true;
mbed_official 15:a81a8d6c1dfe 335 }
mbed_official 15:a81a8d6c1dfe 336
mbed_official 15:a81a8d6c1dfe 337 /* Find the proper channel */
mbed_official 15:a81a8d6c1dfe 338 new_channel = _dma_find_first_free_channel_and_allocate();
mbed_official 15:a81a8d6c1dfe 339
mbed_official 15:a81a8d6c1dfe 340 /* If no channel available, return not found */
mbed_official 15:a81a8d6c1dfe 341 if (new_channel == DMA_INVALID_CHANNEL) {
mbed_official 15:a81a8d6c1dfe 342 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 343
mbed_official 15:a81a8d6c1dfe 344 return STATUS_ERR_NOT_FOUND;
mbed_official 15:a81a8d6c1dfe 345 }
mbed_official 15:a81a8d6c1dfe 346
mbed_official 15:a81a8d6c1dfe 347 /* Set the channel */
mbed_official 15:a81a8d6c1dfe 348 resource->channel_id = new_channel;
mbed_official 15:a81a8d6c1dfe 349
mbed_official 15:a81a8d6c1dfe 350 /** Perform a reset for the allocated channel */
mbed_official 15:a81a8d6c1dfe 351 DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 352 DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
mbed_official 15:a81a8d6c1dfe 353 DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;
mbed_official 15:a81a8d6c1dfe 354
mbed_official 15:a81a8d6c1dfe 355 #ifdef FEATURE_DMA_CHANNEL_STANDBY
mbed_official 15:a81a8d6c1dfe 356 if(config->run_in_standby) {
mbed_official 15:a81a8d6c1dfe 357 DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_RUNSTDBY;
mbed_official 15:a81a8d6c1dfe 358 }
mbed_official 15:a81a8d6c1dfe 359 #endif
mbed_official 15:a81a8d6c1dfe 360
mbed_official 15:a81a8d6c1dfe 361 /** Configure the DMA control,channel registers and descriptors here */
mbed_official 15:a81a8d6c1dfe 362 _dma_set_config(resource, config);
mbed_official 15:a81a8d6c1dfe 363
mbed_official 15:a81a8d6c1dfe 364 resource->descriptor = NULL;
mbed_official 15:a81a8d6c1dfe 365
mbed_official 15:a81a8d6c1dfe 366 /* Log the DMA resource into the internal DMA resource pool */
mbed_official 15:a81a8d6c1dfe 367 _dma_active_resource[resource->channel_id] = resource;
mbed_official 15:a81a8d6c1dfe 368
mbed_official 15:a81a8d6c1dfe 369 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 370
mbed_official 15:a81a8d6c1dfe 371 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 372 }
mbed_official 15:a81a8d6c1dfe 373
mbed_official 15:a81a8d6c1dfe 374 /**
mbed_official 15:a81a8d6c1dfe 375 * \brief Free an allocated DMA resource.
mbed_official 15:a81a8d6c1dfe 376 *
mbed_official 15:a81a8d6c1dfe 377 * This function will free an allocated DMA resource.
mbed_official 15:a81a8d6c1dfe 378 *
mbed_official 15:a81a8d6c1dfe 379 * \param[in,out] resource Pointer to the DMA resource
mbed_official 15:a81a8d6c1dfe 380 *
mbed_official 15:a81a8d6c1dfe 381 * \return Status of the free procedure.
mbed_official 15:a81a8d6c1dfe 382 *
mbed_official 15:a81a8d6c1dfe 383 * \retval STATUS_OK The DMA resource was freed successfully
mbed_official 15:a81a8d6c1dfe 384 * \retval STATUS_BUSY The DMA resource was busy and can't be freed
mbed_official 15:a81a8d6c1dfe 385 * \retval STATUS_ERR_NOT_INITIALIZED DMA resource was not initialized
mbed_official 15:a81a8d6c1dfe 386 */
mbed_official 15:a81a8d6c1dfe 387 enum status_code dma_free(struct dma_resource *resource)
mbed_official 15:a81a8d6c1dfe 388 {
mbed_official 15:a81a8d6c1dfe 389 Assert(resource);
mbed_official 15:a81a8d6c1dfe 390 Assert(resource->channel_id != DMA_INVALID_CHANNEL);
mbed_official 15:a81a8d6c1dfe 391
mbed_official 15:a81a8d6c1dfe 392 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 393
mbed_official 15:a81a8d6c1dfe 394 /* Check if channel is busy */
mbed_official 15:a81a8d6c1dfe 395 if (dma_is_busy(resource)) {
mbed_official 15:a81a8d6c1dfe 396 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 397 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 398 }
mbed_official 15:a81a8d6c1dfe 399
mbed_official 15:a81a8d6c1dfe 400 /* Check if DMA resource was not allocated */
mbed_official 15:a81a8d6c1dfe 401 if (!(_dma_inst.allocated_channels & (1 << resource->channel_id))) {
mbed_official 15:a81a8d6c1dfe 402 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 403 return STATUS_ERR_NOT_INITIALIZED;
mbed_official 15:a81a8d6c1dfe 404 }
mbed_official 15:a81a8d6c1dfe 405
mbed_official 15:a81a8d6c1dfe 406 /* Release the DMA resource */
mbed_official 15:a81a8d6c1dfe 407 _dma_release_channel(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 408
mbed_official 15:a81a8d6c1dfe 409 /* Reset the item in the DMA resource pool */
mbed_official 15:a81a8d6c1dfe 410 _dma_active_resource[resource->channel_id] = NULL;
mbed_official 15:a81a8d6c1dfe 411
mbed_official 15:a81a8d6c1dfe 412 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 413
mbed_official 15:a81a8d6c1dfe 414 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 415 }
mbed_official 15:a81a8d6c1dfe 416
mbed_official 15:a81a8d6c1dfe 417 /**
mbed_official 15:a81a8d6c1dfe 418 * \brief Start a DMA transfer.
mbed_official 15:a81a8d6c1dfe 419 *
mbed_official 15:a81a8d6c1dfe 420 * This function will start a DMA transfer through an allocated DMA resource.
mbed_official 15:a81a8d6c1dfe 421 *
mbed_official 15:a81a8d6c1dfe 422 * \param[in,out] resource Pointer to the DMA resource
mbed_official 15:a81a8d6c1dfe 423 *
mbed_official 15:a81a8d6c1dfe 424 * \return Status of the transfer start procedure.
mbed_official 15:a81a8d6c1dfe 425 *
mbed_official 15:a81a8d6c1dfe 426 * \retval STATUS_OK The transfer was started successfully
mbed_official 15:a81a8d6c1dfe 427 * \retval STATUS_BUSY The DMA resource was busy and the transfer was not started
mbed_official 15:a81a8d6c1dfe 428 * \retval STATUS_ERR_INVALID_ARG Transfer size is 0 and transfer was not started
mbed_official 15:a81a8d6c1dfe 429 */
mbed_official 15:a81a8d6c1dfe 430 enum status_code dma_start_transfer_job(struct dma_resource *resource)
mbed_official 15:a81a8d6c1dfe 431 {
mbed_official 15:a81a8d6c1dfe 432 Assert(resource);
mbed_official 15:a81a8d6c1dfe 433 Assert(resource->channel_id != DMA_INVALID_CHANNEL);
mbed_official 15:a81a8d6c1dfe 434
mbed_official 15:a81a8d6c1dfe 435 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 436
mbed_official 15:a81a8d6c1dfe 437 /* Check if resource was busy */
mbed_official 15:a81a8d6c1dfe 438 if (resource->job_status == STATUS_BUSY) {
mbed_official 15:a81a8d6c1dfe 439 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 440 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 441 }
mbed_official 15:a81a8d6c1dfe 442
mbed_official 15:a81a8d6c1dfe 443 /* Check if transfer size is valid */
mbed_official 15:a81a8d6c1dfe 444 if (resource->descriptor->BTCNT.reg == 0) {
mbed_official 15:a81a8d6c1dfe 445 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 446 return STATUS_ERR_INVALID_ARG;
mbed_official 15:a81a8d6c1dfe 447 }
mbed_official 15:a81a8d6c1dfe 448
mbed_official 15:a81a8d6c1dfe 449 /* Enable DMA interrupt */
mbed_official 15:a81a8d6c1dfe 450 system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_DMA);
mbed_official 15:a81a8d6c1dfe 451
mbed_official 15:a81a8d6c1dfe 452 /* Set the interrupt flag */
mbed_official 15:a81a8d6c1dfe 453 DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 454 DMAC->CHINTENSET.reg = (DMAC_CHINTENSET_MASK & g_chan_interrupt_flag[resource->channel_id]);
mbed_official 15:a81a8d6c1dfe 455 /* Set job status */
mbed_official 15:a81a8d6c1dfe 456 resource->job_status = STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 457
mbed_official 15:a81a8d6c1dfe 458 /* Set channel x descriptor 0 to the descriptor base address */
mbed_official 15:a81a8d6c1dfe 459 memcpy(&descriptor_section[resource->channel_id], resource->descriptor,
mbed_official 15:a81a8d6c1dfe 460 sizeof(DmacDescriptor));
mbed_official 15:a81a8d6c1dfe 461
mbed_official 15:a81a8d6c1dfe 462 /* Enable the transfer channel */
mbed_official 15:a81a8d6c1dfe 463 DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
mbed_official 15:a81a8d6c1dfe 464
mbed_official 15:a81a8d6c1dfe 465 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 466
mbed_official 15:a81a8d6c1dfe 467 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 468 }
mbed_official 15:a81a8d6c1dfe 469
mbed_official 15:a81a8d6c1dfe 470 /**
mbed_official 15:a81a8d6c1dfe 471 * \brief Abort a DMA transfer.
mbed_official 15:a81a8d6c1dfe 472 *
mbed_official 15:a81a8d6c1dfe 473 * This function will abort a DMA transfer. The DMA channel used for the DMA
mbed_official 15:a81a8d6c1dfe 474 * resource will be disabled.
mbed_official 15:a81a8d6c1dfe 475 * The block transfer count will be also calculated and written to the DMA
mbed_official 15:a81a8d6c1dfe 476 * resource structure.
mbed_official 15:a81a8d6c1dfe 477 *
mbed_official 15:a81a8d6c1dfe 478 * \note The DMA resource will not be freed after calling this function.
mbed_official 15:a81a8d6c1dfe 479 * The function \ref dma_free() can be used to free an allocated resource.
mbed_official 15:a81a8d6c1dfe 480 *
mbed_official 15:a81a8d6c1dfe 481 * \param[in,out] resource Pointer to the DMA resource
mbed_official 15:a81a8d6c1dfe 482 *
mbed_official 15:a81a8d6c1dfe 483 */
mbed_official 15:a81a8d6c1dfe 484 void dma_abort_job(struct dma_resource *resource)
mbed_official 15:a81a8d6c1dfe 485 {
mbed_official 15:a81a8d6c1dfe 486 uint32_t write_size;
mbed_official 15:a81a8d6c1dfe 487 uint32_t total_size;
mbed_official 15:a81a8d6c1dfe 488
mbed_official 15:a81a8d6c1dfe 489 Assert(resource);
mbed_official 15:a81a8d6c1dfe 490 Assert(resource->channel_id != DMA_INVALID_CHANNEL);
mbed_official 15:a81a8d6c1dfe 491
mbed_official 15:a81a8d6c1dfe 492 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 493
mbed_official 15:a81a8d6c1dfe 494 DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 495 DMAC->CHCTRLA.reg = 0;
mbed_official 15:a81a8d6c1dfe 496
mbed_official 15:a81a8d6c1dfe 497 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 498
mbed_official 15:a81a8d6c1dfe 499 /* Get transferred size */
mbed_official 15:a81a8d6c1dfe 500 total_size = descriptor_section[resource->channel_id].BTCNT.reg;
mbed_official 15:a81a8d6c1dfe 501 write_size = _write_back_section[resource->channel_id].BTCNT.reg;
mbed_official 15:a81a8d6c1dfe 502 resource->transfered_size = total_size - write_size;
mbed_official 15:a81a8d6c1dfe 503
mbed_official 15:a81a8d6c1dfe 504 resource->job_status = STATUS_ABORTED;
mbed_official 15:a81a8d6c1dfe 505 }
mbed_official 15:a81a8d6c1dfe 506
mbed_official 15:a81a8d6c1dfe 507 /**
mbed_official 15:a81a8d6c1dfe 508 * \brief Suspend a DMA transfer.
mbed_official 15:a81a8d6c1dfe 509 *
mbed_official 15:a81a8d6c1dfe 510 * This function will request to suspend the transfer of the DMA resource.
mbed_official 15:a81a8d6c1dfe 511 * The channel is kept enabled, can receive transfer triggers (the transfer
mbed_official 15:a81a8d6c1dfe 512 * pending bit will be set), but will be removed from the arbitration scheme.
mbed_official 15:a81a8d6c1dfe 513 * The channel operation can be resumed by calling \ref dma_resume_job().
mbed_official 15:a81a8d6c1dfe 514 *
mbed_official 15:a81a8d6c1dfe 515 * \note This function sets the command to suspend the DMA channel
mbed_official 15:a81a8d6c1dfe 516 * associated with a DMA resource. The channel suspend interrupt flag
mbed_official 15:a81a8d6c1dfe 517 * indicates whether the transfer is truly suspended.
mbed_official 15:a81a8d6c1dfe 518 *
mbed_official 15:a81a8d6c1dfe 519 * \param[in] resource Pointer to the DMA resource
mbed_official 15:a81a8d6c1dfe 520 *
mbed_official 15:a81a8d6c1dfe 521 */
mbed_official 15:a81a8d6c1dfe 522 void dma_suspend_job(struct dma_resource *resource)
mbed_official 15:a81a8d6c1dfe 523 {
mbed_official 15:a81a8d6c1dfe 524 Assert(resource);
mbed_official 15:a81a8d6c1dfe 525 Assert(resource->channel_id != DMA_INVALID_CHANNEL);
mbed_official 15:a81a8d6c1dfe 526
mbed_official 15:a81a8d6c1dfe 527 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 528
mbed_official 15:a81a8d6c1dfe 529 /* Select the channel */
mbed_official 15:a81a8d6c1dfe 530 DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 531
mbed_official 15:a81a8d6c1dfe 532 /* Send the suspend request */
mbed_official 15:a81a8d6c1dfe 533 DMAC->CHCTRLB.reg |= DMAC_CHCTRLB_CMD_SUSPEND;
mbed_official 15:a81a8d6c1dfe 534
mbed_official 15:a81a8d6c1dfe 535 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 536 }
mbed_official 15:a81a8d6c1dfe 537
mbed_official 15:a81a8d6c1dfe 538 /**
mbed_official 15:a81a8d6c1dfe 539 * \brief Resume a suspended DMA transfer.
mbed_official 15:a81a8d6c1dfe 540 *
mbed_official 15:a81a8d6c1dfe 541 * This function try to resume a suspended transfer of a DMA resource.
mbed_official 15:a81a8d6c1dfe 542 *
mbed_official 15:a81a8d6c1dfe 543 * \param[in] resource Pointer to the DMA resource
mbed_official 15:a81a8d6c1dfe 544 *
mbed_official 15:a81a8d6c1dfe 545 */
mbed_official 15:a81a8d6c1dfe 546 void dma_resume_job(struct dma_resource *resource)
mbed_official 15:a81a8d6c1dfe 547 {
mbed_official 15:a81a8d6c1dfe 548 uint32_t bitmap_channel;
mbed_official 15:a81a8d6c1dfe 549 uint32_t count = 0;
mbed_official 15:a81a8d6c1dfe 550
mbed_official 15:a81a8d6c1dfe 551 Assert(resource);
mbed_official 15:a81a8d6c1dfe 552 Assert(resource->channel_id != DMA_INVALID_CHANNEL);
mbed_official 15:a81a8d6c1dfe 553
mbed_official 15:a81a8d6c1dfe 554 /* Get bitmap of the allocated DMA channel */
mbed_official 15:a81a8d6c1dfe 555 bitmap_channel = (1 << resource->channel_id);
mbed_official 15:a81a8d6c1dfe 556
mbed_official 15:a81a8d6c1dfe 557 /* Check if channel was suspended */
mbed_official 15:a81a8d6c1dfe 558 if (resource->job_status != STATUS_SUSPEND) {
mbed_official 15:a81a8d6c1dfe 559 return;
mbed_official 15:a81a8d6c1dfe 560 }
mbed_official 15:a81a8d6c1dfe 561
mbed_official 15:a81a8d6c1dfe 562 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 563
mbed_official 15:a81a8d6c1dfe 564 /* Send resume request */
mbed_official 15:a81a8d6c1dfe 565 DMAC->CHID.reg = DMAC_CHID_ID(resource->channel_id);
mbed_official 15:a81a8d6c1dfe 566 DMAC->CHCTRLB.reg |= DMAC_CHCTRLB_CMD_RESUME;
mbed_official 15:a81a8d6c1dfe 567
mbed_official 15:a81a8d6c1dfe 568 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 569
mbed_official 15:a81a8d6c1dfe 570 /* Check if transfer job resumed */
mbed_official 15:a81a8d6c1dfe 571 for (count = 0; count < MAX_JOB_RESUME_COUNT; count++) {
mbed_official 15:a81a8d6c1dfe 572 if ((DMAC->BUSYCH.reg & bitmap_channel) == bitmap_channel) {
mbed_official 15:a81a8d6c1dfe 573 break;
mbed_official 15:a81a8d6c1dfe 574 }
mbed_official 15:a81a8d6c1dfe 575 }
mbed_official 15:a81a8d6c1dfe 576
mbed_official 15:a81a8d6c1dfe 577 if (count < MAX_JOB_RESUME_COUNT) {
mbed_official 15:a81a8d6c1dfe 578 /* Job resumed */
mbed_official 15:a81a8d6c1dfe 579 resource->job_status = STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 580 } else {
mbed_official 15:a81a8d6c1dfe 581 /* Job resume timeout */
mbed_official 15:a81a8d6c1dfe 582 resource->job_status = STATUS_ERR_TIMEOUT;
mbed_official 15:a81a8d6c1dfe 583 }
mbed_official 15:a81a8d6c1dfe 584 }
mbed_official 15:a81a8d6c1dfe 585
mbed_official 15:a81a8d6c1dfe 586 /**
mbed_official 15:a81a8d6c1dfe 587 * \brief Create a DMA transfer descriptor with configurations.
mbed_official 15:a81a8d6c1dfe 588 *
mbed_official 15:a81a8d6c1dfe 589 * This function will set the transfer configurations to the DMA transfer
mbed_official 15:a81a8d6c1dfe 590 * descriptor.
mbed_official 15:a81a8d6c1dfe 591 *
mbed_official 15:a81a8d6c1dfe 592 * \param[in] descriptor Pointer to the DMA transfer descriptor
mbed_official 15:a81a8d6c1dfe 593 * \param[in] config Pointer to the descriptor configuration structure
mbed_official 15:a81a8d6c1dfe 594 *
mbed_official 15:a81a8d6c1dfe 595 */
mbed_official 15:a81a8d6c1dfe 596 void dma_descriptor_create(DmacDescriptor* descriptor,
mbed_official 15:a81a8d6c1dfe 597 struct dma_descriptor_config *config)
mbed_official 15:a81a8d6c1dfe 598 {
mbed_official 15:a81a8d6c1dfe 599 /* Set block transfer control */
mbed_official 15:a81a8d6c1dfe 600 descriptor->BTCTRL.bit.VALID = config->descriptor_valid;
mbed_official 15:a81a8d6c1dfe 601 descriptor->BTCTRL.bit.EVOSEL = config->event_output_selection;
mbed_official 15:a81a8d6c1dfe 602 descriptor->BTCTRL.bit.BLOCKACT = config->block_action;
mbed_official 15:a81a8d6c1dfe 603 descriptor->BTCTRL.bit.BEATSIZE = config->beat_size;
mbed_official 15:a81a8d6c1dfe 604 descriptor->BTCTRL.bit.SRCINC = config->src_increment_enable;
mbed_official 15:a81a8d6c1dfe 605 descriptor->BTCTRL.bit.DSTINC = config->dst_increment_enable;
mbed_official 15:a81a8d6c1dfe 606 descriptor->BTCTRL.bit.STEPSEL = config->step_selection;
mbed_official 15:a81a8d6c1dfe 607 descriptor->BTCTRL.bit.STEPSIZE = config->step_size;
mbed_official 15:a81a8d6c1dfe 608
mbed_official 15:a81a8d6c1dfe 609 /* Set transfer size, source address and destination address */
mbed_official 15:a81a8d6c1dfe 610 descriptor->BTCNT.reg = config->block_transfer_count;
mbed_official 15:a81a8d6c1dfe 611 descriptor->SRCADDR.reg = config->source_address;
mbed_official 15:a81a8d6c1dfe 612 descriptor->DSTADDR.reg = config->destination_address;
mbed_official 15:a81a8d6c1dfe 613
mbed_official 15:a81a8d6c1dfe 614 /* Set next transfer descriptor address */
mbed_official 15:a81a8d6c1dfe 615 descriptor->DESCADDR.reg = config->next_descriptor_address;
mbed_official 15:a81a8d6c1dfe 616 }
mbed_official 15:a81a8d6c1dfe 617
mbed_official 15:a81a8d6c1dfe 618 /**
mbed_official 15:a81a8d6c1dfe 619 * \brief Add a DMA transfer descriptor to a DMA resource.
mbed_official 15:a81a8d6c1dfe 620 *
mbed_official 15:a81a8d6c1dfe 621 * This function will add a DMA transfer descriptor to a DMA resource.
mbed_official 15:a81a8d6c1dfe 622 * If there was a transfer descriptor already allocated to the DMA resource,
mbed_official 15:a81a8d6c1dfe 623 * the descriptor will be linked to the next descriptor address.
mbed_official 15:a81a8d6c1dfe 624 *
mbed_official 15:a81a8d6c1dfe 625 * \param[in] resource Pointer to the DMA resource
mbed_official 15:a81a8d6c1dfe 626 * \param[in] descriptor Pointer to the transfer descriptor
mbed_official 15:a81a8d6c1dfe 627 *
mbed_official 15:a81a8d6c1dfe 628 * \retval STATUS_OK The descriptor is added to the DMA resource
mbed_official 15:a81a8d6c1dfe 629 * \retval STATUS_BUSY The DMA resource was busy and the descriptor is not added
mbed_official 15:a81a8d6c1dfe 630 */
mbed_official 15:a81a8d6c1dfe 631 enum status_code dma_add_descriptor(struct dma_resource *resource,
mbed_official 15:a81a8d6c1dfe 632 DmacDescriptor* descriptor)
mbed_official 15:a81a8d6c1dfe 633 {
mbed_official 15:a81a8d6c1dfe 634 DmacDescriptor* desc = resource->descriptor;
mbed_official 15:a81a8d6c1dfe 635
mbed_official 15:a81a8d6c1dfe 636 if (resource->job_status == STATUS_BUSY) {
mbed_official 15:a81a8d6c1dfe 637 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 638 }
mbed_official 15:a81a8d6c1dfe 639
mbed_official 15:a81a8d6c1dfe 640 /* Look up for an empty space for the descriptor */
mbed_official 15:a81a8d6c1dfe 641 if (desc == NULL) {
mbed_official 15:a81a8d6c1dfe 642 resource->descriptor = descriptor;
mbed_official 15:a81a8d6c1dfe 643 } else {
mbed_official 15:a81a8d6c1dfe 644 /* Looking for end of descriptor link */
mbed_official 15:a81a8d6c1dfe 645 while(desc->DESCADDR.reg != 0) {
mbed_official 15:a81a8d6c1dfe 646 desc = (DmacDescriptor*)(desc->DESCADDR.reg);
mbed_official 15:a81a8d6c1dfe 647 }
mbed_official 15:a81a8d6c1dfe 648
mbed_official 15:a81a8d6c1dfe 649 /* Set to the end of descriptor list */
mbed_official 15:a81a8d6c1dfe 650 desc->DESCADDR.reg = (uint32_t)descriptor;
mbed_official 15:a81a8d6c1dfe 651 }
mbed_official 15:a81a8d6c1dfe 652
mbed_official 15:a81a8d6c1dfe 653 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 654 }