i2s_sample_slave.c

来自「最新版IAR FOR ARM(EWARM)5.11中的代码例子」· C语言 代码 · 共 333 行

C
333
字号
/**************************************************************************/
/*                                                                        */
/*     Copyright (C) 2005 Oki Electric Industry Co., LTD.                 */
/*                                                                        */
/*     System Name  :  ML67Q4051/ML67Q4061 series                         */
/*     Module Name  :  ML67Q4051/ML67Q4061 i2s sample program (Slave)     */
/*     File   Name  :  i2s_sample_slave.c                                 */
/*     Revision     :  01.00                                              */
/*     Date         :  05/09/2005                                         */
/*                                                                        */
/**************************************************************************/
#include   "ml674061.h"
#include   "common.h"
#include   "irq.h"

#ifdef __IAR__
#include "intrinsics.h"
#endif

/* constants */
#define BUFF_SIZE		0x400
#define PORTSEL3_I2S	0x1500
#define TMRCYC	(30)			/* interval of timer interrupt (ms) */
#define SYSCLK	(32)			/* SYSCLK (MHz)*/
#define VALUE_OF_TMRLR          /* reload value of timer */\
                (65536 - (TMRCYC * SYSCLK * 1000) / 16)
#if ((VALUE_OF_TMRLR) < 0 || 0x10000 <= (VALUE_OF_TMRLR))
#error "Invalid value : VALUE_OF_TMRLR"
#endif


/* functions */
int  main(void);				/* Main routine */
void init_i2s(void);			/* Initialize I2S */
void dmac_data_receiv(UWORD *);	/* I2S receive process */
void reg_irq_handler(void);		/* Registration of IRQ Handler */
void dmacCH0_handler(void);		/* DMAC CH0 interrupt handler */
void timer_handler(void);		/* System Timer handler */
void setup_dmac(void);			/* setup dmac */
void setup_timer(void);			/* Setup of timer */
void remained_data_read(void);	/* Reading remained data */

/* global variables */
unsigned long I2S_ReceivData1[BUFF_SIZE];		/* Receive buffer1 */
unsigned long I2S_ReceivData2[BUFF_SIZE+10];	/* Receive buffer2 */
UBYTE led_pt;							/* LED pattern */
UHWORD err_status;						/* Error status */
volatile UHWORD end_flag;				/* Flag for Program end */
UHWORD timeout_flag;					/* Flag for Time Out */
static volatile int counter;

enum err_num {			/* Error number */
	NO_ERR, 			/* No error */
	DATA_SEND_ERR,		/* Data sending error */
	DATA_RECEIV_ERR		/* Data receiving error */
};

/******************************************************************/
/*  Entry point                                                   */
/*  Function : main (Slave)                                       */
/*      Parameters                                                */
/*          Input  :  Nothing                                     */
/*          Output :  0                                           */
/******************************************************************/
int main(void)
{
	UWORD  *rp = I2S_ReceivData1;
	
	init_irq();					/* initialize irq */
	reg_irq_handler();			/* register IRQ handlers */
	
	init_led();                 /* initialize led */
	led_on(LED_START_PATTERN);  /* light led start pattern */

	led_pt = LED_NORMAL_END_PATTERN;

	init_i2s();					/* initialize i2s */
	setup_dmac();				/* setup DMAC */
	setup_timer();				/* setup system timer */
	
	set_wbit(I2SCONI, I2SCONI_RSET_ISRUN);	/* receiver start */
	
	end_flag = 0;
	led_pt = LED_NORMAL_END_PATTERN;
	
	#ifdef __IAR__                          /* Enable interrupts */
        __enable_interrupt();
        #else
        irq_en();
        #endif

	dmac_data_receiv(rp);		/* DMAC data receiver */
	if(err_status==NO_ERR)
	{
		if(timeout_flag==1)
		{	/* Reading remained data */
			timeout_flag = 0;
			remained_data_read();
		}
		
		end_flag = 0;
		rp = I2S_ReceivData2;
		
		dmac_data_receiv(rp);
		if(timeout_flag==1)
		{	/* Reading remained data */
			timeout_flag = 0;
			remained_data_read();
		}
	}
	
    #ifdef __IAR__
      __disable_interrupt();                            /* Disable Irqs */
    #else
    irq_dis();
    #endif

	led_on(led_pt);				/* turn on lower square LED */
	
	return 0;
}

/******************************************************************/
/*  Initialize I2S                                                */
/*  Function : init_i2s (Slave)                                   */
/*      Parameters                                                */
/*          Input  :  Nothing                                     */
/*          Output :  Nothing                                     */
/******************************************************************/
void init_i2s(void)
{
	UHWORD  i;
	
	/***********************************************************
	    Setup of I2S
	    I2SCONI_TSET_ISSCKF		32FS
	    I2SCONI_TSET_ISBIT		16bit
	    I2SCONI_TSET_AFO		I2S
	***********************************************************/
	put_wvalue(I2SCONI, 0x40);
	
	put_wvalue(I2SAFRI, 0x20);	/* almost full threshold 32 */
	put_wvalue(I2SAERI, 0x01);	/* almost empty 1 */
	
	set_wbit(I2SCLKI, I2SCLKI_RSET_ISMST);	/* slave mode */
	set_wbit(I2SCLKI, I2SCLKI_RSET_ISCLR);	/* FIFO clear */
	
	set_wbit(PORTSEL3, PORTSEL3_I2S);	/* selection of a secondary function */
	
	/***********************************************************
	    Clear receive_buffer and err_status
	***********************************************************/
	for(i=0; i<BUFF_SIZE; i++)
	{
		I2S_ReceivData1[i] = 0xFF;
		I2S_ReceivData2[i] = 0xFF;
	}
	
	err_status = NO_ERR;
	return;
}

/******************************************************************/
/*  I2S receive                                                   */
/*  Function : dmac_data_receiv                                   */
/*      Parameters                                                */
/*          Input  :  destination address                         */
/*          Output :  Nothing                                     */
/******************************************************************/
void dmac_data_receiv(UWORD * rp)
{
	put_wvalue(DMACDAD0, (UWORD)rp);   /* destination address */
	put_wvalue(DMACSIZ0, BUFF_SIZE);	/* number of transmission */
	put_wvalue(DMACMSK0, 0x0);  /* channel mask cancel */
	put_wvalue(I2SIMRI, 0xF);   /* available DMA request transmission */
	
	counter = 0;
	timeout_flag = 0;
	put_wvalue(TMEN, 0x01);     /* enable timer (write '1' in TMEN[0]) */
	
	while(end_flag!=1)
	{	/* Waiting for DMA data transfer finishing */
		if(counter>200)
		{
			timeout_flag = 1;
			break;
		}
	}
	
    put_wvalue(TMEN,  0x0);     /* disable timer (write '0' in TMEN[0])*/
	return;
}

/****************************************************************************/
/*  Registration of IRQ Handler                                             */
/*  Function : reg_irq_handler                                              */
/*      Parameters                                                          */
/*          Input   :   Nothing                                             */
/*          Output  :   Nothing                                             */
/*  Note : Initialize of IRQ needs to be performed before this process.     */
/****************************************************************************/
void reg_irq_handler(void)
{
	/* register IRQ handlers into handler table */
	IRQ_HANDLER_TABLE[INT_DMA0] = dmacCH0_handler;
    IRQ_HANDLER_TABLE[INT_SYSTEM_TIMER] = timer_handler;
	
	/* setup interrupt level */
	set_wbit(EXILCA, ILC_ILC24 & ILC_INT_LV7);	/* dmac handler(nIRQ[24]) -> level7 */
    set_wbit(ILC0, ILC0_ILR0 & ILC0_INT_LV1);	/* timer handler(nIRQ[0]) -> level1 */

	return;
}

/*****************************************************************************/
/*  DMAC CH0 interrupt handler                                               */
/*      Function : dmacCH0_handler(void)                                     */
/*          Parameters                                                       */
/*              Input  : Nothing                                             */
/*              Output : Nothing                                             */
/*****************************************************************************/
void dmacCH0_handler(void)
{
	UWORD sta = get_wvalue(DMAINT);
	
	put_wvalue(DMACMSK0, 0x1);		/* channel mask */
	set_wbit(I2SIMRI, 0x10);		/* DMA mask */
	put_wvalue(DMACCINT0, 0xFF);	/* end status clear */
	
    if((sta & DMAINT_ISTA0)==DMAINT_ISTA0)
    {
		if((sta & DMAINT_ISTP0)==DMAINT_ISTP0)
		{	/* write error */
			err_status = DATA_SEND_ERR;
			led_pt = LED_1;	/* turn on LED error */
		}
		else
		{	/* read error */
			err_status = DATA_RECEIV_ERR;
			led_pt = LED_2;	/* turn on LED error */
		}
	}
	
	end_flag = 1;
    return;
}

/******************************************************************/
/*  Setup dmac                                                    */
/*  Function : setup_dmac                                         */
/*      Parameters                                                */
/*          Input  :  Nothing                                     */
/*          Output :  Nothing                                     */
/******************************************************************/
void setup_dmac(void)
{
	put_wvalue(DMARQCNT, 0x9);		/* I2S reception(CH0) */
	put_wvalue(DMACMSK0, 0x1);		/* channel mask */
	
	/***********************************************************
	    DMACTMOD0_ARQ		dreq transmit request
	    DMACTMOD0_TSIZ		half word
	    DMACTMOD0_SDP		source address fixation
	    DMACTMOD0_DDP		destination address increment
	    DMACTMOD0_BRQ		cycle steal mode
	    DMACTMOD0_IML		interruption mask
	***********************************************************/
	put_wvalue(DMACTMOD0, 0x34);
	
	put_wvalue(DMACCINT0, 0xFF);		/* DMACCINT0 clear */
	put_wvalue(DMACSAD0, I2SFIFOI);		/* source address */
	
	return;
}
/****************************************************************************/
/*  Setup of timer                                                          */
/*  Function : setup_timer                                                  */
/*      Parameters                                                          */
/*          Input   :   Nothing                                             */
/*          Output  :   Nothing                                             */
/****************************************************************************/
void setup_timer(void)
{
    put_wvalue(TMEN,  0x0);	/* disable timer (write '0' in TMEN[0])*/
    put_wvalue(TMOVF, 0x1);	/* clear overflow register (write '1' in TMOVF[0])*/

    put_wvalue(TMRLR, VALUE_OF_TMRLR);	/* set TMRLR */

    return;
}

/*****************************************************************************/
/*  System Timer handler                                                     */
/*  Function : timer_handler                                                 */
/*     Parameters                                                            */
/*          Input   :   Nothing                                              */
/*          Output  :   Nothing                                              */
/*****************************************************************************/
void timer_handler(void)
{
    counter++;

    put_wvalue(TMOVF, 0x01);    /* clear TMOVF register (write '1' in TMOVF[0]) */
    return;
}

/******************************************************************/
/*  Reading remained data                                         */
/*  Function : remained_data_read                                 */
/*      Parameters                                                */
/*          Input  :  Nothing                                     */
/*          Output :  Nothing                                     */
/******************************************************************/
void remained_data_read(void)
{
	UWORD data_size;
	UWORD * rp;
	
	put_wvalue(DMACMSK0, 0x1);		/* channel mask */
	set_wbit(I2SIMRI, 0x10);		/* DMA mask */
	
	data_size = (get_wvalue(I2SLRSI) & I2SLRSI_RFIFOLVL) >>8;
	
	rp = (UWORD *)get_wvalue(DMACDAD0);
	
	for(; data_size>0; rp++, data_size--)
	{
		*rp = get_wvalue(I2SFIFOI);
	}
	
	return;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?