/*************************************************************************************************************
* 文件名: dma.c
* 功能: S3C6410 DMA底层驱动函数
* 作者: cp1300@139.com
* 创建时间: 2013年01月23日21:06
* 最后修改时间:2013年01月23日
* 详细: DMA控制器底层驱动
*************************************************************************************************************/
#include "system.h"
#include "DMA.h"
/*************************************************************************************************************************
*函数 : void DMA_Init(void)
*功能 : DMA初始化
*参数 : 无
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 无
*************************************************************************************************************************/
void DMA_Init(void)
{
Set_GateClk(HCLK_DMA0, ENABLE);
Set_GateClk(HCLK_DMA1, ENABLE);
}
/*************************************************************************************************************************
*函数 : void DMA_SetConfig(DMA_TypeDef *DMA, DMA_CHX ch, DMA_Config *config)
*功能 : DMA配置
*参数 : DMA:DMA模块选择,见DMA_TypeDef;ch:通道选择,见DMA_CHX;config:配置,见DMA_Config
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 用于设置DMA
*************************************************************************************************************************/
void DMA_SetConfig(DMA_TypeDef *DMA, DMA_CHX ch, DMA_Config *config)
{
DMA_Enable(DMA); //使能DMA模块
(DMA->CH[ch]).SrcAddr = config->SrcAddr; //设置源地址
(DMA->CH[ch]).DestAddr = config->DestAddr; //设置目标地址
(DMA->CH[ch]).Control0 = 0x80000000 //1<<31 //是否在当前的传输完成后产生中断
| ((config->DestIncrement == ENABLE) ? (1 << 27) : 0) //目标地址自增
| ((config->SrcIncrement == ENABLE) ? (1 << 26) : 0) //源地址自增
| ((config->DestPeripheral == DMA_MEM) ? AHB_M1 : AHB_M2) << 25 //目标AHB主机选择
| ((config->SrcPeripheral == DMA_MEM) ? AHB_M1 : AHB_M2) << 24 //源AHB主机选择
| (config->FlowWidth & 0x7) << 21 //目标传输宽度
| (config->FlowWidth & 0x7) << 18 //源传输宽度
| (config->BurstSize & 0x7) << 15 //目标传输脉冲大小,单次传输的数量
| (config->BurstSize & 0x7) << 12; //源传输脉冲大小,单次传输的数量
(DMA->CH[ch]).Control1 = config->DataSize & 0x1ffffff; //传输数据数量
(DMA->CH[ch]).Config = (0<<18)// enable DMA requests
| (0<<16) // disables locked transfers
| (1<<15) // Teminal count interrupt enable
| (0<<14) // Interrupt error mask //允许DMA请求
| (((config->SrcPeripheral == DMA_MEM) ? 0 : 1) << 12)
| (((config->DestPeripheral == DMA_MEM) ? 0 : 1) << 11) //传输模式,如内存到内存等
| (config->DestPeripheral & 0x0f) << 6 //目标外设
| (config->SrcPeripheral & 0x0f) << 1; //源外设
(DMA->CH[ch]).LLI = config->LLIArrd; //下一个传输LLI配置位置
//(DMA->CH[ch]).ConfigExp = 7;
}
/*************************************************************************************************************************
*函数 : void DMA_Enable(DMA_TypeDef *DMA)
*功能 : DMA使能
*参数 : DMA:DMA模块选择,见DMA_TypeDef;
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 无
*************************************************************************************************************************/
void DMA_Enable(DMA_TypeDef *DMA)
{
DMA->Config = 0x01; //AHB小端模式,启动DMA控制器
}
/*************************************************************************************************************************
*函数 : void DMA_Disable(DMA_TypeDef *DMA)
*功能 : DMA关闭
*参数 : DMA:DMA模块选择,见DMA_TypeDef;
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 无
*************************************************************************************************************************/
void DMA_Disable(DMA_TypeDef *DMA)
{
DMA->Config = 0x00; //AHB小端模式,关闭DMA控制器
}
/*************************************************************************************************************************
*函数 : void DMA_StartChannels(DMA_TypeDef *DMA, DMA_CHX ch)
*功能 : DMA通道传输开始
*参数 : DMA:DMA模块选择,见DMA_TypeDef;ch:通道选择,见DMA_CHX;
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 无
*************************************************************************************************************************/
void DMA_StartChannels(DMA_TypeDef *DMA, DMA_CHX ch)
{
DMA_ClearIntTCStatus(DMA0, ch);
DMA_ClearIntErrorStatus(DMA0, ch);
(DMA->CH[ch]).Config |= 1 << 0; //通道使能
}
/*************************************************************************************************************************
*函数 : void DMA_WaitComplete(DMA_TypeDef *DMA, DMA_CHX ch)
*功能 : 等待传输完成
*参数 : DMA:DMA模块选择,见DMA_TypeDef;ch:通道选择,见DMA_CHX;
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 无
*************************************************************************************************************************/
void DMA_WaitComplete(DMA_TypeDef *DMA, DMA_CHX ch)
{
while(!(DMA->RawIntTCStatus & (1 << ch)));
}
/*************************************************************************************************************************
*函数 : void DMA_ClearIntTCStatus(DMA_TypeDef *DMA, DMA_CHX ch)
*功能 : DMA清除DMA传输完成中断状态
*参数 : DMA:DMA模块选择,见DMA_TypeDef;ch:通道选择,见DMA_CHX;
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 无
*************************************************************************************************************************/
void DMA_ClearIntTCStatus(DMA_TypeDef *DMA, DMA_CHX ch)
{
DMA->IntTcClear |= 1 << ch;
}
/*************************************************************************************************************************
*函数 : void DMA_ClearIntErrorStatus(DMA_TypeDef *DMA, DMA_CHX ch)
*功能 : 清除DMA传输错误中断状态
*参数 : DMA:DMA模块选择,见DMA_TypeDef;ch:通道选择,见DMA_CHX;
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 20130131
*最后修改时间 : 20130131
*说明 : 无
*************************************************************************************************************************/
void DMA_ClearIntErrorStatus(DMA_TypeDef *DMA, DMA_CHX ch)
{
DMA->IntErrClear |= 1 << ch;
}
#ifndef DMA_H_
#define DMA_H_
//DMA通道定义
typedef enum
{
DMA_CH0 = 0,
DMA_CH1 = 1,
DMA_CH2 = 2,
DMA_CH3 = 3,
DMA_CH4 = 4,
DMA_CH5 = 5,
DMA_CH6 = 6,
DMA_CH7 = 7,
}DMA_CHX;
//DMA单独通道结构
typedef volatile struct
{
vu32 SrcAddr;
vu32 DestAddr;
vu32 LLI;
vu32 Control0;
vu32 Control1;
vu32 Config;
vu32 ConfigExp;
vu32 Reserved;
}DMA_CH_Config;
//DMA寄存器结构
typedef volatile struct
{
vu32 IntStatus; //中断状态
vu32 IntTcStatus; //处理过程中中断状态
vu32 IntTcClear; //中断清除
vu32 IntErrorStatus;
vu32 IntErrClear;
vu32 RawIntTCStatus;
vu32 RawIntErrorStatus;
vu32 EnbldChns;
vu32 SoftBReq;
vu32 SoftSReq;
vu32 SoftLBReq;
vu32 SoftLSReq;
vu32 Config;
vu32 Sync;
vu32 Reserved[50];//保留
DMA_CH_Config CH[8]; //8个独立通道
} DMA_TypeDef;
//4个DMA控制器的基址
#define DMA0_BASE 0x75000000
#define DMA1_BASE 0x75100000
#define SDMA0_BASE 0x7DB00000
#define SDMA1_BASE 0x7DC00000
//DMA寄存器指针
#define DMA0 ((DMA_TypeDef *)DMA0_BASE)
#define DMA1 ((DMA_TypeDef *)DMA1_BASE)
#define SDMA0 ((DMA_TypeDef *)SDMA0_BASE)
#define SDMA1 ((DMA_TypeDef *)SDMA1_BASE)
//DMA源定义
typedef enum
{
//DMA0,SDMA0
DMA_MEM = 0,
DMA_UART0_0 = 0,
DMA_UART0_1 = 1,
DMA_UART1_0 = 2,
DMA_UART1_1 = 3,
DMA_UART2_0 = 4,
DMA_UART2_1 = 5,
DMA_UART3_0 = 6,
DMA_UART3_1 = 7,
DMA_PCM0_TX = 8,
DMA_PCM0_RX = 9,
DMA_I2S0_TX = 10,
DMA_I2S0_RX = 11,
DMA_SPI0_TX = 12,
DMA_SPI0_RX = 13,
DMA_HSI_TX = 14,
DMA_HSI_RX = 15,
//DMA1,SDMA1
DMA_PCM1_TX = 16,
DMA_PCM1_RX = 17,
DMA_I2S1_TX = 18,
DMA_I2S1_RX = 19,
DMA_SPI1_TX = 20,
DMA_SPI1_RX = 21,
DMA_AC_PCMout = 22,
DMA_AC_PCMin = 23,
DMA_AC_MICin = 24,
DMA_PWM = 25,
DMA_IrDA = 26,
DMA_SECU_RX = 30,
DMA_SECU_TX = 31
}DMA_Sources_Type;
//DMA传输类型定义
/*
typedef enum
{
MemToMem = 0, //内存到内存
MemToPer = 1, //内存到外设
PerToMem = 2, //外设到内存
PerToPer = 3 //外设到外设
}DMA_Transfer_Type;
*/
typedef enum
{
NO_INT_PEND = 0x0,
TC_INT_PEND = 0x1,
ERR_INT_PEND = 0x2,
TC_AND_ERR_INT_PEND = 0x3
} DMA_INT_STATUS;
//DMA AHB主机选择定义
typedef enum
{
AHB_M1 = 0, //AHB主机1
AHB_M2 = 1, //AHB主机2
}DMA_AHB_Type;
//DAM传输宽度
typedef enum
{
WIDTH_8BIT = 0, //8bit
WIDTH_16BIT = 1, //16bit
WIDTH_32BIT = 2 //32bit
}DAM_Width_Type;
//源或目标突发传输大小
typedef enum
{
BURST1 = 0,
BURST4 = 1,
BURST8 = 2,
BURST16 = 4,
BURST32 = 5,
BURST64 = 6,
BURST128 = 7,
BURST256 = 8
}DMA_BurstSize_Type;
/*
*DMAC内部每个通道的4字FIFO。因此,脉冲串的大小和传输宽度是有限的由FIFO
大小。例如,如果数据宽度为字,可用的突发脉冲尺寸是4下。如果数据宽度为字节,可突发尺寸
在16岁以下。
*/
//DMA传输配置
typedef struct
{
u32 SrcAddr; //DMA源地址
u32 DestAddr; //DAM目标地址
DMA_Sources_Type SrcPeripheral; //源外设
DMA_Sources_Type DestPeripheral; //目标外设
FunctionalState SrcIncrement; //源地址增量模式
FunctionalState DestIncrement; //目标地址增量模式
DAM_Width_Type FlowWidth; //传输宽度
DMA_BurstSize_Type BurstSize; //突发传输大小
u32 DataSize; //传输数据个数,32bit
u32 LLIArrd; //下一个传输配置地址
}DMA_Config;
//LLI地址设置
typedef struct
{
u32 SrcAddr; //下一个传输的源地址
u32 DestAddr; //下一个传输的目标地址
u32 LLIAddr; //下一个传输的LLI地址
u32 DMAControl0;//下一个传输的DMAControl0数据
u32 DMAControl1;//下一个传输的DMAControl1数据
}DMA_LLI_Addr;
//函数声明
void DMA_Init(void);
void DMA_SetConfig(DMA_TypeDef *DMA, DMA_CHX ch, DMA_Config *config);
void DMA_Enable(DMA_TypeDef *DMA);
void DMA_Disable(DMA_TypeDef *DMA);
void DMA_WaitComplete(DMA_TypeDef *DMA, DMA_CHX ch);
void DMA_ClearIntTCStatus(DMA_TypeDef *DMA, DMA_CHX ch);
void DMA_ClearIntErrorStatus(DMA_TypeDef *DMA, DMA_CHX ch);
void DMA_StartChannels(DMA_TypeDef *DMA, DMA_CHX ch);
#endif /*DMA_H_*/