Modified version of the mbed library for use with the Nucleo boards.
Dependents: EEPROMWrite Full-Project
Fork of mbed-src by
Diff: targets/hal/TARGET_Atmel/TARGET_SAM21/dma_api.c
- Revision:
- 613:bc40b8d2aec4
- Parent:
- 612:fba1c7dc54c0
- Child:
- 614:9d86c2ae5de0
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/dma_api.c Tue Aug 18 15:00:09 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,372 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "mbed_assert.h" -#include "system.h" -#include "dma_api.h" -#include "dma_api_HAL.h" - -#include <math.h> - -#include "cmsis.h" -#include "pinmap.h" - -/** - * \internal - * Structure redefinition, already defined in dma.c. - * Redefining as that definition is not available here - */ -struct _dma_module { - volatile bool _dma_init; - volatile uint32_t allocated_channels; - uint8_t free_channels; -}; - -extern struct _dma_module _dma_inst; -extern uint8_t g_sys_init; - -static struct dma_instance_s dma_channels[CONF_MAX_USED_CHANNEL_NUM]; - -/** - * \internal - * Get resource index from channel id - * - * @param[in] channelid Valid DMA channel id - * @return index to DMA instance - */ -static uint8_t get_index_from_id(int channelid) -{ - /* Sanity check arguments */ - MBED_ASSERT(channelid < CONF_MAX_USED_CHANNEL_NUM); - - uint8_t i; - - for (i=0; i<CONF_MAX_USED_CHANNEL_NUM; i++) { - if ((dma_channels[i].status & DMA_ALLOCATED) - && (dma_channels[i].resource.channel_id == channelid)) { - break; - } - } - - return i; -} - -/** - * \internal - * Handler function for DMA callback - * - * @param[in] resource pointer to the resource - * @return void - */ -static void dma_handler(const struct dma_resource* const resource) -{ - MBED_ASSERT(resource); - void (*callback_func)(void); - - uint8_t channelid = resource->channel_id; - uint8_t channel_index; - - channel_index = get_index_from_id(channelid); - if (channel_index >= CONF_MAX_USED_CHANNEL_NUM) { - return; - } - - callback_func = dma_channels[channel_index].handler; - if (callback_func) { - callback_func(); - } -} - -/** - * \internal - * Configure a DMA channel for specified resource - * - * @param[in] channel_index index to the resource - * @return void - */ -static void configure_dma_resource(uint8_t channel_index) -{ - /* Sanity check arguments */ - MBED_ASSERT(channel_index < CONF_MAX_USED_CHANNEL_NUM); - - enum status_code ret; - struct dma_resource_config config; - - if (dma_channels[channel_index].status & DMA_ALLOCATED) { - return; - } - - /* Get default configuration for DMA */ - dma_get_config_defaults(&config); - - /* Allocate a free channel */ - ret = dma_allocate(&dma_channels[channel_index].resource, &config); - - if (ret == STATUS_OK) { - dma_channels[channel_index].status = DMA_ALLOCATED; - } -} - -/** Setup a DMA descriptor for specified resource - * - * @param[in] channel_index DMA channel id - * @param[in] src source address - * @param[in] src_inc_enable source address auto increment enable flag - * @param[in] desc destination address - * @param[in] desc_inc_enable destination address auto increment enable flag - * @param[in] length length of data to be transferred - * @param[in] beat_size beat size to be set - * @return void - */ -void dma_setup_transfer(uint8_t channelid, uint32_t src, bool src_inc_enable, uint32_t desc, bool desc_inc_enable, uint32_t length, uint8_t beat_size) -{ - enum status_code result; - uint8_t channel_index; - struct dma_descriptor_config descriptor_config; - - /* Sanity check arguments */ - MBED_ASSERT(channelid < CONF_MAX_USED_CHANNEL_NUM); - MBED_ASSERT(src); - MBED_ASSERT(desc); - - channel_index = get_index_from_id(channelid); - - dma_descriptor_get_config_defaults(&descriptor_config); - - if (beat_size <= 8) { - descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; - } else if ((beat_size > 8) && (beat_size <= 16)) { - descriptor_config.beat_size = DMA_BEAT_SIZE_HWORD; - } else { - descriptor_config.beat_size = DMA_BEAT_SIZE_WORD; - } - descriptor_config.block_transfer_count = length; - descriptor_config.source_address = src; - descriptor_config.destination_address = desc; - - /* Source address auto-increment is enabled by default */ - if (!src_inc_enable) { - descriptor_config.src_increment_enable = false; - } - - /* Destination address auto-increment is enabled by default */ - if (!desc_inc_enable) { - descriptor_config.dst_increment_enable = false; - } - - dma_descriptor_create(&dma_channels[channel_index].descriptor, &descriptor_config); - - /* Add descriptor to resource */ - if (dma_channels[channel_index].resource.descriptor == NULL) { - /* Multiple calls to this function without releasing already allocated channel is not handled now */ - result = dma_add_descriptor(&dma_channels[channel_index].resource, &dma_channels[channel_index].descriptor); - if (result != STATUS_OK) { - dma_channels[channel_index].status |= DMA_ERROR; - } - } -} - - -/** Initialize the DMA - * - * Configures clock for DMAC - */ -void dma_init() -{ - int i; - - if (g_sys_init == 0) { - system_init(); - g_sys_init = 1; - } - - if (!_dma_inst._dma_init) { - for (i=0; i<CONF_MAX_USED_CHANNEL_NUM; i++) { - dma_channels[i].status = DMA_NOT_USED; - } - } - /* Do nothing for now. ASF does the clock init when allocating channel */ -} - -/** Allocates channel for DMA - * - * Allocates channel for DMA with specified capability - * @param[in] capabilities Capability of DMA channel - */ -int dma_channel_allocate(uint32_t capabilities) -{ - uint8_t channel_index = 0; - - for (channel_index=0; channel_index<CONF_MAX_USED_CHANNEL_NUM; channel_index++) { - if (dma_channels[channel_index].status == DMA_NOT_USED) { - break; - } - } - - if (channel_index != CONF_MAX_USED_CHANNEL_NUM) { - configure_dma_resource(channel_index); - if (dma_channels[channel_index].status & DMA_ALLOCATED) { - return dma_channels[channel_index].resource.channel_id; - } - } - - /* Couldn't find a channel. */ - return DMA_ERROR_OUT_OF_CHANNELS; -} - -/** Start DMA transfer - * - * Kick starts transfer in DMA channel with specified channel id - * @param[in] channelid Channel id of DMA channel - * @return zero if success otherwise non zero - */ -bool dma_start_transfer(int channelid) -{ - /* Sanity check arguments */ - MBED_ASSERT(channelid < CONF_MAX_USED_CHANNEL_NUM); - - uint8_t channel_index; - - channel_index = get_index_from_id(channelid); - - if (channel_index >= CONF_MAX_USED_CHANNEL_NUM) { - /* Return invalid value for now */ - return false; - } - - if (!(dma_channels[channel_index].status & DMA_ALLOCATED)) { - /* DMA not allocated, return invalid value for now */ - return false; - } - - /* Start DMA transfer */ - if (STATUS_OK != dma_start_transfer_job(&dma_channels[channel_index].resource)) { - /* Error in starting DMA transfer */ - return false; - } - - return true; -} - -/** DMA channel busy check - * - * To check whether DMA channel is busy with a job or not - * @param[in] channelid Channel id of DMA channel - * @return non zero if busy otherwise zero - */ -bool dma_busy(int channelid) -{ - int res = 0; - /* Sanity check arguments */ - MBED_ASSERT(channelid < CONF_MAX_USED_CHANNEL_NUM); - - uint8_t channel_index; - - channel_index = get_index_from_id(channelid); - - if (channel_index >= CONF_MAX_USED_CHANNEL_NUM) { - /* This channel is not active! return zero for now */ - res = 0; - } - - return dma_is_busy(&dma_channels[channel_index].resource); -} - -/** DMA channel transfer completion check - * - * To check whether DMA channel job is completed or not - * @param[in] channelid Channel id of DMA channel - * @return non zero if busy otherwise zero - */ -bool dma_is_transfer_complete(int channelid) -{ - int res = 0; - /* Sanity check arguments */ - MBED_ASSERT(channelid < CONF_MAX_USED_CHANNEL_NUM); - - uint8_t channel_index; - - channel_index = get_index_from_id(channelid); - - if (channel_index >= CONF_MAX_USED_CHANNEL_NUM) { - /* This channel is not active! return zero for now */ - res = 0; - } - - return (STATUS_OK == dma_get_job_status(&dma_channels[channel_index].resource)); -} - -/** Registers callback function for DMA - * - * Registers callback function for DMA for specified events - * @param[in] channelid Channel id of DMA channel - * @param[in] handler Callback function pointer - * @param[in] event Events mask - * @return void - */ -void dma_set_handler(int channelid, uint32_t handler, uint32_t event) -{ - /* Sanity check arguments */ - MBED_ASSERT(channelid < CONF_MAX_USED_CHANNEL_NUM); - - uint8_t channel_index; - - channel_index = get_index_from_id(channelid); - - if (channel_index >= CONF_MAX_USED_CHANNEL_NUM) { - /* Return for now */ - return; - } - - dma_channels[channel_index].handler = handler; - if (event & DMA_TRANSFER_ERROR) { - dma_register_callback(&dma_channels[channel_index].resource, dma_handler, DMA_CALLBACK_TRANSFER_ERROR); - } - if (event & DMA_TRANSFER_COMPLETE) { - dma_register_callback(&dma_channels[channel_index].resource, dma_handler, DMA_CALLBACK_TRANSFER_DONE); - } - - /* Set interrupt vector if someone have removed it */ - NVIC_SetVector(DMAC_IRQn, (uint32_t)DMAC_Handler); - /* Enable interrupt */ - NVIC_EnableIRQ(DMAC_IRQn); -} - -/** Frees an allocated DMA channel - * - * Frees an already allocated DMA channel with specified channel id - * @param[in] channelid Channel id of DMA channel to be disabled - * @return zero if success - */ -int dma_channel_free(int channelid) -{ - /* Sanity check arguments */ - MBED_ASSERT(channelid < CONF_MAX_USED_CHANNEL_NUM); - - uint8_t channel_index; - - channel_index = get_index_from_id(channelid); - - if (STATUS_OK == dma_free(&dma_channels[channel_index].resource)) { - dma_channels[channel_index].status = DMA_NOT_USED; - dma_channels[channel_index].resource.descriptor = NULL; - return 0; - } else { - /* Return invalid value for now */ - return -1; - } -} - -