Build, run, debug
This section is for how to build, run and debug project in ZStudio with ZCC, ZEMU and ZDB.
Build
ZStudio use project file .zsproj
rather than makefile or cmake to
organize each project. The project file contains all information and
instructions that ZStudio needs to operate projects, including build
configuration, run configuration, debug configuration and profile
configuration.
In this section, we use the example solution in Quick Start. To build a project:
-
Ensure the project you want to build is set to active
To make the project active, choose the project in the Active Project dialogue in Project Controller.
-
Choose build profile
To use the Debug, Release, Min Size or Release with Debug information profiles, select them from the Configuration dialogue in Project Controller.
-
Debug: Used during development, includes extensive debugging information.
-
Release: Used for production, excludes debugging information.
-
Min Size: Focuses on minimizing the final file size.
-
Release with Debug Information: Retains some debugging information on top of the release build.
-
-
Set build configuration
By clicking the (Build Configuration) button, you can specify parameters to the current project and toolchain. You may also right-click the project node to trigger the pull-down menu and select Build Configuration:
Build Configuration
-
Arch: Specify which CPU architecture the compiler will generate code for, such as "rv32imac". You can choose
arch
from dropdown list or input manually.For the lacked library of the architecture you specified, ZStudio will remind you of downloading from pack manager. The downloaded libraries would be added in toolchain and apply globally.
-
ABI: Specify binary interface of RISC-V application, such as"ilp32" indicates that in a 32-bit system, the integer,long, a nd pointer data types are all 32 bits.
-
CPU: The CPU option is used to enable specific optimizations, effectively specifying the Arch, ABI and scheduling model simultaneously, with the highest priority.
-
Compiler options allow you to set compilation flags, such as optimization level and debug level.
-
Linker options allow you to disable the default library and start file and specify linker scripts.
-
Assembler options allow you to set assembler flags.
-
NM/Readelf/Objdump/Objcopy/Size tool allows you to enable/disable output and control output content.
For more details see the Configure build settings subsection.
-
-
Build project
To build a project, go to Build in the menu bar or clicking the button in Project Controller view.
-
Check build result
Check the build result in the Build Console view, you can filter the build information in the drop-down box.
-
Verify output file
The executable files and object files are by default generated under output node in Project Navigator and
{project_name}\output
in File Navigator.
Configure build settings
To configure build settings for a project, go to Tool Settings page which list the available build options. Select and make the desired modifications.
-
Compiler > Optimization
This page allows you to configure optimization level, optimization options, and the code model for your project.
-
Optimization level: This option allows you to configure the level of optimization performed by compiler on the generated code. you can select from six optimization levels (from -o0 to -os) to control the trade-off between performance and code size according to your needs.
-
Code model: ZCC compiler supports the
medany
andmedlow
options, which are equivalent to themedium
andsmall
options in the GCC compiler for the RISC-V architecture, as shown in the table below.Supported code models of ZCC for RV32 and RV64 Code Model ZCC GCC text/data/rodata RISC-V architecture medlow small Full 32-bit addressing space & The highest 2 GiB and the lowest 2 GiB in 64-bit addressing space RISC-V architecture medany medium Full 32-bit addressing space & PC ± 2 GiB in 64-bit addressing space -
Loop Unroll: This option allow you to unroll all loops and turn on complete loop peeling (
-funroll-loops
) or turn off loop unroller (-fno-unroll-loops
) . And the option "Pass no flags to compiler" means compiler defaults to partial loop unrolling. -
Link Time Optimization : This option makes it possible to apply aggressive link time optimization to your projects. ZCC enable link time optimization by default , while some other toolchains do not have this feature. This option allows you to manually turn on (
-flto
) or turn off (-fno-lto
) link time optimization or just use the default flag applicable to the compiler. -
Remove unused function sections (
-ffunction-sections
) and unused data sections (-fdata-sections
) : These options allow the removal of never referenced sections. When both options are selected, the compiler places each function/data item into its own section of the output file, whereupon the--gc-sections
option is passes to the linker for the removal of never-referenced function/data. If ZCC(or other toolchain) is a linker, then the-wl, --gc-sections
option is used instead. -
Other optimization flags: This option allows you to manually add optimization flags or turn off default optimization options applicable to a particular optimization level.
-
-
Compiler > Debugging
This page allows you to configure the degree or intensity of debugging information that is generated for your project.
- None: No debugging information is generated or displayed.
- Minimal: Basic debugging information, such as critical errors or checkpoints, is logged.
- Default: More detailed information, including variable values or function call traces, is recorded.
- Maximum: Highest level of detail, capturing extensive information for thorough debugging analysis.
-
Linker > General
This page allows you to configure linker options, such as disable the default library and start file and specify linker scripts.
-
Linker Script : Assign a linker script to your project. You have to specify a linker script here. ZCC linker does not support the
DEFINED
macro inside the link script. For link scripts that useDEFINED
, you need to make some modifications as following example. For requirements and limitations pertaining to the link scripts, please refer to the ZCC User Guide.- __stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
+ __stack_size = 2K;
-
-
Binutils
When binutils (NM/Readelf/Objdump/Objcopy/Size) are enabled, the output is generated in project output node after the project is built.
Run
ZStudio provides several ways to run projects. You need to create necessary run configurations for each of the project and target that need to be launched.
Run on board
ZStudio supports running/debugging on board with OpenOCD, Please refer Start debugging on board and the Demo project Hello_with_dsp_and_nn_sdk_0.4.0.
Run on simulator
To run project on simulator:
-
Ensure the run parameters
You can change the run configuration by clicking the (Run Configuration) button and fill in the parameters you want to specify.
Run Configuration
-
Program Argument: Pass arguments to program.
-
Connection Target: Choose where your project will be executed, physical board or simulator.
-
Choose Virtual Board:
-
Built-in: You can choose built-in boards from Simulator Virtual Board drop-down list.
-
Custom: You need to specify
.zvb
configuration file in **Board Configuration. You can specify here custom virtual SoCs constructed by ZVB in ZExplorer.
-
-
Simulation Accuracy Level:
- Emulation: Emulation mode offers faster execution speeds and is primarily used to verify program functionality. However, it provides limited performance data.
- Simulation: Simulation mode operates at a lower speed but provides cycle information about the program which can be used for performance analysis.
-
Display Statistics: Choose whether to print performance statistics of the executable program.
-
Simulator Argument: Pass arguments to ZEMU. Use
--stat
to generates analytical data about the execution or performance of a program.
-
-
Go to Run in the menu bar or clicking the button in Project Controller view, ZStudio invoke ZEMU to run the compiled executable file of active project. The output is displayed in the Run Console in the bottom panel.
Debug
ZStudio's built-in debugger ZDB help quickly find errors in the code and repair projects.
Start debugging on board
To start debugging on board, you need to build the project and flash it to the device.
-
Connect the board to your PC and make sure it is really recognized by the PC.
tipPlease refer to the user guide of Development Board and check if the board need Driver.
-
Create serial port connect
From the main menu, select View > Serial Port Monitor to invoke the view. Click the + button to configure the port settings, the Serial Port box automatically detects any communication port connected to your computer. Click OK to build the connect.
The status icon becomes green means Serial Port connect successfully. And the disconnect of board may cause serial port connect failure and the status icon will become red.
See the following table to learn about the settings that the Serial Port Monitor provides.
Configurable settings Settings Usage Available options Port Use the Serial Port dropdown to select ports Automatically detects serial port compatible devices connected to the device Baud Rate Use the Baud Rate dropdown or write a custom rate in the text box to decide the frequency at which the monitor attempts to communicate with the connected device 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 250000, custom rate Data Bits Use the Data Bits dropdown to select how many data bits are used for the serial port connection 5, 6, 7, 8 Parity Use the Parity dropdown to select what parity is used for the serial port connection None, Odd, Even, Mark, Space Stop Bits Use the Stop Bits to select how many stop bits are used for the serial port connection 1, 1, 5, 2 -
Add OpenOCD configuration and start OpenOCD.
From the main menu, select View > OpenOCD Explorer, click + to create an OpenOCD configuration. In the settings, you need to point ZStudio to the OpenOCD executable and configuration file in your PC file system.
tipPlease refer to the user guide of Development Board to download OpenOCD executable and configuration file.
Right-click the exist OpenOCD and select start or stop in context menu to control the OpenOCD process, the status icon becomes green means OpenOCD process is on.
tipTurn off or disconnect the board may cause the disconnection of OpenOCD and your board despite the OpenOCD process signal is green. Please check and restart OpenOCD.
-
Specify debug configuration
On the Project Controller, click the the (Debug Configuration) button to invoke configuration wizard. Set Board as run and debug target and select the OpenOCD configuration that matches the board you connected.
-
Add a breakpoint and start debug session. The debugger runs to the first breakpoint it encounters and stops. Click Step Over button and check the project output in Serial Port Monitor view.
About the Demo of debugging on board, please refer to Hello_with_dsp_and_nn_sdk_0.4.0.
Start debugging on simulator
- Select the Debug build profile for the project you want to debug and rebuild.
- If necessary, modify the debug configuration or create the detailed parameters by clicking the (Debug Configuration) button.
- Set breakpoint in the source code and click the button to start debug session.
Check if Windows Defender Firewall allow zemu.exe
to create port
listening.
Once a debug session starts, the Debug toolbar will be available to help you debug your projects more quickly:
- Pause/Continue F5
- Step Over F10 : Steps over the current line and takes you to the next line even if the current line includes function calls. The calls are skipped, and you move straight to the next line of the caller.
- Step Into F11 : Advance the debugger into each function. Steps inside the code of a called function.
- Step Out Shift+F11: Steps out of the current function and takes you to the code of the caller.
- Restart Control+Shift+F5
- Stop Shift+F5
You can check information related to debug include:
- THREADS: examine and work with threads in the code that you are debugging.
- CALL STACK: the call stack shows the order in which methods and functions are called.
- REGISTERS: you can inspect registers variables here.
- VARIABLES: you can inspect local, global variables here.
- WATCH: keep track of some variable or the result of a complex expression.
- BREAKPOINTS: add, remove, edit or disable and enable breakpoints.
The status bar will change to orange once debugging session has started. The user can change the debug configuration by clicking Configuration Active Project and the target by clicking Debug on Simulator/board in the status bar.
Set breakpoint
You can set one or more breakpoints to suspend your running code in order to take a look at variables' values, or see whether or not a block of code is getting executed.
Once you have set a breakpoint, you can remove it, edit it, or disable and enable it again from the BREAKPOINTS list. The buttons are:
- Add Function Breakpoints
- Activate/Deactivate Breakpoints
- Remove All Breakpoints
Besides, you can also right-click the breakpoint and select Remove Breakpoint, Edit Breakpoint, Disable Breakpoint or Enable Breakpoint.
Line Breakpoint
To set a breakpoint, click in the margin to the left of a line of code
in the editor. A red dot is displayed. In the example sum.c
below,
debugger runs to the first breakpoint it encounters and stops:
Exception Breakpoint
Exception breakpoint suspends the project when the specified exception
is thrown. When a project throws an exception (throw
) or catches an
exception (catch
), the debugger interrupts the project's execution.
Exception breakpoints can help users quickly locate and solve exception
issues in the project, such as accessing null pointers and dividing by
zero. In the example below, you can set exception breakpoints through
the following steps.
- Click BREAKPOINTS section in the left part of the Debug View
- Check the box next to C++ Catch and C++ Throw
- Start debugging
C++ Throw can capture the exception that project throws. In this
case, the division
function throws an exception.
C++ Catch is used to catch thrown exceptions. When an exception
occurs, the project jumps to the specified catch
statement to handle
the exception and stops executing the subsequent code. In this case, the
division
function catches an exception.
Function Breakpoint
It is useful to set function breakpoint when you know the function name but not its location. With function breakpoint, you can break execution when a function is called. To set a function breakpoint:
- Unfold the BREAKPOINT list in debug view.
- Click the Add Function Breakpoint button, the dialog box opens.
- Type the name of function you are looking for and click OK.
The execution break when debugger runs to the function breakpoint you set.
Conditional Breakpoint
Conditional breakpoints allow you to break inside a code block when a defined condition is met. You can set two types of conditions.
- Expressions: The debugger pauses when the expression you defined is true.
- Hit Count: The debugger pauses after a specified number of hits, called a hit count. If you suspect that a loop in your code starts misbehaving after a certain number of iterations, you can set a breakpoint to stop execution after that number of hits.
As the example below, you can set a expression as conditional breakpoint:
-
Right-click in the margin to the left of a line of code in the editor and select Add Conditional Breakpoint....
If you already have a breakpoint defined, you can also right-click the breakpoint and select Edit Breakpoint....
-
In the drop-down list that is displayed, select Expression or Hit Count and set a condition as follows:
-
Expression: Can be any valid expression that the debugger recognizes. The debugger pauses when the expression is satisfied.
-
Hit Count: Specify the number of iterations (hits) after which execution will stop.
-
-
Press Enter.
In the editor, conditional breakpoints are indicated by a breakpoint
symbol that has a equals sign inside of it. You can place the cursor
over a conditional breakpoint to show its condition. The debugger will
evaluate the condition when it hit the breakpoint. When the expression
of i==3
is satisfied, the debugger paused.
Inspect memory
In some cases, for example, when debugging data processing problems, you may need to view raw memory of the running process. For this, ZStudio provides Memory View which is default displayed in right side bar. You can click the memory icon to unfold it and check raw memory when you need.
To inspect memory:
- Get the required address: you can input `
p &variable_name
command in REPL to get required address of the variables. - Jump to the address: Input the hex address and click Go; the
memory view initially shows a 256-byte region that starts from the
chosen address, with higher memory address at the bottom of the
window. You can check more data by setting
LENGTH
.
As the example below, you can trace the change of the array
in the
memory view. When you click step over, the memory data will be
highlighted.
Format settings
you can change the memory data format by clicking settings button. For example, you can set byte size as 8, bytes per groups as 4, groups per row as 1 to control how much data you see at once,and how it's grouped for you preferences. Regardless, Changing the view does not change the actual data in memory --- it simply changes how you're looking at it.
Inspect registers
The Debug view provides functionality to inspect register values. Register values can be modified with the Set Value action from the register's context menu. For example, to set value of register while debugging:
- Wait for your project to stop at a breakpoint.
- Unfold REGISTERS section in the Debug view and find the target register
- Double-click the register or right -click the register and select Set Value, type the new value and click OK.
Inspect variables
All Local, Global variables are shown in the VARIABLES section. When
the debugger is paused, hover over an object with the mouse, and you
will see its current property value. You can also inspect variable
values in the VARIABLES section. you can use the Step Over
debug
command, you can observe how the variables change as each step is
executed.
If there is a need to test how the project would behave in certain conditions or fix its current behavior at runtime, you can do that by setting/changing the variable values.
- Right-click a variable on the VARIABLES section and select Set Value, or double-click the variable name.
- Enter the value for the variable and click OK.
When the debugger is paused, several options are available when you right-click a variable from the VARIABLES section:
- Copy Value: Allows you to copy the value of a variable.
- Copy As Expression: Allows you to copy the name of a variable.
Set watch expressions
If you want to keep track of some variable or the result of a more complex expression, you can set up a watch for this variable or expression.
- Click the + button in the WATCH section to open Edit Watch Expression dialog box.
- Type the name of a variable or expression and click OK.
The project will pause at the line where the breakpoint is set and
display the value of the variable. You can step over as needed to
observe whether the value of the variable sum
is computing as
expected.
More options are available from the WATCH section:
- Collapse All
- Remove All Expressions
Debug console
Debug Console view is used to output debugging results and information. To open the Debug Console, click the View > Debug Console in menu bar or press Control+Shift+Y. When starting debugging, the Debug Console panel will show debug output.
REPL
The Debug Console REPL (Read-Eval-Print Loop) feature is on the bottom of the view and can be used to calculate the return value of a variable or function. Click the button in the up right corner of Debug view to open REPL input box.
In this example below, typing i+count
in the REPL window and then
pressing Enter to send it, the Debug Console output the return value of
i+count
.
If you are an advanced user, you can use the REPL to interact with the debugger through frequently used ZDB/GDB commands. When entering a command, it needs to start with `. It provides functionality the UI does not expose, including:
bt
p <expression>
For the example below, enter `p &i in the REPL window at the bottom, and then press Enter to send it, the Debug Console will output the address of the current variable.
::: tip
You must be in a running debug session to use the Debug Console REPL. When use the REPL to interact with the debugger , it is necessary to consider the potential risks of calling functions or changing variable values. :::
Disassembly view
The disassembly view is provided in debugging to display high-level source code with its associated assembler code for use in identifying instruction issues during debugging. You can switch to the disassembly view by following these steps.
- Make sure the debug session is on;
- Open the disassembly view from view's pull-down menu.