📄 emif to fife.c
字号:
Sample Code
/********************************************************/
/* Fiforead.c */
/* */
/* This program uses the HF flag of a FIFO to */
/* trigger reads, guaranteeing that the FIFO is */
/* never blocked for the writer, giving high */
/* throughput for the reader (bursts of D/2 = 128) */
/* and guaranteeing that the the reader will not be */
/* stuck in the top half of the FIFO. */
/* */
/* Assumes that: */
/* Ext_Int6 = HF */
/* TINP0 = HF */
/* Fifo in CE0 */
/********************************************************/
#include <dma.h>
#include <emif.h>
#include <intr.h>
#include <timer.h>
#define FIFO_ADDR 0x00400000
#define BUFF_ADDR 0x80000000
#define FIFO_DEPTH 256
#define NUM_FRAMES 8
void set_EMIF();
void set_DMA();
void set_intr();
interrupt void c_int06();
interrupt void c_int08();
int fifo_halffull();
int num_frames = NUM_FRAMES;
int done = 0;
void
main(){
set_EMIF();
set_intr();
set_DMA();
while (!done){
// execute_user_code
}
printf("DONE \n\n");
}
/* This function sets up ce0 as ASRAM */
void set_EMIF(){
/* Get default values for all EMIF registers */
unsigned int g_ctrl = GET_REG(EMIF_GCTRL);
unsigned int ce0_ctrl = GET_REG(EMIF_CE0_CTRL);
unsigned int ce1_ctrl = GET_REG(EMIF_CE1_CTRL);
unsigned int ce2_ctrl = GET_REG(EMIF_CE2_CTRL);
unsigned int ce3_ctrl = GET_REG(EMIF_CE3_CTRL);
unsigned int sdram_ctrl = GET_REG(EMIF_SDRAM_CTRL);
unsigned int sdram_ref = GET_REG(EMIF_SDRAM_REF);
/* Configure CE0 as ASRAM for FIFO interface */
LOAD_FIELD(&ce0_ctrl, MTYPE_32ASYNC, MTYPE , MTYPE_SZ );
LOAD_FIELD(&ce0_ctrl, 1 , READ_SETUP , READ_SETUP_SZ );
LOAD_FIELD(&ce0_ctrl, 4 , READ_STROBE , READ_STROBE_SZ );
LOAD_FIELD(&ce0_ctrl, 2 , READ_HOLD , READ_HOLD_SZ );
/* Store EMIF Control Registers */
emif_init(g_ctrl, ce0_ctrl, ce1_ctrl, ce2_ctrl, ce3_ctrl,
sdram_ctrl, sdram_ref);
}
/* set up the DMA */
void set_DMA(){
unsigned int channel = 0;
unsigned int pri_ctrl= GET_REG(DMA0_PRIMARY_CTRL);
unsigned int sec_ctrl= GET_REG(DMA0_SECONDARY_CTRL);
unsigned int src_addr = 0;
unsigned int dst_addr = 0;
unsigned int trans_ctr= 0;
dma_reset();
/** Set DMA primary control register for channel 0 **/
LOAD_FIELD(&pri_ctrl, DMA_STOP_VAL , START , START_SZ);
LOAD_FIELD(&pri_ctrl, DMA_ADDR_NO_MOD, SRC_DIR, SRC_DIR_SZ);
LOAD_FIELD(&pri_ctrl, DMA_ADDR_INC , DST_DIR, DST_DIR_SZ);
LOAD_FIELD(&pri_ctrl, DMA_ESIZE32 , ESIZE , ESIZE_SZ);
SET_BIT(&pri_ctrl, PRI);
SET_BIT(&pri_ctrl, TCINT);
/** Set DMA secondary control register for channel 0 **/
LOAD_FIELD(&sec_ctrl, DMAC_BLOCK_COND, DMAC_EN, DMAC_EN_SZ);
SET_BIT(&sec_ctrl, BLOCK_IE);
/** Set source address register **/
src_addr = FIFO_ADDR;
/** Set destination address register **/
dst_addr = BUFF_ADDR;
/** Set transfer counter **/
LOAD_FIELD(&trans_ctr, FIFO_DEPTH/2, ELEMENT_COUNT, ELEMENT_COUNT_SZ);
/** Set the DMA registers **/
dma_init(channel, pri_ctrl, sec_ctrl, src_addr, dst_addr,trans_ctr);
}
/****
/* This routine uses the Peripheral Support Library functions
/* to initialize the interrupt vector table and enable the required
/* interrupts.
/****/
void
set_intr()
{
intr_init();
intr_map(CPU_INT6, ISN_EXT_INT6);
intr_map(CPU_INT8, ISN_DMA_INT0);
intr_hook(c_int06, CPU_INT6);
intr_hook(c_int08, CPU_INT8);
INTR_GLOBAL_ENABLE;
INTR_ENABLE(CPU_INT_NMI);
INTR_ENABLE(CPU_INT6);
INTR_ENABLE(CPU_INT8);
}
****
/* This routine checks the current state of the FIFO
/* by monitoring the TINP0 pin.
/* Returns : 1 if HF flag is set indicating the FIFO is half full
/* 0 if HF flag is not set, indicating less than half full.
/****/
int
fifo_halffull()
{
int half_full ;
half_full = TINP_GET(0);
return half_full;
}
/****
/* This interrupt service routine is entered when the half full
/* flag (on the Ext_Int6 pin) changes state from low to high,
/* then kicks off a DMA transfer of 1/2 of the FIFO depth.
/****/
interrupt void
c_int06() /* EXT_int6 */
{
INTR_DISABLE(6); /* Disable interrupt 6, so that any toggling */
/* of the HF flag is disregarded until the DMA*/
/* transfer is complete. */
if (num_frames > 0){
DMA_START(0); /* Starts the DMA transfer, if haven’t */
/* transferred the desired number of frames. */
}
}
/****
/* This interrupt service routine is entered when the DMA Block Cond
/* is set, indicating that the DMA transfer has completed. This
/* routine will check the current state of the FIFO. If the FIFO is
/* still half full, it will start another DMA transfer, since a low to
/* high transition will not be able to occur on Ext_Int6 (since HF is
/* already high). This technique prevents the FIFO from becoming stuck
/* half full.
/****
interrupt void
c_int08() /* DMA Interrupt */
{
int half_full;
num_frames--; /* Decrement frame counter */
RESET_BIT(DMA_SECONDARY_CTRL_ADDR(0), BLOCK_COND);
* (unsigned int *) DMA_XFR_COUNTER_ADDR(0) = FIFO_DEPTH/2;
/* Check the state of the FIFO */
half_full = fifo_halffull();
if (num_frames > 0){
if (half_full)
DMA_START(0); /* Start the DMA if the FIFO is */
/* still half full, and all the */
/* frames have not already been */
else /* read, otherwise, */
INTR_ENABLE(6); /* enable interrupt 6, to detect */
/* the next rising edge of HF */
}
else
done = 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -