/* CSIのSOUTとSINをつなげば、LoopBackでDMA転送できるはず。 (このプログラムは実機では試していません) */ #define CSIOBALREG 0xaf000028 #define CSIOBAHREG 0xaf00002a #define CSIIBALREG 0xaf000020 #define CSIIBAHREG 0xaf000022 #define DMARSTRREG 0xaf000040 #define DMASENREG 0xaf000044 #define DMAMSKREG 0xaf000046 #define DMAREQREG 0xaf000048 #define CONTROLREG 0xaf00004e #define DMAABITREG 0xaf00004c #define CMUREG 0xaf000060 #define CSI_MODEREG 0xaf0001a0 #define CSI_CLKSELREG 0xaf0001a1 #define CSI_CNTREG 0xaf0001b0 #define CSI_INTREG 0xaf0001b2 #define MSYSINT2REG 0xaf0000a6 #define MCSIINTREG 0xaf0000b6 int chk_result(void); void mak_source(void); void WriteReg8(long addr, int data); volatile int ReadReg8(long addr); void WriteReg16(long addr, int data); volatile int ReadReg16(long addr); void WriteReg32(long addr, int data); volatile int ReadReg32(long addr); int main(void) { int dat; asm("mtc0 $0,$12"); /* 割り込み禁止 */ CPU_UartPuts("Making Source Data\n"); mak_source(); CPU_UartPuts("CSI Setup\n"); WriteReg16(CMUREG, ReadReg16(CMUREG)|0x1040);/* クロックマスク解除 MSKSCSI=MSKCSI=1 */ WriteReg16(MCSIINTREG, 0x3);/* 受信DMA1ページ割り込み&FIFO受信オーバーラン割り込み */ dat = ReadReg16(MSYSINT2REG); WriteReg16(MSYSINT2REG, dat | 0x0100);/* CSI割り込み許可 */ WriteReg16(DMARSTRREG,0x1);/* DMAリセット */ WriteReg16(DMARSTRREG,0x0); WriteReg16(DMAMSKREG, 0x6);/* CSI送受信許可 */ WriteReg16(DMASENREG, 0x1);/* DMAシーケンサ許可 */ WriteReg16(DMAREQREG, 0x0);/* IO->RAM間の転送停止 */ WriteReg16(CONTROLREG,0x0);/* オートイニシャライズ禁止&DMAブロックサイズ4B */ WriteReg16(DMAABITREG,0x2);/* CSI受信優先 */ WriteReg32(CSIOBALREG, 0x00210000);/* ソースアドレス */ WriteReg32(CSIIBALREG, 0x00220000);/* デスティネーションアドレス */ dat = ReadReg16(CSI_CNTREG); WriteReg16(CSI_CNTREG, dat | 0x8000);/* CSIリセット */ WriteReg16(CSI_CNTREG, dat & 0x7fff);/* CSIリセット解除 */ while((ReadReg8(CSI_MODEREG) & 0x0001)!=0); /* アイドル状態を待つ */ WriteReg8(CSI_CLKSELREG, 0x6);/* クロック0.288MHz */ while((ReadReg8(CSI_MODEREG) & 0x0001)!=0); /* アイドル状態を待つ */ WriteReg8(CSI_MODEREG, 0xe4);/* CSIE=1 TRMD=CCL=1 AUTO=1 */ asm(".set noat"); asm("li $1,0x401"); asm("mtc0 $1,$12");/* 割り込み許可 */ asm(".set at"); dat = ReadReg16(CSI_INTREG); WriteReg16(CSI_INTREG, dat);/* 割り込みクリア */ CPU_UartPuts("DMA Start\n"); WriteReg16(CSI_CNTREG, 0x707);/* DMA開始 T_FIFOE=T_P1STP=T_DMAEN=R_FOFOE=R_P1STP=R_DMAEN=1 */ CPU_UartPuts("Wait for Interrupt\n"); asm(".word 0x42000021");/* STANDBY 割り込みを待つ */ return 0; } void mak_source(void) { short *s; short *e; int dat; s = (short*)0xa0210000; e = (short*)0xa0210800;/* 2KB=2Page */ dat = 0; while(s != e) *s++ = dat++; } int chk_result(void) { short *s; short *e; int dat; int dst; s = (short*)0xa0220000; e = (short*)0xa0220400;/* 1KB=1Page */ dat = 0; while(s != e){ dst = *s++; if(dst != dat) return 0; dat++; } return 1; } void WriteReg8(long addr, int data) { *(volatile char*)addr = data; } int ReadReg8(long addr) { return *(volatile char*)addr; } void WriteReg16(long addr, int data) { *(volatile short*)addr = data; } int ReadReg16(long addr) { return *(volatile short*)addr; } void WriteReg32(long addr, int data) { *(volatile long*)addr = data; } int ReadReg32(long addr) { return *(volatile long*)addr; } /* 割り込みハンドラの本体 */ void __global_exception_func(void) { int exc; __asm__ __volatile__ (/* Read Cause Register */ "mfc0 %0,$13\n\t" : "=r" (exc) : "0" (exc)); exc &= 0xfc; if(exc == 0){ CPU_UartPuts("Interrupt Occurred!\n"); exc = ReadReg16(CSI_INTREG); if(exc & 1) CPU_UartPuts("R_OVER\n"); if(exc & 2) CPU_UartPuts("R_P1STP\n"); WriteReg16(CSI_INTREG, exc);/* 割り込みクリア */ WriteReg16(CSI_CNTREG, 0x0);/* DMA停止 */ CPU_UartPuts("Checking Destination Data\n"); if(chk_result()==1) CPU_UartPuts("DMA Result is OK!\n"); else CPU_UartPuts("DMA Result is NG!\n"); } else CPU_UartPuts("Exception Occurred!\n"); }