mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 08:36:24 +08:00
kinetis:Replace DMA
Kinetis:DMAMUX use hex in mask
This commit is contained in:
committed by
Xiang Xiao
parent
3439c40044
commit
78bf264af0
@@ -751,7 +751,7 @@ config KINETIS_FTFL
|
||||
---help---
|
||||
Support FLASH
|
||||
|
||||
config KINETIS_DMA
|
||||
config KINETIS_EDMA
|
||||
bool "DMA"
|
||||
default n
|
||||
depends on KINETIS_HAVE_DMA
|
||||
@@ -1114,6 +1114,96 @@ config KINETIS_SD4BIT_FREQ
|
||||
endif
|
||||
endmenu # Kinetis SDHC Configuration
|
||||
|
||||
menu "eDMA Configuration"
|
||||
depends on KINETIS_EDMA
|
||||
|
||||
config KINETIS_EDMA_NTCD
|
||||
int "Number of transfer descriptors"
|
||||
default 0
|
||||
---help---
|
||||
Number of pre-allocated transfer descriptors. Needed for scatter-
|
||||
gather DMA. Make to be set to zero to disable in-memory TCDs in
|
||||
which case only the TCD channel registers will be used and scatter-
|
||||
will not be supported.
|
||||
|
||||
config KINETIS_EDMA_ELINK
|
||||
bool "Channeling Linking"
|
||||
default n
|
||||
---help---
|
||||
This option enables optional minor or major loop channel linking:
|
||||
|
||||
Minor loop channel linking: As the channel completes the minor
|
||||
loop, this flag enables linking to another channel. The link target
|
||||
channel initiates a channel service request via an internal
|
||||
mechanism that sets the TCDn_CSR[START] bit of the specified
|
||||
channel.
|
||||
|
||||
If minor loop channel linking is disabled, this link mechanism is
|
||||
suppressed in favor of the major loop channel linking.
|
||||
|
||||
Major loop channel linking: As the channel completes the minor
|
||||
loop, this option enables the linking to another channel. The link
|
||||
target channel initiates a channel service request via an internal
|
||||
mechanism that sets the TCDn_CSR[START] bit of the linked channel.
|
||||
|
||||
config KINETIS_EDMA_ERCA
|
||||
bool "Round Robin Channel Arbitration"
|
||||
default n
|
||||
---help---
|
||||
Normally, a fixed priority arbitration is used for channel
|
||||
selection. If this option is selected, round robin arbitration is
|
||||
used for channel selection.
|
||||
|
||||
config KINETIS_EDMA_ERGA
|
||||
bool "Round Robin Group Arbitration"
|
||||
default n
|
||||
---help---
|
||||
Normally, a fixed priority arbitration is used for channel
|
||||
selection among the groups. If this option is selected,
|
||||
round Round robin arbitration is used for selection among
|
||||
the groups.
|
||||
|
||||
config KINETIS_EDMA_HOE
|
||||
bool "Halt On Error"
|
||||
default y
|
||||
---help---
|
||||
Any error causes the HALT bit to set. Subsequently, all service
|
||||
requests are ignored until the HALT bit is cleared.
|
||||
|
||||
config KINETIS_EDMA_CLM
|
||||
bool "Continuous Link Mode"
|
||||
default n
|
||||
---help---
|
||||
By default, A minor loop channel link made to itself goes through
|
||||
channel arbitration before being activated again. If this option is
|
||||
selected, a minor loop channel link made to itself does not go
|
||||
through channel arbitration before being activated again. Upon minor
|
||||
loop completion, the channel activates again if that channel has a
|
||||
minor loop channel link enabled and the link channel is itself. This
|
||||
effectively applies the minor loop offsets and restarts the next
|
||||
minor loop.
|
||||
|
||||
config KINETIS_EDMA_EMLIM
|
||||
bool "Minor Loop Mapping"
|
||||
default n
|
||||
---help---
|
||||
Normally TCD word 2 is a 32-bit NBYTES field. When this option is
|
||||
enabled, TCD word 2 is redefined to include individual enable fields,
|
||||
an offset field, and the NBYTES field. The individual enable fields
|
||||
allow the minor loop offset to be applied to the source address, the
|
||||
destination address, or both. The NBYTES field is reduced when either
|
||||
offset is enabled.
|
||||
|
||||
config KINETIS_EDMA_EDBG
|
||||
bool "Enable Debug"
|
||||
default n
|
||||
---help---
|
||||
When in debug mode, the DMA stalls the start of a new channel. Executing
|
||||
channels are allowed to complete. Channel execution resumes when the
|
||||
system exits debug mode or the EDBG bit is cleared
|
||||
|
||||
endmenu # eDMA Global Configuration
|
||||
|
||||
if KINETIS_USBHS && USBHOST
|
||||
|
||||
menu "USB host controller driver (HCD) options"
|
||||
@@ -1208,42 +1298,42 @@ config KINETIS_UARTFIFOS
|
||||
config KINETIS_UART0_RXDMA
|
||||
bool "UART0 Rx DMA"
|
||||
default n
|
||||
depends on KINETIS_UART0 && KINETIS_DMA
|
||||
depends on KINETIS_UART0 && KINETIS_EDMA
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
config KINETIS_UART1_RXDMA
|
||||
bool "UART1 Rx DMA"
|
||||
default n
|
||||
depends on KINETIS_UART1 && KINETIS_DMA
|
||||
depends on KINETIS_UART1 && KINETIS_EDMA
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
config KINETIS_UART2_RXDMA
|
||||
bool "UART2 Rx DMA"
|
||||
default n
|
||||
depends on KINETIS_UART2 && KINETIS_DMA
|
||||
depends on KINETIS_UART2 && KINETIS_EDMA
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
config KINETIS_UART3_RXDMA
|
||||
bool "UART3 Rx DMA"
|
||||
default n
|
||||
depends on KINETIS_UART3 && KINETIS_DMA
|
||||
depends on KINETIS_UART3 && KINETIS_EDMA
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
config KINETIS_UART4_RXDMA
|
||||
bool "UART4 Rx DMA"
|
||||
default n
|
||||
depends on KINETIS_UART4 && KINETIS_DMA
|
||||
depends on KINETIS_UART4 && KINETIS_EDMA
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
config KINETIS_UART5_RXDMA
|
||||
bool "UART5 Rx DMA"
|
||||
default n
|
||||
depends on KINETIS_UART5 && KINETIS_DMA
|
||||
depends on KINETIS_UART5 && KINETIS_EDMA
|
||||
---help---
|
||||
In high data rate usage, Rx DMA may eliminate Rx overrun errors
|
||||
|
||||
|
||||
@@ -140,8 +140,8 @@ CHIP_CSRCS += kinetis_usbhshost.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_KINETIS_DMA),y)
|
||||
CHIP_CSRCS += kinetis_dma.c kinetis_pindma.c
|
||||
ifeq ($(CONFIG_KINETIS_EDMA),y)
|
||||
CHIP_CSRCS += kinetis_edma.c kinetis_pindma.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PWM),y)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,7 @@
|
||||
/* Channel n Configuration Register */
|
||||
|
||||
#define DMAMUX_CHCFG_SOURCE_SHIFT (0) /* Bits 0-5: DMA Channel Source (slot) */
|
||||
#define DMAMUX_CHCFG_SOURCE_MASK (63 << DMAMUX_CHCFG_SOURCE_SHIFT)
|
||||
#define DMAMUX_CHCFG_SOURCE_MASK (0x3f << DMAMUX_CHCFG_SOURCE_SHIFT)
|
||||
#define DMAMUX_CHCFG_TRIG (1 << 6) /* Bit 6: DMA Channel Trigger Enable */
|
||||
#define DMAMUX_CHCFG_ENBL (1 << 7) /* Bit 7: DMA Channel Enable */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,455 +0,0 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/kinetis/kinetis_dma.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "arm_arch.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
#include "kinetis_config.h"
|
||||
#include "chip.h"
|
||||
#include "kinetis_dma.h"
|
||||
#include "hardware/kinetis_dmamux.h"
|
||||
#include "hardware/kinetis_sim.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DMA_CHN_PER_GROUP
|
||||
# define DMA_CHN_PER_GROUP KINETIS_NDMACH /* Number of channels per group */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct kinetis_dma_ch
|
||||
{
|
||||
bool used;
|
||||
uint8_t ind;
|
||||
uint8_t irq;
|
||||
enum kinetis_dma_direction_e dir;
|
||||
enum kinetis_dma_data_sz_e data_sz;
|
||||
dma_callback_t callback;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct kinetis_dma_ch g_channels[KINETIS_NDMACH];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int kinetis_dmainterrupt_int(int irq, void *context,
|
||||
struct kinetis_dma_ch *ch)
|
||||
{
|
||||
/* Clear bit in the interrupt */
|
||||
|
||||
putreg8(ch->ind, KINETIS_DMA_CINT);
|
||||
|
||||
/* Invoke the callback */
|
||||
|
||||
if (ch->callback)
|
||||
{
|
||||
ch->callback((DMA_HANDLE)&ch, ch->arg, 0);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int kinetis_dmainterrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
uint8_t irq_int = *(uint8_t *)arg;
|
||||
uint32_t regval;
|
||||
regval = getreg32(KINETIS_DMA_INT);
|
||||
|
||||
/* Channel irq_int and irq_int + DMA_CHN_PER_GROUP use the same arg. Check
|
||||
* which one requested an interrupt
|
||||
*/
|
||||
|
||||
if ((regval & (1 << irq_int)) != 0)
|
||||
{
|
||||
kinetis_dmainterrupt_int(irq, context, &g_channels[irq_int]);
|
||||
}
|
||||
|
||||
if ((regval & (1 << (irq_int + DMA_CHN_PER_GROUP))) != 0)
|
||||
{
|
||||
kinetis_dmainterrupt_int(irq, context,
|
||||
&g_channels[irq_int + DMA_CHN_PER_GROUP]);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
size_t kinetis_dmaresidual(DMA_HANDLE handle)
|
||||
{
|
||||
struct kinetis_dma_ch *ch = (struct kinetis_dma_ch *)handle;
|
||||
|
||||
/* Channel Linking Disabled */
|
||||
|
||||
return ((getreg16(KINETIS_DMA_TCD_CITER(ch->ind)) >>
|
||||
DMA_TCD_CITER2_SHIFT) & DMA_TCD_CITER2_MASK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmainitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the DMA subsystem.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void weak_function arm_dma_initialize(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t regval;
|
||||
int ret;
|
||||
|
||||
for (i = KINETIS_NDMACH - 1; i >= 0; i--)
|
||||
{
|
||||
g_channels[i].ind = i;
|
||||
g_channels[i].used = false;
|
||||
g_channels[i].irq = KINETIS_IRQ_FIRST + (i % DMA_CHN_PER_GROUP);
|
||||
|
||||
if (i < DMA_CHN_PER_GROUP)
|
||||
{
|
||||
/* Attach DMA interrupt */
|
||||
|
||||
ret = irq_attach(g_channels[i].irq, kinetis_dmainterrupt,
|
||||
(void *)&g_channels[i].ind);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Enable the IRQ at the NVIC (still disabled at the DMA
|
||||
* controller)
|
||||
*/
|
||||
|
||||
up_enable_irq(g_channels[i].irq);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_channels[i].used = true;
|
||||
g_channels[i + DMA_CHN_PER_GROUP].used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable clocking for DMA */
|
||||
|
||||
regval = getreg32(KINETIS_SIM_SCGC7);
|
||||
regval |= SIM_SCGC7_DMA;
|
||||
putreg32(regval, KINETIS_SIM_SCGC7);
|
||||
|
||||
/* Configure DMA for round robin arbitration */
|
||||
|
||||
regval = 0;
|
||||
regval |= DMA_CR_ERCA | DMA_CR_ERGA;
|
||||
putreg32(regval, KINETIS_DMA_CR);
|
||||
|
||||
/* Enable clocking for the DMA mux */
|
||||
|
||||
regval = getreg32(KINETIS_SIM_SCGC6);
|
||||
regval |= SIM_SCGC6_DMAMUX0;
|
||||
putreg32(regval, KINETIS_SIM_SCGC6);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmachannel
|
||||
*
|
||||
* Description:
|
||||
* Allocate a DMA channel. This function sets aside a DMA channel and
|
||||
* gives the caller exclusive access to the DMA channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, this function returns a non-NULL, void* DMA channel handle.
|
||||
* NULL is returned on any failure. This function can fail only if no DMA
|
||||
* channel is available.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DMA_HANDLE kinetis_dmachannel(uint8_t src, uint32_t per_addr,
|
||||
enum kinetis_dma_data_sz_e per_data_sz,
|
||||
enum kinetis_dma_direction_e dir)
|
||||
{
|
||||
int i;
|
||||
int ch_ind;
|
||||
uint8_t regval8;
|
||||
uint16_t regval16;
|
||||
irqstate_t flags;
|
||||
struct kinetis_dma_ch *ch;
|
||||
|
||||
/* Find available channel */
|
||||
|
||||
ch_ind = -1;
|
||||
flags = enter_critical_section();
|
||||
for (i = 0; i < KINETIS_NDMACH; i++)
|
||||
{
|
||||
if (!g_channels[i].used)
|
||||
{
|
||||
ch_ind = i;
|
||||
g_channels[ch_ind].used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ch_ind == -1)
|
||||
{
|
||||
/* No available channel */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ch = &g_channels[ch_ind];
|
||||
|
||||
/* Copy arguments */
|
||||
|
||||
ch->dir = dir;
|
||||
ch->data_sz = per_data_sz;
|
||||
|
||||
/* DMAMUX Set DMA channel source and enable it */
|
||||
|
||||
regval8 = ((((uint8_t)src) << DMAMUX_CHCFG_SOURCE_SHIFT) &
|
||||
DMAMUX_CHCFG_SOURCE_MASK) | DMAMUX_CHCFG_ENBL;
|
||||
putreg8(regval8, KINETIS_DMAMUX_CHCFG(ch_ind));
|
||||
|
||||
/* DMA Set peripheral address in TCD */
|
||||
|
||||
if (ch->dir == KINETIS_DMA_DIRECTION_PERIPHERAL_TO_MEMORY)
|
||||
{
|
||||
putreg32(per_addr, KINETIS_DMA_TCD_SADDR(ch->ind));
|
||||
putreg16(0, KINETIS_DMA_TCD_SOFF(ch->ind));
|
||||
putreg32(0, KINETIS_DMA_TCD_SLAST(ch->ind));
|
||||
}
|
||||
else if (ch->dir == KINETIS_DMA_DIRECTION_MEMORY_TO_PERIPHERAL)
|
||||
{
|
||||
putreg32(per_addr, KINETIS_DMA_TCD_DADDR(ch->ind));
|
||||
putreg16(0, KINETIS_DMA_TCD_DOFF(ch->ind));
|
||||
putreg32(0, KINETIS_DMA_TCD_DLASTSGA(ch->ind));
|
||||
}
|
||||
else
|
||||
{
|
||||
ch->used = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set data sizes */
|
||||
|
||||
regval16 = (DMA_TCD_ATTR_SSIZE_MASK & ((uint16_t)per_data_sz) <<
|
||||
DMA_TCD_ATTR_SSIZE_SHIFT);
|
||||
regval16 |= (DMA_TCD_ATTR_DSIZE_MASK & ((uint16_t)per_data_sz) <<
|
||||
DMA_TCD_ATTR_DSIZE_SHIFT);
|
||||
putreg16(regval16, KINETIS_DMA_TCD_ATTR(ch->ind));
|
||||
|
||||
/* Set minor loop count */
|
||||
|
||||
putreg32(1 << (uint8_t)per_data_sz, KINETIS_DMA_TCD_NBYTES(ch->ind));
|
||||
return (DMA_HANDLE)ch;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmafree
|
||||
*
|
||||
* Description:
|
||||
* Release a DMA channel. NOTE: The 'handle' used in this argument must
|
||||
* NEVER be used again until kinetis_dmachannel() is called again to
|
||||
* re-gain a valid handle.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kinetis_dmafree(DMA_HANDLE handle)
|
||||
{
|
||||
struct kinetis_dma_ch *ch = (struct kinetis_dma_ch *)handle;
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(handle != NULL);
|
||||
|
||||
/* Disable DMA channel in the dmamux */
|
||||
|
||||
putreg8(0, KINETIS_DMAMUX_CHCFG(ch->ind));
|
||||
|
||||
flags = enter_critical_section();
|
||||
ch->used = false;
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmasetup
|
||||
*
|
||||
* Description:
|
||||
* Configure DMA for one transfer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int kinetis_dmasetup(DMA_HANDLE handle, uint32_t mem_addr, size_t ntransfers,
|
||||
uint16_t control)
|
||||
{
|
||||
struct kinetis_dma_ch *ch = (struct kinetis_dma_ch *)handle;
|
||||
uint16_t regval = 0;
|
||||
uint32_t nbytes;
|
||||
|
||||
if (ntransfers > (DMA_TCD_CITER2_MASK >> DMA_TCD_CITER2_SHIFT))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DEBUGASSERT(handle != NULL);
|
||||
|
||||
nbytes = (uint32_t)ntransfers * (uint32_t)(1 << (uint8_t)ch->data_sz);
|
||||
|
||||
if (ch->dir == KINETIS_DMA_DIRECTION_PERIPHERAL_TO_MEMORY)
|
||||
{
|
||||
putreg32(mem_addr, KINETIS_DMA_TCD_DADDR(ch->ind));
|
||||
putreg16(1 << (uint8_t)ch->data_sz, KINETIS_DMA_TCD_DOFF(ch->ind));
|
||||
putreg32(-nbytes, KINETIS_DMA_TCD_DLASTSGA(ch->ind));
|
||||
}
|
||||
else if (ch->dir == KINETIS_DMA_DIRECTION_MEMORY_TO_PERIPHERAL)
|
||||
{
|
||||
putreg32(mem_addr, KINETIS_DMA_TCD_SADDR(ch->ind));
|
||||
putreg16(1 << (uint8_t)ch->data_sz, KINETIS_DMA_TCD_SOFF(ch->ind));
|
||||
putreg32(-nbytes, KINETIS_DMA_TCD_SLAST(ch->ind));
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set up channel with control word */
|
||||
|
||||
regval = (control & DMA_TCD_CSR_MAJORELINK) ? ch->ind : 0;
|
||||
regval <<= DMA_TCD_CSR_MAJORLINKCH_SHIFT;
|
||||
regval &= DMA_TCD_CSR_MAJORLINKCH_MASK;
|
||||
regval |= (DMA_TCD_CSR_INTMAJOR |
|
||||
(control & (DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_MAJORELINK)));
|
||||
putreg16(regval, KINETIS_DMA_TCD_CSR(ch->ind));
|
||||
|
||||
/* Set major loop count */
|
||||
|
||||
putreg16(ntransfers, KINETIS_DMA_TCD_BITER(ch->ind));
|
||||
putreg16(ntransfers, KINETIS_DMA_TCD_CITER(ch->ind));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmastart
|
||||
*
|
||||
* Description:
|
||||
* Start the DMA transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int kinetis_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
{
|
||||
struct kinetis_dma_ch *ch = (struct kinetis_dma_ch *)handle;
|
||||
|
||||
DEBUGASSERT(handle != NULL);
|
||||
|
||||
ch->callback = callback;
|
||||
ch->arg = arg;
|
||||
|
||||
/* Enable request register for this channel */
|
||||
|
||||
putreg8(ch->ind, KINETIS_DMA_SERQ);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmastop
|
||||
*
|
||||
* Description:
|
||||
* Cancel the DMA. After kinetis_dmastop() is called, the DMA channel is
|
||||
* reset and kinetis_dmasetup() must be called before kinetis_dmastart()
|
||||
* can be called again
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kinetis_dmastop(DMA_HANDLE handle)
|
||||
{
|
||||
struct kinetis_dma_ch *ch = (struct kinetis_dma_ch *)handle;
|
||||
|
||||
DEBUGASSERT(handle != NULL);
|
||||
|
||||
putreg8(ch->ind, KINETIS_DMA_CERQ);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmasample
|
||||
*
|
||||
* Description:
|
||||
* Sample DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void kinetis_dmasample(DMA_HANDLE handle, struct kinetis_dmaregs_s *regs)
|
||||
{
|
||||
DEBUGASSERT(handle != NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmadump
|
||||
*
|
||||
* Description:
|
||||
* Dump previously sampled DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void kinetis_dmadump(DMA_HANDLE handle, const struct kinetis_dmaregs_s *regs,
|
||||
const char *msg)
|
||||
{
|
||||
DEBUGASSERT(handle != NULL);
|
||||
}
|
||||
#endif
|
||||
@@ -1,250 +0,0 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/kinetis/kinetis_dma.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_KINETEIS_KINETEIS_DMA_H
|
||||
#define __ARCH_ARM_SRC_KINETEIS_KINETEIS_DMA_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "hardware/kinetis_dma.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef FAR void *DMA_HANDLE;
|
||||
typedef void (*dma_callback_t)(DMA_HANDLE handle, void *arg, int result);
|
||||
|
||||
/* The following is used for sampling DMA registers when CONFIG DEBUG_DMA is
|
||||
* selected.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
struct kinetis_dmaglobalregs_s
|
||||
{
|
||||
#warning "Missing logic"
|
||||
/* Global Registers */
|
||||
};
|
||||
|
||||
struct kinetis_dmachanregs_s
|
||||
{
|
||||
#warning "Missing logic"
|
||||
/* Channel Registers */
|
||||
};
|
||||
|
||||
struct kinetis_dmaregs_s
|
||||
{
|
||||
/* Global Registers */
|
||||
|
||||
struct kinetis_dmaglobalregs_s gbl;
|
||||
|
||||
/* Channel Registers */
|
||||
|
||||
struct kinetis_dmachanregs_s ch;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum kinetis_dma_direction_e
|
||||
{
|
||||
KINETIS_DMA_DIRECTION_PERIPHERAL_TO_MEMORY,
|
||||
KINETIS_DMA_DIRECTION_MEMORY_TO_PERIPHERAL
|
||||
};
|
||||
|
||||
/* Kinetis data transfer size */
|
||||
|
||||
enum kinetis_dma_data_sz_e
|
||||
{
|
||||
KINETIS_DMA_DATA_SZ_8BIT = 0,
|
||||
KINETIS_DMA_DATA_SZ_16BIT = 1,
|
||||
KINETIS_DMA_DATA_SZ_32BIT = 2,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmainitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the GPDMA subsystem.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kinetis_dmainitialize(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmachannel
|
||||
*
|
||||
* Description:
|
||||
* Allocate a DMA channel. This function sets aside a DMA channel and
|
||||
* gives the caller exclusive access to the DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* src - DMA request source
|
||||
* per_addr - Address of the peripheral data
|
||||
* per_data_sz - Peripheral data size (register size). Note that if this
|
||||
* does not agree with the peripheral register size, DMA
|
||||
* transfers will silently fail during operation.
|
||||
* dir - transfer direction
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, this function returns a non-NULL, void* DMA channel handle.
|
||||
* NULL is returned on any failure. This function can fail only if no DMA
|
||||
* channel is available.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DMA_HANDLE kinetis_dmachannel(uint8_t src,
|
||||
uint32_t per_addr,
|
||||
enum kinetis_dma_data_sz_e per_data_sz,
|
||||
enum kinetis_dma_direction_e dir);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmafree
|
||||
*
|
||||
* Description:
|
||||
* Release a DMA channel. NOTE: The 'handle' used in this argument must
|
||||
* NEVER be used again until kinetis_dmachannel() is called again to re-
|
||||
* gain a valid handle.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kinetis_dmafree(DMA_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmasetup
|
||||
*
|
||||
* Description:
|
||||
* Configure DMA for one transfer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mem_addr - Memory address
|
||||
* ntransfers - Number of transfers. Must be 0<= ntransfers <= 0x7FFF
|
||||
* control - Channel control configuration
|
||||
*
|
||||
* Returned Value:
|
||||
* result: 0 if ok, negative else
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int kinetis_dmasetup(DMA_HANDLE handle, uint32_t mem_addr,
|
||||
size_t ntransfers, uint16_t control);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmastart
|
||||
*
|
||||
* Description:
|
||||
* Start the DMA transfer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int kinetis_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmastop
|
||||
*
|
||||
* Description:
|
||||
* Cancel the DMA. After kinetis_dmastop() is called, the DMA channel is
|
||||
* reset and kinetis_dmasetup() must be called before kinetis_dmastart()
|
||||
* can be called again
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kinetis_dmastop(DMA_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmaresidual
|
||||
*
|
||||
* Description:
|
||||
* Returns the number of transfers left
|
||||
*
|
||||
* Returned Value:
|
||||
* Residual transfers
|
||||
****************************************************************************/
|
||||
|
||||
size_t kinetis_dmaresidual(DMA_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmasample
|
||||
*
|
||||
* Description:
|
||||
* Sample DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void kinetis_dmasample(DMA_HANDLE handle, struct kinetis_dmaregs_s *regs);
|
||||
#else
|
||||
# define kinetis_dmasample(handle,regs)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmadump
|
||||
*
|
||||
* Description:
|
||||
* Dump previously sampled DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void kinetis_dmadump(DMA_HANDLE handle, const struct kinetis_dmaregs_s *regs,
|
||||
const char *msg);
|
||||
#else
|
||||
# define kinetis_dmadump(handle,regs,msg)
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_ARM_SRC_KINETEIS_KINETEIS_DMA_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,455 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/kinetis/kinetis_edma.h
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* This file was leveraged from the NuttX i.MXRT port.
|
||||
* Portions of that eDMA logic derived from NXP sample code which has
|
||||
* a compatible BSD 3-clause license:
|
||||
*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_KINETIS_KINETIS_EDMAC_H
|
||||
#define __ARCH_ARM_SRC_KINETIS_KINETIS_EDMAC_H
|
||||
|
||||
/* General Usage:
|
||||
*
|
||||
* 1. Allocate a DMA channel
|
||||
*
|
||||
* DMACH_HANDLE handle;
|
||||
* handle = edma_dmach_alloc(dmamux, dchpri);
|
||||
*
|
||||
* Where 'dmamux' is the channel DMAMUX configuration register setting and
|
||||
* 'dchpri' is the channel DCHPRIO priority register setting.
|
||||
*
|
||||
* 2. Create the transfer configuration:
|
||||
*
|
||||
* struct kinetis_edma_xfrconfig_s config;
|
||||
* config.saddr = ..;
|
||||
* config.daddr = ..;
|
||||
* etc.
|
||||
*
|
||||
* 3. Setup the transfer in hardware:
|
||||
*
|
||||
* int ret;
|
||||
* ret = kinetis_dmach_xfrsetup(handle, &config);
|
||||
*
|
||||
* 4. If you are setting up a scatter gather DMA
|
||||
* (with CONFIG_KINETIS_EDMA_NTCD > 0), then repeat steps 2 and 3 for
|
||||
* each segment of the transfer.
|
||||
*
|
||||
* 5. Start the DMA:
|
||||
*
|
||||
* ret = kinetis_dmach_start(handle, my_callback_func, priv);
|
||||
*
|
||||
* Where my_callback_func() is called when the DMA completes or an error
|
||||
* occurs. 'priv' represents some internal driver state that will be
|
||||
* provided with the callback.
|
||||
*
|
||||
* 6. If you need to stop the DMA and free resources (such as if a timeout
|
||||
* occurs), then:
|
||||
*
|
||||
* i mxrt_dmach_stop(handle);
|
||||
*
|
||||
* 7. The callback will be received when the DMA completes (or an error
|
||||
* occurs). After that, you may free the DMA channel, or re-use it on
|
||||
* subsequent DMAs.
|
||||
*
|
||||
* kinetis_dmach_free(handle);
|
||||
*
|
||||
* Almost non-invasive debug instrumentation is available. You may call
|
||||
* kinetis_dmasample() to save the current state of the eDMA registers at
|
||||
* any given point in time. At some later, postmortem analysis, you can
|
||||
* dump the content of the buffered registers with kinetis_dmadump().
|
||||
* kinetis_dmasample() is also available for monitoring DMA progress.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hardware/kinetis_edma.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration flags.
|
||||
*
|
||||
* REVISIT: Many missing options that should be represented as flags:
|
||||
* 1. Bandwidth
|
||||
* 2. Source/Destination modulo
|
||||
*/
|
||||
|
||||
#define EDMA_CONFIG_LINKTYPE_SHIFT (0) /* Bits 0-1: Link type */
|
||||
#define EDMA_CONFIG_LINKTYPE_MASK (3 << EDMA_CONFIG_LINKTYPE_SHIFT)
|
||||
# define EDMA_CONFIG_LINKTYPE_LINKNONE (0 << EDMA_CONFIG_LINKTYPE_SHIFT) /* No channel link */
|
||||
# define EDMA_CONFIG_LINKTYPE_MINORLINK (1 << EDMA_CONFIG_LINKTYPE_SHIFT) /* Channel link after each minor loop */
|
||||
# define EDMA_CONFIG_LINKTYPE_MAJORLINK (2 << EDMA_CONFIG_LINKTYPE_SHIFT) /* Channel link when major loop count exhausted */
|
||||
|
||||
#define EDMA_CONFIG_LOOP_SHIFT (2) /* Bits 2: Loop type */
|
||||
#define EDMA_CONFIG_LOOP_MASK (3 << EDMA_CONFIG_LOOP_SHIFT)
|
||||
# define EDMA_CONFIG_LOOPNONE (0 << EDMA_CONFIG_LOOP_SHIFT) /* No looping */
|
||||
# define EDMA_CONFIG_LOOPSRC (1 << EDMA_CONFIG_LOOP_SHIFT) /* Source looping */
|
||||
# define EDMA_CONFIG_LOOPDEST (2 << EDMA_CONFIG_LOOP_SHIFT) /* Dest looping */
|
||||
|
||||
#define EDMA_CONFIG_INTHALF (1 << 3) /* Bits 3: Int on HALF */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef FAR void *DMACH_HANDLE;
|
||||
typedef void (*edma_callback_t)(DMACH_HANDLE handle,
|
||||
void *arg, bool done, int result);
|
||||
|
||||
/* eDMA transfer type */
|
||||
|
||||
enum kinetis_edma_xfrtype_e
|
||||
{
|
||||
EDMA_MEM2MEM = 0, /* Transfer from memory to memory */
|
||||
EDMA_PERIPH2MEM, /* Transfer from peripheral to memory */
|
||||
EDMA_MEM2PERIPH, /* Transfer from memory to peripheral */
|
||||
};
|
||||
|
||||
/* eDMA transfer sises */
|
||||
|
||||
enum kinetis_edma_sizes_e
|
||||
{
|
||||
EDMA_8BIT = 0, /* Transfer data size 8 */
|
||||
EDMA_16BIT = 1, /* Transfer data size 16 */
|
||||
EDMA_32BIT = 2, /* Transfer data size 32 */
|
||||
};
|
||||
|
||||
/* This structure holds the source/destination transfer attribute
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
struct kinetis_edma_xfrconfig_s
|
||||
{
|
||||
uint32_t saddr; /* Source data address. */
|
||||
uint32_t daddr; /* Destination data address. */
|
||||
int16_t soff; /* Sign-extended offset for current source address. */
|
||||
int16_t doff; /* Sign-extended offset for current destination address. */
|
||||
uint16_t iter; /* Major loop iteration count. */
|
||||
uint8_t flags; /* See EDMA_CONFIG_* definitions */
|
||||
uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in rdware/. */
|
||||
uint8_t dsize; /* Destination data transfer size. */
|
||||
uint8_t ttype; /* Transfer type (see enum kinetis_edma_xfrtype_e). */
|
||||
#ifdef CONFIG_KINETIS_EDMA_EMLIM
|
||||
uint16_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
#else
|
||||
uint32_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
#endif
|
||||
#ifdef CONFIG_KINETIS_EDMA_ELINK
|
||||
DMACH_HANDLE linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The following is used for sampling DMA registers when CONFIG DEBUG_DMA
|
||||
* is selected
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
struct kinetis_dmaregs_s
|
||||
{
|
||||
uint8_t chan; /* Sampled channel */
|
||||
|
||||
/* eDMA Global Registers */
|
||||
|
||||
uint32_t cr; /* Control */
|
||||
uint32_t es; /* Error Status */
|
||||
uint32_t erq; /* Enable Request */
|
||||
uint32_t req; /* Interrupt Request */
|
||||
uint32_t err; /* Error */
|
||||
uint32_t hrs; /* Hardware Request Status */
|
||||
uint32_t ears; /* Enable Asynchronous Request in Stop */
|
||||
|
||||
/* eDMA Channel registers */
|
||||
|
||||
uint8_t dchpri; /* Channel priority */
|
||||
|
||||
/* eDMA TCD */
|
||||
|
||||
uint32_t saddr; /* TCD Source Address */
|
||||
uint16_t soff; /* TCD Signed Source Address Offset */
|
||||
uint16_t attr; /* TCD Transfer Attributes */
|
||||
uint32_t nbml; /* TCD Signed Minor Loop Offset / Byte Count */
|
||||
uint32_t slast; /* TCD Last Source Address Adjustment */
|
||||
uint32_t daddr; /* TCD Destination Address */
|
||||
uint16_t doff; /* TCD Signed Destination Address Offset */
|
||||
uint16_t citer; /* TCD Current Minor Loop Link, Major Loop Count */
|
||||
uint32_t dlastsga; /* TCD Last Destination Address Adjustment/Scatter Gather Address */
|
||||
uint16_t csr; /* TCD Control and Status */
|
||||
uint16_t biter; /* TCD Beginning Minor Loop Link, Major Loop Count */
|
||||
|
||||
/* DMAMUX registers */
|
||||
|
||||
uint32_t dmamux; /* Channel configuration */
|
||||
};
|
||||
#endif /* CONFIG_DEBUG_DMA */
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmach_alloc
|
||||
*
|
||||
* Allocate a DMA channel. This function sets aside a DMA channel,
|
||||
* initializes the DMAMUX for the channel, then gives the caller exclusive
|
||||
* access to the DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dmamux - DMAMUX configuration see DMAMUX channel configuration register
|
||||
* bit-field definitions in hardware/kinetis_dmamux.h.
|
||||
* Settings include:
|
||||
*
|
||||
* DMAMUX_CHCFG_SOURCE Chip-specific DMA source (required)
|
||||
* DMAMUX_CHCFG_TRIG DMA Channel Trigger Enable (optional)
|
||||
* DMAMUX_CHCFG_ENBL DMA Mux Channel Enable (required)
|
||||
*
|
||||
* A value of zero will disable the DMAMUX channel.
|
||||
* dchpri - DCHPRI channel priority configuration. See DCHPRI channel
|
||||
* configuration register bit-field definitions in
|
||||
* hardware/kinetis_edma.h. Meaningful settings include:
|
||||
*
|
||||
* EDMA_DCHPRI_CHPRI Channel Arbitration Priority
|
||||
* DCHPRI_DPA Disable Preempt Ability
|
||||
* DCHPRI_ECP Enable Channel Preemption
|
||||
*
|
||||
* The power-on default, 0x05, is a reasonable choice.
|
||||
*
|
||||
* Returned Value:
|
||||
* If a DMA channel is available, this function returns a non-NULL, void*
|
||||
* DMA channel handle. NULL is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DMACH_HANDLE kinetis_dmach_alloc(uint8_t dmamux, uint8_t dchpri);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmach_free
|
||||
*
|
||||
* Description:
|
||||
* Release a DMA channel.
|
||||
* NOTE: The 'handle' used in this argument must NEVER be used again
|
||||
* until kinetis_dmach_alloc() is called again to re-gain a valid handle.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kinetis_dmach_free(DMACH_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmach_xfrsetup
|
||||
*
|
||||
* Description:
|
||||
* This function adds the eDMA transfer to the DMA sequence. The request
|
||||
* is setup according to the content of the transfer configuration
|
||||
* structure. For "normal" DMA, kinetis_dmach_xfrsetup is called only
|
||||
* once.
|
||||
* Scatter/gather DMA is accomplished by calling this function repeatedly,
|
||||
* once for each transfer in the sequence. Scatter/gather DMA processing
|
||||
* is enabled automatically when the second transfer configuration is
|
||||
* received.
|
||||
*
|
||||
* This function may be called multiple times to handle multiple,
|
||||
* discontinuous transfers (scatter-gather)
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - DMA channel handle created by kinetis_dmach_alloc()
|
||||
* config - A DMA transfer configuration instance, populated by the
|
||||
* The content of 'config' describes the transfer
|
||||
*
|
||||
* Returned Value
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int kinetis_dmach_xfrsetup(DMACH_HANDLE *handle,
|
||||
const struct kinetis_edma_xfrconfig_s *config);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmach_start
|
||||
*
|
||||
* Description:
|
||||
* Start the DMA transfer by enabling the channel DMA request.
|
||||
* This function should be called after the final call to
|
||||
* kinetis_dmasetup() in order to avoid race conditions.
|
||||
*
|
||||
* At the conclusion of each major DMA loop, a callback to the
|
||||
* user-provided function is made: |For "normal" DMAs, this will
|
||||
* correspond to the DMA DONE interrupt; for scatter gather DMAs, multiple
|
||||
* interrupts will be generated with the final being the DONE interrupt.
|
||||
*
|
||||
* At the conclusion of the DMA, the DMA channel is reset, all TCDs are
|
||||
* freed, and the callback function is called with the the success/fail
|
||||
* result of the DMA.
|
||||
*
|
||||
* NOTE:
|
||||
* On Rx DMAs (peripheral-to-memory or memory-to-memory), it is necessary
|
||||
* to invalidate the destination memory. That is not done automatically
|
||||
* by the DMA module. Invalidation of the destination memory regions is
|
||||
* the responsibility of the caller.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - DMA channel handle created by kinetis_dmach_alloc()
|
||||
* callback - The callback to be invoked when the DMA is completes or is
|
||||
* aborted.
|
||||
* arg - An argument that accompanies the callback
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int kinetis_dmach_start(DMACH_HANDLE handle,
|
||||
edma_callback_t callback, void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmach_stop
|
||||
*
|
||||
* Description:
|
||||
* Cancel the DMA. After kinetis_dmach_stop() is called, the DMA channel
|
||||
* is reset, all TCDs are freed, and kinetis_dmarx/txsetup() must be called
|
||||
* before kinetis_dmach_start() can be called again
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - DMA channel handle created by kinetis_dmach_alloc()
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kinetis_dmach_stop(DMACH_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmach_getcount
|
||||
*
|
||||
* Description:
|
||||
* This function checks the TCD (Task Control Descriptor) status for a
|
||||
* specified eDMA channel and returns the the number of major loop counts
|
||||
* that have not finished.
|
||||
*
|
||||
* NOTES:
|
||||
* 1. This function can only be used to get unfinished major loop count of
|
||||
* transfer without the next TCD, or it might be inaccuracy.
|
||||
* 2. The unfinished/remaining transfer bytes cannot be obtained directly
|
||||
* from registers while the channel is running.
|
||||
*
|
||||
* Because to calculate the remaining bytes, the initial NBYTES configured
|
||||
* in DMA_TCDn_NBYTES_MLNO register is needed while the eDMA IP does not
|
||||
* support getting it while a channel is active. In another words, the
|
||||
* NBYTES value reading is always the actual (decrementing) NBYTES value
|
||||
* the dma_engine is working with while a channel is running.
|
||||
* Consequently, to get the remaining transfer bytes, a software-saved
|
||||
* initial value of NBYTES (for example copied before enabling the channel)
|
||||
* is needed. The formula to calculate it is shown below:
|
||||
*
|
||||
* RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured)
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - DMA channel handle created by kinetis_dmach_alloc()
|
||||
*
|
||||
* Returned Value:
|
||||
* Major loop count which has not been transferred yet for the current TCD.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
unsigned int kinetis_dmach_getcount(DMACH_HANDLE *handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmasample
|
||||
*
|
||||
* Description:
|
||||
* Sample DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void kinetis_dmasample(DMACH_HANDLE handle, struct kinetis_dmaregs_s *regs);
|
||||
#else
|
||||
# define kinetis_dmasample(handle,regs)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kinetis_dmadump
|
||||
*
|
||||
* Description:
|
||||
* Dump previously sampled DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void kinetis_dmadump(const struct kinetis_dmaregs_s *regs, const char *msg);
|
||||
#else
|
||||
# define kinetis_dmadump(handle,regs,msg)
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_ARM_SRC_KINETIS_KINETIS_EDMAC_H */
|
||||
Reference in New Issue
Block a user