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.
Looks like the original question will remain unsolved. For other things I had to make quite some changes into the code, and the problen doesn't show up anymore.
Instead, using the double vectoring caused some instabilities, and I'm about to become insane. I haven't found the cause, and the main symptom is that the serial line seems to stop working. I suspect that something somewhere turns the interrupt mask on. Hard to debug, when the problem "mutes" the only communication channel, and the LEDs are not informative enough...
It can be quite difficult to debug without having a display or a communications channel to a computer.
Remember that you can blink the LEDs.
One blink + long delay means this ...
Two blinks + long delay means that ...
Three blinks + long delay ... etc. ...
If you have more than one LED available, then you can switch between them; or you can blink LED 1 X times, then blink LED 2 Y times, then have a few seconds delay.
Note: I sometimes connect a small Cortex-M to one pin, which I can send data through.
Eg. for instance, if I have a problem on a STM32F427, and I can't use the UART for debugging, I bit-bang the data on a GPIO pin to a STM32F103.
The STM32F103 watches one GPIO pin and when a data-byte is received, it can output it on a connected SPI-display.
-Or it can transmit the data to a computer via the UART.
You can easily receive 16 bits at a time on the GPIO pins with the STM32F103, so it's a great little tool.
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.