4. Debugging the Application
During development it is necessary to be able to deeply inspect internals of the BMS application. This is only possible through a debugger. Apart from that a debugger is a required tool for downloading code into the BMS.
A debugger attaches to the microcontroller on the BMS which will be called target in the following text. The interface through which the connection to the target is established is called JTAG. The debugger can halt execution of the program on the target, download register values and restart execution. Moreover it is possible to mark locations in the code in such a way that the target will automatically halt once it reaches this location. This is called a breakpoint.
For more in-depth analysis of program flow it can be necessary to attach a trace probe to the target. This trace probe is a specialized hardware that is capable of parsing compressed information that the target can output through its trace port. This is not necessary for normal debug sessions.
4.1. How to debug
This manual is not able to describe in depth how to debug an application on an embedded target as this requires education and experience that have to be obtained through other means. Nevertheless, this section tries to walk through the main points of debugging this specific application. As this relies on basic debugger features it should work with any debugger.
4.1.1. Software structure
The main structure of foxBMS 2 are several interacting finite-state machines. For more information on the system structure please refer to Section 4 of this documentation.
In order to debug behavior of these state machines it is often helpful to keep
track of the struct that contains the state of the state machine.
The state of a state machine is tracked in a variable that is most of the time
called *_state
.
For details on the anatomy of this style of code please refer to
Section 8.2.1.2.1.
The second central point to look into are the database tables that contain
all values that are passed between state machines.
As an example the table data_blockCellVoltage
contains the consolidated
cell voltages that are used by the BMS for decisions.
For more information on the database refer to the database documentation in
Section 4.7.
For both of these variable types it can be helpful to monitor them continuously. Most debugger know a concept that is often called watch window. This watch window can be configured to monitor and continuously show updates of certain variables. This way it can be observed which values these variables take. Please note that even though the updates of a watch window might seem to be real-time, they are obtained by continuously halting the target and sampling the registers of the target. That means that firstly the shown values do not necessarily have to be all values (there might be values in-between) and secondly showing too many values might impact the performance of the target depending on the debugger implementation and thus alter real-time behavior during the debug session.
4.1.2. Assertions
Assertions are a method of ensuring that conditions that are thought to be true are actually true. foxBMS 2 uses assertions and the standard behavior is to completely stop the system in case of an assertion. That means that all interrupts are disabled and the system will come to a halt.
This state can be detected by checking if the system stops and if it does
controlling the value of the struct fas_assertLocation
.
It stores the program counter and the line number of the location of an
assertion that has failed.
The value of the program counter can be used to find the exact location in code
where the assertion has failed.
It is recommended to add the fas_assertLocation
variable to the watch
window or to set a write breakpoint that trips on writing to this variable in
order to easily see when an assertion has failed.
4.1.3. Version struct
Each binary is automatically marked with the software version from which it
has been built.
The current version is stored in the global variable
ver_versionInformation
and can be inspected with the debugger.
4.2. Choice of debugger
The choice of the correct debugger depends on many factors and can not be decided based solely on the information of this manual. The authors of this manual use a Lauterbach Trace32 debugger. The following section describes the configuration and usage of the Lauterbach Trace32 debugger.