Welcome to module 7 of the Linux Board Porting On-Line Series. This is the final in a series of three modules, which are centered around debugging U-boot in Code Composer Studio using JTAG based debugging. And as you might guess, this is the module where we will finally connect to a running board using JTAG and step through our U-boot code at the source level using JTAG debugging.
Here you can see the hardware setup that we'll be using for our U-boot and SPL JTAG based debugging labs, which is modules five through eight in this series. I have my x86 host computer. The computer is attached to a BeagleBone Black development board. Its first type of attachment is over USB, so you can see the USB connection there.
In this series of labs, the only thing that I'll be using that USB connection for is actually to power the BeagleBone Black. You can also see that I have an XDS 560 emulator. It's attached to the host computer via USB, and it's attached to the BeagleBone development board using a 15 pin JTAG header.
Next, we need to set up the target configuration. This is basically our configuration of the JTAG interface, which we'll use for debugging. So first step, I'm going to minimize Code Composer Studio and the terminal and go to the Spectrum Digital config utility. This is just a good reality check.
If I go here to USB, and find all connected emulators, I can just verify that, OK it was able to find the emulator. So it's been attached. And then I could do a loop back test and just verify that basically we have a good, active connection.
And here, we get a loop back pass. So this is an optional step. There's nothing that's required to be set up here, but it is good as a starting point just to verify that you've got a good connection to your emulator.
Going back to Code Composer Studio, the next thing we'll need is File, New, and then Target Configuration File. You can name it whatever you like. I'm going to use BBB for BeagleBone Black underscore TC for Target Configuration.
Now, under Connection, we'll need to select what is the emulator we're using. I'm using the x Spectrum Digital xds560 version 2, and I'm using it in USB attach. So this would be the correct connection for me. Obviously, if you're using a different emulator, you would select that emulator.
And then under the device, the AM335x. So here's is my configuration. I'll save it, and then I'm going to do test connection, which is a good idea. And so here it's just testing the connection, seeing if it can communicate with both the Spectrum Digital emulator, and then it'll try the development board.
So if I scroll down, we see quite a bit of feedback. And finally the JTAG scan test has succeeded. So obviously that's good news, indicating that we have a good connection set up to the board. I can hide that, and then even just close this down.
At this point we're ready to connect to the board and begin debugging. In most cases, once you've created the target configuration, the target configuration view will be up. But if it's not, just go to Window, Show View, and Target Configurations.
Once the target configuration view is up, I can Right-click on my BeagleBone Black target configuration and launch the selected config. I'll go ahead and leave this recording, because it's probably important to see the different steps that it's going to go through as it attaches to the board. If the emulator attaches correctly, then we'll see this window here will update in just a moment. And it shows us a number of different cores in the JTAG, including the programmable real time units and an M3 unit on the device.
But what we care about, of course, is the cortex AA core. So I'm going to right-click on that, and then just select Connect Target. And here you see, it connects. It's at a random location with the program counter.
I also like to, after connecting, go ahead and do Reset, CPU Reset, and do a software reset. You can close this disassembly view down. Now let's open up the core registers. Within the CPSR, if you do the software reset, then you should actually see it listed here as not in thumb mode. But if you see a 1 here for thumb mode, it's important that you turn that off.
So the U-boot code expects the ROM boot loader to have initialized the system so that we are not in thumb mode. So just double check that under the CPSR. Always make sure that that is 0, and that we're not in thumb mode. I'll take that back down.
Now, we're doing this sort of manually. If this was a CCS project that was CCS managed, then a lot of this would be done for us more routinely. But what we're going to have to do is begin by loading the memory.
And you can browse to this within the project, but I think the easiest thing is to just use File, Load Memory. So we're at our TIDSK board support. Then within the U-boot source directory, then SPL, and u-boot-spl.bin.
Now, when you first browse to the SPL directory, what you're going to see is you're not going to see the file. The reason is, it's sorting on TI data format, which is the default. So you need to go down to All, and then we can put in the u-boot-spl.bin. You'll see that they all show up.
again I would definitely recommend you use that Browse button for this step, because typing everything in by hand, you're liable to make a mistake. We'll say Next. Here's the start address, 402f0400. In just a second, I'll show you how you would know that that was the start address. And this is very important, the type size needs to be 32-bits. It'll start as a default of 8-bits, but you need to go through and select 32-bits.
Press Finish, and you'll see that load memory window popped up very briefly. You may not have seen it, but that's because I'm using an XDX560, which downloads it very quickly. Now that has loaded the binary onto the target, but we don't have the symbols.
So the next thing I need to do is go to Run, Load, Load Symbols. And again, this is just under SPL, U-boot SPL. I'm going to be looking for certain extensions, but go to All Files, and here's the U-boot SPL.
Now, why is it that we're loading u-boot-spl.bin and loading the symbols from U-boot SPL? The reason for this, notice that u-boot-spl.bin is much smaller. That's because this binary file doesn't have symbols in it. And so the binary is what actually needs to be loaded onto the device.
However, u-boot-spl is a file that also contains the debug information, basically the symbols. So we're going to load the symbols from the full file that has the debug information, while obviously we loaded the binary file. You don't need a code or data offset. Go ahead and press OK there.
And the last thing that we're going to do is we want to open up board.c. So recall that board.c is the file that is the top level config file, basically, for U-boot. And it's the file that you would spend most of your time in doing a board port.
So if I back up just a little bit, you see this is my TISDK directory board support U-boot source code, and then board TI AM335x. You can browse to this in the project window, but again I think this is the easier way to do it. Now I open up board.c, and remember that our entry point for the SPL is s_init. So I'm going to hit Control+F and find s_init.
Pulling this up, I'll just go to, we're not doing a [? norboot ?] so this won't be valid code. But I can go to what's basically the first line of code here at 594. Now this is important. Some people may be used to double-clicking in the field here. That will set a breakpoint, but not a hardware breakpoint.
And what'll happen is you won't stop at the breakpoint. So that's a common mistake to make when you're first starting, but it's very important that you right-click, do breakpoint Code Composer Studio. And you'll notice that you have a number of options, breakpoint, hardware breakpoint, hardware watchpoint, and then profile control point. If hardware break point doesn't show up, then you need to go back through the steps that we've done so far, because something's wrong.
If you select breakpoint, it's a software breakpoint instead of a hardware breakpoint, and it won't work correctly. So you need to go ahead there and select the breakpoint, hardware breakpoint. And at this point, we're almost ready to go. So I will make that window smaller.
And then the last thing is, remember that we loaded the program at 402f0400. And before I forget, let me go back to the CCS edit window. Here's our console where we built U-boot. And notice here near the end of the steps, you see this DCONFIG_SPL_TEXT_BASE=0#402F0400. So what you can do-- and there's a little bit more here.
GP header, load address, 402f 0400. So you can see that there's a couple of places in the build feedback where it's actually telling us that information. So that's how you would locate it. So I'm going to put the program counter to that location.
At this point-- let's do also Window, Show View, Disassembly. So here we see 402f. You should see something that looks like this in your code, which indicates that we have a valid program loaded up. Usually it's pretty easy to tell if it's just garbage and not a valid program. And at this point, I can hit the Resume button to start running.
You might have seen it run for just a little bit. Here, when I look at my registers, everything that's highlighted in yellow are registers that have changed since I ran it. So you can see that it's changed a few of those.
And then at the disassembly window, you can see that we're in s_init, and we've stopped at this write command. This is the C command, and these are the assembly commands corresponding to it. Here's our breakpoint. Again, it's a hardware breakpoint.
You might be able to see that there's sort of like a cross hairs on top of it. That's another way you can tell that it's a hardware breakpoint. And we can go to board.c.
Now, you'll also notice these little bugs that show up. This is because CCS doesn't know how to find a lot of the different tags that are in this file. The reason is it can't find the header files. We're building off of a makefile, CCS won't parse that makefile.
It is possible to go into the project file and tell it where to find all of the proper header files, but I'm just not going to do that because it's not required at this step. And it takes quite a bit of time, obviously, to sit there and tell it the paths and the header files to search. But that's why these little red bugs are showing up, and they're nothing that is going to stop you from being able to debug.
At this point, I could do an assembly step into. We can see it single stepping through the code. We go to our disassembly window, I'm going to put in the 402f1cec. Sorry, it needs to have 0x in front of it.
Expand the disassembly window. So here you see, this is the beginning of s_init. This is where we set our breakpoint. And now we can step here within the assembly code. And you can see it stepping as it goes through.
We can view these CPU registers back in the register window. So here's the R0, R1, are R2. You can see that they're changing as the various operations go about. So here's our general purpose registers.
Disassembly is set with an option where it shows you the C code. So here's 597, this writeL command, we're inside of that. I can single step again. Take me to the next line.
If I go back to the source code, it's a little bit difficult to see because of these bug indicators. It's a little bit hard to see these bug indicators, but you might be able to see that there's an arrow there right next to line 597. I can even do a stepover over of C code. And you can see the arrow is here on 598.
So once you've debugged there to your heart's content, then we can press Resume and it will continue running. The problem is, it's looking for a U-boot to load off the multimedia card and it doesn't have one. So let's go ahead and hit Suspend. And here, we're suspended here at 402f4744, but more importantly, notice that it pulled up spl.c, and the line that we are suspended on is error, please reset the board.
The reason for this, again, is that there is no valid image for it to load. But that's OK, because at this point we're going to use the JTAG to load the image for it. Now, it's important at this point that you do not reset the board. So if you reset the board, then everything that the SPL has done up until this point will be reset.
But what we'll do is we'll go to Run, Load, Load Program. We're going to browse here to our U-boot file, and this is not the U-boot SPL, but it's the U-boot binary. So I'm going to go ahead, and-- oh, I'm sorry. We're not going to use the U-boot binary. We're going to use the full U-boot file that has the symbols, and just go ahead and load those directly.
At this point, we're almost ready to go with debugging the full U-boot, but there's one last kind of funny little detail, which is that U-boot relocates itself early on in its code. And in order to do the debugging correctly, we're going to have to determine what the relocation address is, so that the debugger can find the new location of all the code. And so what we'll do is we'll open up a serial connection to the board.
I'll open a terminal with Control+Alt+T and minicom. Needless to say, if your board has a serial terminal, then you'll be able to use this step. If it doesn't, then you won't. This is without a doubt the easiest way of finding the offset, so this is what I'll show you.
If you're using something like the BeagleBone, which doesn't have a serial connection, then what you'll have to do is actually single step and trace through the code until you get to the point where it relocates, and then actually view the variables. But most of the boards you're working with should have a serial connection. So what you can do-- and you're going to have to be quick care, because we need to jump in to the serial terminal before you U-boot countdown elapses.
What I'll do here is just go ahead and hit Start. And if you're fast enough, you should be able to halt it here, where it says hit any key to stop autoboot and enter into command mode before it proceeds past that point. If you get to this point, then it's real easy. We can just use the bdinfo, or board info, command.
And when we do board info, this is the address we're looking for here, 8fb4c000, the relocation address. We're not looking for the relocation offset. You remember, we started at [? #adad0000 ?]. That, plus this offset, equals the actual address, which is the 8fb4c000.
You'll see in a second, when we enter it, it's going to ask for an offset. But you want the relocation address, not an offset. They're basically two different offsets, what Code Composer Studio considers an offset and what U-boot considers an offset. But this is the address that we'll want to use.
So we can just go back here and halt. And now the last thing that we're going to need to do is reload the U-boot program. So fortunately, we don't have to go back through the SPL, because all of the configuration that was done for the SPL will still be there. But we need to start U-boot over at this point. So let's reload the program.
So I reload it. And then once I have the U-boot reloaded, this is the important step. This is why we went through that effort. I need to do Load, Load Symbols. Notice here that I have my code offset of 8fb4c000. That is exactly the offset that we got from when we looked at the serial terminal and we did the board information.
So you need to load the program without an offset, because it's going to relocate itself. But when we load the symbols, we need to load the symbols with an offset that specifies the relocation address. And what this will do is it will give us the ability to debug after U-boot relocates itself, which is what we're going to do.
So we press OK to load those new symbols at the offset. And now I can go back to board.c, and we're not interested in the SPL code. But what I can do is a Find Replace, and go to board_init.
Here's my board_init file. And I'm just going to go to this i2c init, set a hardware breakpoint. So now we have our breakpoint inside of board_init for the U-boot. And I can just go ahead and resume here, because the program counter's at the correct point.
Now you'll notice, it's actually pulled up this omap24xx_i2c, so just-- when it set the breakpoint, it apparently set it at the first breakpoint here of this i2c init function. So the first line of the i2c init function. If I hover over speed here, you can see the hex value of speed or the init, the integer value. So just hovering over these variables gives you that feedback. And so here we have a valid connection with our debugging stepping and variable watch tied into the U-boot code.
This concludes module 7 of the Linux Board Porting On-line Series. The final three modules in the series cover debugging the Linux kernel using JTAG from within Code Composer Studio. Please proceed to Module 8, where we will be installing the software development kit and rebuilding the Linux kernel with debug information.

Module 4 - Linux/U-boot Source Code Structure: Overview of the layered organization of the source code files for both Linux and U-boot, focusing on those files which are most pertinent to a typical board porting effort.

Module 5 - Installing Code Composer Studio: This first lab exercise of the series is a recording of the presenter installing Code Composer Studio. In particular, installation of the proper JTAG drivers and a valid CCS license are required to debug U-boot. This is the first of three lab exercises centered around debugging U-boot using JTAG.

Module 6 - Building U-boot in CCS: This lab exercise shows the user how to set up a makefile-based project in Code Composer Studio in order to rebuild u-boot from source code.

Module 7 - Debugging U-boot with JTAG in CCS: This module is a recording of the presenter using Code Composer Studio and an xds560 emulator to debug U-boot on the Beaglebone Black platform.

Module 8 - Installing SDK and Building Kernel with Debug Symbols: This module is a recording of the presenter installing the Sitara Software Development Kit (SDK) and rebuilding the Linux Kernel with Debugging Symbols. It is the first of three modules demonstrating the debugging of the Linux Kernel in Code Composer Studio using JTAG.

Module 9 - Booting Linux from MMC/SD Card and TFTP: This module is a recording of the presenter using the SDK utility to build a bootable MMC/SD card for the AM335x starter kit and modifying the card to load the Linux Kernel from a TFTP server.

Module 10 - Debugging Linux Kernel with JTAG in CCS: This module is a recording of the presenter configuring JTAG debugging of the Linux Kernel using Code Composer Studio. It is the final in a ten-part series.