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