rt-thread/bsp/synwit/swm341/libraries/SWM341_StdPeriph_Driver/SWM341_dma.c

243 lines
12 KiB
C
Raw Normal View History

/******************************************************************************************************************************************
* : SWM341_dma.c
* : SWM341单片机的DMA功能驱动库
* : http://www.synwit.com.cn/e/tool/gbook/?bid=1
* :
* : V1.0.0 2016130
* :
*
*
*******************************************************************************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
* REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
* FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
* -ECTION WITH THEIR PRODUCTS.
*
* COPYRIGHT 2012 Synwit Technology
*******************************************************************************************************************************************/
#include "SWM341.h"
#include "SWM341_dma.h"
2023-12-12 18:23:12 +08:00
/******************************************************************************************************************************************
* : DMA_CH_Init()
* : DMA通道初始化
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
* DMA_InitStructure * initStruct DMA通道相关设定值的结构体
* :
* :
******************************************************************************************************************************************/
void DMA_CH_Init(uint32_t chn, DMA_InitStructure * initStruct)
{
DMA->EN = 1; //每个通道都有自己独立的开关控制,所以总开关可以是一直开启的
DMA_CH_Close(chn); //关闭后配置
DMA->CH[chn].CR = (initStruct->Mode << DMA_CR_AUTORE_Pos) |
2023-12-12 18:23:12 +08:00
((initStruct->Count ? initStruct->Count - 1 : 0) << DMA_CR_LEN_Pos);
DMA->CH[chn].SRC = initStruct->SrcAddr;
DMA->CH[chn].DST = initStruct->DstAddr;
DMA->CH[chn].AM = (initStruct->SrcAddrInc << DMA_AM_SRCAM_Pos) |
(initStruct->DstAddrInc << DMA_AM_DSTAM_Pos) |
(initStruct->Unit << DMA_AM_SRCBIT_Pos) |
(initStruct->Unit << DMA_AM_DSTBIT_Pos);
switch(initStruct->Handshake & DMA_HS_MSK)
{
case DMA_HS_NO:
DMA->CH[chn].MUX = 0;
break;
case DMA_HS_SRC:
DMA->CH[chn].MUX = ((initStruct->Handshake & 0xF) << DMA_MUX_SRCHSSIG_Pos) | (1 << DMA_MUX_SRCHSEN_Pos);
break;
case DMA_HS_DST:
DMA->CH[chn].MUX = ((initStruct->Handshake & 0xF) << DMA_MUX_DSTHSSIG_Pos) | (1 << DMA_MUX_DSTHSEN_Pos);
break;
case DMA_HS_EXT:
DMA->CH[chn].MUX = ((initStruct->Handshake & 0xF) << DMA_MUX_EXTHSSIG_Pos) | (1 << DMA_MUX_EXTHSEN_Pos);
DMA->CH[chn].CR |= (1 << DMA_CR_STEPOP_Pos);
break;
default:
break;
}
2023-12-12 18:23:12 +08:00
int totalBytes = initStruct->Count * (1 << initStruct->Unit);
if(initStruct->DstAddrInc == 2) // Destination Scatter-Gather Transfer
{
DMA->CH[chn].DSTSGADDR1 = initStruct->DstAddr + totalBytes / 4 * 1;
DMA->CH[chn].DSTSGADDR2 = initStruct->DstAddr + totalBytes / 4 * 2;
DMA->CH[chn].DSTSGADDR3 = initStruct->DstAddr + totalBytes / 4 * 3;
}
if(initStruct->SrcAddrInc == 2) // Source Scatter-Gather Transfer
{
DMA->CH[chn].SRCSGADDR1 = initStruct->SrcAddr + totalBytes / 4 * 1;
DMA->CH[chn].SRCSGADDR2 = initStruct->SrcAddr + totalBytes / 4 * 2;
DMA->CH[chn].SRCSGADDR3 = initStruct->SrcAddr + totalBytes / 4 * 3;
}
DMA->PRI &= ~(1 << chn);
DMA->PRI |= (initStruct->Priority << chn);
2023-12-12 18:23:12 +08:00
DMA->IM |= (1 << chn); // 默认全部关闭
DMA->DSTSGIM |= (3 << (chn * 2));
DMA->SRCSGIM |= (3 << (chn * 2));
DMA->IE |= (1 << chn); // 标志总是可查
DMA->DSTSGIE |= (3 << (chn * 2));
DMA->SRCSGIE |= (3 << (chn * 2));
DMA_CH_INTClr(chn, initStruct->INTEn);
DMA_CH_INTEn(chn, initStruct->INTEn);
2023-12-12 18:23:12 +08:00
if(initStruct->INTEn) NVIC_EnableIRQ(DMA_IRQn);
}
/******************************************************************************************************************************************
* : DMA_CH_Open()
* : DMA通道开启
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
* :
* :
******************************************************************************************************************************************/
void DMA_CH_Open(uint32_t chn)
{
DMA->CH[chn].CR |= (1 << DMA_CR_RXEN_Pos);
}
/******************************************************************************************************************************************
* : DMA_CH_Close()
* : DMA通道关闭
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
* :
* :
******************************************************************************************************************************************/
void DMA_CH_Close(uint32_t chn)
{
DMA->CH[chn].CR &= ~(DMA_CR_TXEN_Msk | DMA_CR_RXEN_Msk);
}
2023-12-12 18:23:12 +08:00
/******************************************************************************************************************************************
* : DMA_CH_SetCount()
* : Unit
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
* uint32_t count Unit 0x100000
* :
* :
******************************************************************************************************************************************/
void DMA_CH_SetCount(uint32_t chn, uint32_t count)
{
DMA->CH[chn].CR &= ~DMA_CR_LEN_Msk;
DMA->CH[chn].CR |= ((count - 1) << DMA_CR_LEN_Pos);
}
/******************************************************************************************************************************************
* : DMA_CH_GetRemaining()
* : Unit
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
* : uint32_t Unit
* :
******************************************************************************************************************************************/
uint32_t DMA_CH_GetRemaining(uint32_t chn)
{
return (DMA->CH[chn].DSTSR & DMA_DSTSR_LEN_Msk);
}
/******************************************************************************************************************************************
* : DMA_CH_SetSrcAddress()
* :
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
* uint32_t address
* :
* :
******************************************************************************************************************************************/
void DMA_CH_SetSrcAddress(uint32_t chn, uint32_t address)
{
DMA->CH[chn].SRC = address;
}
/******************************************************************************************************************************************
* : DMA_CH_SetDstAddress()
* :
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
* uint32_t address
* :
* :
******************************************************************************************************************************************/
void DMA_CH_SetDstAddress(uint32_t chn, uint32_t address)
{
DMA->CH[chn].DST = address;
}
/******************************************************************************************************************************************
* : DMA_CH_INTEn()
2023-12-12 18:23:12 +08:00
* : DMA中断使能
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
2023-12-12 18:23:12 +08:00
* uint32_t it interrupt type DMA_IT_DONEDMA_IT_DSTSG_HALFDMA_IT_DSTSG_DONEDMA_IT_SRCSG_HALF
* DMA_IT_SRCSG_DONE
* :
* :
******************************************************************************************************************************************/
2023-12-12 18:23:12 +08:00
void DMA_CH_INTEn(uint32_t chn, uint32_t it)
{
2023-12-12 18:23:12 +08:00
DMA->IM &= ~(it << chn);
DMA->DSTSGIM &= ~((it >> 8) << (chn * 2));
DMA->SRCSGIM &= ~((it >> 16) << (chn * 2));
}
/******************************************************************************************************************************************
* : DMA_CH_INTDis()
2023-12-12 18:23:12 +08:00
* : DMA中断禁止
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
2023-12-12 18:23:12 +08:00
* uint32_t it interrupt type DMA_IT_DONEDMA_IT_DSTSG_HALFDMA_IT_DSTSG_DONEDMA_IT_SRCSG_HALF
* DMA_IT_SRCSG_DONE
* :
* :
******************************************************************************************************************************************/
2023-12-12 18:23:12 +08:00
void DMA_CH_INTDis(uint32_t chn, uint32_t it)
{
2023-12-12 18:23:12 +08:00
DMA->IM |= (it << chn);
DMA->DSTSGIM |= ((it >> 8) << (chn * 2));
DMA->SRCSGIM |= ((it >> 16) << (chn * 2));
}
/******************************************************************************************************************************************
* : DMA_CH_INTClr()
* : DMA中断标志清除
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
2023-12-12 18:23:12 +08:00
* uint32_t it interrupt type DMA_IT_DONEDMA_IT_DSTSG_HALFDMA_IT_DSTSG_DONEDMA_IT_SRCSG_HALF
* DMA_IT_SRCSG_DONE
* :
* :
******************************************************************************************************************************************/
2023-12-12 18:23:12 +08:00
void DMA_CH_INTClr(uint32_t chn, uint32_t it)
{
2023-12-12 18:23:12 +08:00
DMA->IF = (it << chn);
DMA->DSTSGIF = ((it >> 8) << (chn * 2));
DMA->SRCSGIF = ((it >> 16) << (chn * 2));
}
/******************************************************************************************************************************************
* : DMA_CH_INTStat()
* : DMA中断状态查询
* : uint32_t chn DMA_CH0DMA_CH1DMA_CH2DMA_CH3
2023-12-12 18:23:12 +08:00
* uint32_t it interrupt type DMA_IT_DONEDMA_IT_DSTSG_HALFDMA_IT_DSTSG_DONEDMA_IT_SRCSG_HALF
* DMA_IT_SRCSG_DONE
* : uint32_t 1 0
* :
******************************************************************************************************************************************/
2023-12-12 18:23:12 +08:00
uint32_t DMA_CH_INTStat(uint32_t chn, uint32_t it)
{
2023-12-12 18:23:12 +08:00
return ((DMA->IF & (it << chn)) ||
(DMA->DSTSGIF & ((it >> 8) << (chn * 2))) ||
(DMA->SRCSGIF & ((it >> 16) << (chn * 2))));
}