📄 basiccrt.s
字号:
/* Copyright (C) 2000 Analog Devices Inc., All Rights Reserved.
** This contains Analog Devices Background IP and Development IP as
** defined in the ADI/Intel Collaboration Agreement.
** ADI/Intel Confidential.
*/
// basic startup code which
// - installs default event handlers (!SMALL)
// - turns the cycle counter on
// - loads up FP & SP (both supervisor and user)
// - initialises the device drivers (FIOCRT)
// - gets out of supervisor mode and into user mode (!SMALL)
// - loads other registers with unassigned pattern 0x81818181 (!SMALL)
// - calls monstartup to set up the profiling routines (PROFCRT)
// - calls the C++ startup (CPLUSCRT)
// - initialises argc/argv (FIOCRT/normal)
// - calls _main
// - calls _exit (which calls monexit to dump accumulated prof data (PROFCRT))
// - defines dummy IO routines (!FIOCRT)
#include <DefBlackfin.h>
#define IVBh (EVT0 >> 16)
#define IVBl (EVT0 & 0xFFFF)
#ifdef SMALL
#define UNASSIGNED_FILL 0
// just IVG15
#define INTERRUPT_BITS 0x400
#else
#define UNASSIGNED_FILL 1
// all interrupts
#define INTERRUPT_BITS 0x7FF
#endif
.section program;
.align 4;
start:
// Zap loop counters to zero, to make sure that
// hw loops are disabled - it could be really baffling
// if the counters and bottom regs are set, and we happen
// to run into them.
P0.H = 0xFFC0;
P0.L = 0x4C0A;
r1.h = 0x0000;
r1.l = 0x0817; //Micron 64MB MT48LC4M16A2-7E
w[p0] = r1;
p0 += -6;
r1.h = 0x0404; //Micron 64MB MT48LC4M16A2-7E
r1.l = 0x0015; //Micron 64MB MT48LC4M16A2-7E
[p0] = r1;
p0 += -4;
r1.h = 0x0091; //Micron 64MB MT48LC4M16A2-7E
r1.l = 0x99fb; //Micron 64MB MT48LC4M16A2-7E
[p0] = r1;
R7 = 0;
LC0 = R7;
LC1 = R7;
// Clear the DAG Length regs too, so that it's safe to
// use I-regs without them wrapping around.
L0 = R7;
L1 = R7;
L2 = R7;
L3 = R7;
// Initialise the Event Vector table.
P0.H = IVBh;
P0.L = IVBl;
#ifdef SMALL
// For the small environment, zero the EVT, so that
// there is defined behaviour.
P0 += 2*4; // Skip Emulation and Reset
P1 = 13;
//R1 = 0;
R1.H = usermode;
R1.L = usermode;
LSETUP (.ivt,.ivt) LC0 = P1;
.ivt: [P0++] = R1;
// Set IVG15's handler to be the start of the mode-change
// code. Then, before we return from the Reset back to user
// mode, we'll raise IVG15. This will mean we stay in supervisor
// mode, and continue from the mode-change point., but at a
// much lower priority.
P1.H = supervisor_mode;
P1.L = supervisor_mode;
[P0] = P1;
#else
// Clear out the IVT. Install exception handler
// to deal with ISR-registering, exit/abort, and
// file I/O.
R1 = 0;
P1 = 12;
LSETUP(.ivt, .ivt) LC0 = P1;
P1.L=_ex_def_exception;
P1.H=_ex_def_exception;
[P0++]=R1; // emu
[P0++]=R1; // reset
[P0++]=R1; // nmi
[P0++]=P1; // exceptions
.ivt: [P0++]=R1; // remaining entries
#endif /* SMALL */
R0 = SYSCFG; // Enable the Cycle counter
BITSET(R0,1);
SYSCFG = R0;
// Initialise the stacks. First the user-mode stack:
FP.L=ldf_stack_end;
FP.H=ldf_stack_end;
SP.L=ldf_stack_end;
SP.H=ldf_stack_end;
usp = sp;
// Now the supervisor stack.
SP.L=ldf_sysstack_end - 16;
SP.H=ldf_sysstack_end - 16;
#ifdef L1CACHE
#define NUM_ICPLBS 16
#define NUM_DCPLBS 16
#ifdef ICACHE
// Enable Code L1 memory as Cache
P0.L = (IMEM_CONTROL & 0xFFFF);
P0.H = (IMEM_CONTROL >> 16);
R0 = [P0];
R1 = ENIM|IMC;
R0 = R0 | R1;
[P0] = R0;
//Invalidate the cache for Code L1
P3.L = (ITEST_DATA0 & 0xFFFF);
P3.H = (ITEST_DATA0 >> 16);
R0=0;[P3]=R0; // Cache Line Invalid Command
P3.L = (ITEST_COMMAND & 0xFFFF);
P3.H = (ITEST_COMMAND >> 16);
p2=0x4; // Four Mini Banks
lsetup(iflushs0,iflushe0) lc1=p2;
iflushs0:
p2=0x40; //128 cache lines 32 bytes per line one mini-bank
lsetup(iflushs1,iflushe1) lc0=p2;
iflushs1:
r0=lc1;
r0+=-1;
r0<<=16; // place mini banks at 16:17
r1=lc0;
r1+=-1;
r1<<=5;
r2=r0 | r1;
bitset(r2,1); // Write access
[p3]=r2; // Way 0
bitset(r2,26); // Set to Way 1
[p3]=r2; // Way 1
bitset(r2,27); // Set to Way 3
[p3]=r2; // Way 3
bitclr(r2,26); // Set to Way 2
[p3]=r2; // Way 2
iflushe1:nop;
iflushe0:nop;
#endif
#ifdef DCACHE
// Enable Data Bank A and Bank B for Cache
P0.L = (DMEM_CONTROL & 0xFFFF);
P0.H = (DMEM_CONTROL >> 16);
R0 = [P0];
R1 = ENDM|ACACHE_BCACHE ;
R0 = R0 | R1;
[P0] = R0;
//Invalidate the cache for Bank A
P3.L = (DTEST_DATA0 & 0xFFFF);
P3.H = (DTEST_DATA0 >> 16);
R0=0;[P3]=R0; // Cache Line Invalid Command
P3.L = (DTEST_COMMAND & 0xFFFF);
P3.H = (DTEST_COMMAND >> 16);
p2=0x4; // Four Mini Banks
lsetup(dbankaflushs0,dbankaflushe0) lc1=p2;
dbankaflushs0:
p2=0x40; //128 cache lines 32 bytes per line one mini-bank
lsetup(dbankaflushs1,dbankaflushe1) lc0=p2;
dbankaflushs1:
r0=lc1;
r0+=-1;
r0<<=16; // place mini banks at 16:17
r1=lc0;
r1+=-1;
r1<<=5; // place Index at 5:10
r2=r0 | r1;
bitset(r2,1); // Write access
[p3]=r2; // Way 0
bitset(r2,26); // Set to Way 1
[p3]=r2; // Way 1
dbankaflushe1:nop;
dbankaflushe0:nop;
//Invalidate the cache for Bank B
P3.L = (DTEST_DATA0 & 0xFFFF);
P3.H = (DTEST_DATA0 >> 16);
R0=0;[P3]=R0; // Cache Line Invalid Command
P3.L = (DTEST_COMMAND & 0xFFFF);
P3.H = (DTEST_COMMAND >> 16);
p2=0x4; // Four Mini Banks
lsetup(dbankbflushs0,dbankbflushe0) lc1=p2;
dbankbflushs0:
p2=0x40; //128 cache lines 32 bytes per line one mini-bank
lsetup(dbankbflushs1,dbankbflushe1) lc0=p2;
dbankbflushs1:
r0=lc1;
r0+=-1;
r0<<=16; // place mini banks at 16:17
r1=lc0;
r1+=-1;
r1<<=5;
r2=r0 | r1;
bitset(r2,1); // Write access
bitset(r2,23); // Data Bank B
[p3]=r2; // Way 0
bitset(r2,26); // Set to Way 1
[p3]=r2; // Way 1
dbankbflushe1:nop;
dbankbflushe0:nop;
// set ITestCmd back to 0 so the write bit is not set
// set DTestCmd back to 0 so the write bit is not set
P3.L = (DTEST_COMMAND & 0xFFFF);
P3.H = (DTEST_COMMAND >> 16);
r0 = 0;
[p3] = r0;
#endif
#ifdef ICACHE
P3.L = (ITEST_COMMAND & 0xFFFF);
P3.H = (ITEST_COMMAND >> 16);
r0 = 0;
[p3] = r0;
#endif
#ifdef DCACHE
P0.L = (DMEM_CONTROL & 0xFFFF);
P0.H = (DMEM_CONTROL >> 16);
R0 = [P0];
R1 = ~ENDM;
R0 = R0 & R1;
[P0] = R0;
#endif
#ifdef ICACHE
P0.L = (IMEM_CONTROL & 0xFFFF);
P0.H = (IMEM_CONTROL >> 16);
R0 = [P0];
R1 = ~ENIM;
R0 = R0 & R1;
[P0] = R0;
// Set up ICPLBs
i0.l = ICPLB_ADDR0 & 0xFFFF;
i0.h = ICPLB_ADDR0 >> 16;
i1.l = ICPLB_DATA0 & 0xFFFF;
i1.h = ICPLB_DATA0 >> 16;
i2.l = icplbs_table;
i2.h = icplbs_table;
p4 = NUM_ICPLBS;
lsetup(start_icplb, end_icplb) lc0=p4;
start_icplb: r2 = [i2++]; // address
[i0++] = r2;
r2 = [i2++]; // data
end_icplb: [i1++] = r2;
#endif
#ifdef DCACHE
// Set up DCPLBs
i0.l = DCPLB_ADDR0 & 0xFFFF;
i0.h = DCPLB_ADDR0 >> 16;
i1.l = DCPLB_DATA0 & 0xFFFF;
i1.h = DCPLB_DATA0 >> 16;
i2.l = dcplbs_table;
i2.h = dcplbs_table;
/* read entries from table */
p4 = NUM_DCPLBS;
lsetup(start_dcplb, end_dcplb) lc0=p4;
start_dcplb: r2 = [i2++]; // address
[i0++] = r2;
r2 = [i2++]; // data
end_dcplb: [i1++] = r2;
#endif
#ifdef ICACHE
// Enable Cache with CPLBs enabled
p0.l = IMEM_CONTROL & 0xFFFF;
p0.h = IMEM_CONTROL >> 16;
r0 = (IMC | ENICPLB | ENIM);
[p0] = r0;
#endif
#ifdef DCACHE
p0.l = DMEM_CONTROL & 0xFFFF;
p0.h = DMEM_CONTROL >> 16;
r0 = (ACACHE_BCACHE | ENDCPLB | ENDM);
[p0] = r0;
#endif
#endif /* L1CACHE */
#ifdef FIOCRT
// initialise the devices known about for stdio.
call _init_devtab;
#endif /* FIOCRT */
// Enable interrupts
R0 = INTERRUPT_BITS;
R0 <<= 5; // enable interrupts; 4-0 not settable
STI R0;
#ifdef SMALL
RAISE 15;
#endif
// Move the processor into user mode.
P0.L=usermode;
P0.H=usermode;
RETI=P0;
rti; // should take us to following instruction in user mode
usermode:
#ifdef SMALL
// In the small configuration, we don't want to be in user mode,
// because of the bloat required to service requests to supervisor
// resources. So we've arranged for IVG15 to be raised earlier,
// and it should take effect here...
JUMP usermode;
// ...and bring us to here.
supervisor_mode:
[--SP] = RETI; // re-enables the interrupt system
#endif /* SMALL */
#ifdef UNASSIGNED_FILL
P0.L=unass;
P0.H=unass;
R0=[P0];
R2=R0;
R3=R0;
R4=R0;
R5=R0;
R6=R0;
R7=R0;
P0=R0;
P1=R0;
P2=R0;
P3=R0;
P4=R0;
P5=R0;
[SP]=R0;
[SP+4]=R0;
[FP]=R0;
[FP+4]=R0;
#endif
#ifdef PROFCRT
call monstartup; // initialise profiling routines
#endif /* PROFCRT */
#ifdef PROFGUIDE
call ___start_prof; // initialise profile guided routine
#endif /* PROFGUIDE */
#ifdef CPLUSCRT
R0=0; // load up R0 and R1 and call _main()
R1=R0;
call ___ctorloop;
#endif /* CPLUSCRT */
#ifdef FIOCRT
// FILE IO provides access to real command-line arguments.
// call __getargv;
r1.l=__Argv;
r1.h=__Argv;
#else
// Default to having no arguments and a null list.
R0=0;
R1.L=argv;
R1.H=argv;
#endif /* FIOCRT */
// At long last, call the application program.
call _main;
call _exit; // passing in main's return value
nop;
nop;
HLT; // In case we're still here.
.global start;
.type start,STT_FUNC;
.global _main;
.type _main,STT_FUNC;
.global _exit;
.type _exit,STT_FUNC;
#ifdef FIOCRT
.global __getargv;
.type __getargv,STT_FUNC;
.global _init_devtab;
.type _init_devtab,STT_FUNC;
#else
// If File IO support isn't provided, then
// we provide dummy versions of the device-handling
// functions, so that the exception handlers don't rely
// on the file IO library
.align 2;
_dev_open:
_dev_close:
_dev_write:
_dev_read:
_dev_seek:
_dev_dup:
R0 = -1;
RTS;
.global _dev_open;
.type _dev_open,STT_FUNC;
.global _dev_close;
.type _dev_close,STT_FUNC;
.global _dev_write;
.type _dev_write,STT_FUNC;
.global _dev_read;
.type _dev_read,STT_FUNC;
.global _dev_seek;
.type _dev_seek,STT_FUNC;
.global _dev_dup;
.type _dev_dup,STT_FUNC;
#endif /* FIOCRT */
.section data1;
#ifndef FIOCRT
// With no FILE IO support, we cannot fetch arguments
// from the command line, so we provide a null list.
.align 4;
argv:
.byte4=0; // argv[0]==0
#endif /* !FIOCRT */
.align 4;
unass:
.byte4=0x81818181;
.align 4;
nullp:
.byte4=0; // no environment pointers
.align 4;
__Environ:
.byte4=nullp;
.global __Environ;
.type __Environ,STT_OBJECT;
#ifdef L1CACHE
// Data for use when initialising the CPLBs when setting up
// the cache.
icplbs_table:
.byte4=
0xEF000000, (PAGE_SIZE_4MB | CPLB_LOCK | CPLB_VALID), // Needed for 21535 chip anomaly
0xF0000000, (PAGE_SIZE_1MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // L2 SRAM
0x03400000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x03000000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x02C00000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x02800000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x02400000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x02000000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x01C00000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x01800000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x01400000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x01000000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x00C00000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x00800000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x00400000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID), // SDRAM
0x00000000, (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID); // SDRAM
dcplbs_table:
#define SGENERIC (CPLB_L1_CHBL | CPLB_WT | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID)
#define AGENERIC (CPLB_WT | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID)
.byte4=
0xFFC00000, (PAGE_SIZE_4MB | CPLB_WT | CPLB_SUPV_WR | CPLB_LOCK | CPLB_VALID), // MMRs
0xFFB00000, (PAGE_SIZE_1MB | CPLB_WT | CPLB_SUPV_WR | CPLB_LOCK | CPLB_VALID), // Scratchpad
0xF0000000, (PAGE_SIZE_1MB | SGENERIC), // L2 SRAM
0xEEF00000, (PAGE_SIZE_1MB | CPLB_WT | CPLB_SUPV_WR | CPLB_LOCK | CPLB_VALID), // PCI
0x02C00000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x02800000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x02400000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x02000000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x01C00000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x01800000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x01400000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x01000000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x00C00000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x00800000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x00400000, (PAGE_SIZE_4MB | SGENERIC), // SDRAM
0x00000000, (PAGE_SIZE_4MB | SGENERIC); // SDRAM
#endif /* L1CACHE */
#ifdef CPLUSCRT
.section ctor;
.align 4;
___ctor_table:
.byte4=0;
.global ___ctor_table;
.type ___ctor_table,STT_OBJECT;
#endif /* CPLUSCRT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -