📄 161_spi.asm
字号:
//--------------- 6 0x0006 INIT DM40 ---------------
test_dm40_init: R0=R0-1; // checks for tag init dm40
IF NE JUMP (PC, test_pm_zero);
dm40_init: B0=R3;
LCNTR=R2, DO dm40_init.end UNTIL LCE;
CALL read_dma_info;
PX=dm(0x40004);
dm(i0,M6)=PX;
PX=dm(0x40005);
dm40_init.end: dm(i0,M6)=PX;
JUMP read_boot_info;
// -------------------------------------------------------
//--------------- 7 0x0007 ZERO PM16 ---------------
//--------------- 8 0x0008 ZERO PM32 ---------------
//--------------- 9 0x0009 ZERO PM40 ---------------
//--------------- 10 0x000A ZERO PM48 ---------------
test_pm_zero: R0=R0-R5; // R5=2, checks for tag zero pm16, zero pm32
IF LE JUMP (PC, dm_zero);
R0=R0-R5; // R5=2, checks for tag zero pm40, zero 48
IF LE JUMP (PC, dm40_zero);
// -------------------------------------------------------
//--------------- 11 0x000B INIT PM16 ---------------
//--------------- 12 0x000C INIT PM32 ---------------
//--------------- 13 0x000D INIT PM40 ---------------
//--------------- 14 0x000E INIT PM48 ---------------
test_pm_init: R0=R0-R5; // R5=2, checks for tag init pm16, init pm32
IF LE JUMP (PC, dm_init);
R0=R0-R5; // R5=2, checks for tag init pm40, init pm48
IF LE JUMP (PC, dm40_init);
// -------------------------------------------------------
//--------------- 15 0x000F ZERO DM64 ---------------
test_dm64_zero: R0=R0-1;
IF NE JUMP (PC, test_dm64_init);
dm64_zero: R2=R2+R2; //double count and initialize in NW memory
R3 = LSHIFT R3 by 1; //double longword address to NW memory
jump dm_zero;
//------------------------------------------------------------
//--------------- 16 0x0010 INIT DM64 ---------------
test_dm64_init: R0=R0-1;
IF NE JUMP (PC, test_pm64_zero);
dm64_init: I0=R3;
LCNTR=R2, DO dm64_init.end UNTIL LCE;
CALL read_SPI_word; /* read 32 lsbs of 64-bit word */
PX2=R8;
CALL read_SPI_word; /* read 32 msbs of 64-bit word */
PX1=R8;
nop;
nop; /* Call cannot be in last 3 instructions of loop */
dm64_init.end: DM(I0,M6)=PX (lw); /* write all 64-bits to longword address location */
JUMP read_boot_info;
//------------------------------------------------------------
//--------------- 17 0x0011 ZERO PM64 ---------------
//--------------- 18 0x0012 INIT PM64 ---------------
test_pm64_zero: R0=R0-1;
IF EQ JUMP (PC, dm64_zero);
test_pm64_init: R0=R0-1;
IF EQ JUMP (PC, dm64_init);
//------------------------------------------------------------
//=================================================================================
// "INIT PMx EXT" load "packed" instructions into external memory. External memory
// starts at address 0x200000 on the 21161. The format for this packing can be found
// in the Chapter 5 of the 21161 Hardware Reference. Zero-init code sections (many
// consecutive NOP's) are initialized using the EXT_ZERO_CODE subroutine above.
//----------------------------------------------------------------------------------
//--------------- 19 0x0013 INIT PM8 EXT ---------------
test_pm8_init_ext:
R0=R0-1; //checks for init pm8 ext tag
IF NE JUMP (PC, test_pm16_init_ext);
B0=R3;
R2=LSHIFT R2 by -1; //r2 was # 32-bit words -> two inits per loop, so half R2
LCNTR=R2, DO pm8_init.end UNTIL LCE;
CALL read_SPI_word; // r8 = B1 B2 B3 B4
lcntr=4, do loop8 until lce;
r8=rot r8 by 8; // rotate the 32 word left by 8 bits
loop8: DM(I0,M6)=R8; // to write out MSB (B1) first
CALL read_SPI_word; // r8 = B0 B0 B5 B6
DM(1,I0)=R8; // write out B6 to address n+1
R8=rot R8 by -8;
pm8_init.end: DM(I0,4)=R8; // write out B5 to address N, and then leave two
// blank addresses to comply w/ 8-bit packing convention.
JUMP read_boot_info;
//------------------------------------------------------------
//--------------- 20 0X0014 INIT PM16 EXT ---------------
test_pm16_init_ext:
R0=R0-1; //checks for init pm16 ext tag
IF NE JUMP (PC, test_pm32_init_ext);
B0=R3;
R2=LSHIFT R2 by -1;
LCNTR=R2, DO pm16_init.end UNTIL LCE;
CALL read_SPI_word; // r8 = B1 B2 B3 B4
DM(1,I0)=R8; // write out b3, b4
R8=LSHIFT R8 by -16;
DM(I0,2)=R8; // write out b1, b2
CALL read_SPI_word; // r8 = B0 B0 B5 B6
DM(I0,2)=R8; // write out B5, b6, leave 1 black address for 16-bit packing
nop;
pm16_init.end: nop; // call can't be in last 3 instructions of loop
JUMP read_boot_info;
//------------------------------------------------------------
//--------------- 21 0X0015 INIT PM32 EXT ---------------
test_pm32_init_ext:
R0=R0-1;
IF NE JUMP (PC, test_pm48_init_ext);
B0=R3;
LCNTR=R2, DO pm32_init.end UNTIL LCE;
CALL read_SPI_word;// r8 = B1 B2 B3 B4, then R8 = B0 B0 B5 B6
DM(I0,M6)=R8;
nop;
pm32_init.end: nop; // a call can't be in the last 3 instructions
JUMP read_boot_info;
//------------------------------------------------------------
//--------------- 22 0X0016 INIT PM48 EXT ---------------
test_pm48_init_ext:
R0=R0-1; //checks for init pm48 ext tag
IF NE JUMP (PC, ext_zero_code);
// configure External port for 48-bit writes (disable linkports)
ustat1=dm(SYSCON);
bit set ustat1 IPACK0;
dm(SYSCON)=ustat1;
I8=R3;
lcntr=R2, do pm48_init.end until lce;
CALL read_dma_info; // get 2 instructions (three 32-bit words)
I6=0x40004;
LCNTR=0x2, do loop1 until lce;
PX=DM(I6,M6); // read word from internal scratch locations
R0=PX1; // swap px registers for external write
PX1=PX2; // (see pag 5-13 of the 161 HW-Ref Rev3.0)
PX2=R0;
loop1: PM(I8,M14)=px; //write word to external memory
pm48_init.end: nop; //nested loops can't terminate on the same instruction
jump read_boot_info;
//===========================================================================
//============================= EXT_ZERO_CODE =============================
// This portion of code is used to initialize external memory with zero's
// r0 holds (tag - 22)
// r2 holds number of external #NOP's to be initialized
//
// calculate how many external addresses are used by each NOP based on the tag:
//
// If pm8 (tag: 23 0X0017 ZERO PM8 EXT), r0 = 1, so multiply count by 8 (lshift r2 by 3)
// If pm16 (tag: 24 0X0018 ZERO PM16 EXT), r0 = 2, so multiply count by 4 (lshift r2 by 2)
// If pm32 (tag: 25 0X0019 ZERO PM32 EXT), r0 = 3, so multiply count by 2 (lshift r2 by 1)
// If pm48 (tag: 26 0X001A ZERO PM48 EXT), r0 = 4, so multiply count by 1 (lshift r2 by 0)
//------------------------------------------------------------
ext_zero_code: r6=4;
r0=r6-r0, I0=R3; // calculate amount to shift by based on (4 - tag)
r2=lshift r2 by r0; // r2 = number addresses per NOP
LCNTR=R2, DO ext_zero_code.end UNTIL LCE;
ext_zero_code.end: DM(I0,M6)=M13; //m13=0
JUMP read_boot_info; //fetch header for next block
//===========================================================================
//============================= read_dma_info =============================
// This section performs a length 3, 32bit dma into scratch location
// that can be read out as 2 40 or 48 bit words
//------------------------------------------------------------
read_dma_info:
DM(IMSRX)=M14; /* setup up modify to 1*/
DM(CSRX)=M15; /* Setup DMA count to be 3 ~ 3 32 bit words = 2 48 bit words */
jump more;
//============================= read_SPI_word =============================
// This section reads ONE 32-bit spi word into a scratch location (0x40006)
// and then also into register R8
//------------------------------------------------------------
read_SPI_word:
DM(IMSRX)=M14; /* setup up modify to 1*/
DM(CSRX)=M14; /* Setup DMA count to be 1 */
more: DM(IISRX)=I15; /* Setup DMA destination address; I15 should be 0x40006*/
ustat1=dm(SPICTL);
bit set ustat1 RDMAEN;
dm(SPICTL)=ustat1;
SPI_DMA_not_done_yet: // Test SPI completion
R1 = DMA8ST;
R0 = DM(DMASTAT);
R0 = R0 AND R1;
IF NE jump SPI_DMA_not_done_yet;
ustat1=dm(SPICTL);
bit clr ustat1 RDMAEN;
dm(SPICTL)=ustat1;
r8=dm(0x40006);
rts;
//===========================================================================
// ============================= USER_INIT ========================================
// If any registers need initialization before the kernel begins importing the application,
// they should be done so here. Typically, a user would need to initialize SDRAM settings,
// but they may also modify WAIT, SYSCON, SPICTL, or LCTL to increase the speed of the boot
// process.
//
// This subroutine may include NO MORE THAN 48 instructions (in addition to the RTS). As
// modifications are made, "kernel.map" shows the updated number of remaining free locations
// under "Memory-Words-Unused".
// -----------------------------------------------------------------------------------
user_init:
#if SDRAM
r0=0xFFFFF; // clear MSx waitstate and mode
dm(WAIT)=r0;
r0=900; // refresh rate
dm(SDRDIV)=r0;
r0=0x5114662; // SDRAM running @ Core-clock
dm(SDCTL)=r0;
#endif
// ~~~~~INSERT SYSTEM INITIALIZATION CODE HERE ~~~~
RTS; // return from user_init to loader_kernel_init
// ============================ END USER_INIT =====================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -