📄 dma.c
字号:
#include <string.h>
#include "dma.h"
// DMA不是直接进行或是讲不能逐一配置。把配置写到一块内存之后ARM命令自动加载
DMA_DESC dmaChannel1to2[2];
// 映射表,用来把DMA号与处理函数连接。.
DMA_TABLE_ENTRY dmaTable[DMA_ADM_NUMBER_OF_CHANNELS];
//-----------------------------------------------------------------------------
// See cul.h for a description of this function.
//-----------------------------------------------------------------------------
void DmaInit(void){
// 清0DMA结构内存
memset((void*)dmaChannel1to2, 0, sizeof(dmaChannel1to2));
// 清0DMA映射表,
memset((void*)dmaTable, 0, sizeof(dmaTable));
// 1到4的所有装配位清0,到用时单个使能
DMAARM &= DMA_CHANNEL_0;
// 1到4的DMA请求位清0,这些位由硬件自动置位,也可以人工置位
DMAREQ &= DMA_CHANNEL_0;
// 中断标志1到4清0,这是传输完毕后置位,相当于中断中的局部中断
DMAIRQ &= DMA_CHANNEL_0;
// 清0 DMA中断标志位,在全局中断里
INT_SETFLAG(INUM_DMA, INT_CLR);
// 使能中断标志,在全局中断里
INT_ENABLE(INUM_DMA, INT_ON);
// DMA1到4的配置导入到寄存器,其实就要配置内存的一个指针。(多个DMA不能并行的工作,1到4共用一个配置REG)
DMA_SET_ADDR_DESC12(dmaChannel1to2);
} // ends culDmaInit()
//分配DMA通道
DMA_DESC *DmaAllocChannel(UINT8* pDmaChannelNumber, FUNCTION* callBackFunction){
DMA_DESC* dmaDesc;
BYTE savedIntEnable = 0x00;
INT8 i;
// 查看那个DMA通道没使用
for(i = 1; i <= DMA_ADM_NUMBER_OF_CHANNELS; i++){
if(dmaTable[i].assigned == FALSE){
break;
}
}
// If no channel is available, the function returns.
if(i > DMA_ADM_NUMBER_OF_CHANNELS){
*pDmaChannelNumber = 0x00;
dmaDesc = NULL;
}
// An available table entry was found
else {
// Deactivating the channel and erasing old interrupt flag
DMA_ABORT_CHANNEL(i);
DMAIRQ &= ~(1 << i);
// Storing interrupt enable register and turning off interrupts.
savedIntEnable = IEN0;
GLOBAL_INT_ENABLE(INT_OFF);
// Reserving the DMA channel.
dmaTable[i].assigned = TRUE;
dmaTable[i].callBackFunction = callBackFunction;
*pDmaChannelNumber = i;
// Restoring old interrupt enable register.
IEN0 = savedIntEnable;
dmaDesc = &dmaChannel1to2[i-1];
}
// Returning pointer to the DMA descriptor
return dmaDesc;
}
void DmaFromRadio(DMA_DESC* pDmaChannel, BYTE *pDstAddr, BOOL generateInterrupt)
{
SET_WORD(pDmaChannel->SRCADDRH, pDmaChannel->SRCADDRL, &X_RFD); // The start address of the segment
SET_WORD(pDmaChannel->DESTADDRH, pDmaChannel->DESTADDRL, pDstAddr); // Tx FiFo address
SET_WORD(pDmaChannel->LENH, pDmaChannel->LENL, 255); // Maximum of the Tx FiFo.
pDmaChannel->VLEN = VLEN_1_P_VALOFFIRST;// The first byte indicates transfer length
pDmaChannel->PRIORITY = PRI_HIGH;
pDmaChannel->M8 = M8_USE_7_BITS;
pDmaChannel->IRQMASK = generateInterrupt; // The DMA complete interrupt flag is set at completion.
pDmaChannel->DESTINC = DESTINC_1; // The destination is constant
pDmaChannel->SRCINC = SRCINC_0; // The address for data fetch is incremented by 1 byte after each transfer.
pDmaChannel->TRIG = DMATRIG_RADIO; // DMA is started by the radio receiver.
pDmaChannel->TMODE = TMODE_SINGLE; // One byte is transferred at each DMA trigger.
pDmaChannel->WORDSIZE = WORDSIZE_BYTE; // Byte transfer.
return;
}
#pragma vector=DMA_VECTOR
__interrupt void dma_IRQ (void){
GLOBAL_INT_ENABLE(INT_OFF);
// Clearing the interrupt flag.
DMAIF = 0;
if(DMAIRQ & DMA_CHANNEL_0){
// Clearing interrupt flag
DMAIRQ &= ~DMA_CHANNEL_0;
// Calling the callback function.
if(dmaTable[0].callBackFunction){
dmaTable[0].callBackFunction();
}
}
if(DMAIRQ & DMA_CHANNEL_1){
// Clearing interrupt flag
DMAIRQ &= ~DMA_CHANNEL_1;
// Calling the callback function.
if(dmaTable[1].callBackFunction){
dmaTable[1].callBackFunction();
}
}
if(DMAIRQ & DMA_CHANNEL_2){
// Clearing interrupt flag
DMAIRQ &= ~DMA_CHANNEL_2;
// Calling the callback function.
if(dmaTable[2].callBackFunction){
dmaTable[2].callBackFunction();
}
}
GLOBAL_INT_ENABLE(INT_ON);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -