rt-thread/bsp/lm3s/driverlib/udma.c

1248 lines
44 KiB
C

//*****************************************************************************
//
// udma.c - Driver for the micro-DMA controller.
//
// Copyright (c) 2007-2009 Luminary Micro, Inc. All rights reserved.
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 4694 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************
//*****************************************************************************
//
//! \addtogroup udma_api
//! @{
//
//*****************************************************************************
#include "inc/hw_types.h"
#include "inc/hw_udma.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h"
#include "driverlib/udma.h"
//*****************************************************************************
//
//! Enables the uDMA controller for use.
//!
//! This function enables the uDMA controller. The uDMA controller must be
//! enabled before it can be configured and used.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAEnable(void)
{
//
// Set the master enable bit in the config register.
//
HWREG(UDMA_CFG) = UDMA_CFG_MASTEN;
}
//*****************************************************************************
//
//! Disables the uDMA controller for use.
//!
//! This function disables the uDMA controller. Once disabled, the uDMA
//! controller will not operate until re-enabled with uDMAEnable().
//!
//! \return None.
//
//*****************************************************************************
void
uDMADisable(void)
{
//
// Clear the master enable bit in the config register.
//
HWREG(UDMA_CFG) = 0;
}
//*****************************************************************************
//
//! Gets the uDMA error status.
//!
//! This function returns the uDMA error status. It should be called from
//! within the uDMA error interrupt handler to determine if a uDMA error
//! occurred.
//!
//! \return Returns non-zero if a uDMA error is pending.
//
//*****************************************************************************
unsigned long
uDMAErrorStatusGet(void)
{
//
// Return the uDMA error status.
//
return(HWREG(UDMA_ERRCLR));
}
//*****************************************************************************
//
//! Clears the uDMA error interrupt.
//!
//! This function clears a pending uDMA error interrupt. It should be called
//! from within the uDMA error interrupt handler to clear the interrupt.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAErrorStatusClear(void)
{
//
// Clear the uDMA error interrupt.
//
HWREG(UDMA_ERRCLR) = 1;
}
//*****************************************************************************
//
//! Enables a uDMA channel for operation.
//!
//! \param ulChannel is the channel number to enable.
//!
//! This function enables a specific uDMA channel for use. This function must
//! be used to enable a channel before it can be used to perform a uDMA
//! transfer.
//!
//! When a uDMA transfer is completed, the channel will be automatically
//! disabled by the uDMA controller. Therefore, this function should be called
//! prior to starting up any new transfer.
//!
//! The \e ulChannel parameter must be one of the following:
//!
//! - \b UDMA_CHANNEL_UART0RX for UART 0 receive channel
//! - \b UDMA_CHANNEL_UART0TX for UART 0 transmit channel
//! - \b UDMA_CHANNEL_UART1RX for UART 1 receive channel
//! - \b UDMA_CHANNEL_UART1TX for UART 1 transmit channel
//! - \b UDMA_CHANNEL_SSI0RX for SSI 0 receive channel
//! - \b UDMA_CHANNEL_SSI0TX for SSI 0 transmit channel
//! - \b UDMA_CHANNEL_SSI1RX for SSI 1 receive channel
//! - \b UDMA_CHANNEL_SSI1TX for SSI 1 transmit channel
//! - \b UDMA_CHANNEL_SW for the software dedicated uDMA channel
//!
//! And for microcontrollers that have a USB peripheral:
//!
//! - \b UDMA_CHANNEL_USBEP1RX for USB endpoint 1 receive
//! - \b UDMA_CHANNEL_USBEP1TX for USB endpoint 1 transmit
//! - \b UDMA_CHANNEL_USBEP2RX for USB endpoint 2 receive
//! - \b UDMA_CHANNEL_USBEP2TX for USB endpoint 2 transmit
//! - \b UDMA_CHANNEL_USBEP3RX for USB endpoint 3 receive
//! - \b UDMA_CHANNEL_USBEP3TX for USB endpoint 3 transmit
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelEnable(unsigned long ulChannel)
{
//
// Check the arguments.
//
ASSERT(ulChannel < 32);
//
// Set the bit for this channel in the enable set register.
//
HWREG(UDMA_ENASET) = 1 << ulChannel;
}
//*****************************************************************************
//
//! Disables a uDMA channel for operation.
//!
//! \param ulChannel is the channel number to disable.
//!
//! This function disables a specific uDMA channel. Once disabled, a channel
//! will not respond to uDMA transfer requests until re-enabled via
//! uDMAChannelEnable().
//!
//! The \e ulChannel parameter must be one of the following:
//!
//! - \b UDMA_CHANNEL_UART0RX for UART 0 receive channel
//! - \b UDMA_CHANNEL_UART0TX for UART 0 transmit channel
//! - \b UDMA_CHANNEL_UART1RX for UART 1 receive channel
//! - \b UDMA_CHANNEL_UART1TX for UART 1 transmit channel
//! - \b UDMA_CHANNEL_SSI0RX for SSI 0 receive channel
//! - \b UDMA_CHANNEL_SSI0TX for SSI 0 transmit channel
//! - \b UDMA_CHANNEL_SSI1RX for SSI 1 receive channel
//! - \b UDMA_CHANNEL_SSI1TX for SSI 1 transmit channel
//! - \b UDMA_CHANNEL_SW for the software dedicated uDMA channel
//!
//! And for microcontrollers that have a USB peripheral:
//!
//! - \b UDMA_CHANNEL_USBEP1RX for USB endpoint 1 receive
//! - \b UDMA_CHANNEL_USBEP1TX for USB endpoint 1 transmit
//! - \b UDMA_CHANNEL_USBEP2RX for USB endpoint 2 receive
//! - \b UDMA_CHANNEL_USBEP2TX for USB endpoint 2 transmit
//! - \b UDMA_CHANNEL_USBEP3RX for USB endpoint 3 receive
//! - \b UDMA_CHANNEL_USBEP3TX for USB endpoint 3 transmit
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelDisable(unsigned long ulChannel)
{
//
// Check the arguments.
//
ASSERT(ulChannel < 32);
//
// Set the bit for this channel in the enable clear register.
//
HWREG(UDMA_ENACLR) = 1 << ulChannel;
}
//*****************************************************************************
//
//! Checks if a uDMA channel is enabled for operation.
//!
//! \param ulChannel is the channel number to check.
//!
//! This function checks to see if a specific uDMA channel is enabled. This
//! can be used to check the status of a transfer, since the channel will
//! be automatically disabled at the end of a transfer.
//!
//! The \e ulChannel parameter must be one of the following:
//!
//! - \b UDMA_CHANNEL_UART0RX for UART 0 receive channel
//! - \b UDMA_CHANNEL_UART0TX for UART 0 transmit channel
//! - \b UDMA_CHANNEL_UART1RX for UART 1 receive channel
//! - \b UDMA_CHANNEL_UART1TX for UART 1 transmit channel
//! - \b UDMA_CHANNEL_SSI0RX for SSI 0 receive channel
//! - \b UDMA_CHANNEL_SSI0TX for SSI 0 transmit channel
//! - \b UDMA_CHANNEL_SSI1RX for SSI 1 receive channel
//! - \b UDMA_CHANNEL_SSI1TX for SSI 1 transmit channel
//! - \b UDMA_CHANNEL_SW for the software dedicated uDMA channel
//!
//! And for microcontrollers that have a USB peripheral:
//!
//! - \b UDMA_CHANNEL_USBEP1RX for USB endpoint 1 receive
//! - \b UDMA_CHANNEL_USBEP1TX for USB endpoint 1 transmit
//! - \b UDMA_CHANNEL_USBEP2RX for USB endpoint 2 receive
//! - \b UDMA_CHANNEL_USBEP2TX for USB endpoint 2 transmit
//! - \b UDMA_CHANNEL_USBEP3RX for USB endpoint 3 receive
//! - \b UDMA_CHANNEL_USBEP3TX for USB endpoint 3 transmit
//!
//! \return Returns \b true if the channel is enabled, \b false if disabled.
//
//*****************************************************************************
tBoolean
uDMAChannelIsEnabled(unsigned long ulChannel)
{
//
// Check the arguments.
//
ASSERT(ulChannel < 32);
//
// AND the specified channel bit with the enable register, and return the
// result.
//
return((HWREG(UDMA_ENASET) & (1 << ulChannel)) ? true : false);
}
//*****************************************************************************
//
//! Sets the base address for the channel control table.
//!
//! \param pControlTable is a pointer to the 1024 byte aligned base address
//! of the uDMA channel control table.
//!
//! This function sets the base address of the channel control table. This
//! table resides in system memory and holds control information for each uDMA
//! channel. The table must be aligned on a 1024 byte boundary. The base
//! address must be set before any of the channel functions can be used.
//!
//! The size of the channel control table depends on the number of uDMA
//! channels, and which transfer modes are used. Refer to the introductory
//! text and the microcontroller datasheet for more information about the
//! channel control table.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAControlBaseSet(void *pControlTable)
{
//
// Check the arguments.
//
ASSERT(((unsigned long)pControlTable & ~0x3FF) ==
(unsigned long)pControlTable);
ASSERT((unsigned long)pControlTable >= 0x20000000);
//
// Program the base address into the register.
//
HWREG(UDMA_CTLBASE) = (unsigned long)pControlTable;
}
//*****************************************************************************
//
//! Gets the base address for the channel control table.
//!
//! This function gets the base address of the channel control table. This
//! table resides in system memory and holds control information for each uDMA
//! channel.
//!
//! \return Returns a pointer to the base address of the channel control table.
//
//*****************************************************************************
void *
uDMAControlBaseGet(void)
{
//
// Read the current value of the control base register, and return it to
// the caller.
//
return((void *)HWREG(UDMA_CTLBASE));
}
//*****************************************************************************
//
//! Requests a uDMA channel to start a transfer.
//!
//! \param ulChannel is the channel number on which to request a uDMA transfer.
//!
//! This function allows software to request a uDMA channel to begin a
//! transfer. This could be used for performing a memory to memory transfer,
//! or if for some reason a transfer needs to be initiated by software instead
//! of the peripheral associated with that channel.
//!
//! The \e ulChannel parameter must be one of the following:
//!
//! - \b UDMA_CHANNEL_UART0RX for UART 0 receive channel
//! - \b UDMA_CHANNEL_UART0TX for UART 0 transmit channel
//! - \b UDMA_CHANNEL_UART1RX for UART 1 receive channel
//! - \b UDMA_CHANNEL_UART1TX for UART 1 transmit channel
//! - \b UDMA_CHANNEL_SSI0RX for SSI 0 receive channel
//! - \b UDMA_CHANNEL_SSI0TX for SSI 0 transmit channel
//! - \b UDMA_CHANNEL_SSI1RX for SSI 1 receive channel
//! - \b UDMA_CHANNEL_SSI1TX for SSI 1 transmit channel
//! - \b UDMA_CHANNEL_SW for the software dedicated uDMA channel
//!
//! And for microcontrollers that have a USB peripheral:
//!
//! - \b UDMA_CHANNEL_USBEP1RX for USB endpoint 1 receive
//! - \b UDMA_CHANNEL_USBEP1TX for USB endpoint 1 transmit
//! - \b UDMA_CHANNEL_USBEP2RX for USB endpoint 2 receive
//! - \b UDMA_CHANNEL_USBEP2TX for USB endpoint 2 transmit
//! - \b UDMA_CHANNEL_USBEP3RX for USB endpoint 3 receive
//! - \b UDMA_CHANNEL_USBEP3TX for USB endpoint 3 transmit
//!
//! \note If the channel is \b UDMA_CHANNEL_SW and interrupts are used, then
//! the completion will be signaled on the uDMA dedicated interrupt. If a
//! peripheral channel is used, then the completion will be signaled on the
//! peripheral's interrupt.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelRequest(unsigned long ulChannel)
{
//
// Check the arguments.
//
ASSERT(ulChannel < 32);
//
// Set the bit for this channel in the software uDMA request register.
//
HWREG(UDMA_SWREQ) = 1 << ulChannel;
}
//*****************************************************************************
//
//! Enables attributes of a uDMA channel.
//!
//! \param ulChannel is the channel to configure.
//! \param ulAttr is a combination of attributes for the channel.
//!
//! The \e ulChannel parameter must be one of the following:
//!
//! - \b UDMA_CHANNEL_UART0RX for UART 0 receive channel
//! - \b UDMA_CHANNEL_UART0TX for UART 0 transmit channel
//! - \b UDMA_CHANNEL_UART1RX for UART 1 receive channel
//! - \b UDMA_CHANNEL_UART1TX for UART 1 transmit channel
//! - \b UDMA_CHANNEL_SSI0RX for SSI 0 receive channel
//! - \b UDMA_CHANNEL_SSI0TX for SSI 0 transmit channel
//! - \b UDMA_CHANNEL_SSI1RX for SSI 1 receive channel
//! - \b UDMA_CHANNEL_SSI1TX for SSI 1 transmit channel
//! - \b UDMA_CHANNEL_SW for the software dedicated uDMA channel
//!
//! And for microcontrollers that have a USB peripheral:
//!
//! - \b UDMA_CHANNEL_USBEP1RX for USB endpoint 1 receive
//! - \b UDMA_CHANNEL_USBEP1TX for USB endpoint 1 transmit
//! - \b UDMA_CHANNEL_USBEP2RX for USB endpoint 2 receive
//! - \b UDMA_CHANNEL_USBEP2TX for USB endpoint 2 transmit
//! - \b UDMA_CHANNEL_USBEP3RX for USB endpoint 3 receive
//! - \b UDMA_CHANNEL_USBEP3TX for USB endpoint 3 transmit
//!
//! The \e ulAttr parameter is the logical OR of any of the following:
//!
//! - \b UDMA_ATTR_USEBURST is used to restrict transfers to use only a burst
//! mode.
//! - \b UDMA_ATTR_ALTSELECT is used to select the alternate control structure
//! for this channel.
//! - \b UDMA_ATTR_HIGH_PRIORITY is used to set this channel to high priority.
//! - \b UDMA_ATTR_REQMASK is used to mask the hardware request signal from the
//! peripheral for this channel.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelAttributeEnable(unsigned long ulChannel, unsigned long ulAttr)
{
//
// Check the arguments.
//
ASSERT(ulChannel < 32);
ASSERT((ulAttr & ~(UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK)) == 0);
//
// Set the useburst bit for this channel if set in ulConfig.
//
if(ulAttr & UDMA_ATTR_USEBURST)
{
HWREG(UDMA_USEBURSTSET) = 1 << ulChannel;
}
//
// Set the alternate control select bit for this channel,
// if set in ulConfig.
//
if(ulAttr & UDMA_ATTR_ALTSELECT)
{
HWREG(UDMA_ALTSET) = 1 << ulChannel;
}
//
// Set the high priority bit for this channel, if set in ulConfig.
//
if(ulAttr & UDMA_ATTR_HIGH_PRIORITY)
{
HWREG(UDMA_PRIOSET) = 1 << ulChannel;
}
//
// Set the request mask bit for this channel, if set in ulConfig.
//
if(ulAttr & UDMA_ATTR_REQMASK)
{
HWREG(UDMA_REQMASKSET) = 1 << ulChannel;
}
}
//*****************************************************************************
//
//! Disables attributes of a uDMA channel.
//!
//! \param ulChannel is the channel to configure.
//! \param ulAttr is a combination of attributes for the channel.
//!
//! This function is used to disable attributes of a uDMA channel.
//!
//! The \e ulChannel parameter must be one of the following:
//!
//! - \b UDMA_CHANNEL_UART0RX for UART 0 receive channel
//! - \b UDMA_CHANNEL_UART0TX for UART 0 transmit channel
//! - \b UDMA_CHANNEL_UART1RX for UART 1 receive channel
//! - \b UDMA_CHANNEL_UART1TX for UART 1 transmit channel
//! - \b UDMA_CHANNEL_SSI0RX for SSI 0 receive channel
//! - \b UDMA_CHANNEL_SSI0TX for SSI 0 transmit channel
//! - \b UDMA_CHANNEL_SSI1RX for SSI 1 receive channel
//! - \b UDMA_CHANNEL_SSI1TX for SSI 1 transmit channel
//! - \b UDMA_CHANNEL_SW for the software dedicated uDMA channel
//!
//! And for microcontrollers that have a USB peripheral:
//!
//! - \b UDMA_CHANNEL_USBEP1RX for USB endpoint 1 receive
//! - \b UDMA_CHANNEL_USBEP1TX for USB endpoint 1 transmit
//! - \b UDMA_CHANNEL_USBEP2RX for USB endpoint 2 receive
//! - \b UDMA_CHANNEL_USBEP2TX for USB endpoint 2 transmit
//! - \b UDMA_CHANNEL_USBEP3RX for USB endpoint 3 receive
//! - \b UDMA_CHANNEL_USBEP3TX for USB endpoint 3 transmit
//!
//! The \e ulAttr parameter is the logical OR of any of the following:
//!
//! - \b UDMA_ATTR_USEBURST is used to restrict transfers to use only a burst
//! mode.
//! - \b UDMA_ATTR_ALTSELECT is used to select the alternate control structure
//! for this channel.
//! - \b UDMA_ATTR_HIGH_PRIORITY is used to set this channel to high priority.
//! - \b UDMA_ATTR_REQMASK is used to mask the hardware request signal from the
//! peripheral for this channel.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelAttributeDisable(unsigned long ulChannel, unsigned long ulAttr)
{
//
// Check the arguments.
//
ASSERT(ulChannel < 32);
ASSERT((ulAttr & ~(UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK)) == 0);
//
// Clear the useburst bit for this channel if set in ulConfig.
//
if(ulAttr & UDMA_ATTR_USEBURST)
{
HWREG(UDMA_USEBURSTCLR) = 1 << ulChannel;
}
//
// Clear the alternate control select bit for this channel, if set in
// ulConfig.
//
if(ulAttr & UDMA_ATTR_ALTSELECT)
{
HWREG(UDMA_ALTCLR) = 1 << ulChannel;
}
//
// Clear the high priority bit for this channel, if set in ulConfig.
//
if(ulAttr & UDMA_ATTR_HIGH_PRIORITY)
{
HWREG(UDMA_PRIOCLR) = 1 << ulChannel;
}
//
// Clear the request mask bit for this channel, if set in ulConfig.
//
if(ulAttr & UDMA_ATTR_REQMASK)
{
HWREG(UDMA_REQMASKCLR) = 1 << ulChannel;
}
}
//*****************************************************************************
//
//! Gets the enabled attributes of a uDMA channel.
//!
//! \param ulChannel is the channel to configure.
//!
//! This function returns a combination of flags representing the attributes of
//! the uDMA channel.
//!
//! The \e ulChannel parameter must be one of the following:
//!
//! - \b UDMA_CHANNEL_UART0RX for UART 0 receive channel
//! - \b UDMA_CHANNEL_UART0TX for UART 0 transmit channel
//! - \b UDMA_CHANNEL_UART1RX for UART 1 receive channel
//! - \b UDMA_CHANNEL_UART1TX for UART 1 transmit channel
//! - \b UDMA_CHANNEL_SSI0RX for SSI 0 receive channel
//! - \b UDMA_CHANNEL_SSI0TX for SSI 0 transmit channel
//! - \b UDMA_CHANNEL_SSI1RX for SSI 1 receive channel
//! - \b UDMA_CHANNEL_SSI1TX for SSI 1 transmit channel
//! - \b UDMA_CHANNEL_SW for the software dedicated uDMA channel
//!
//! And for microcontrollers that have a USB peripheral:
//!
//! - \b UDMA_CHANNEL_USBEP1RX for USB endpoint 1 receive
//! - \b UDMA_CHANNEL_USBEP1TX for USB endpoint 1 transmit
//! - \b UDMA_CHANNEL_USBEP2RX for USB endpoint 2 receive
//! - \b UDMA_CHANNEL_USBEP2TX for USB endpoint 2 transmit
//! - \b UDMA_CHANNEL_USBEP3RX for USB endpoint 3 receive
//! - \b UDMA_CHANNEL_USBEP3TX for USB endpoint 3 transmit
//!
//! \return Returns the logical OR of the attributes of the uDMA channel, which
//! can be any of the following:
//! - \b UDMA_ATTR_USEBURST is used to restrict transfers to use only a burst
//! mode.
//! - \b UDMA_ATTR_ALTSELECT is used to select the alternate control structure
//! for this channel.
//! - \b UDMA_ATTR_HIGH_PRIORITY is used to set this channel to high priority.
//! - \b UDMA_ATTR_REQMASK is used to mask the hardware request signal from the
//! peripheral for this channel.
//
//*****************************************************************************
unsigned long
uDMAChannelAttributeGet(unsigned long ulChannel)
{
unsigned long ulAttr = 0;
//
// Check the arguments.
//
ASSERT(ulChannel < 32);
//
// Check to see if useburst bit is set for this channel.
//
if(HWREG(UDMA_USEBURSTSET) & (1 << ulChannel))
{
ulAttr |= UDMA_ATTR_USEBURST;
}
//
// Check to see if the alternate control bit is set for this channel.
//
if(HWREG(UDMA_ALTSET) & (1 << ulChannel))
{
ulAttr |= UDMA_ATTR_ALTSELECT;
}
//
// Check to see if the high priority bit is set for this channel.
//
if(HWREG(UDMA_PRIOSET) & (1 << ulChannel))
{
ulAttr |= UDMA_ATTR_HIGH_PRIORITY;
}
//
// Check to see if the request mask bit is set for this channel.
//
if(HWREG(UDMA_REQMASKSET) & (1 << ulChannel))
{
ulAttr |= UDMA_ATTR_REQMASK;
}
//
// Return the configuration flags.
//
return(ulAttr);
}
//*****************************************************************************
//
//! Sets the control parameters for a uDMA channel.
//!
//! \param ulChannel is the logical OR of the uDMA channel number with
//! \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT.
//! \param ulControl is logical OR of several control values to set the control
//! parameters for the channel.
//!
//! This function is used to set control parameters for a uDMA transfer. These
//! are typically parameters that are not changed often.
//!
//! The \e ulChannel parameter is one of the choices documented in the
//! uDMAChannelEnable() function. It should be the logical OR of the channel
//! with one of \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT to choose whether
//! the primary or alternate data structure is used.
//!
//! The \e ulControl parameter is the logical OR of five values: the data size,
//! the source address increment, the destination address increment, the
//! arbitration size, and the use burst flag. The choices available for each
//! of these values is described below.
//!
//! Choose the data size from one of \b UDMA_SIZE_8, \b UDMA_SIZE_16, or
//! \b UDMA_SIZE_32 to select a data size of 8, 16, or 32 bits.
//!
//! Choose the source address increment from one of \b UDMA_SRC_INC_8,
//! \b UDMA_SRC_INC_16, \b UDMA_SRC_INC_32, or \b UDMA_SRC_INC_NONE to select
//! an address increment of 8-bit bytes, 16-bit halfwords, 32-bit words, or
//! to select non-incrementing.
//!
//! Choose the destination address increment from one of \b UDMA_DST_INC_8,
//! \b UDMA_DST_INC_16, \b UDMA_DST_INC_32, or \b UDMA_DST_INC_NONE to select
//! an address increment of 8-bit bytes, 16-bit halfwords, 32-bit words, or
//! to select non-incrementing.
//!
//! The arbitration size determines how many items are transferred before
//! the uDMA controller re-arbitrates for the bus. Choose the arbitration size
//! from one of \b UDMA_ARB_1, \b UDMA_ARB_2, \b UDMA_ARB_4, \b UDMA_ARB_8,
//! through \b UDMA_ARB_1024 to select the arbitration size from 1 to 1024
//! items, in powers of 2.
//!
//! The value \b UDMA_NEXT_USEBURST is used to force the channel to only
//! respond to burst requests at the tail end of a scatter-gather transfer.
//!
//! \note The address increment cannot be smaller than the data size.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelControlSet(unsigned long ulChannel, unsigned long ulControl)
{
tDMAControlTable *pCtl;
//
// Check the arguments.
//
ASSERT(ulChannel < 64);
ASSERT(HWREG(UDMA_CTLBASE) != 0);
//
// Get the base address of the control table.
//
pCtl = (tDMAControlTable *)HWREG(UDMA_CTLBASE);
//
// Get the current control word value and mask off the fields to be
// changed, then OR in the new settings.
//
pCtl[ulChannel].ulControl = ((pCtl[ulChannel].ulControl &
~(UDMA_CHCTL_DSTINC_M |
UDMA_CHCTL_DSTSIZE_M |
UDMA_CHCTL_SRCINC_M |
UDMA_CHCTL_SRCSIZE_M |
UDMA_CHCTL_ARBSIZE_M |
UDMA_CHCTL_NXTUSEBURST)) |
ulControl);
}
//*****************************************************************************
//
//! Sets the transfer parameters for a uDMA channel.
//!
//! \param ulChannel is the logical or of the uDMA channel number with either
//! \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT.
//! \param ulMode is the type of uDMA transfer.
//! \param pvSrcAddr is the source address for the transfer.
//! \param pvDstAddr is the destination address for the transfer.
//! \param ulTransferSize is the number of data items to transfer.
//!
//! This function is used to set the parameters for a uDMA transfer. These are
//! typically parameters that are changed often. The function
//! uDMAChannelControlSet() MUST be called at least once for this channel prior
//! to calling this function.
//!
//! The \e ulChannel parameter is one of the choices documented in the
//! uDMAChannelEnable() function. It should be the logical OR of the channel
//! with either \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT to choose whether the
//! primary or alternate data structure is used.
//!
//! The \e ulMode parameter should be one of the following values:
//!
//! - \b UDMA_MODE_STOP stops the uDMA transfer. The controller sets the mode
//! to this value at the end of a transfer.
//! - \b UDMA_MODE_BASIC to perform a basic transfer based on request.
//! - \b UDMA_MODE_AUTO to perform a transfer that will always complete once
//! started even if request is removed.
//! - \b UDMA_MODE_PINGPONG to set up a transfer that switches between the
//! primary and alternate control structures for the channel. This allows
//! use of ping-pong buffering for uDMA transfers.
//! - \b UDMA_MODE_MEM_SCATTER_GATHER to set up a memory scatter-gather
//! transfer.
//! - \b UDMA_MODE_PER_SCATTER_GATHER to set up a peripheral scatter-gather
//! transfer.
//!
//! The \e pvSrcAddr and \e pvDstAddr parameters are pointers to the first
//! location of the data to be transferred. These addresses should be aligned
//! according to the item size. The compiler will take care of this if the
//! pointers are pointing to storage of the appropriate data type.
//!
//! The \e ulTransferSize parameter is the number of data items, not the number
//! of bytes.
//!
//! The two scatter/gather modes, memory and peripheral, are actually different
//! depending on whether the primary or alternate control structure is
//! selected. This function will look for the \b UDMA_PRI_SELECT and
//! \b UDMA_ALT_SELECT flag along with the channel number and will set the
//! scatter/gather mode as appropriate for the primary or alternate control
//! structure.
//!
//! The channel must also be enabled using uDMAChannelEnable() after calling
//! this function. The transfer will not begin until the channel has been set
//! up and enabled. Note that the channel is automatically disabled after the
//! transfer is completed, meaning that uDMAChannelEnable() must be called
//! again after setting up the next transfer.
//!
//! \note Great care must be taken to not modify a channel control structure
//! that is in use or else the results will be unpredictable, including the
//! possibility of undesired data transfers to or from memory or peripherals.
//! For BASIC and AUTO modes, it is safe to make changes when the channel is
//! disabled, or the uDMAChannelModeGet() returns \b UDMA_MODE_STOP. For
//! PINGPONG or one of the SCATTER_GATHER modes, it is safe to modify the
//! primary or alternate control structure only when the other is being used.
//! The uDMAChannelModeGet() function will return \b UDMA_MODE_STOP when a
//! channel control structure is inactive and safe to modify.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelTransferSet(unsigned long ulChannel, unsigned long ulMode,
void *pvSrcAddr, void *pvDstAddr,
unsigned long ulTransferSize)
{
tDMAControlTable *pControlTable;
unsigned long ulControl;
unsigned long ulSize;
unsigned long ulInc;
//
// Check the arguments.
//
ASSERT(ulChannel < 64);
ASSERT(HWREG(UDMA_CTLBASE) != 0);
ASSERT(ulMode <= UDMA_MODE_PER_SCATTER_GATHER);
ASSERT((unsigned long)pvSrcAddr >= 0x20000000);
ASSERT((unsigned long)pvDstAddr >= 0x20000000);
ASSERT((ulTransferSize != 0) && (ulTransferSize <= 1024));
//
// Get the base address of the control table.
//
pControlTable = (tDMAControlTable *)HWREG(UDMA_CTLBASE);
//
// Get the current control word value and mask off the mode and size
// fields.
//
ulControl = (pControlTable[ulChannel].ulControl &
~(UDMA_CHCTL_XFERSIZE_M | UDMA_CHCTL_XFERMODE_M));
//
// Adjust the mode if the alt control structure is selected.
//
if(ulChannel & UDMA_ALT_SELECT)
{
if((ulMode == UDMA_MODE_MEM_SCATTER_GATHER) ||
(ulMode == UDMA_MODE_PER_SCATTER_GATHER))
{
ulMode |= UDMA_MODE_ALT_SELECT;
}
}
//
// Set the transfer size and mode in the control word (but dont write the
// control word yet as it could kick off a transfer).
//
ulControl |= ulMode | ((ulTransferSize - 1) << 4);
//
// Get the data item size from the control word (set previously).
//
ulSize = (ulControl & UDMA_CHCTL_DSTSIZE_M) >> 28;
//
// Convert the transfer size to be in units of bytes. Shift (multiply) to
// get the value in bytes, based on the data item size.
//
ulTransferSize = ulTransferSize << ulSize;
//
// Get the address increment value for the source, from the control word.
//
ulInc = (ulControl & UDMA_CHCTL_SRCINC_M);
//
// Compute the ending source address of the transfer. If the source
// increment is set to none, then the ending address is the same as the
// beginning.
//
if(ulInc != UDMA_SRC_INC_NONE)
{
pvSrcAddr = (void *)((unsigned long)pvSrcAddr + ulTransferSize - 1);
}
//
// Load the source ending address into the control block.
//
pControlTable[ulChannel].pvSrcEndAddr = pvSrcAddr;
//
// Get the address increment value for the destination, from the control
// word.
//
ulInc = (ulControl & UDMA_CHCTL_DSTINC_M);
//
// Compute the ending destination address of the transfer. If the
// destination increment is set to none, then the ending address is the
// same as the beginning.
//
if(ulInc != UDMA_DST_INC_NONE)
{
pvDstAddr = (void *)((unsigned long)pvDstAddr + ulTransferSize - 1);
}
//
// Load the destination ending address into the control block.
//
pControlTable[ulChannel].pvDstEndAddr = pvDstAddr;
//
// Write the new control word value.
//
pControlTable[ulChannel].ulControl = ulControl;
}
//*****************************************************************************
//
//! Gets the current transfer size for a uDMA channel.
//!
//! \param ulChannel is the logical or of the uDMA channel number with either
//! \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT.
//!
//! This function is used to get the uDMA transfer size for a channel. The
//! transfer size is the number of items to transfer, where the size of an item
//! might be 8, 16, or 32 bits. If a partial transfer has already occurred,
//! then the number of remaining items will be returned. If the transfer is
//! complete, then 0 will be returned.
//!
//! The \e ulChannel parameter is one of the choices documented in the
//! uDMAChannelEnable() function. It should be the logical OR of the channel
//! with either \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT to choose whether
//! the primary or alternate data structure is used.
//!
//! \return Returns the number of items remaining to transfer.
//
//*****************************************************************************
unsigned long
uDMAChannelSizeGet(unsigned long ulChannel)
{
tDMAControlTable *pControlTable;
unsigned long ulControl;
//
// Check the arguments.
//
ASSERT(ulChannel < 64);
ASSERT(HWREG(UDMA_CTLBASE) != 0);
//
// Get the base address of the control table.
//
pControlTable = (tDMAControlTable *)HWREG(UDMA_CTLBASE);
//
// Get the current control word value and mask off all but the size field.
//
ulControl = pControlTable[ulChannel].ulControl & UDMA_CHCTL_XFERSIZE_M;
//
// Shift the size field and add one, then return to user.
//
return((ulControl >> 4) + 1);
}
//*****************************************************************************
//
//! Gets the transfer mode for a uDMA channel.
//!
//! \param ulChannel is the logical or of the uDMA channel number with either
//! \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT.
//!
//! This function is used to get the transfer mode for the uDMA channel. It
//! can be used to query the status of a transfer on a channel. When the
//! transfer is complete the mode will be \b UDMA_MODE_STOP.
//!
//! The \e ulChannel parameter is one of the choices documented in the
//! uDMAChannelEnable() function. It should be the logical OR of the channel
//! with either \b UDMA_PRI_SELECT or \b UDMA_ALT_SELECT to choose whether the
//! primary or alternate data structure is used.
//!
//! \return Returns the transfer mode of the specified channel and control
//! structure, which will be one of the following values: \b UDMA_MODE_STOP,
//! \b UDMA_MODE_BASIC, \b UDMA_MODE_AUTO, \b UDMA_MODE_PINGPONG,
//! \b UDMA_MODE_MEM_SCATTER_GATHER, or \b UDMA_MODE_PER_SCATTER_GATHER.
//
//*****************************************************************************
unsigned long
uDMAChannelModeGet(unsigned long ulChannel)
{
tDMAControlTable *pControlTable;
unsigned long ulControl;
//
// Check the arguments.
//
ASSERT(ulChannel < 64);
ASSERT(HWREG(UDMA_CTLBASE) != 0);
//
// Get the base address of the control table.
//
pControlTable = (tDMAControlTable *)HWREG(UDMA_CTLBASE);
//
// Get the current control word value and mask off all but the mode field.
//
ulControl = pControlTable[ulChannel].ulControl & UDMA_CHCTL_XFERMODE_M;
//
// Check if scatter/gather mode, and if so, mask off the alt bit.
//
if(((ulControl & ~UDMA_MODE_ALT_SELECT) == UDMA_MODE_MEM_SCATTER_GATHER) ||
((ulControl & ~UDMA_MODE_ALT_SELECT) == UDMA_MODE_PER_SCATTER_GATHER))
{
ulControl &= ~UDMA_MODE_ALT_SELECT;
}
//
// Return the mode to the caller.
//
return(ulControl);
}
//*****************************************************************************
//
//! Select the secondary peripheral for a set of uDMA channels.
//!
//! \param ulSecPeriphs is the logical or of the uDMA channels for which to
//! use the secondary peripheral, instead of the default peripheral.
//!
//! This function is used to select the secondary peripheral assignment for
//! a set of uDMA channels. By selecting the secondary peripheral assignment
//! for a channel, the default peripheral assignment is no longer available
//! for that channel.
//!
//! The parameter \e ulSecPeriphs can be the logical OR of any of the
//! following macros. If one of the macros below is in the list passed
//! to this function, then the secondary peripheral (marked as \b _SEC_)
//! will be selected.
//!
//! - \b UDMA_DEF_USBEP1RX_SEC_UART2RX
//! - \b UDMA_DEF_USBEP1TX_SEC_UART2TX
//! - \b UDMA_DEF_USBEP2RX_SEC_TMR3A
//! - \b UDMA_DEF_USBEP2TX_SEC_TMR3B
//! - \b UDMA_DEF_USBEP3RX_SEC_TMR2A
//! - \b UDMA_DEF_USBEP3TX_SEC_TMR2B
//! - \b UDMA_DEF_ETH0RX_SEC_TMR2A
//! - \b UDMA_DEF_ETH0TX_SEC_TMR2B
//! - \b UDMA_DEF_UART0RX_SEC_UART1RX
//! - \b UDMA_DEF_UART0TX_SEC_UART1TX
//! - \b UDMA_DEF_SSI0RX_SEC_SSI1RX
//! - \b UDMA_DEF_SSI0TX_SEC_SSI1TX
//! - \b UDMA_DEF_RESERVED_SEC_UART2RX
//! - \b UDMA_DEF_RESERVED_SEC_UART2TX
//! - \b UDMA_DEF_ADC00_SEC_TMR2A
//! - \b UDMA_DEF_ADC01_SEC_TMR2B
//! - \b UDMA_DEF_ADC02_SEC_RESERVED
//! - \b UDMA_DEF_ADC03_SEC_RESERVED
//! - \b UDMA_DEF_TMR0A_SEC_TMR1A
//! - \b UDMA_DEF_TMR0B_SEC_TMR1B
//! - \b UDMA_DEF_TMR1A_SEC_GPIORX
//! - \b UDMA_DEF_TMR1B_SEC_GPIOTX
//! - \b UDMA_DEF_UART1RX_SEC_RESERVED
//! - \b UDMA_DEF_UART1TX_SEC_RESERVED
//! - \b UDMA_DEF_SSI1RX_SEC_ADC10
//! - \b UDMA_DEF_SSI1TX_SEC_ADC11
//! - \b UDMA_DEF_RESERVED_SEC_ADC12
//! - \b UDMA_DEF_RESERVED_SEC_ADC13
//! - \b UDMA_DEF_I2S0RX_SEC_RESERVED
//! - \b UDMA_DEF_I2S0TX_SEC_RESERVED
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelSelectSecondary(unsigned long ulSecPeriphs)
{
//
// Select the secondary peripheral for the specified channels.
//
HWREG(UDMA_CHALT) |= ulSecPeriphs;
}
//*****************************************************************************
//
//! Select the default peripheral for a set of uDMA channels.
//!
//! \param ulDefPeriphs is the logical or of the uDMA channels for which to
//! use the default peripheral, instead of the secondary peripheral.
//!
//! This function is used to select the default peripheral assignment for
//! a set of uDMA channels.
//!
//! The parameter \e ulDefPeriphs can be the logical OR of any of the
//! following macros. If one of the macros below is in the list passed
//! to this function, then the default peripheral (marked as \b _DEF_)
//! will be selected.
//!
//! - \b UDMA_DEF_USBEP1RX_SEC_UART2RX
//! - \b UDMA_DEF_USBEP1TX_SEC_UART2TX
//! - \b UDMA_DEF_USBEP2RX_SEC_TMR3A
//! - \b UDMA_DEF_USBEP2TX_SEC_TMR3B
//! - \b UDMA_DEF_USBEP3RX_SEC_TMR2A
//! - \b UDMA_DEF_USBEP3TX_SEC_TMR2B
//! - \b UDMA_DEF_ETH0RX_SEC_TMR2A
//! - \b UDMA_DEF_ETH0TX_SEC_TMR2B
//! - \b UDMA_DEF_UART0RX_SEC_UART1RX
//! - \b UDMA_DEF_UART0TX_SEC_UART1TX
//! - \b UDMA_DEF_SSI0RX_SEC_SSI1RX
//! - \b UDMA_DEF_SSI0TX_SEC_SSI1TX
//! - \b UDMA_DEF_RESERVED_SEC_UART2RX
//! - \b UDMA_DEF_RESERVED_SEC_UART2TX
//! - \b UDMA_DEF_ADC00_SEC_TMR2A
//! - \b UDMA_DEF_ADC01_SEC_TMR2B
//! - \b UDMA_DEF_ADC02_SEC_RESERVED
//! - \b UDMA_DEF_ADC03_SEC_RESERVED
//! - \b UDMA_DEF_TMR0A_SEC_TMR1A
//! - \b UDMA_DEF_TMR0B_SEC_TMR1B
//! - \b UDMA_DEF_TMR1A_SEC_GPIORX
//! - \b UDMA_DEF_TMR1B_SEC_GPIOTX
//! - \b UDMA_DEF_UART1RX_SEC_RESERVED
//! - \b UDMA_DEF_UART1TX_SEC_RESERVED
//! - \b UDMA_DEF_SSI1RX_SEC_ADC10
//! - \b UDMA_DEF_SSI1TX_SEC_ADC11
//! - \b UDMA_DEF_RESERVED_SEC_ADC12
//! - \b UDMA_DEF_RESERVED_SEC_ADC13
//! - \b UDMA_DEF_I2S0RX_SEC_RESERVED
//! - \b UDMA_DEF_I2S0TX_SEC_RESERVED
//!
//! \return None.
//
//*****************************************************************************
void
uDMAChannelSelectDefault(unsigned long ulDefPeriphs)
{
//
// Select the default peripheral for the specified channels.
//
HWREG(UDMA_CHALT) &= ~ulDefPeriphs;
}
//*****************************************************************************
//
//! Gets the uDMA controller channel interrupt status.
//!
//! This function is used to get the interrupt status of the uDMA controller.
//! The returned value is a 32-bit bit mask that indicates which channels are
//! requesting an interrupt. This function can be used from within an
//! interrupt handler to determine or confirm which uDMA channel has requested
//! an interrupt.
//!
//! \return Returns a 32-bit mask which indicates requesting uDMA channels.
//! There is a bit for each channel, and a 1 in a bit indicates that channel
//! is requesting an interrupt. Multiple bits can be set.
//
//*****************************************************************************
unsigned long
uDMAIntStatus(void)
{
return(HWREG(UDMA_CHIS));
}
//*****************************************************************************
//
//! Clears uDMA interrupt status.
//!
//! \param ulChanMask is a 32-bit mask with one bit for each uDMA channel.
//!
//! Clears bits in the uDMA interrupt status register according to which bits
//! are set in \e ulChanMask. There is one bit for each channel. If a a bit
//! is set in \e ulChanMask, then that corresponding channel's interrupt
//! status will be cleared (if it was set).
//!
//! \return None.
//
//*****************************************************************************
void
uDMAIntClear(unsigned long ulChanMask)
{
HWREG(UDMA_CHIS) = ulChanMask;
}
//*****************************************************************************
//
//! Registers an interrupt handler for the uDMA controller.
//!
//! \param ulIntChannel identifies which uDMA interrupt is to be registered.
//! \param pfnHandler is a pointer to the function to be called when the
//! interrupt is activated.
//!
//! This sets and enables the handler to be called when the uDMA controller
//! generates an interrupt. The \e ulIntChannel parameter should be one of the
//! following:
//!
//! - \b UDMA_INT_SW to register an interrupt handler to process interrupts
//! from the uDMA software channel (UDMA_CHANNEL_SW)
//! - \b UDMA_INT_ERR to register an interrupt handler to process uDMA error
//! interrupts
//!
//! \sa IntRegister() for important information about registering interrupt
//! handlers.
//!
//! \note The interrupt handler for uDMA is for transfer completion when the
//! channel UDMA_CHANNEL_SW is used, and for error interrupts. The
//! interrupts for each peripheral channel are handled through the individual
//! peripheral interrupt handlers.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAIntRegister(unsigned long ulIntChannel, void (*pfnHandler)(void))
{
//
// Check the arguments.
//
ASSERT(pfnHandler);
ASSERT((ulIntChannel == UDMA_INT_SW) || (ulIntChannel == UDMA_INT_ERR));
//
// Register the interrupt handler.
//
IntRegister(ulIntChannel, pfnHandler);
//
// Enable the memory management fault.
//
IntEnable(ulIntChannel);
}
//*****************************************************************************
//
//! Unregisters an interrupt handler for the uDMA controller.
//!
//! \param ulIntChannel identifies which uDMA interrupt to unregister.
//!
//! This function will disable and clear the handler to be called for the
//! specified uDMA interrupt. The \e ulIntChannel parameter should be one of
//! \b UDMA_INT_SW or \b UDMA_INT_ERR as documented for the function
//! uDMAIntRegister().
//!
//! \sa IntRegister() for important information about registering interrupt
//! handlers.
//!
//! \return None.
//
//*****************************************************************************
void
uDMAIntUnregister(unsigned long ulIntChannel)
{
//
// Disable the interrupt.
//
IntDisable(ulIntChannel);
//
// Unregister the interrupt handler.
//
IntUnregister(ulIntChannel);
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************