cancel
Showing results for 
Search instead for 
Did you mean: 

What is the best way to debug both ends of a communications link?

Harvey White
Senior III

Windows 10, CubeMXIDE 1.12.0

Mixed C/C++, STM32L562 processor on custom board.

using STLINK V2 and V3 debugging.

Common software installed as links, configuration file and main.c are really the only unique files that I provide. Configuration file is a bunch of #defines to switch in hardware and software features. All other files that I provide are identical, working equally well on both ends of the system (Root and new node).

I'm debugging both ends of an NRF24L01 mesh network at the same time, watching how each module responds (SPI interface). It's done, the mesh works but needs some refinement, but the communications sequences and responses are working properly.

Hardware debuggers work well with each, but as far as debugging both ends of the link at the same time, I'm wondering if there is an easier way.

With both projects in the same workspace, there is a problem with each debugger pulling up a "copy" of the source (it's the same). There's no really obvious way to tell which is which for the linked files, and I end up with two files in the editor that are out of sync. Any suggestions about that?

When debugging, the breakpoints are not separated by processor (and could be, and perhaps should be). This makes life difficult as well. Common software is working differently depending on the function, but the main loops are still identical. Breakpoints do not readily identify which processor is what, even though they are detailed in the thread descriptions. I'm looking for more obvious.

Any suggestions on the programs in the same workspace method?

I've also got the system set up with two instances of the IDE, which is better when identifying which processor is which. Needs dual monitors, but that's less of a problem than otherwise.

breakpoints would and are separate, so that is less of a problem.

The difficulty I see is in file synchronization. Changing one instance of a file for one processor does not automatically change the instance in the other IDE. Granted, when the software is recompiled, the file on disk changes.

However, that is not necessarily picked up by the second IDE. Since the natural inclination is to debug programs for each processor in the separate window, there are file synchronization problems.

Any comments about this method?

I'm suspecting that I might be missing something, but normally, I do not have two simultaneous debug sections running (and I foresee lots of them when I get into board to board communications). Surely there are people who do this a lot, so what am I missing? I have no real desire to change operating systems, but I'm used to FreeRTOS, know where the bodies are buried, and AZURE does not like C++, and I don't like AZURE queues. A topic for another time.

What's the better method?

14 REPLIES 14

I've noticed that with two instances of the IDE, making a change in one will be reflected in the other, without having to it F5. The changes do have to be saved, of course. Makes life more convenient.

In this instance, I'm debugging the actual communications logic, the mesh networking handshaking. I'm doing a similar thing with some direct wired connections when boards are in a common stack.

Timing assures that the master processor can become a root node in the mesh network if no other processor is available, else it becomes another node. The remaining processors in a board stack do not boot until a master processor is assigned (if any). They can become a node, but not a root node (already picked if a master processor exists).

Slave processors may either be standalone, or linked to the master processor by I2C links. Makes sense if you have board stacks and a separate mesh environment.

I also have two instances of the IDE, each project is under its own IDE workspace. Under each debugger configuration, once I select the S-link with the corresponding SN number, it works fine to download and debug when both boards are running, but I had to select "Autostart local GDB server" at the same time though.

I also have many files same for both projects. How do you structure your two projects? Do you let the master project list all the common files and folders including Hal driver folders and let the slave project pointes to the master project common folders? The include file folder setup usually use relative path rather than absolute directory. So in the slave project, to reference so many common files/folders under the master project, they will need to be use absolute directory, or maybe up more levels but need to reference the master project folder name for sure, right?

Thanks

Harvey White
Senior III

I've had some problems with how CubeMX finds files, so I've had to resort to absolute paths. Because of this, I've tried things and the existing structure of my project reflects the experiments (that didn't work). I've tried relative paths, and the like, and I found that project properties/paths entries don't work well for me. I've resorted to absolute paths. Because the project structure is similar for many projects of this type, the absolute paths work from project to project.

The basic project structure (modified from the default) is to add SUBSYSTEMS, which is a file structure that has all of the common files. It does not include any unique files per project. Each file in SUBSYSTEMS is common to all projects.

0693W00000aJo7EQAS.pngNow the overall directory structure is

0693W00000aJo8vQAC.pngand the project directory is

0693W00000aJo9PQAS.pngand just for fun, the common files are:

0693W00000aJo9eQAC.pngNow, there's no reason that you have to follow this setup, but it does work for me.

In each file, as needed, insert the following which (as you see, has multiple projects under the same overall umbrella, using the same common files

#if (defined _PCA9634) && (defined _I2C) && (defined _PACKET)
#include "D:\Documents\Projects\ARM projects\PROJECT 42\SUBSYSTEMS\SYSTEM_CPP\SYSTEM_LED.hpp"
	extern SYSTEM_LED* pca9634;
#endif
 
// *********************************************************************** end revised *
	#include "D:\Documents\Projects\ARM projects\PROJECT 42\SUBSYSTEMS\HAL_CPP\HAL_I2C.hpp"
 
	#include "SYSTEM_I2C.hpp"
 

when I created links by importing the files, I did not copy the files, I simply allowed it to link to existing files. (A little iffy on that, mostly because I've never seen a good explanation of what CubeIDE really does here. Major thing is not to copy files at all. Using the absolute paths gets rid of a lot of "I can't find it".

So for your specific questions or comments:

I use autostart GDB. I don't seem to have a problem there.

I just bypassed the relative path by using absolute paths. Because the major directory structure is independent of the project (see the project folder), for a particular incarnation of "I'm doing it this way", all of this is under Project 42, a number which may indicate the answer to everything <obscure reference>, the paths from part to part in the SUBSYSTEM files do not vary per project. Figure it out once, and it works.

Now, all this is under CubeIDE, so it produces a main.c file. The main.c file links to a C++ file "CPP_LINK", which sets up certain subsystems, mostly displays, I2C, and SPI. At this point, the overall system boot sequence can use an existing OLED display (small: 128 x 64).

CPP_LINK then calls a create routine which sets up the main project .cpp file. That conditionally sets up (using an included options.h with a lot of #define declarations) the subsystems: Networking, packets, mesh networking, display templates, various I2C hardware and the like.

Once this is done, there is a loop updating the status (OLED) display every five seconds or so.

The entire system runs on FreeRTOS, is written in C++, and is an event driven system (mostly). Touches on a display generally cause things to happen. External messages from other processors or processors in the mesh network cause things to happen.

It's a lot easier now, once I figured out this project structure. Is it perfect? no. Is it the only way to do things? no. Does it work? yes.

Hope that this helps and answers your questions.

Hope that this also helps others who stumble on this thread with much the same problems.

Thanks for your reply and showing the detailed folder structure. I see how you are doing it. I think if you setup the include file path under each project, you don't need to add the absolute path inside the source code file. I'll try to setup it up later when I'm ready, now I need to debug some functionality first.

Thanks

I did this, this way, specifically for the following reasons:

1) I could not get the include path in the project to work properly.

2) I had to set up each project (I've got a lot of them) individually, so a bother

3) I got really tired with messing around with this. Eclipse (the basis of CubeMX) has (I heard) some long standing issues with relative path resolution.

4) it works. Seems to be reliable, so that's good.

5) if I change paths, for whatever reason, a good blanket compilation will point out the unresolved paths, Somewhat tedious, but those changes do the entire project.

If the relative paths work for you, then that's good, and I'd like to hear of it.

Hope it all turns out well, glad to be of help.