/*************************************************************************************************************
* File name: dma.c
* Function: S3C6410 DMA bottom-level driver function
* Author: cp1300@139.com
* Created: 2013-01-23 21:06
* Last modified: January 23, 2013
* Details: DMA controller underlying driver
*************************************************************************************************************/
#include "system.h"
#include "DMA.h"
/*************************************************************************************************************************
*Function: void DMA_Init(void)
*Function: DMA initialization
*Parameters: None
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
* Description: None
*************************************************************************************************************************/
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)
*Function: DMA configuration
*Parameters: DMA: DMA module selection, see DMA_TypeDef; ch: channel selection, see DMA_CHX; config: configuration, see DMA_Config
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
*Description: Used to set DMA
*************************************************************************************************************************/
void DMA_SetConfig(DMA_TypeDef *DMA, DMA_CHX ch, DMA_Config *config)
{
DMA_Enable(DMA); //Enable DMA module
(DMA->CH[ch]).SrcAddr = config->SrcAddr; //Set source address
(DMA->CH[ch]).DestAddr = config->DestAddr; //Set the destination address
(DMA->CH[ch]).Control0 = 0x80000000 //1<<31 //Whether to generate an interrupt after the current transfer is completed
| ((config->DestIncrement == ENABLE) ? (1 << 27) : 0) //Destination address increments
| ((config->SrcIncrement == ENABLE) ? (1 << 26) : 0) // Source address auto-increment
| ((config->DestPeripheral == DMA_MEM) ? AHB_M1 : AHB_M2) << 25 //Target AHB host selection
| ((config->SrcPeripheral == DMA_MEM) ? AHB_M1 : AHB_M2) << 24 //Source AHB host selection
| (config->FlowWidth & 0x7) << 21 // Target transfer width
| (config->FlowWidth & 0x7) << 18 //Source transfer width
| (config->BurstSize & 0x7) << 15 // Target transmission pulse size, number of single transmissions
| (config->BurstSize & 0x7) << 12; //Source transmission pulse size, the number of single transmissions
(DMA->CH[ch]).Control1 = config->DataSize & 0x1ffffff; //Number of data to be transferred
(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 // Allow DMA request
| (((config->SrcPeripheral == DMA_MEM) ? 0 : 1) << 12)
| (((config->DestPeripheral == DMA_MEM) ? 0 : 1) << 11) //Transfer mode, such as memory to memory, etc.
| (config->DestPeripheral & 0x0f) << 6 //Destination peripheral
| (config->SrcPeripheral & 0x0f) << 1; //源外设
(DMA->CH[ch]).LLI = config->LLIArrd; //Next transfer LLI configuration location
//(DMA->CH[ch]).ConfigExp = 7;
}
/*************************************************************************************************************************
*函数 : void DMA_Enable(DMA_TypeDef *DMA)
*Function: DMA enable
*Parameter: DMA: DMA module selection, see DMA_TypeDef;
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
* Description: None
*************************************************************************************************************************/
void DMA_Enable(DMA_TypeDef *DMA)
{
DMA->Config = 0x01; //AHB little-endian mode, start DMA controller
}
/*************************************************************************************************************************
*函数 : void DMA_Disable(DMA_TypeDef *DMA)
*Function: DMA off
*Parameter: DMA: DMA module selection, see DMA_TypeDef;
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
* Description: None
*************************************************************************************************************************/
void DMA_Disable(DMA_TypeDef *DMA)
{
DMA->Config = 0x00; //AHB little-endian mode, turn off DMA controller
}
/*************************************************************************************************************************
*函数 : void DMA_StartChannels(DMA_TypeDef *DMA, DMA_CHX ch)
*Function: DMA channel transfer starts
*Parameters: DMA: DMA module selection, see DMA_TypeDef; ch: channel selection, see DMA_CHX;
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
* Description: None
*************************************************************************************************************************/
void DMA_StartChannels(DMA_TypeDef *DMA, DMA_CHX ch)
{
DMA_ClearIntTCStatus(DMA0, ch);
DMA_ClearIntErrorStatus(DMA0, ch);
(DMA->CH[ch]).Config |= 1 << 0; //Channel enable
}
/*************************************************************************************************************************
*函数 : void DMA_WaitComplete(DMA_TypeDef *DMA, DMA_CHX ch)
*Function: Wait for the transfer to complete
*Parameters: DMA: DMA module selection, see DMA_TypeDef; ch: channel selection, see DMA_CHX;
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
* Description: None
*************************************************************************************************************************/
void DMA_WaitComplete(DMA_TypeDef *DMA, DMA_CHX ch)
{
while(!(DMA->RawIntTCStatus & (1 << ch)));
}
/*************************************************************************************************************************
*函数 : void DMA_ClearIntTCStatus(DMA_TypeDef *DMA, DMA_CHX ch)
*Function: DMA clears DMA transfer completion interrupt status
*Parameters: DMA: DMA module selection, see DMA_TypeDef; ch: channel selection, see DMA_CHX;
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
* Description: None
*************************************************************************************************************************/
void DMA_ClearIntTCStatus(DMA_TypeDef *DMA, DMA_CHX ch)
{
DMA->IntTcClear |= 1 << ch;
}
/*************************************************************************************************************************
*函数 : void DMA_ClearIntErrorStatus(DMA_TypeDef *DMA, DMA_CHX ch)
*Function: Clear DMA transfer error interrupt status
*Parameters: DMA: DMA module selection, see DMA_TypeDef; ch: channel selection, see DMA_CHX;
*Return: None
*Depends on: underlying
*Author : cp1300@139.com
*Time: 20130131
*Last modified: 20130131
* Description: None
*************************************************************************************************************************/
void DMA_ClearIntErrorStatus(DMA_TypeDef *DMA, DMA_CHX ch)
{
DMA->IntErrClear |= 1 << ch;
}
#ifndef DMA_H_
#define DMA_H_
//DMA channel definition
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 single channel structure
typedef volatile struct
{
vu32 SrcAddr;
vu32 DestAddr;
vu32 LLI;
vu32 Control0;
vu32 Control1;
vu32 Config;
vu32 ConfigExp;
vu32 Reserved;
}DMA_CH_Config;
//DMA register structure
typedef volatile struct
{
vu32 IntStatus; //Interrupt status
vu32 IntTcStatus; //Interrupt status during processing
vu32 IntTcClear; //Interrupt clear
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]; //Reserved
DMA_CH_Config CH[8]; //8 independent channels
} DMA_TypeDef;
//Base address of 4 DMA controllers
#define DMA0_BASE 0x75000000
#define DMA1_BASE 0x75100000
#define SDMA0_BASE 0x7DB00000
#define SDMA1_BASE 0x7DC00000
//DMA register pointer
#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 source definition
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 transfer type definition
/*
typedef enum
{
MemToMem = 0, // memory to memory
MemToPer = 1, // memory to peripherals
PerToMem = 2, //peripheral to memory
PerToPer = 3 //Peripheral to peripheral
}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 host selection definition
typedef enum
{
AHB_M1 = 0, //AHB host 1
AHB_M2 = 1, //AHB host 2
}DMA_AHB_Type;
//DAM transmission width
typedef enum
{
WIDTH_8BIT = 0, //8bit
WIDTH_16BIT = 1, //16bit
WIDTH_32BIT = 2 //32bit
}DAM_Width_Type;
//Source or destination burst transfer size
typedef enum
{
BURST1 = 0,
BURST4 = 1,
BURST8 = 2,
BURST16 = 4,
BURST32 = 5,
BURST64 = 6,
BURST128 = 7,
BURST256 = 8
}DMA_BurstSize_Type;
/*
*4-word FIFO per channel inside the DMAC. Therefore, the burst size and transfer width are limited by the FIFO
For example, if the data width is words, the available burst size is 4. If the data width is bytes, the available burst size is
Under 16 years of age.
*/
//DMA transfer configuration
typedef struct
{
u32 SrcAddr; //DMA source address
u32 DestAddr; //DAM target address
DMA_Sources_Type SrcPeripheral; //源外设
DMA_Sources_Type DestPeripheral; //Destination peripheral
FunctionalState SrcIncrement; //Source address increment mode
FunctionalState DestIncrement; //Destination address increment mode
DAM_Width_Type FlowWidth; //Transmission width
DMA_BurstSize_Type BurstSize; //Burst transfer size
u32 DataSize; //Number of data to be transmitted, 32 bits
u32 LLIArrd; //Next transmission configuration address
}DMA_Config;
//LLI address setting
typedef struct
{
u32 SrcAddr; //The source address of the next transmission
u32 DestAddr; //The destination address of the next transfer
u32 LLIAddr; //LLI address of the next transmission
u32 DMAControl0; //The next DMAControl0 data to be transferred
u32 DMAControl1; //The next DMAControl1 data to be transferred
}DMA_LLI_Addr;
// Function declaration
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_*/
Previous article:Mini2440 bare metal MMU experiment
Next article:OK6410 Assembly Program Exercise
Recommended ReadingLatest update time:2024-11-17 04:23
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- Rambus Launches Industry's First HBM 4 Controller IP: What Are the Technical Details Behind It?
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- Another new board has arrived~~Jiefa AC7801X motor demo board is here, and the evaluation activity will be online soon...
- CY8CKIT-149 PSoC 4100S Review (1)
- STM32F765@216MHz running NES emulator [code] [video]
- Which expert can help me solve the volume control problem of the digital-analog chip WM8766G?
- Please help me find out what this part is. I have asked many people but they can't figure it out.
- Please recommend a LED driver IC
- Recommend! Good domestic chips you have used
- I heard someone bought a fake chip? I'm doubting myself after adjusting the fake chip
- Warm congratulations to the Chinese men's football team for drawing with the powerful Philippines
- Hilarious call from the customer service center