pyocd / pyOCD

Open source Python library for programming and debugging Arm Cortex-M microcontrollers
https://pyocd.io
Apache License 2.0
1.12k stars 478 forks source link

Unable to set breakpoint on Realtek RTL8195AM #317

Open marcuschangarm opened 7 years ago

marcuschangarm commented 7 years ago

When I try to set a breakpoint, for example on mbedtls_ssl_handshake in the test example below:

https://github.com/marcuschangarm/mbed-os-example-tls/tree/master/tls-client

I get this error:

(gdb) break mbedtls_ssl_handshake
Cannot access memory at address 0x3001c660

pyocd-gdbserver: 0.8.1a1 and 0.8.1a2.dev38 DAPLINK: 0241 GCC: 5.4.1 20160609 GDB: 7.10.1.20160616-cvs

marcuschangarm commented 7 years ago

@c1728p9 @0xc0170

flit commented 7 years ago

What target are you using for pyOCD (since the RTL8195 is not directly supported)?

Assuming the RTL8195 doesn't use an M7 core, the address 0x3001c660 is outside the supported hardware breakpoint range. So pyOCD will have to use a software breakpoint. If that address is not writeable, it will fail.

marcuschangarm commented 7 years ago

Oh, that's interesting. The RTL8195AM is a bit weird. It doesn't have execute-in-place flash, so code is copied to RAM and executed from there. It also has functions in ROM to complicate matters.

pyOCD detects it as a generic Cortex-M3:

WARNING:root:Unsupported board found 
INFO:root:DAP SWD MODE initialised
INFO:root:ROM table #0 @ 0xe00ff000 cidr=b105100d pidr=4000bb4c3
INFO:root:[0]<e000e000:SCS-M3 cidr=b105e00d, pidr=4000bb000, class=14>
WARNING:root:Invalid coresight component, cidr=0x0
INFO:root:[1]<e0001000: cidr=0, pidr=0, component invalid>
INFO:root:[2]<e0002000:FPB cidr=b105e00d, pidr=4002bb003, class=14>
WARNING:root:Invalid coresight component, cidr=0xb1b1b1b1
INFO:root:[3]<e0000000: cidr=b1b1b1b1, pidr=b1b1b1b1b1b1b1b1, component invalid>
WARNING:root:Invalid coresight component, cidr=0x0
INFO:root:[4]<e0040000: cidr=0, pidr=0, component invalid>
INFO:root:[5]<e0041000:ETM-M3 cidr=b105900d, pidr=4003bb924, class=9, devtype=13, devid=0>
INFO:root:CPU core is Cortex-M3
INFO:root:6 hardware breakpoints, 4 literal comparators
INFO:root:4 hardware watchpoints
INFO:root:Telnet: server started on port 4444
INFO:root:GDB server started at port:3333

The 0x3001c660 address is in a memory mapped SD-RAM chip:

MEMORY
{
  TCM (rwx)        : ORIGIN = 0x1FFF0000, LENGTH = 0x00010000
  ROM_USED_RAM (rwx)  : ORIGIN = 0x10000bc8, LENGTH = 0x10006000-0x10000bc8
  DATA_RAM (rwx)   : ORIGIN = 0x10002100, LENGTH = 0x10006000 - 0x10002100
  BD_RAM (rwx)     : ORIGIN = 0x10006000, LENGTH = 0x10070000 - 0x10006000
  SD_RAM (rwx)     : ORIGIN = 0x30000000, LENGTH = 2M
}
flit commented 7 years ago

Ok, I checked the code. If the target doesn't have a memory map, then it only supports using hardware breakpoints. But if the address is outside the hw breakpoint range, then the breakpoint request will fail. Sorry, but it won't work for the time being. The best solution is to add RTL8195AM support to pyOCD so it has a memory map.

@c1728p9 We should change BreakpointManager.set_breakpoint() to allow software breakpoints if there isn't a memory map, and only fail if the memory write fails.

marcuschangarm commented 7 years ago

@flit thank you for looking into it!

c1728p9 commented 7 years ago

@v2422 added limited support for this target in #322. You might give this a try @marcuschangarm

marcuschangarm commented 7 years ago

With the new version, I get the error after I try to continue the application:

(gdb) break mbedtls_ssl_handshake
Breakpoint 1 at 0x30025160
(gdb) mon reset
(gdb) c
Continuing.
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x30025160

(gdb) mon reset
Protocol error with Rcmd
(gdb) 

And this is the error output from pyOCD:

0040177:ERROR:gdbserver:Unhandled exception in handleMsg: 
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/pyOCD/gdbserver/gdbserver.py", line 471, in handleMsg
    reply = handler(msg[msgStart:])
  File "/Library/Python/2.7/site-packages/pyOCD/gdbserver/gdbserver.py", line 1016, in handleQuery
    return self.handleRemoteCommand(cmd)
  File "/Library/Python/2.7/site-packages/pyOCD/gdbserver/gdbserver.py", line 1125, in handleRemoteCommand
    self.target.resetStopOnReset()
  File "/Library/Python/2.7/site-packages/pyOCD/core/coresight_target.py", line 188, in resetStopOnReset
    return self.selected_core.resetStopOnReset(software_reset)
  File "/Library/Python/2.7/site-packages/pyOCD/coresight/cortex_m.py", line 529, in resetStopOnReset
    self.halt()
  File "/Library/Python/2.7/site-packages/pyOCD/coresight/cortex_m.py", line 442, in halt
    self.dp.flush()
  File "/Library/Python/2.7/site-packages/pyOCD/coresight/dap.py", line 125, in flush
    self.link.flush()
  File "/Library/Python/2.7/site-packages/pyOCD/pyDAPAccess/dap_access_cmsis_dap.py", line 583, in flush
    self._read_packet()
  File "/Library/Python/2.7/site-packages/pyOCD/pyDAPAccess/dap_access_cmsis_dap.py", line 738, in _read_packet
    decoded_data = cmd.decode_data(raw_data)
  File "/Library/Python/2.7/site-packages/pyOCD/pyDAPAccess/dap_access_cmsis_dap.py", line 419, in decode_data
    data = self._decode_transfer_data(data)
  File "/Library/Python/2.7/site-packages/pyOCD/pyDAPAccess/dap_access_cmsis_dap.py", line 317, in _decode_transfer_data
    raise DAPAccessIntf.TransferTimeoutError()
TransferTimeoutError

I'm using the newest Daplink 0243 and invoking pyOCD with the rtl8195am target.

samchuarm commented 7 years ago

@v2422

v2422 commented 7 years ago

Hi @marcuschangarm,

0x3xxxxxxx belongs to SDRAM. I think the reason is that SDRAM can't be accessed without initialization after reset. But breakpoint setup will try to do it.

I will try to fix it from pyOCD. Before that, I think you can stop at some early place first after bootloader, then you can setup your SDRAM breakpoint there. Like the following sequence

(gdb) b PLAT_Start
(gdb) mon reset
(gdb) c
(gdb) b mbedtls_ssl_handshake

Besides, I found that we can't set a hardware breakpoint at the address > 0x20000000. https://github.com/mbedmicro/pyOCD/blob/master/pyOCD/debug/breakpoints/manager.py#L52 Is it the limitation from coresight hardware?

marcuschangarm commented 7 years ago

@v2422 Thank you for looking into this!

As a reference, I can confirm that using a Segger JLink attached to the JTAG port allows me to set breakpoints in the SD-RAM.

However, I'm still having problems stepping through the code. I wonder if the elf-to-bin python script is confusing the debugger? and/or the pre-compiled binaries?

v2422 commented 7 years ago

Hi @marcuschangarm,

I don't fully understand. Could you describe more details?

  1. What's the break type about breakpoint/step on Segger? SW or HW breakpoint?
  2. Frankly speaking, elf-to-bin just transfers an ELF file into the image stored in flash. The bootloader initializes SDRAM then copies text/data to its execution address. The debugger just reads ELF then setups breakpoints on specific address. elf-to-bin should not influence debugger.
samchuarm commented 7 years ago

@marcuschangarm Could you please help answer Viller's questions?

marcuschangarm commented 7 years ago

Hi, sorry for the delay.

I misunderstood your original reply. When I do what you wrote I can debug the RTL8195AM using my Segger JLink. (I can't see what type of breakpoints it is setting, though).

When I use pyOCD, I don't get the break at PLAT_Start, the application just continues.

v2422 commented 7 years ago

Hi @marcuschangarm,

I think the bootloader overwrite your break instruction in PLAT_Start. Please replace b PLAT_Start with hb PLAT_Start

The steps look like,

  1. mon reset
  2. b PLAT_Start ; replace the instruction with BREAK
  3. continue
  4. bootloader copies instructions from LMA to VMA; in the steps, it overwrites your BREAK with real instruction
  5. PC goes to PLAT_Start

In steps 4, your software breakpoint is overwritten, so please use hardware breakpoint before bootloader. Then CPU will stop at PLAT_Start. Besides, what's the address of PLAT_Start?

c1728p9 commented 7 years ago

Hi @v2422, yep, the limitation here is a hardware limitation of the coresight breakpoint module. The address compare register of the FBP (flash break point) module only supports up to bit 28 (0 to 0x1FFFFFFF).

As a workaround, you may be able to use a data breakpoint to determine when the image has been loaded into ram. Once loaded you could use breakpoints like normal.