357 lines
11 KiB
C
357 lines
11 KiB
C
//###########################################################################
|
|
//
|
|
// FILE: dma.c
|
|
//
|
|
// TITLE: C28x DMA driver.
|
|
//
|
|
//###########################################################################
|
|
// $Copyright:
|
|
// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
|
|
//
|
|
// 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.
|
|
// $
|
|
//###########################################################################
|
|
|
|
#include "dma.h"
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// DMA_configAddresses
|
|
//
|
|
//*****************************************************************************
|
|
void DMA_configAddresses(uint32_t base, const void *destAddr,
|
|
const void *srcAddr)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(DMA_isBaseValid(base));
|
|
|
|
EALLOW;
|
|
|
|
//
|
|
// Set up SOURCE address.
|
|
//
|
|
HWREG(base + DMA_O_SRC_BEG_ADDR_SHADOW) = (uint32_t)srcAddr;
|
|
HWREG(base + DMA_O_SRC_ADDR_SHADOW) = (uint32_t)srcAddr;
|
|
|
|
//
|
|
// Set up DESTINATION address.
|
|
//
|
|
HWREG(base + DMA_O_DST_BEG_ADDR_SHADOW) = (uint32_t)destAddr;
|
|
HWREG(base + DMA_O_DST_ADDR_SHADOW) = (uint32_t)destAddr;
|
|
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// DMA_configBurst
|
|
//
|
|
//*****************************************************************************
|
|
void DMA_configBurst(uint32_t base, uint16_t size, int16_t srcStep,
|
|
int16_t destStep)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(DMA_isBaseValid(base));
|
|
ASSERT((size >= 1U) && (size <= 32U));
|
|
|
|
EALLOW;
|
|
|
|
//
|
|
// Set up BURST registers.
|
|
//
|
|
HWREGH(base + DMA_O_BURST_SIZE) = size - 1U;
|
|
HWREGH(base + DMA_O_SRC_BURST_STEP) = srcStep;
|
|
HWREGH(base + DMA_O_DST_BURST_STEP) = destStep;
|
|
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// DMA_configTransfer
|
|
//
|
|
//*****************************************************************************
|
|
void DMA_configTransfer(uint32_t base, uint32_t transferSize, int16_t srcStep,
|
|
int16_t destStep)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(DMA_isBaseValid(base));
|
|
ASSERT(transferSize <= 0x10000U);
|
|
|
|
EALLOW;
|
|
|
|
//
|
|
// Set up TRANSFER registers.
|
|
//
|
|
HWREGH(base + DMA_O_TRANSFER_SIZE) = (uint16_t)(transferSize - 1U);
|
|
HWREGH(base + DMA_O_SRC_TRANSFER_STEP) = srcStep;
|
|
HWREGH(base + DMA_O_DST_TRANSFER_STEP) = destStep;
|
|
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// DMA_configWrap
|
|
//
|
|
//*****************************************************************************
|
|
void DMA_configWrap(uint32_t base, uint32_t srcWrapSize, int16_t srcStep,
|
|
uint32_t destWrapSize, int16_t destStep)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(DMA_isBaseValid(base));
|
|
ASSERT((srcWrapSize <= 0x10000U) || (destWrapSize <= 0x10000U));
|
|
|
|
EALLOW;
|
|
|
|
//
|
|
// Set up WRAP registers.
|
|
//
|
|
HWREGH(base + DMA_O_SRC_WRAP_SIZE) = (uint16_t)(srcWrapSize - 1U);
|
|
HWREGH(base + DMA_O_SRC_WRAP_STEP) = srcStep;
|
|
|
|
HWREGH(base + DMA_O_DST_WRAP_SIZE) = (uint16_t)(destWrapSize - 1U);
|
|
HWREGH(base + DMA_O_DST_WRAP_STEP) = destStep;
|
|
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// DMA_configMode
|
|
//
|
|
//*****************************************************************************
|
|
void DMA_configMode(uint32_t base, DMA_Trigger trigger, uint32_t config)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(DMA_isBaseValid(base));
|
|
|
|
EALLOW;
|
|
|
|
//
|
|
// Set up trigger selection in the CMA/CLA trigger source selection
|
|
// registers. These are considered part of system control.
|
|
//
|
|
switch(base)
|
|
{
|
|
case DMA_CH1_BASE:
|
|
//
|
|
// Channel 1
|
|
//
|
|
HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) =
|
|
(HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) &
|
|
~((uint32_t)SYSCTL_DMACHSRCSEL1_CH1_M)) |
|
|
((uint32_t)trigger << SYSCTL_DMACHSRCSEL1_CH1_S);
|
|
|
|
//
|
|
// Set peripheral interrupt select bits to the channel number.
|
|
//
|
|
HWREGH(DMA_CH1_BASE + DMA_O_MODE) =
|
|
(HWREGH(DMA_CH1_BASE + DMA_O_MODE) & ~DMA_MODE_PERINTSEL_M) | 1U;
|
|
break;
|
|
|
|
case DMA_CH2_BASE:
|
|
//
|
|
// Channel 2
|
|
//
|
|
HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) =
|
|
(HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) &
|
|
~((uint32_t)SYSCTL_DMACHSRCSEL1_CH2_M)) |
|
|
((uint32_t)trigger << SYSCTL_DMACHSRCSEL1_CH2_S);
|
|
|
|
//
|
|
// Set peripheral interrupt select bits to the channel number.
|
|
//
|
|
HWREGH(DMA_CH2_BASE + DMA_O_MODE) =
|
|
(HWREGH(DMA_CH2_BASE + DMA_O_MODE) & ~DMA_MODE_PERINTSEL_M) | 2U;
|
|
break;
|
|
|
|
case DMA_CH3_BASE:
|
|
//
|
|
// Channel 3
|
|
//
|
|
HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) =
|
|
(HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) &
|
|
~((uint32_t)SYSCTL_DMACHSRCSEL1_CH3_M)) |
|
|
((uint32_t)trigger << SYSCTL_DMACHSRCSEL1_CH3_S);
|
|
|
|
//
|
|
// Set peripheral interrupt select bits to the channel number.
|
|
//
|
|
HWREGH(DMA_CH3_BASE + DMA_O_MODE) =
|
|
(HWREGH(DMA_CH3_BASE + DMA_O_MODE) & ~DMA_MODE_PERINTSEL_M) | 3U;
|
|
break;
|
|
|
|
case DMA_CH4_BASE:
|
|
//
|
|
// Channel 4
|
|
//
|
|
HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) =
|
|
(HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL1) &
|
|
~((uint32_t)SYSCTL_DMACHSRCSEL1_CH4_M)) |
|
|
((uint32_t)trigger << SYSCTL_DMACHSRCSEL1_CH4_S);
|
|
|
|
//
|
|
// Set peripheral interrupt select bits to the channel number.
|
|
//
|
|
HWREGH(DMA_CH4_BASE + DMA_O_MODE) =
|
|
(HWREGH(DMA_CH4_BASE + DMA_O_MODE) & ~DMA_MODE_PERINTSEL_M) | 4U;
|
|
break;
|
|
|
|
case DMA_CH5_BASE:
|
|
//
|
|
// Channel 5
|
|
//
|
|
HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL2) =
|
|
(HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL2) &
|
|
~((uint32_t)SYSCTL_DMACHSRCSEL2_CH5_M)) |
|
|
((uint32_t)trigger << SYSCTL_DMACHSRCSEL2_CH5_S);
|
|
|
|
//
|
|
// Set peripheral interrupt select bits to the channel number.
|
|
//
|
|
HWREGH(DMA_CH5_BASE + DMA_O_MODE) =
|
|
(HWREGH(DMA_CH5_BASE + DMA_O_MODE) & ~DMA_MODE_PERINTSEL_M) | 5U;
|
|
break;
|
|
|
|
case DMA_CH6_BASE:
|
|
//
|
|
// Channel 6
|
|
//
|
|
HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL2) =
|
|
(HWREG(DMACLASRCSEL_BASE + SYSCTL_O_DMACHSRCSEL2) &
|
|
~((uint32_t)SYSCTL_DMACHSRCSEL2_CH6_M)) |
|
|
((uint32_t)trigger << SYSCTL_DMACHSRCSEL2_CH6_S);
|
|
|
|
//
|
|
// Set peripheral interrupt select bits to the channel number.
|
|
//
|
|
HWREGH(DMA_CH6_BASE + DMA_O_MODE) =
|
|
(HWREGH(DMA_CH6_BASE + DMA_O_MODE) & ~DMA_MODE_PERINTSEL_M) | 6U;
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Invalid base.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Write the configuration to the mode register.
|
|
//
|
|
HWREGH(base + DMA_O_MODE) &= ~(DMA_MODE_DATASIZE | DMA_MODE_CONTINUOUS |
|
|
DMA_MODE_ONESHOT);
|
|
HWREGH(base + DMA_O_MODE) |= config;
|
|
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// DMA_configChannel
|
|
//
|
|
//*****************************************************************************
|
|
void DMA_configChannel(uint32_t base, const DMA_ConfigParams *transfParams)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(DMA_isBaseValid(base));
|
|
|
|
//
|
|
// Configure DMA Channel
|
|
//
|
|
DMA_configAddresses(base, (const void *)transfParams->destAddr,
|
|
(const void *)transfParams->srcAddr);
|
|
|
|
//
|
|
// Configure the size of each burst and the address step size
|
|
//
|
|
DMA_configBurst(base, transfParams->burstSize, transfParams->srcBurstStep,
|
|
transfParams->destBurstStep);
|
|
|
|
//
|
|
// Configure the transfer size and the address step that is
|
|
// made after each burst.
|
|
//
|
|
DMA_configTransfer(base, transfParams->transferSize,
|
|
transfParams->srcTransferStep,
|
|
transfParams->destTransferStep);
|
|
|
|
//
|
|
// Configure the DMA channel's wrap settings
|
|
//
|
|
DMA_configWrap(base, transfParams->srcWrapSize, transfParams->srcWrapStep,
|
|
transfParams->destWrapSize, transfParams->destWrapStep);
|
|
|
|
//
|
|
// Configure the DMA channel's trigger and mode
|
|
//
|
|
DMA_configMode(base, transfParams->transferTrigger,
|
|
transfParams->transferMode | transfParams->reinitMode |
|
|
transfParams->configSize);
|
|
|
|
//
|
|
// Enable the selected peripheral trigger to start a DMA transfer
|
|
//
|
|
DMA_enableTrigger(base);
|
|
|
|
if(transfParams->enableInterrupt)
|
|
{
|
|
//
|
|
// Set the channel interrupt mode
|
|
//
|
|
DMA_setInterruptMode(base, transfParams->interruptMode);
|
|
|
|
//
|
|
// Enable the indicated DMA channel interrupt source
|
|
//
|
|
DMA_enableInterrupt(base);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable the indicated DMA channel interrupt source
|
|
//
|
|
DMA_disableInterrupt(base);
|
|
}
|
|
}
|
|
|