mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
screamer
Date:
Tue Aug 02 14:07:36 2016 +0000
Revision:
144:423e1876dc07
Parent:
15:a81a8d6c1dfe
Added targets.json file for the supported targets in the release

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 }