Jan 1

I like LED’s that indicate activity, also here a 90 degrees bended version should be used. Next to this, the type to be used should be a low current version to reduce the amount of power consumed. There are various types available, in 3mm and in 5mm. They use 2mA of current compared to normally 10 or 20, they 5mm versions have an extra mechanical snap which I guess is good for robots that run around all the time, so I will uses the 5mm versions for now.

There are two signals to monitor; the CAN frames that are send by the PMC and are address to the PMC and the commands from and to the FOXBoard. For the first one, the ATDVK90CAN1 board has two LED’s tied directly to the TXD and the RXD lines. This is not what I want since in that case it shows any CAN frame while I’m only interested in RoboCAN commands that are processed by the PMC. This will require an extra out of the AT90CAN and a software modification in the RoboCAN library. The second one is already implemented.

For the micro controller, there are three AT90CAN’s available were the main difference is in memory and price:

  • AT90CAN32, 32KB Flash, 2KB SRAM and 1KB EEPROM, 6.89 EUR at 10 units
  • AT90CAN64, 64KB Flash, 4KB SRAM and 2KB EEPROM, 7.36 EUR at 10 units
  • AT90CAN128, 128KB Flash, 4KB SRAM and 4KB EEPROM, 11.92 EUR at 10 units

The safest choice in life is always the middle one, I guess also here. Compiling the Primary Motor Cortex basic implementation that can interface with the FOXBoard and has the full RoboCAN protocol added uses 20KB of Flash and 1.6KB of SRAM. The AT90CAN32 can be used if not much additional application is added that uses variables as well. For only 0.47 EUR you can twice the amount of SRAM and FLASH, so I guess that is not worth taking the risk that the application just runs out of memory which would mean removing the part and soldering a larger on on the board. Time consuming and you risk damaging the board.

The cost adder for the AT90CAN128 is significant while only increasing the amount of FLASH. At the time of writing this, the number of code lines are:

  • CAN.c, 576 lines
  • RoboCAN.c, 885 lines
  • FOXBoard.c, 340 lines
  • Primary Motor Cortex, 213 lines

Lines of code do not directly translate to number of bytes, but for a rough estimation of how many lines the application can contain it will do: (20KB/(576+885+340+213))=10 bytes per line. 44KB/10=4500 lines of code. The largest application I wrote contained 3530 lines of code and there I was close to of-loading sub-systems to secondary micro controllers due to the complexity of the product. So using the AT90CAN64 is a safe choice for the PMC.

In order to connect the JTAG to the AT90CAN64 a 2×5 header needs to be used. Also here a 90 degrees bended version should be used so that any code can be updated later or any micro controller can be debugged later while no parts of SnakeBot have to be disassembled.

Combining all above results in the first version of the schematic. I will develop the PCB later, first the schematic should be on my desk for some days to review it several times.

Dec 31

Before the electrical design can start some items need to be considered.

I want to stack more add-on boards on top of the FOXBoard, this allows me to re-use some of the boards (or designs) when I start on another robot. The FOXBoard uses 2 headers of 2×20 pins, these are available as female sockets with variable pin length ranging from 3 to 17mm. Examples are the 962-60206-12 from EPT that offers a body height of 11.45mm and a pin length of 12.2mm. Using a PCB thickness of 1.5mm and an inserting of the pin in another female socket of 3 to 6mm this offers a maximum component height of 16.15 to 19.15mm.

If one board is stacked on top of another one connectors, LED’s, buttons and so on are not longer accessible, for this reason all these components should be placed on the side of the board and be a 90 degrees bended version.

For the CAN interface to the actuators, 2 signal wires are needed that must be twisted. Based on the basic electrical architecture of SnakeBot, there are 3 additional wires needed: power, ground and charge. It might be an option to use normal UTP cable, this consists of 4 pairs of 2 twisted wires. In this case one pair can be used for the ground, one for the power, one for the charge and one for the CAN interface.

A wire in an UTP cable is a 24 gauge copper wire, this limits the current per wire to 0.577A or 1.15A per pair. This is not so much, when using 10 or 15 segments for SnakeBot each charging with 250mA as a minimum but with more advanced charging up to 2.5A the total current through the charge wire can be in the range to 10 to 15A. This is indeed not very realistic since the charger must be capable of supplying this current, but nevertheless the 1A is by far to low.

I guess the best solution here is to use normal household appliance power cord cable for the three power lines and use a separate two wire cable (shielded and/or twisted) for the CAN interface. This also “feels” better since drawing high current spikes trough a conductor that is a millimeter away from a communication bus running at 1Mbps is probably begging for problems.

In order to connect the power cables, best option is to use terminal blocks with a screw. Reason for this is that there will be a rather thick core that needs to be inserted. When wiring SnakeBot the (for example) charge line need to go into a segment and leave the segment again to go to the next segment. You do not want to place a connector on the front of the PCB and route the charge line over the board to the other side and place a connector here as well to go to the next segment. If this was done than all the charge current of all segments combined will run though the PCB of the first segment causing serious layout problems. Instead, the charge line will be cut, both ends stripped, twisted together, soldered and than inserted in a single connector that only supplies the current to that segment.

A power cord that can handle 16A uses a core of 2.5mm2, twisting both of them together results in a 5mm2 surface that makes a circle of SQRT(5/3.14)*2=2.6mm in diameter. That would require a terminal block that can handle AWG 10 or less, these are available but the height is 21.5mm which is too high and they are not 90 degrees bended.

Next best solution might be automotive crimp terminals, these can handle high current, are available in many shapes and have PCB terminals. For example this female connector and this pcb connector.

In principle this is the same for the CAN interface except that the cores are much thinner. Remains the problem that the screw can not be fastened since there might be another board on top. There are terminal blocks available that offer both a male and female part. The cable entry part is 2.5mm2, so inserting two wires will not work. As an alternative the power cable cut be cut, stripped and third small piece of about 5cm could be added to make a T-junction using shrinktube for isolation. Than the 5cm long wire could be inserted in the terminal block. For the CAN-wires this is not needed, two wires can be twisted, soldered and inserted without any problem.

For now, I will use the terminal connector using the male-female combination. For some reason this feels the best. I will split the connector in 2 times 3 pins connectors. For one that the PMC will only use the CAN signals and not the power lines but also giving me the option to buy a bit more of them and keep them on stock for other projects (2 and 3 pins connectors are used the most, 6 pins much less).

Dec 29

At this moment the only add-on defined is the Primary Motor Cortex, I can imagine there will be more added in a later phase. For this it is important that the software and the electrical design are defined so that more add-ons can be placed in parallel.

Below the impact on the electronics:

  • Address lines, are all inputs. No special action other than that one add-on board should enable the pull-up resistors while the others don’t. If all add-ons would enable the pull-ups they would all be placed in parallel and as such reduce the value (and increase the current consumption).
  • Data lines, all bi-directional but by default set to input. Also here the pull-ups must be enabled on one add-on only.
  • /WR, /RD lines, are all inputs. Again the action on the pull-ups.
  • /INT line, is an input that each add-on can activate. Should be an open collector in that case . In the test software the output is pulled low. Using an open collector circuit would require a transistor, in this case the output on the AT90CAN128 should be inverted. Also a pull-up to the collector input of the transistor would be required, this should only be enabled on one add-on board again using a jumper.
  • /ACK line, is an input that each add-on can activate so same as the /INT line.

Below the impact for the software:

  • Use a define to enable or disable the pull-up on the address, data and control lines.
  • Apply a filter in the read and write ISR’s to see if the command is for that specific add-on.
Dec 28

Oops. I said the FB was slow with it’s 10us time required for an IO call and that the AT90CAN128 would always be waiting for it to change states. Well, I stand corrected. 

I was testing the code with a dummy command that takes 16 bytes that the FB sends to the AT. I noticed that about 3 to 4 out of the 16 bytes were well received and the rest got lost. It also did not receive 0..3 and than stopped, not the AT received 0, 4, 8 or something like that. Stepping trough the code on both sides showed everything was working and all 16 bytes were well received, this typically means there is a timing problem (stepping is working at low speed, executing is non-working at high speed).

Monitoring /WR and the LED output using a scope revealed that when the first byte is received on the AT it takes 17us to process the falling edge on /WR. The next ones go faster but it already takes 3us from a level change to start of ISR. With an 8MHz crystal each cycle takes 0.125us, so apparently there are 24 instructions needed to push everything on stack and execute the ISR. A 16Mhz crystal would reduce everything by 2 but the 17us would than still take 8.5us. True, this is in O0 mode for the compiler, so non-optimized, but it still worries me. Later the RoboCAN interface will be running as well, there is a big chance now that bytes will be missed if one of the CAN ISR’s is executed which are even more complex than the ones for interfacing with the FOXBoard. Also the optimizer can be enabled, a small test with -O2 shows a small us improvement but nothing drastic. I also don’t like to work with the optimizer during development since it makes debugging complex.

That leaves only one option, data transfer must use a handshake method. An extra input on the FB is required for this called /ACK were 1 means the AT is ready and 0 means it is busy.

For writing from the FB to the AT this means:

  • Set the data bus to output (if not done already)
  • Set the 1’s of the command (address) and data pins
  • Set the 0’s of the command and data pins including the low level of the /WR pin
  • Wait until ACK is low
  • Raise /WR
  • Wait until ACK is high
  • Repeat this process for each data byte of the command

For reading by the FB from the AT this means:

  • Set the data bus to input (if not done already)
  • Set the 1’s of the command (address)
  • Set the 0’s of the command including the low level of the /RD pin
  • Wait until ACK is low
  • Read the data pins and store them
  • Raise /RD
  • Wait until ACK is high
  • Repeat this process for each data byte of the command

In both cases the rising flank of /WR or /RD will still trigger the interrupt in order to indicate the byte in finished.

Some testing later I have to conclude that this works perfectly. A write or read command that uses 16 bytes of data takes about 1.4ms, this is not very fast but I expect some improvements by increasing the crystal of the AT bring it to about 1.0ms.

The frequency of the AT90CAN128 can not go up to 16MHz since the voltage is 3V3, at this voltage the maximum frequency can be ((8/1.8)*(3.3-2.7))+8=10.6MHz. This is over the full temperature range, typically a 12MHz crystal should be OK, further testing at that moment.

Downloads:

Dec 23

Processing a command that writes data from the FB to the PMC is very straight forward:

  • Set the data bus to output (if not done already)
  • Set the 1’s of the command (address) and data pins
  • Set the 0’s of the command and data pins including the low level of the /WR pin
  • Repeat this process for each data byte of the command

Since the falling edge of the /WR pin on the PMC triggers an ISR and the write speed of the FB is limited to 10.8us (46kHz*2) per set or clear cycle there is no need to worry that data will be lost. The moment the ISR is triggered, the data is available on the data bus, so the ISR does not have to include any delay which will block the whole system (including the RoboCAN interface). 

Since the command is received in an ISR and ISR’s should consume the least possible amount of time, processing the command received can only be part of the ISR if it sets or clears some variables. Any action that would require (for example) communication using the RoboCAN interface should be executed outside the ISR as part of the main application. Remember that a command over the RoboCAN interface might take several milli seconds in case the interface is busy or the received does not respond.

Processing a command that reading data is by definition more complex since there is a “slow” device (the FB) that needs to copy the data from the databus.  

  • Set the data bus to input (if not done already)
  • Set the 1’s of the command (address)
  • Set the 0’s of the command including the low level of the /RD pin
  • Read the data pins and store them
  • Repeat this process for each data byte of the command

Since it takes 10.8us for the FB to read the data (if not blocked by other processes) it means the PMC is stuck in the ISR linked to the falling edge of the /RD signal. One option is to leave the data on the bus and simply exit the ISR. This can (will) however create bus conflicts the moment the FB decides to write data.

In a normal bus system the slave places data on the bus at the falling edge of /RD and removes it on the rising edge of /RD. The best solution than is to trigger the ISR on each edge and decide what to do the moment the ISR is executed. The AT90CAN128 supports this behavior, it can trigger the interrupt on any logical change.

As a result, a falling edge on /RD will place the data on the bus and exit the ISR. At the rising edge of /RD the data is removed, final question to answer is when to generate the rising edge? If it is part of the read function on the FB it will require an additional IO call at the end of the read function (reading more bits will automatically raise /RD when the 1’s of the command are set). If this is not done, than the /RD will remain low until the next read or write command. This is not prefer ed since if a write follows the /RD pins is raised but the data lines are already reversed before this raise and so creating a bus conflict.

The big question is how much time the AT90CAN128 needs to prepare the data and set the first byte of this data on the bus. If this is not finished before the FB copies the data from the data lines than we have a problem. Based on the 10.8us for an IO call on the FB I don’t for see any problem as long as (again) filling the data to return does not include any calls on the AT90CAN128 other than copying existing known data into the buffer. Also the interrupt used is the second highest available interrupt source on the AT90CAN128. The highest is for the /WR signal, since the FB can not read and write at the same time there is no difference in the priorities, if /RD is lowered (or raised) the ISR will be called directly unless it is stuck into another ISR. This will be the first thing to check if strange data is read back.

For the /WR signal it is good enough to trigger only on the falling edge, but it makes sense to trigger on any level change as well to enable of disable the communication LED. To prevent reacting on undefined states when the FOXBoard is still booting or when the SnakeBot application is not started or starting the PMC needs to ignore any change until it detects a stable state (/RD is high and /WR is high).

While implementing the first command to set a power mode on the PMC I already struggle with processing this command inside the ISR. It will require commands send to the various actuators, so the command must be buffered and executed as part of the main program and not inside the ISR. Sending a command from the PMC to the FB is not interrupt based, so only received commands need to be buffered.

Claiming an array of command structures is not memory friendly, instead a simple circular buffer will do the trick in which the command (2 bytes), the amount if data bytes (1 byte) and the data (x) bytes can be stored. Two command pointers (one points to the next to read and one points to the first free position) do the maintenance of the buffer. This buffer is called CommandBuffer and made 128 bytes long. Time will tell if this is enough. Two functions are defined; StoreCommand and GetCommand. The first is now called when a full command is received in the /RD ISR. The application can call the function CommandReceived to check if a command is available in the buffer or simple call GetCommand which will fail if no command is available.

Here is the latest version of the PMC code. Here is the latest version of the FB test program.

Dec 15

Some IO pins on the FB have separate pins for input and output. For example, input 1 on port G is available on pin J6.24 while the output 1 of port G is available on pin J6.23. On most controllers all pins are bi-directional, outputs are internally fed back to the input buffer so when you set an output and read the port status it shows the current output state.

On the FB this seems to be different for certain pins, to verify if indeed there is no internal feedback line a small test setup is made. A 220E resistor is connected to J6.40 (Vdd) and to the anode (+) of a low current LED. The cathode (-) is connected to J6.23 (OG1). The LED lights up, so this means the output is low. A separate wire is connected to J6.1 (Gnd) and so far not connected on the other side. This will be uses to apply a low level to J6.24 (IG1).

Using a SSH terminal to the FB, type the command setbits -p g -b 1 -s 1, this will set bit 1 on port g to a high level and the LED will switch off. Using setbits -p g -b 1 -s 0 the low level is put back and the LED will light again.

The command readbits will display a bit pattern of all the available ports a, b and g. The most right one using 32 bits is of port g, MSB on the left, LSB on the right. The 2nd most right indicates the state of IG1, with the wire disconnected this is a high level. When inserting the wire into J6.24 and repeating the readbits command indeed the level is now 0.

The final test is simple (but almost no longer needed), set OG1 to 1 and keep the wire inserted. The LED will switch off, using the readbits command will still show IG1 is 0. Conclusion, no internal feedback so the suggested use for the interface between the FB and the primary motor cortex is possible.

Oct 19

The whole chain from entering source code in Geany, compiling using gcc-cris, transfering the application to the target using ssh and finally debugging it using gdbserver, gdb-cris and kdbg is now working using below makefile. In Geany the execute button executes the make execute command in the folder holding the source of the application and the makefile.

COMPILER = /usr/local/cris/bin/gcc-cris
CFLAGS = -g -fno-omit-frame-pointer -O0 -mlinux -o
SOURCES = main.c MyUnit.c
TARGET = Hello_World
USER = root@FOXBoard
DESTINATION = /mnt/flash/bin/HelloWorld

# top-level rule to create the program, executed by default if no params are provided
all: compile

# Called by pressing the Compile or Build button in Geanny
compile: $(SOURCES)
<TAB>$(COMPILER) $(CFLAGS) $(TARGET) $(SOURCES)

build: compile
<TAB>scp $(TARGET) $(USER):$(DESTINATION)

execute: build
<TAB>ssh $(USER) “gdbserver :1234 $(DESTINATION)/$(TARGET)” &
<TAB>sleep 5
<TAB>kdbg -r FOXBoard:1234 $(TARGET)
<TAB>ssh $(USER) “/mnt/flash/bin/StopRemote.sh $(TARGET)”

Everything works great except one thing: the printf command does not show anything in either the terminal available in Kdbg or in Geany. Although I can fully debug the application in theory I do not need printf to debug by application but using printf to display progress or status in my applications would be very nice.

When I start gdbserver on the FB using a ssh terminal than printf works when using Kdbg (or gdb-cris manually) although not in the terminal from Kdbg but in the terminal that was used to start gdbserver. When starting gdbserver using a ssh root@FOXBoard “gdbserver….” command than printf does not work until the moment that the application (and so gdbserver) is stopped.

My guess is that printf prints to the terminal that was used for starting the application. In case of using the ssh root@FOXBoard “gdbserver….” command a new shell is started in which the command passed to ssh is executed.

Thinking about this more, over the last days I find myself always having a ssh terminal running to the FOXBoard doing maintenance like organizing files and (previously) killing gdbserver from time to time. So it would not be a bad idea to not fully automate the process. Perhaps a better option is to have three programs open (Geany, a ssh terminal and Kdbg) in which case the order would be:

  • Change code in Geany, execute compilation and secure copy the application to the FB
  • In case of debugging, start gdbserver in the ssh terminal (arrow up and enter the second time)
  • In case of normal development, start the application in the ssh terminal
  • In case of debugging, in Kdbg select File |Recent Executables…, select the application and press F1 to reload the source before starting the debugging.

For now I will start working like this to see if this is an acceptable way of working. The only change needed in order to work like this is to change the command that will be executed when pressing the Compile button in Geany. In Build | Set Includes and arguments change the Compile command into make build. As a result, pressing the Compile button will compile and copy the application to the FB. Pressing the Execute button will also start gdbserver and Kdbg.

Oct 13

When debuging is stopped while the application on the remote target is not finished I want the remote application and gdbserver to be stopped for several reasons. For one, debugging means finding a problem in an application so execution is apparently not correct and is must be stopped. Secondly, the next time that the executable must be copied it will fail since the executable is still locked.

The Execution | Kill command in KDbg does this, it send a kill command to gdb-cris, this stops execution of the remote program and gdbserver. So perfect, problem is that this is not done automatically when you close KDbg so you always need to do this first before returning to the code. As an option, a script can be launched when Kdbg is stopped that investigates if the application and/or gdbserver is still running. If so, they can be stopped remotely.

Killing gdbserver is done using the kill command, open a terminal and run the command ssh root@FOXBoard “gdbserver :1234 /mnt/flash/bin/HelloWorld/Hello_World”. Next open open a remote shell to the FB and type the command ps. This will list all processes running including their process ID. If gdbserver is running you will see three processes running:

  • 834 root  536 S   sh -c gdbserver :1234 /mnt/flash/bin/HelloWorld/Hello
  • 835 root  512 S   gdbserver :1234 /mnt/flash/bin/HelloWorld/Hello_World
  • 836 root  32 T   /mnt/flash/bin/HelloWorld/Hello_World

The first one is the secure shell used for remotly starting gdbserver, second one is gdbserver and the last is the application being executed. The number in front of it is the process ID of the application, this must be pass to the kill command. If you would kill gdbserver please note that this prevents the application from being executed. After gdbserver is killed this means that the application starts (or continues) executing since it is no longer being kept on hold. In parallel the remote shell sees that gdbserver is finished and wants to close the shell but this is not allowed since a second process (the application) is also using the shell to execute. As a result, process 834 and 835 are killed using the kill 835 command but the prompt is not released in the terminal that was used for the ssh command. Only when the second kill 836 command is executed all applications in the shell are finished and the command prompt is released in the terminal.

This is not the behavior I’m looking for since this means the application continues running out of control after gdbserver is stopped half way the debugging process. In most cases this means the issue has been located and the application must be stopped as well since the application is not working correctly.

The correct order to prevent the application from running without gdbserver is to kill the application first and than kill gdbserver. Giving the command kill 836 will the application although it remains visible when showing all running processes. I guess this is because gdbserver also has a lock to it since giving the command kill 835 will kill gdbserver and the application at the same time.

I’m not sure how but this all should be possible in shell script that is kept universal so that it only needs to be written ones and can be used for all future FB projects. The first step is to create the basic script. Start gedit StopRemote.sh to create a new file, copy below text, save and close.

#
# (c)2008 J.P. van de Kamer
#
echo “Stop gdbserver and target application on the FOXBoard…”
executable=$1
echo $executable

This script will do nothing else than printing the first parameter that is passed to the script when started. In order to make the script executable, enter the command chmod 0755 StopRemote.sh, this will change the attributes of the script so anybody that starts this script in a shell can execute it. Enter the command ./StopRemote Hello_World, this will show below output:

jan@ITX-Development:~/FOXBoard/HelloWorld$ ./StopRemote.sh Hello_World
Starting gdbserver with target application on the FOXBoard…
Hello_World

The kill command requires the process ID of the process. In order to find the PID of the application, the command pidof Hello_World can be given, there is no need to pass a full path to the application, only the executable filename will do. The result is the PID, this must be passed to the kill command. In order to do this, we first assign it to a variable using the command

pid=`ssh root@FOXBoard “pidof $executable”`

Note the ` character, everything between two of them is execute and the output is seen as the value in the equation. In this case the variable pid is assigned the output of the remote command.

It’s time to make a small change, executing the commands remotely takes a long time. So it’s better to make this script a local script that is stored on the FB and executed with a single remote call. As a result, the script so far should be:

echo “Stopping the target application and gdbserver on the FOXBoard…”
executable=$1
pid=`pidof $executable`
echo The PID of $executable is $pid

When an executable name is passed to the script that is not executed the value of PID is empty. Before killing the PID, a check should be done to see if a value is assigned to PID, if not, the kill command can be skipped.

if [ “$pid” != “” ]
then
echo The PID of $executable is $pid
else
echo $executable is not running
fi

Couple of this to note here:

  • The spaces after the [ and before the ] are not optional
  • The $pid must be between “”, this will result in a string compare between the pid and an empty string
  • The then must be on a new line

And now convert it so it actually kill something:

if [ “$pid” != “” ]
then
echo Stopping $executable…
kill $pid
else
echo $executable is not running
fi

Next is to kill gdbserver, a simple copy/paste/modify action will do this. Below the whole script:

#
# (c)2008 J.P. van de Kamer
#
echo “Stopping the target application and gdbserver on the FOXBoard…”

executable=$1
pid=`pidof $executable`

if [ “$pid” != “” ]
then
echo Stopping $executable…
kill $pid
else
echo $executable is not running
fi

pid=`pidof gdbserver`

if [ “$pid” != “” ]
then
echo Stopping gdbserver…
kill $pid
else
echo gdbserver is not running
fi

Copy this script on the FB, in my case in /mnt/flash/bin using the scp StopRemote.sh root@FOXBoard:/mnt/flash/bin command.

Now a single command ssh root@FOXBoard “/mnt/flash/bin/StopRemote.sh Hello_World” will stop the application and gdbserver.

Oct 6

During my search on how to debug the applications on the FB, I found a very interesting feature of ssh in order to execute gdbserber on a remote target. Normally executing such an application would require:

  • open a secure shell using ssh root@FOXBoard
  • navigate to the folder
  • start gdbserver using gdbserver :1234 MyProgram
  • when it finishes, closing the terminal would require the exit command

All this can also be done using a “non-documented” feature of ssh to enter the command to execute directly after the target between colons.

  • ssh root@FOXBoard ‘gdbserver :1234 /mnt/flash/bin/HelloWorld/MyProgram’

This opens the shell, logs on, start gdbserver in the right location with the right program and logs off when the application finishes. It does not only work for starting gdbserver, any remote command can be placed between the colons, e.g ssh root@FOXBoard ‘rm /mnt/flash/bin/HelloWorld/MyProgram’ will remove the application.

This is perfect in order to be used in a makefile for remote maintenance in combination with preventing the password to be given after every secure command.

Oct 6
DDD

Searching the web how to restart an application on a remote target does not provide any clue how to do this. I found one link to another debugger that acts as a wrapper around gbd, it is called DDD. The benifit of this debugger is that it is less integrated meaning it shows a terminal with gdb running, pressing the buttons basicly types the command linked to the button in the terminal and executes it. Any feedback from gdb is shown (of course) in the terminal.

Open a terminal, change to the location that holds the HelloWord application and enter the command ddd –debugger /usr/local/gdb-cris/gdb-cris, this will start ddd using gdb-cris as the debugger. Use the File | Open Program option to load the HelloWorld application. This will open main.c in the source window.

In a second terminal, start a secure shell terminal to the FB. In the folder containg the HelloWorld application, enter the command gdbserver :1234 Hello_World. I figured out that the IP address of the remote PC that will be used for the debugging is not needed, so less typing.

In the bottom terminal window of ddd type the command target remote FOXBoard:1234 as you would do with the bare version of gdb. The FB will respond with a “Remote debugging from host xxx” indicating the connection has been made.

Any button you now press results in a command being send to gdbserver. For example, click on the first line of the program and press the STOP icon. This sends the command break “something”, as a result this tool can be used to quickly learn the basic gdb commands.

In the File menu, there is a restart option. Pressing this button actually restarts ddd….

Reloading the Hello_World application results in the same killing of gdbserver. After another 30 minutes of tying I give up, the only way to restart the application is indeed killing the current version of gdbserver, start it again and reload the executable.

Although ddd shows the commands send to gdb and allows manual intervention I still like the look and feel of Kdbg so that will be my main debugger. From time to time I might use ddd or even gdb-cris directly if it is not clear what goes on or if special commands must be given.

« Previous Entries