I am working on a MIPS32 SOC system, where there is 32MB DRAM.
I want to setup interrupt and exception handlers for it, per MIPS ISA, I clear the BEV in status register and set IV in cause register of CP0, I would use 0x80000180 and 0x80000200 for exception and interrupt handling. So I worked out a board.ld as follows,
OUTPUT_FORMAT("elf32-tradlittlemips")
OUTPUT_ARCH(mips)
ENTRY(__start)
MEMORY
{
ram (rwx) : ORIGIN = 0x80100000, LENGTH = 31M
ramv (rwx) : ORIGIN = 0x80000000, LENGTH = 16K
}
SECTIONS
{
.start : {
*(.start)
} > ram
.vectors_load : {
_vectors_load_start = .;
. = ALIGN(4);
KEEP(*(.reset))
. = _vectors_load_start + 0x180;
. = ALIGN(4);
KEEP(*(.gen_excpt))
. = _vectors_load_start + 0x200;
. = ALIGN(4);
KEEP(*(.ebase_excpt))
. = _vectors_load_start + 0x300;
. = ALIGN(4);
KEEP(*(.cache_excpt))
. = _vectors_load_start + 0x380;
. = ALIGN(4);
KEEP(*(.bev_excpt))
. = _vectors_load_start + 0x400;
. = ALIGN(4);
KEEP(*(.int_excpt))
. = _vectors_load_start + 0x480;
. = ALIGN(4);
KEEP(*(.dbg_excpt))
. = _vectors_load_start + 0x500;
_vectors_load_end = .;
} > ramv
.text : {
_stext = .;
*(.text .text.*)
......
}
which defined entry point (__start) is 0x80100000, and the vectors are all in 0x80000N00.
From the following in System.map I think the vectors are in the location specified by board.ld.
Memory Configuration
Name Origin Length Attributes
ram 0x0000000080100000 0x0000000001f00000 xrw
ramv 0x0000000080000000 0x0000000000004000 xrw
*default* 0x0000000000000000 0xffffffffffffffff
Linker script and memory map
.start 0x0000000080100000 0x178
*(.start)
.start 0x0000000080100000 0x178 my_head.o
0x0000000080100000 __start
.vectors_load 0x0000000080000000 0x500
0x0000000080000000 _vectors_load_start = .
0x0000000080000000 . = ALIGN (0x4)
*(.reset)
.reset 0x0000000080000000 0x10 my_head.o
0x0000000080000000 __reset
0x0000000080000180 . = (_vectors_load_start + 0x180)
*fill* 0x0000000080000010 0x170
0x0000000080000180 . = ALIGN (0x4)
*(.gen_excpt)
.gen_excpt 0x0000000080000180 0x10 my_head.o
0x0000000080000200 . = (_vectors_load_start + 0x200)
*fill* 0x0000000080000190 0x70
0x0000000080000200 . = ALIGN (0x4)
*(.ebase_excpt)
.ebase_excpt 0x0000000080000200 0x10 my_head.o
0x0000000080000300 . = (_vectors_load_start + 0x300)
*fill* 0x0000000080000210 0xf0
0x0000000080000300 . = ALIGN (0x4)
*(.cache_excpt)
0x0000000080000380 . = (_vectors_load_start + 0x380)
*fill* 0x0000000080000300 0x80
0x0000000080000380 . = ALIGN (0x4)
*(.bev_excpt)
.bev_excpt 0x0000000080000380 0x10 my_head.o
0x0000000080000400 . = (_vectors_load_start + 0x400)
*fill* 0x0000000080000390 0x70
0x0000000080000400 . = ALIGN (0x4)
*(.int_excpt)
.int_excpt 0x0000000080000400 0x10 my_head.o
0x0000000080000480 . = (_vectors_load_start + 0x480)
*fill* 0x0000000080000410 0x70
0x0000000080000480 . = ALIGN (0x4)
*(.dbg_excpt)
0x0000000080000500 . = (_vectors_load_start + 0x500)
*fill* 0x0000000080000480 0x80
0x0000000080000500 _vectors_load_end = .
.text 0x0000000080100180 0x51260
0x0000000080100180 _stext = .
*(.text .text.*)
Here is the codes to setup interrupt and exception.
cp0_putebase(0x80000000);
/* Set the INTCTL vector spacing to non-zero */
cp0_putintctl(0x00000020);
/* Set the IV bit in the CAUSE register */
regval = cp0_getcause();
regval |= CP0_CAUSE_IV;
cp0_putcause(regval);
/* Clear the EXL and BEV bits in the STATUS register */
regval = cp0_getstatus();
regval &= ~(CP0_STATUS_EXL | CP0_STATUS_BEV);
cp0_putstatus(regval);
__asm__ volatile(
"sync\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
);
With JTAG and GDB, I loaded my image to 0x80000000 (so the vectors are well populated), I started running the image from 0x80100000.
To my surprise, I hit the codes in _bev_exception at 0x80000380 instead of 0x80000200 when the interrupt is enabled through status register, which caused no calling of interrupt handler!
I checked the cause and status registers of CP0, when _bev_exception is called, they are,
status: 00000303; cause: 40808100, there seemed be interrupt but why it is trapped to _bev_exception instead of 0x80000200?