-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathDebugging_physical_targets_(FPGA%2FASIC).mw
261 lines (175 loc) · 15 KB
/
Debugging_physical_targets_(FPGA%2FASIC).mw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
==Introduction==
Physical implementations of OpenRISC systems can be debugged using a set of tools made available here at OpenCores.org. Whether simply poking registers in IP cores or debugging complex software executing on the processor, these tools provide a useful debugging capability. This section will outline how to setup the required tools, and perform debugging on a physical OpenRISC target.
==Overview==
The components involved in debugging a physical target are outlined here.
The following block diagram gives a simplistic representation of the components involved in debugging a physical target.
debugging physical target block diagram
[[File:debugger-fpga-block.png|1000px|center|debugging physical target block diagram Photo]]
===GDB for OpenRISC===
The GNU debugger, GDB, is a popular tool that is capable of debugging many architectures from many platforms. The OpenRISC port of GDB, currently maintained by Jeremy Bennett of [http://www.embecosm.com/ Embecosm] is used as the primary debugging tool for all OpenRISC targets. It functions as, among other things, the actual user interface when debugging.
===The OpenRISC Debug Proxy===
[http://openocd.sourceforge.net/ OpenOCD] is used as the debug proxy both for verilog simulations and for running OpenRISC on a physical target.
===The JTAG TAP===
These two modules located in the OpenRISC-based design implement the JTAG communications and debugging capability, respectively. JTAG actually refers to the name of the group which oversaw the definition of a 5-pin serial protocol for accessing and controlling digital circuitry. The Joint Test Action Group defined a testing architecture, called the JTAG boundary scan which is commonly used to test digital integrated circuits. It is also used for other purposes, such as configuring FPGAs, and in this case, to communicate with the debug module inside our design.
The JTAG TAP, or test access point is a state machine controlling the boundary scan architecture. In our case, we use it solely to connect to the debug interface module.
For further information, it is possible to obtain the actual JTAG standard as published by the IEEE, however it is not free. There also exists a wide selection of introductions to the JTAG boundary scan architecture. Texas Instruments have available a JTAG primer. Embecosm also have a good overview of the JTAG boundary scan architecture.
===The SoC debug interface module===
The [http://opencores.org/project,dbg_interface SoC debug interface] is the module implementing the ability to control the CPU, and access the system's Wishbone bus, from the JTAG port. When the TAP is in debug mode, the JTAG pins are connected directly to this module.For more information about the module, see the project's documentation (must be logged into OpenCores).
==Getting Started==
To debug a physical target, the tools in the chain must be installed and configured.
===GDB===
For information on installing the OpenRISC compatible GDB, see the OpenRISC project's [[OpenRISC GNU tool chain|GNU toolchain]] page here at OpenCores.
==Setup a UART Console==
The UART console is an extremely useful part of the OpenRISC system. Setting up a console on the PC which communicates with the board via the UART is briefly outlined here.
The default configuration of the UART in most of the software used on OpenCores is with a baud rate of 115200bps, no parity bits and one stop bit (115200/N/1). Setting up a console application, such as minicom in Linux or HyperTerminal in Windows, is relatively easy to do.
===Windows===
Open HyperTerminal (usually in Start->Programs->Accessories->Communications->HyperTerminal), and configure a new connection using the COMport for the debug cable (usually a random number, in the author's case it was COM10, typically it's greater than 4), and set Bits per second to 115200, Data bits to 8, Parity to none, Stop bits to 1, and Flow control to none.
The magnificent Windows Vista did not ship with HyperTerminal, so an alternative called TeraTerm can be used instead. It can be obtained from the project's homepage.
===Linux===
There are several possible terminal applications that can be used under Linux. A few are minicom, gtkterm and kermit. It should be relatively straight forward to setup any of these according to the configuration cited above (115200bps, 8-data/noparity/1-stop bits).
===minicom===
Setting up minicom to use as a terminal with the OpenRISC system is now explained.
It should be simple to install minicom using the package manager on your distribution. Under Ubuntu, it can be done with apt-get like so:
user@host:~/$ sudo apt-get install minicom
Once installed, minicom must be run once as the root user with the -s option to create essential configuration files. Running sudo minicom -s brings up minicom's setup menu. Going to the Serial port setup submenu, change the Serial Device to /dev/ttyUSB0, the Bps/Par/Bits to 115200 8N1, and set both Hardware Flow Control and Software Flow Control to No. Go back to the main menu and choose Save setup as dfl. minicom is now ready to use, and can be launched with no command line parameters.
===gtkterm===
gtkterm is a more graphical terminal. Just like minicom, it should be easy enough to install on most Linux distributions, and can be done under Ubuntu like so:
user@host:~/$ sudo apt-get install gtkterm
It can then be launched from a console with the following line:
gtkterm --speed=115200 -p /dev/ttyUSB0
===A note on starting the proxy and terminal===
When the proxy is launched, one of the two ttyUSB devices will disappear because it is claimed by the D2XX driver. It is recommended that the proxy is launched before the terminal - this should ensure the remaining ttyUSB device is the UART descriptor. However, due to inconsistencies with the FTDI D2XX driver under different Linux distributions, it can be the case that the UART is on device /dev/ttyUSB1. If this is the case, the terminal application must be reconfigured to point to this device.
Another issue to be aware of is that closing and restarting the proxy while the terminal console is connected will cause the descriptor for the UART to change and the terminal getting disconnected from the UART device. If the proxy is restarted and the terminal is connected, the terminal must be restarted before it will work again.
==Debugging The Target==
The following explains how to setup the connection to the physical target.
===Connecting to the target===
Start OpenOCD in a new terminal window with the correct OpenOCD configuration files. The configuration files are used to identify both how to connect to the JTAG interface and how to communicate with the on-chip debug interface.
OpenOCD supports [http://repo.or.cz/w/openocd.git/tree/HEAD:/tcl/interface many different JTAG adapters], so the first step is to find out which adapter to use. Below is a list of common interfaces used for OpenRISC development
{|
! style="text-align:left;"| Config file
! Usage
|-
|jtag_vpi.cfg
|Used for verilog simulations only. Can connect to a jtag_vpi instance in a running simulator (e.g. modelsim, Icarus)
|-
|altera_usb_blaster.cfg
|Connects to an Altera USB Blaster programming cable
|}
The next step is to select a configuration file that describes the target that the JTAG interface connects to. For OpenRISC we only need to specify the <code>or1k_generic.cfg</code> file as that contains the necessary information for OpenOCD
Below is an example for how to connect to an OpenRISC system using the Altera Virtual JTAG TAP and Advanced Debug Interface
openocd -f tcl/interface/altera-usb-blaster.cfg -f tcl/board/or1k_generic.cfg
===Connecting GDB to the proxy===
Once the proxy is running, the next step is connecting to the proxy from GDB. Since GDB 6.8, communication between the proxy and GDB uses the remote serial protocol. The older remote JTAG protocol used with previous versions of GDB for the OpenRISC is now deprecated. If using the version of GDB installed with the OpenRISC toolchain install script then it will be compatible with the proxy.
The following commands show an example of starting GDB and connecting to the proxy. If the proxy is running on the same machine as GDB is being run on, then the following commands will work, otherwise substitute the IP of the machine running the proxy for localhost:
user@host:~$ or1k-elf-gdb
...
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x00000594 in ?? ()
(gdb)
GDB normally attempts to display where the processor is located in the code whenever the system is halted, but as we have not provided GDB with any code it is not aware of the context, hence the ?? (), indicating this.
At this stage, the proxy is connected to the board, and GDB is connected to the proxy. At this stage all connections enabling debugging are complete.
==Run the UART terminal==
At this stage, it is a good idea to start running the terminal that will interface with the target via its UART.
===Example Debugging Session===
The following is an example of a debugging session that uses a simple hello-world type application to demonstrate some common debugging tasks.
===Compiling and downloading an application===
This section outlines an example of compiling and downloading a program to the target. The program used is a simple hello-world type application which prints a line and then echos any received characters back to the terminal on the PC.
The code for this example can be downloaded from [http://opencores.org/openrisc,file,ZGVtb19vcjMyX3N3LnppcA== here]. Extract it, and compile it with make all. It requires the OpenRISC GNU toolchain to build it. The resulting executable will be echo.or32.
Load this file into GDB with the file command, and then download it into the board with load:
(gdb) file demo_or32_sw/echo.or32
Reading symbols from /home/orsoc1/demo_or32_sw/echo.or32...done.
(gdb) load
Loading section .vectors, size 0x900 lma 0x1000100
Loading section .text, size 0xa98 lma 0x1003000
Loading section .rodata, size 0x2d lma 0x1003a98
Start address 0x1000100, load size 5061
Transfer rate: 17 KB/sec, 241 bytes/write.
The entry point is set to a correct value in this executable, but often the NPC must be set with spr npc addr to the appropriate reset address.
===Running and halting the application===
Ensure the terminal program is open and connected, and continue execution on the target.
(gdb) c
Continuing.
The terminal should print the following, and then echo anything typed in:
Hello World!
Echoing received chars...
testtest123
Try interrupting execution now by pressing ^C (ctrl+C) in GDB:
(gdb) c
Continuing.
^C
Program received signal 0, Signal 0.
0x01003a2c in uart_getc () at uart.c:185
185 WAIT_FOR_CHAR;
(gdb)
We can see the address where it has been stopped, and the line number, 185, corresponds to the C-code macro where the UART receive register is polled.
===Setting breakpoints and instruction stepping===
To test breakpoints we can set a breakpoint for the next line which reads out the value of a received character. This will get tripped when we enter the next character into the console. To enable a breakpoint on the next line, do the following:
(gdb) break uart.c:187
Breakpoint 1 at 0x1003a4c: file uart.c, line 187.
(gdb) c
Continuing.
Next, press a key in the terminal window. The processor will pause execution at the breakpoint, and return control to GDB which displays the following:
(gdb) c
Continuing.
Breakpoint 1, uart_getc () at uart.c:187
187 c = REG8(UART_BASE + UART_RX);
(gdb)
Entering c again will continue execution and the character will be echoed back to the terminal.
Press another key in the terminal to trip the same breakpoint. This time, enter si to single instruction step the processor just once, and continue pressing enter (on an empty line at the GDB console to repeat the last command) to step execution through its echoing of the character back to the users terminal. It should take up to about 50 instruction steps to print the character to the terminal via the UART and get back to polling for a new character.
(gdb) c
Continuing.
Breakpoint 1, uart_getc () at uart.c:187
187 c = REG8(UART_BASE + UART_RX);
(gdb) si
0x01003a50 187 c = REG8(UART_BASE + UART_RX);
(gdb)
0x01003a54 187 c = REG8(UART_BASE + UART_RX);
(gdb)
0x01003a58 187 c = REG8(UART_BASE + UART_RX);
...
(truncated)
...
(gdb)
0x01003a04 185 WAIT_FOR_CHAR;
(gdb)
Delete the breakpoint with del 1 and continue execution.
(gdb) del 1
(gdb) info br
No breakpoints or watchpoints.
(gdb) c
Continuing.
The program will now execute and echo characters without breaking each time one is entered.
===Resetting execution===
It is possible to reset the application by writing the reset address to the next program counter (NPC). In this example the reset address is 0x01000100. We can set the NPC with spr npc value. After it is set, the processor will execute from the reset address, restarting the program.
(gdb) spr npc 0x01000100
SYS.NPC (SPR0_16) set to 16777472 (0x1000100), was: 16792080 (0x1003a10)
(gdb) c
Continuing.
The terminal should show the hello-world message again to indicate the program has been restarted.
==Troubleshooting==
This section will outline some ways to solve issues with setting up and debugging an OpenRISC based system.
===Building the proxy===
Connecting to the target
Problem: Connection via USB debug cable failed (err = 8)
If the following is seen when attempting to connect to the target:
user@host:~/or_debug_proxy$ ./or_debug_proxy -r 55555
Connecting to OR1k via USB debug cable
Connection via USB debug cable failed (err = 8).
Please ensure the device is attached and correctly installed
then check the permissions on the cable are configured properly. An indication as to whether the permissions on the cable are setup, look at the permissions on the ttyUSB devices. Do this like so:
user@host:~/or_debug_proxy$ ls -l /dev/ttyUSB*
If there are not read or write permissions for the user on these devices (the permissions look something like crw-rw----) then the permissions are not setup correctly. Ensure the udev .rules files are configured correctly. Try changing the numeric prefix of the udev .rules file containing the rule for the debug cable to a higher number, as the current one may be getting overwritten by a higher number rule. You can also confirm this is a permissions issue by running the proxy as root user with sudo however this is not recommended.
Problem: JTAG TAP ID read error. Unable to detect TAP controller.
If the following is seen when running the proxy:
user@host:~/or_debug_proxy$ ./or_debug_proxy -r 55555
===Connecting to OR1k via USB debug cable===
Initialising USB JTAG interface
Initialising USB JTAG interface
Initialising USB JTAG interface
Initialising USB JTAG interface
Initialising USB JTAG interface
Initialising USB JTAG interface
JTAG TAP ID read error. Unable to detect TAP controller.
Please ensure debugger is connected to target correctly.
then the connection between the USB debug cable and the board is the problem. Ensure all cable connectors are orientated the correct way on connection pins. If testing on a new design, ensure all I/O pin mappings are correct.