I was trying to write a register context saving/restoring when I came across a weird behaviour.
My code (sorry, tried to format tens of times, but the editor WANTS to make asm a table):
When the exception is returned from, the calling function:
msg = "returned from SVC\r\n";
serial_io.put_string(msg, util_str_len(msg)+1);
asm volatile (
);
msg = "cpsr = ";
util_word_to_hex(scratchpad, tmp1);
serial_io.put_string(scratchpad, 9);
serial_io.put_string("\r\n", 3);
outputs "returned from SVC" and "cpsr = 60000013".
Why the "00000002"? the barriers don't seem to have any effect.
Now that you've seen my struggle, I wanted to give a status update:
I can now load a program with GDB through my stub, run the loaded program. set and delete breakpoints, and the program really breaks there and the GDB is notified about it. Just the PC gets some weird value, and I haven't found out yet where that comes from, but if I correct it manually from GDB (set $pc = 0x?????) I can 'cont' forward. The weird PC value is not in the memory area of the stub nor the debuggee.
I also tried with branch prediction and caches enabled, and it worked.
Now the code also copies itself into upper memory (0x1f000000) to let the debuggee to load to the default address 0x8000.
I wonder if I could use the hivec, and route all non-stub exceptions to lovec bu just jumping there. Then the debuggee could install its own exception vectors. Stub would just filter its own exceptions in the way (UART0 and BKPT). I could pre-install lovecs to unhandled exception handlers, and the debuggee then - if it wants to handle them - just overwrites them.
Hello turboscrew,
although I cannot catch your problems well, please let me more.
Is the code which will be copied to 0x1f000000 position independent?
Otherwise, did you map VA=0x8000 to PA=0x1f000000 by MMU?
Best regards,
Yasuhiko Koumoto.
No, it's not position independent, but linked like:
MEMORY { LOAD (rwx) : ORIGIN = 0x00008000, LENGTH = 512k /* initial */ EXEC (rwx) : ORIGIN = 0x1f000000, LENGTH = 512k /* runtime */ } SECTIONS { /* Starts at LOADER_ADDR. */ . = 0x8000; __text_start = .; .text : { *(.init) *start1.o(.text) *start1.o(.data) *start1.o(.bss) *(.text.startup) } >LOAD /* .text2 ALIGN(0x1000): - the ">EXEC AT>LOAD" didn't like "ALIGN(0x1000)" */ .text2 : { . = ALIGN(.,0x8); *loader.o(.text) *rpi2.o(.text) *serial.o(.text) *util.o(EXCLUDE_FILE(*instr_util.o).text) *gdb.o(.text) *(.text) } >EXEC AT>LOAD __text_end = .; __load_start = LOADADDR(.text2); __code_begin = ADDR(.text2); ...
The memory map is flat - just 1st level table with sections:
#define MMU_SECT_ATTR_NORMAL 0x00090c0a #define MMU_SECT_ATTR_DEV 0x00090c06 #define MMU_SECT_ENTRY(addr_meg, attr) ((addr_meg << 20) | attr) ... // program RAM for (tmp=0; tmp<0x3b0; tmp++) { master_xlat_tbl[tmp] = MMU_SECT_ENTRY(tmp, MMU_SECT_ATTR_NORMAL); } // video RAM (?) for (tmp=0x3b0; tmp<0x3f0; tmp++) { master_xlat_tbl[tmp] = MMU_SECT_ENTRY(tmp, MMU_SECT_ATTR_DEV); } // peripherals for (tmp=0x3f0; tmp<0xfff; tmp++) { master_xlat_tbl[tmp] = MMU_SECT_ENTRY(tmp, MMU_SECT_ATTR_DEV); }
And since it's write-through, I don't clean the caches, I just invalidate them.
Oh, and the copying is done before the MMU and caches are turned on.
I think this thread has passed its purpose long ago.
There were no answers to that, but the problem went away, and the next best thing to an answer was Jens' LED idea, so I'm marking it as a solution.
View all questions in Embedded forum