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.
Good ideas, but not quite appropriate in my case: I don't know whether the processor's i-mask is somehow set, or the interrupt handling has gone nuts. I might get some sense if I could get a couple of 32-bit values when the problem hits, so LEDs are not very working solution. From the led I know that it at least visited the command interpreter loop, but whether it runs there isolated from the rest of the world or left for better code and left the LED lit, I don't know.
If I add too much led blinking with delays, gdb gets upset and I can't debug. That's why it's hard to use serial for debugging in the first place. The serial seems to work as long as a debuggee that uses interrupts is not started (or hasn't taken the interrupts in the use yet). I once put some serial output in the interrupt handler - the gdb refused to load a program: too much "garbage" instead of ACK.
The other problem is, that I only have one USB/serial cable for RPi (3,3V), and this RPi 2B is my first ARM-board ever. I have one atMega-board, but it's 5V, so better not connect... My other USB/serial cable is for the atMega, it's 5V.
I also don't have a DVI display nor a DVI cable, and writing a graphics driver on top of everything (and as "blindfolded" as now) is a bit heavy thing to do... The same goes with USB-driver.
I guess if I had one more cable, it would be 3,3V - 5V adjustable JTAG.
Summa summarum: Children, don't try this at home!
[EDIT]
Oh, and I forgot - in the command interpreter loop, the first thing is to go and get a command packet...
The program doesn't actually loop...
(It must be this terrible flu - it's participating actively in driving me nuts...)
[/EDIT]
Flu is always terrible.
I know it's not appropriate for this kind of debugging, but if you at some other point needs a 32-bit value and you only have a LED, try this:
repeat(32){ LED(1); delay_ms(200); LED(0); delay_ms(100); LED(value >> 31) &1; value = value << 1; delay_ms(500); LED(0); delay_ms(100); } delay_ms(5000);
This should give you enough time to write the bit values down on a piece of paper.
The quick flashes are there in order to separate the bits visually.
JTAG should not need to be 5V; I think it only needs to be 3.3V, even for 5V devices. It just needs 5V tolerant I/O-pins.
(I prefer JTAG-lock-pick Tiny 2 myself; it's both JTAG and SWD and works very well with all the targets I know; furthermore I think it's compatible with the KEIL tools). Freddie Chopin might be able to tell you more about it.
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.
Your LED idea is clever! Maybe I'll try next time.
I think I'm getting a scent of what's going on. The debuggee interrupt doesn't return where it should.
I guess I have to check my context handling still more carefully - especially the stacks. To avoid overflowing the debuggee's stacks I switch into mine, and then switch back at return.
I copied the breakpoint command and cont command that gdb sends, then I used gdb upto loading the program, disconnected and switched to terminal where I gave the breakpoint command and cont-command manually.
And I finally got to see something...
I got carried away...
Bus Blaster ( Bus Blaster - DP ) could be an option...
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 was so desperate that I was mentally prepared to use ETB...
But I found out that the chip used in RPi2B only has debug logic and performance counters. No other debug peripherals,- and especially: no ETB.
Darn!
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.