knx/source/ti/drivers/dma/UDMACC26XX.h
Nanosonde e51b65f8c2 Squashed 'examples/knx-cc1310/coresdk_cc13xx_cc26xx/' content from commit 0d78d32
git-subtree-dir: examples/knx-cc1310/coresdk_cc13xx_cc26xx
git-subtree-split: 0d78d3280357416a5c0388148cda13717c9ffaa5
2020-10-21 10:00:49 +02:00

439 lines
15 KiB
C

/*
* Copyright (c) 2015-2018, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of Texas Instruments Incorporated 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.
*/
/** ============================================================================
* @file UDMACC26XX.h
*
* @brief UDMACC26XX driver implementation.
*
* # Driver include #
* The UDMACC26XX header file should be included in an application as follows:
* @code
* #include <ti/drivers/dma/UDMACC26XX.h>
* @endcode
*
* # Overview #
* The UDMACC26XX driver currently only supports being used by the SPICC26XXDMA.h. module.
* In other words, the application should never call any of the functions in this file.
*
* # General Behavior #
* This driver is used implicitly by the SPICC26XXDMA.h driver so user should not
* have to interface to this driver from the application.
* The uDMA HW makes use of a control table in RAM which must be 1024 bytes aligned.
* The default base address of this control table is 0x20000400, however this
* can be changed by simply changing UDMACC26XX_CONFIG_BASE.
* The SPICC26XXDMA.h supports SPI0 and SPI1, and uses both TX and RX DMA channels.
* Each control table entry is 16 bytes, so if an application uses both SSI0 and SSI1
* the total RAM usage will be 4*16=64 bytes. If only one SSI module is used
* only 2*16=32 bytes of RAM is used. Please see [Use cases] (@ref USE_CASE) for example.
*
* # Error handling #
* Error handling is handled by the overlying driver which uses the DMA, currently
* this is only SPICC26XXDMA.h
*
* # Power management #
* Power management is handled by the overlying driver which uses the DMA, currently
* this is only SPICC26XXDMA.h
*
* # Supported functions #
* Note that these functions should never be called from the application, they
* are only called from other drivers. They are however included here for completeness:
*
* | API function | Description |
* |------------------------- |----------------------------------------------------------------|
* | UDMACC26XX_open() | Initialize and enable the uDMA HW and set system dependencies. |
* | UDMACC26XX_close() | Disable uUDMA HW and release system dependencies |
*
* @note These functions should not be called by code. These functions are called
* by drivers who're using the DMA.
*
* # Unsupported Functionality #
* No known limitations
*
* # Use Cases @anchor USE_CASE #
* The DMA is only used together with the SPICC26XXDMA.h driver, so the application
* should never call any of the functions in this driver directly.
* The only thing that the application is allowed to modify is the base address
* of the DMA control table in RAM. (Default value is 0x2000_0400)
* Remember it must be 1024 bytes aligned.
* @code
* #define UDMACC26XX_CONFIG_BASE 0x2000_0400
* @endcode
*
* - If only SSI0 is used, this will allocate 2*16=32 RAM bytes at address:\n
* [0x2000_0430-0x2000_044F] = SSI0 RX/TX DMA channels
* - If only SSI1 is used, this will allocate 2*16=32 RAM bytes at address:\n
* [0x2000_0500-0x2000_051F] = SSI1 RX/TX DMA channels
* - If both SSI0 and SSI1 are used, this will allocate 4*16=64 RAM bytes at addresses:\n
* [0x2000_0430-0x2000_044F] = SSI0 RX/TX DMA channels\n
* [0x2000_0500-0x2000_051F] = SSI1 RX/TX DMA channels
*
* # Instrumentation #
* The SPI driver interface produces log statements if instrumentation is
* enabled.
*
* Diagnostics Mask | Log details |
* ---------------- | ----------- |
* Diags_USER1 | basic SPI operations performed |
* Diags_USER2 | detailed SPI operations performed |
*
* ============================================================================
*/
#ifndef ti_drivers_UDMACC26XX__include
#define ti_drivers_UDMACC26XX__include
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(inc/hw_types.h)
#include DeviceFamily_constructPath(driverlib/udma.h)
/**
* @addtogroup DMA_STATUS
* UDMACC26XX_STATUS_* macros are command codes only defined in the
* UDMACC26XX.h driver implementation and need to:
* @code
* #include <ti/drivers/dma/UDMACC26XX.h>
* @endcode
* @{
*/
/* Add DMACC26XX_STATUS_* macros here */
/** @}*/
/**
* @addtogroup DMA_CMD
* UDMACC26XX_CMD_* macros are command codes only defined in the
* UDMACC26XX.h driver implementation and need to:
* @code
* #include <ti/drivers/dma/UDMACC26XX.h>
* @endcode
* @{
*/
/* Add DMACC26XX_CMD_* macros here */
/** @}*/
/*! Base address for the DMA control table, must be 1024 bytes aligned */
#if !defined(UDMACC26XX_CONFIG_BASE) && (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2)
#define UDMACC26XX_CONFIG_BASE 0x20001800
#elif !defined(UDMACC26XX_CONFIG_BASE)
#define UDMACC26XX_CONFIG_BASE 0x20000400
#endif
/*! Make sure DMA control table base address is 1024 bytes aligned */
#if(UDMACC26XX_CONFIG_BASE & 0x3FF)
#error "Base address for DMA control table 'UDMACC26XX_CONFIG_BASE' must be 1024 bytes aligned."
#endif
/*! Compiler specific macros to allocate DMA control table entries */
#if defined(__IAR_SYSTEMS_ICC__)
#define ALLOCATE_CONTROL_TABLE_ENTRY(ENTRY_NAME, CHANNEL_INDEX) \
__no_init static volatile tDMAControlTable ENTRY_NAME @ UDMACC26XX_CONFIG_BASE + CHANNEL_INDEX * sizeof(tDMAControlTable)
#elif defined(__TI_COMPILER_VERSION__)
#define ALLOCATE_CONTROL_TABLE_ENTRY(ENTRY_NAME, CHANNEL_INDEX) \
PRAGMA(LOCATION( ENTRY_NAME , UDMACC26XX_CONFIG_BASE + CHANNEL_INDEX * sizeof(tDMAControlTable) );)\
static volatile tDMAControlTable ENTRY_NAME
#define PRAGMA(x) _Pragma(#x)
#elif defined(__GNUC__)
#define ALLOCATE_CONTROL_TABLE_ENTRY(ENTRY_NAME, CHANNEL_INDEX) \
extern int UDMACC26XX_ ## ENTRY_NAME ## _is_placed; __attribute__ ((section("."#ENTRY_NAME))) static volatile tDMAControlTable ENTRY_NAME = {&UDMACC26XX_ ## ENTRY_NAME ## _is_placed}
#else
#error "don't know how to define ALLOCATE_CONTROL_TABLE_ENTRY for this toolchain"
#endif
/*! Sets the DMA transfer size in number of items */
#define UDMACC26XX_SET_TRANSFER_SIZE(SIZE) (((SIZE - 1) << UDMA_XFER_SIZE_S) & UDMA_XFER_SIZE_M)
/*! Gets the DMA transfer size in number of items*/
#define UDMACC26XX_GET_TRANSFER_SIZE(CONTROL) (((CONTROL & UDMA_XFER_SIZE_M) >> UDMA_XFER_SIZE_S) + 1)
/*!
* @brief UDMACC26XX object
*/
typedef struct UDMACC26XX_Object {
bool isOpen; /*!< Flag for open/close status */
HwiP_Struct hwi; /*!< Embedded Hwi Object */
} UDMACC26XX_Object;
/*!
* @brief UDMACC26XX hardware attributes
*/
typedef struct UDMACC26XX_HWAttrs {
uint32_t baseAddr; /*!< Base adddress for UDMACC26XX */
PowerCC26XX_Resource powerMngrId; /*!< UDMACC26XX Peripheral's power manager ID */
uint8_t intNum; /*!< UDMACC26XX error interrupt number */
/*! @brief UDMACC26XX error interrupt priority.
* intPriority is the DMA peripheral's interrupt priority, as
* defined by the underlying OS. It is passed unmodified to the
* underlying OS's interrupt handler creation code, so you need to
* refer to the OS documentation for usage. If the
* driver uses the ti.dpl interface instead of making OS
* calls directly, then the HwiP port handles the interrupt priority
* in an OS specific way. In the case of the SYS/BIOS port,
* intPriority is passed unmodified to Hwi_create().
*
* The CC26xx uses three of the priority bits,
* meaning ~0 has the same effect as (7 << 5).
*
* (7 << 5) will apply the lowest priority.
*
* (1 << 5) will apply the highest priority.
*
* Setting the priority to 0 is not supported by this driver.
*
* HWI's with priority 0 ignore the HWI dispatcher to support zero-latency interrupts, thus invalidating the critical sections in this driver.
*/
uint8_t intPriority;
} UDMACC26XX_HWAttrs;
/*!
* @brief UDMACC26XX Global configuration
*/
typedef struct UDMACC26XX_Config {
void *object; /*!< Pointer to UDMACC26XX object */
void const *hwAttrs; /*!< Pointer to hardware attribute */
} UDMACC26XX_Config;
/*!
* @brief A handle that is returned from a UDMACC26XX_open() call.
*/
typedef struct UDMACC26XX_Config *UDMACC26XX_Handle;
/* Extern'd hwiIntFxn */
extern void UDMACC26XX_hwiIntFxn(uintptr_t callbacks);
/*!
* @brief Function to initialize the CC26XX DMA driver
*
* The function will set the isOpen flag to false, and should be called prior
* to opening the DMA driver.
*
* @pre Calling context: Hwi, Swi, Task
*
* @return none
*
* @sa UDMACC26XX_open()
*/
__STATIC_INLINE void UDMACC26XX_init(UDMACC26XX_Handle handle)
{
UDMACC26XX_Object *object;
/* Get the pointer to the object */
object = (UDMACC26XX_Object *)(handle->object);
/* mark the module as available */
object->isOpen = false;
}
/*!
* @brief Function to initialize the CC26XX DMA peripheral
*
* The function will set a dependency on the peripheral power domain, i.e. power up the
* module and enable the clock.
* Note this function always uses the first DMA entry in the global UDMACC26XX_config list.
*
* @pre UDMACC26XX_init() has to be called first.
* Calling context: Task
*
* @return UDMACC26XX_Handle on success or NULL if error or if it has been
* already opened
*
* @sa UDMACC26XX_close()
*/
extern UDMACC26XX_Handle UDMACC26XX_open();
/*!
* @internal
* @brief Function to enable a given DMA channel
*
* @pre UDMACC26XX_open() has to be called first.
* Calling context: Hwi, Swi, Task
*
* @param handle A SPI_Handle returned from SPI_open()
*
* @param params A 32-bit bitmask of the channels to enable.
*
* @sa UDMACC26XX_channelDisable
*/
__STATIC_INLINE void UDMACC26XX_channelEnable(UDMACC26XX_Handle handle, uint32_t channelBitMask)
{
UDMACC26XX_HWAttrs const *hwAttrs;
/* Get the pointer to the hwAttrs */
hwAttrs = (UDMACC26XX_HWAttrs *)(handle->hwAttrs);
/* Enable DMA channel */
HWREG(hwAttrs->baseAddr + UDMA_O_SETCHANNELEN) = channelBitMask;
}
/*!
* @internal
* @brief Function to see if a given DMA channel is done.
*
* Will read the request done signal for the give channels
* and return true if all channels are done, otherwise false.
*
* @pre UDMACC26XX_open() has to be called first.
* Calling context: Hwi, Swi, Task
*
* @param handle A SPI_Handle returned from SPI_open()
*
* @param params A 32-bit bitmask of the channels to check for if are done.
*
* @return True if the channels are done, false otherwise.
*
* @sa SPICC26XXDMA_open, UDMACC26XX_channelDisable
*/
__STATIC_INLINE bool UDMACC26XX_channelDone(UDMACC26XX_Handle handle, uint32_t channelBitMask)
{
UDMACC26XX_HWAttrs const *hwAttrs;
/* Get the pointer to the hwAttrs */
hwAttrs = (UDMACC26XX_HWAttrs *)(handle->hwAttrs);
/* Check if REQDONE is set for a specific channel */
return (uDMAIntStatus(hwAttrs->baseAddr) & channelBitMask) ? true : false;
}
/*!
* @internal
* @brief Function to clear a given DMA channel interrupt.
*
* Will clear the DMA interrupt(s) for the given bitmask provided.
*
* @pre UDMACC26XX_open() has to be called first.
* Calling context: Hwi, Swi, Task
*
* @param handle A SPI_Handle returned from SPI_open()
*
* @param params A 32-bit bitmask of the channels to check for if are done.
*
* @param channelBitMask A 32-bit bitmask of the channels to clear interrupts for.
*
* @return none
*/
__STATIC_INLINE void UDMACC26XX_clearInterrupt(UDMACC26XX_Handle handle, uint32_t channelBitMask)
{
UDMACC26XX_HWAttrs const *hwAttrs;
/* Get the pointer to the hwAttrs and object */
hwAttrs = (UDMACC26XX_HWAttrs *)(handle->hwAttrs);
/* Clear UDMA done interrupt */
uDMAIntClear(hwAttrs->baseAddr, channelBitMask);
}
/*!
* @internal
* @brief Function to disable one or more DMA channels.
*
* Will disable the channel(s) for the given bitmask provided.
*
* @pre UDMACC26XX_open() has to be called first.
* Calling context: Hwi, Swi, Task
*
* @param handle A SPI_Handle returned from SPI_open()
*
* @param params A 32-bit bitmask of the channels to disable.
*
* @return none
*
* @sa UDMACC26XX_channelEnable
*/
__STATIC_INLINE void UDMACC26XX_channelDisable(UDMACC26XX_Handle handle, uint32_t channelBitMask)
{
UDMACC26XX_HWAttrs const *hwAttrs = handle->hwAttrs;
HWREG(hwAttrs->baseAddr + UDMA_O_CLEARCHANNELEN) = channelBitMask;
}
/*!
* @internal
* @brief Function to disable a DMA channel's attributes.
*
* Will disable a channel's attributes.
*
* @pre UDMACC26XX_open() has to be called first.
* Calling context: Hwi, Swi, Task
*
* @param handle A UDMACC26XX_Handle returned from UDMACC26XX_open()
*
* @param channelNum the channel to configure.
*
* @param attr Channel attribute to disable.
*
*
* @return none
*
* @sa UDMACC26XX_channelEnable
*/
__STATIC_INLINE void UDMACC26XX_disableAttribute(UDMACC26XX_Handle handle,
uint32_t channelNum, uint32_t attr)
{
UDMACC26XX_HWAttrs const *hwAttrs = (UDMACC26XX_HWAttrs *) handle->hwAttrs;
uDMAChannelAttributeDisable(hwAttrs->baseAddr, channelNum, attr);
}
/*!
* @brief Function to close the DMA driver.
*
* Will disable the DMA hardware, release the power dependency and destruct
* the HWI interrupt.
*
* @pre UDMACC26XX_open() has to be called first.
* Calling context: Task
*
* @param handle A SPI_Handle returned from SPI_open()
*
* @return none
*
* @sa SPICC26XXDMA_open
*/
extern void UDMACC26XX_close(UDMACC26XX_Handle handle);
#ifdef __cplusplus
}
#endif
#endif /* ti_drivers_UDMACC26XX__include */