#include <stdio.h>
#include <csl.h>
#include <csl_cache.h>
#include <csl_edma.h>
#include <csl_timer.h>
#include <csl_irq.h>
//———Global constants———
//Pick which EDMA transfer completion interrupt we want to use
#define TCCINTNUM 10
//Ping-pong buffer sizes in no. of ints
#define BUFF_SZ 128 //这里把BUFF_SZ改成128
//CPU clock frequency
#define FCPU 500000000
//Data sample rate (simulated w/timer
#define SRATE 8000
//Timer period
#define TPRD (FCPU/(4*SRATE))
//Transfer count
#define TRANSFER_CNT 20
//———Global data definition———
//Create the buffers. We want to align the buffers to be cache friendly
// by aligning them on an L2 cache line boundary.
#pragma DATA_SECTION(ping, ".buffers");
#pragma DATA_SECTION(pong, ".buffers");
#pragma DATA_SECTION(outbuff, ".buffers");
#pragma DATA_ALIGN(ping,128);
#pragma DATA_ALIGN(pong,128);
#pragma DATA_ALIGN(outbuff,128);
int ping[BUFF_SZ];
int pong[BUFF_SZ];
int outbuff[BUFF_SZ];
//These two variables serve as the data sources for this example.
//Also want to align these on a cache line boundary since they
// sources of EDMA transfers.
#pragma DATA_SECTION(ping_data, ".buffers");
#pragma DATA_SECTION(pong_data, ".buffers");
#pragma DATA_ALIGN(ping_data,128);
#pragma DATA_ALIGN(pong_data,128);
static int ping_data;
static int pong_data;
//Global variable used to track the ping-pong'ing
static int pingpong = 0;
volatile int transferCount = 0;
//Declare the CSL objects
TIMER_Handle hTimer; //Handle for the timer deviceEDMA_Handle hEdma; //Handle for the EDMA channelEDMA_Handle hEdmaPing; //Handle for the ping EDMA reload parameters
EDMA_Handle hEdmaPong; //Handle for the pong EDMA reload parameters
EDMA_Config cfgEdma; //EDMA configuration structure
//Create the EDMA configuration structure for ping transfers
EDMA_Config cfgEdmaPing =
{ //Making Options parameter register – EDMA_OPT
EDMA_OPT_RMK
( EDMA_OPT_PRI_LOW,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_NONE,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_INC,
EDMA_OPT_TCINT_YES,
EDMA_OPT_TCC_OF(TCCINTNUM),
EDMA_OPT_TCCM_OF(TCCINTNUM >> 4),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_OF(0),
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
),
EDMA_SRC_OF(&ping_data),//Source address register
EDMA_CNT_OF(BUFF_SZ), //Transfer count parameter
EDMA_DST_OF(ping), //Destination address parameter
EDMA_IDX_OF(0x00000004),//Index parameter
EDMA_RLD_OF(0x00000000) //Count reload/link parameter
};
//Create the EDMA configuration structure for pong transfers
EDMA_Config cfgEdmaPong ={
//Making Options parameter register – EDMA_OPT
EDMA_OPT_RMK
( EDMA_OPT_PRI_LOW, EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO, EDMA_OPT_SUM_NONE,
EDMA_OPT_2DD_NO, EDMA_OPT_DUM_INC,
EDMA_OPT_TCINT_YES, EDMA_OPT_TCC_OF(TCCINTNUM),
EDMA_OPT_TCCM_OF(TCCINTNUM >> 4),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_OF(0),
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
),
EDMA_SRC_OF(&pong_data),//Source address register
EDMA_CNT_OF(BUFF_SZ), //Transfer count parameter
EDMA_DST_OF(pong), //Destination address parameter
EDMA_IDX_OF(0x00000004),//Index parameter
EDMA_RLD_OF(0x00000000) //Count reload/link parameter
};
//———Function prototypes———
extern far void vectors();
void setupInterrupts(void);
//Function used to stop EDMA
void stopEdma(void);//———main routine———
void main()
{
//Initialise CSL
CSL_init();
//CACHE_enableCaching(CACHE_EMIFA_CE00);
//Configure L2 for 32K Cache mode
CACHE_setL2Mode(CACHE_32KCACHE); //Initialize the input source data
ping_data=0x00000000;//ping_data是数据而不是地址
pong_data=0x80000000;
//Since these variables are the source of an EDMA transfer, we
// need to flush them out of the cache since we just wrote to them.
CACHE_wbInvL2(&ping_data, 4, CACHE_WAIT);
CACHE_wbInvL2(&pong_data, 4, CACHE_WAIT);
//Let's disable/clear related interrupts just in case they are pending
// from a previous run of the program.
setupInterrupts();
//Although not required, let's clear all of the EDMA parameter RAM.
//This makes it easier to view the RAM and see the changes as we
// configure it.
EDMA_clearPram(0x00000000);
//Let's open up a timer device, we'll use this to simulate input events
// at a given sample rate.
hTimer = TIMER_open(TIMER_DEV1, TIMER_OPEN_RESET);
//Lets open up the EDMA channel associated with timer #1. 打开与定时器1相关联的EDMA通道
hEdma = EDMA_open(EDMA_CHA_TINT1, EDMA_OPEN_RESET);
//We also need two EDMA reload parameter sets so let's allocate them
// here. Notice the -1, this means allocate any availale table.
hEdmaPing = EDMA_allocTable(-1);
hEdmaPong = EDMA_allocTable(-1);
//Let's copy the ping reload configuration structure to an
// intermediate configuration structure. 中间配置结构
cfgEdma = cfgEdmaPing;
//Let's initialize the link fields of the configuration structures 让我们初始化配置结构的链接字段
cfgEdmaPing.rld = EDMA_RLD_RMK(0,hEdmaPing);
cfgEdmaPong.rld = EDMA_RLD_RMK(0,hEdmaPong);
cfgEdma.rld = EDMA_RLD_RMK(0,hEdmaPong);
//Now let's program up the EDMA channel with the configuration structure 现在让我们用配置结构编程EDMA通道
EDMA_config(hEdma, &cfgEdma);
//Let's also configure the reload parameter tables in the EDMA PRAM
// with the values in the configuration structures.
EDMA_config(hEdmaPing, &cfgEdmaPing);
EDMA_config(hEdmaPong, &cfgEdmaPong);
//Configure up the timer
TIMER_configArgs( hTimer, TIMER_CTL_OF(0x00000200), TIMER_PRD_OF(TPRD), //Timer period
TIMER_CNT_OF(0)
);
//Enable the related interrupts 启动相关中断
IRQ_enable(IRQ_EVT_EDMAINT);// 使能事件触发EDMA中断
EDMA_intDisable(TCCINTNUM);
EDMA_intClear(TCCINTNUM); EDMA_intEnable(TCCINTNUM);//中断允许位
//Enable the EDMA channel
EDMA_enableChannel(hEdma); //EER事件使能寄存器使能,允许事件来使能EDMA通道
//Finally, enable the timer which will drive everything
TIMER_start(hTimer);
//Waiting for interrupts
while(transferCount <= TRANSFER_CNT);}
void processbuff(int arg)
{
int *inbuff;
int x;
printf("\n %2d -",transferCount); if (pingpong)
{
//If pingpong is 0, then we own the ping input buffer
inbuff = ping;
printf(" Ping ");
}
else
{
//If pingpong is 1, then we own the pong input buffer
inbuff = pong;
printf(" Pong " );
} transferCount++;
//Now let's process the input buffer, for simplicity, we'll
// just copy it to the output buffer.
for (x=0; x<BUFF_SZ; x++)
outbuff[x] = inbuff[x];
//If this example is enhanced to actually do something with the
// output buffer such as DMA it somewhere, you will want to flush
// it out of the cache first.
CACHE_wbInvL2(outbuff, (BUFF_SZ << 2), CACHE_WAIT);
//Since we're done processing the input buffer, clean it from cache,
// this invalidates it from cache to ensure we read a fresh version
// the next time.
CACHE_wbInvL2(inbuff, (BUFF_SZ << 2), CACHE_WAIT);
}
// Function to sets up interrupts to service EDMA transfers
void setupInterrupts(void)
{
//Point to the IRQ vector table
IRQ_setVecs(vectors);
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_map(IRQ_EVT_EDMAINT, 8);
IRQ_reset(IRQ_EVT_EDMAINT);
}
//Interrupt Service Routine c_int08 : ISR to service EDMAINT.//vecs_edma1.asm must be modified to include c_int08 entry.
interrupt voidc_int08(void){
//Clear the pending interrupt from the EDMA interrupt pending register
EDMA_intClear(TCCINTNUM);
//Perform ping-pong
pingpong = (pingpong + 1) & 1;
//Exit from the program if certain no of transfres are done
if (transferCount >= TRANSFER_CNT)
{
TIMER_pause(hTimer);
stopEdma();
TIMER_close(hTimer);
printf ("\nDone…..");
//exit(0);
}
//Based on if we ping'ed or pong'ed, we need to set the EDMA channel
// link address for the NEXT frame.
if (pingpong)
{
//Currently doing pong so setup next frame for ping //Modify the input data source, this just simulates
// the input data changing.
ping_data++;
//Rememer to flush this variable out of the cache
// since it's the source of an EDMA transfer
CACHE_wbInvL2(&ping_data, 4, CACHE_WAIT);
//Now filling pong so set link to ping
EDMA_link(hEdma,hEdmaPing);
}
else
{
//Currently doing ping so setup next frame for pong
//Modify the output data source, this just simulates
// the input data changing.
pong_data++;
//Rememer to flush this variable out of the cache
// since it's the source of an EDMA transfer CACHE_wbInvL2(&pong_data, 4, CACHE_WAIT);
//Now filling ping so set link to pong
EDMA_link(hEdma,hEdmaPong);
} processbuff(0);
return;
}
//Stops the EDMA service.
void stopEdma(void)
{
//Disable interrupts, close EDMA channel before exit of the program
IRQ_disable(IRQ_EVT_EDMAINT);
EDMA_RSET(CCER,0x00000000);
EDMA_disableChannel(hEdma);
EDMA_intDisable(TCCINTNUM);
EDMA_intClear(TCCINTNUM);
EDMA_close(hEdma);
EDMA_resetAll();
EDMA_RSET(CIPR,0xFFFFFFFF);
EDMA_RSET(ECR,0xFFFFFFFF);
}
上面的程序是我从csl\example里面拷贝的(还有一个中断向量表,这里没有列出),没有错误,但是debug运行的时候进入不了定时器中断。
不知道在软件仿真的情况下 如何进入定时器中断??
Chris Meng:
tao wu4不知道在软件仿真的情况下 如何进入定时器中断??
请问你的代码是运行在DM642的硬件板子上,还是在CCS的simulator下?
tao wu4:
回复 Chris Meng:
使用的是simulator
Chris Meng:
回复 tao wu4:
Wu Tao,
从下面的文档看,EDMA/timer/中断控制器在DM642的simulator下是支持的。
请问你的问题是timer没有中断,还是EDMA没有运行?你的EDMA是用哪个事件触发的?
tao wu4:
回复 Chris Meng:
我直接使用的DM642的事例程序,我的理解是:timer中断触发EDMA事件,这个程序中只写了EDMA的中断服务程序(即edma传输完成交给cpu)。
从这个事例程序中,我并没有看到timer的中断服务函数。所以我觉得是,timer事件来临,产生一个事件中断,这个事件中断触发edma事件,edma
传输完成后,进入中断服务程序。
我的问题是:在simulator下而(不熟悉),我没法知道是timer中断没有产生而导致的EDMA无法运行,还是因为EDMA参数配置的有问题。而且,
我发现edma中断服务程序也进不去,程序运行到while那里,一直卡在那。。。。不知道是什么原因,求解
tao wu4:
回复 Chris Meng:
你好,我今天尝试手动置位相应的IFR中的相应位,发现能够进入中断服务程序。现在的问题是:手动置位定时器1的IFR,能够进入定时器1
的中断服务程序(虽然本程序没有特别设置中断服务程序),按照道理讲:此时edma应该在搬移数据了(&ping_data—–>ping),但是ping
里面的数据始终未发生改变。。。
期待您的回复!!!!
Chris Meng:
回复 tao wu4:
Wu Tao,
建议先单独写一个手动触发的EDMA代码,保证这个代码工作后,再加入中断。