Skip to main content
Version: 4.x

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:

  1. Ensure the project you want to build is set to active

    To make the project active, choose the project in the dialogue in Toolbar.

  2. Choose build profile

    To use the Debug, Release, Min Size or Release with Debug information profiles, select them from dialogue in Toolbar.

    • 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.

  3. Set build configuration

    By clicking the build-configuration-button (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.

      Specify Arch and download library

      Specify Arch and download library

    • 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.

  4. Build project

    To build a project, go to Build in the menu bar or clicking the build-button button in Project Controller view.

  5. Check build result

    Check the build result in the Build Console view, you can filter the build information in the drop-down box.

  6. 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 and medlow options, which are equivalent to the medium and small 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 ModelZCCGCCtext/data/rodata
      RISC-V architecturemedlowsmallFull 32-bit addressing space & The highest 2 GiB and the lowest 2 GiB in 64-bit addressing space
      RISC-V architecturemedanymediumFull 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 use DEFINED, 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, including simulator, virtual development board, and physical development board. You need to select necessary run configurations for each of the project and target that need to be launched.

TargetSimulatorVirtual Dev BoardPhysical Dev BoardRemote Dev Board
ZStudio Desktop
ZStudio Cloud

Run on board

ZStudio supports running/debugging on board with OpenOCD, Please refer Start debugging on board and the Demo project Hello_World_in_hpm_sdk.

ZStudio Cloud supports remote running or debugging using Terapines Board Farm, please refer Remote debugging using Terapines Board Farm.

Run on simulator

To run project on simulator:

  1. Ensure the run parameters

    You can change the run configuration by clicking the build-configuration-button (Run Configuration) button and fill in the parameters you want to specify.

    Run Configuration

    run-project-simulator-1

    run-project-simulator-2

    • Program Argument: Pass arguments to program.

    • Connection Target: Choose where your project will be executed, physical board or simulator.

    • Simulator Type: Choose the type of simulator to use, either built-in or local. If using a local simulator, specify the path to the simulator executable file.

    • Choose Virtual Board:

    • 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. run-with-stat-arguments

    • Simulator Argument: Pass arguments to ZEMU. Use --stat to generates analytical data about the execution or performance of a program.

  2. Go to Run in the menu bar or clicking the run-button 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 provides several debug targets, including simulator, virtual development board, and physical development board. You need to select necessary run configurations for each of the project and target that need to be launched.

TargetSimulatorVirtual Dev BoardPhysical Dev BoardRemote Dev Board
ZStudio Desktop
ZStudio Cloud

Debug layout

ZStudio supports switching between code layout and debug layout. The debug layout facilitates viewing reference information such as registers, variables, and call stacks during debugging, helping to locate issues.

code layout

debug layout

You can switch the layout by clicking the toolbar buttons on top-right corner of the window.

Start debugging on board

To start debugging on board, you need to build the project and flash it to the device.

  1. Connect the board to your PC and make sure it is really recognized by the PC.

    tip

    Please refer to the user guide of Development Board and check if the board need Driver.

  2. 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
    SettingsUsageAvailable options
    PortUse the Serial Port dropdown to select portsAutomatically detects serial port compatible devices connected to the device
    Baud RateUse 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 device300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 250000, custom rate
    Data BitsUse the Data Bits dropdown to select how many data bits are used for the serial port connection5, 6, 7, 8
    ParityUse the Parity dropdown to select what parity is used for the serial port connectionNone, Odd, Even, Mark, Space
    Stop BitsUse the Stop Bits to select how many stop bits are used for the serial port connection1, 1, 5, 2
  3. Specify debug configuration

    On the toolbar, click the the debug-configuration-button (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.

    On debug configuration window, you can specify:

    • whether to build the project before debugging.

    • whether to stop at Main() function when debugging.

  4. 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.

    tip

    Please 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.

    tip

    Turn 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.

  5. 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_World_in_hpm_sdk.

Remote debugging using Terapines Board Farm

ZStudio Cloud support remote debugging using Terapines Board Farm.

  1. Select the Debug build profile for the project you want to debug and rebuild.

  2. Click the debug-configuration-button button to open the configuration window. In Connect Target, select Board.

  3. Reserve a Board

    • In the Physical Board dropdown list, select Apply Online Boards. The system will redirect you to the board sharing platform (Terapines Board Farm).

    • On the platform, select a board compatible with your program and click Apply to enter the details page.

    • In the schedule section, drag to select a time slot, then confirm the reservation in the pop-up dialog.

    apply-online-boards
  4. Select the Reserved Board

    Return to ZStudio and reopen the debug configuration window. In Connect Target, select Board. The Physical Board dropdown list will now display the reserved board and the waiting time, if any.

    选择开发板

    调试布局

  5. Start Debugging

    Add breakpoints and start the debug session. Check the output in the serial monitor.

Start debugging on simulator

  1. Select the Debug build profile for the project you want to debug and rebuild.
  2. If necessary, modify the debug configuration or create the detailed parameters by clicking the debug-configuration-button (Debug Configuration) button.
  3. Set breakpoint in the source code and click the debug-button button to start debug session.
tip

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:

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:

general.cpp
#include <iostream>
using namespace std;

int global = 2;

int sum(int a, int b) {
return a + b;
}

struct Complex {
int a;
int b;

Complex() : a(0), b(0) {}
int Sum() { return a + b; }
};

int main() {
int result = sum(3, 4);
cout << "Sum: " << result << endl;

Complex c;
c.a = 5;
c.b = 7;
cout << "Complex sum: " << c.Sum() << endl;

return 0;
}

  1. Unfold the BREAKPOINT list in debug view.
  2. Click the Add Function Breakpoint button, the dialog box opens.
  3. 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:

sum.c
#include <stdio.h>

int main()
{
int arr[] = {1,2, 3, 4, 5};
int sum = 0;
int i;

for (i = 0; i < sizeof(arr) / sizeof(int); i++) {
sum += arr[i];
printf("sum=%d\n", sum);
}

return 0;
}
  1. 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....

  2. 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.

  3. 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 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.

Inspect variables

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.

  1. Right-click a variable on the VARIABLES section and select Set Value, or double-click the variable name.
  2. 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.

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:

  1. In the Variables view, right-click on a variable and select "Show Variable in Memory Inspector" from the context menu;
  2. The right side bar will automatically expand and jump to the current address of the variable.

As the example below, you can open and view the current address and state of variable i in the memory inspector from the variables view. When performing "step over" debugging, the memory view will highlight the memory address corresponding to the current code and its corresponding value.

Inspect memory

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:

  1. Wait for your project to stop at a breakpoint.
  2. Unfold REGISTERS section in the Debug view and find the target register
  3. Double-click the register or right -click the register and select Set Value, type the new value and click OK.

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.

  1. Click the + button in the WATCH section to open Edit Watch Expression dialog box.
  2. 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 counter is computing as expected.

main.c
#include <stdio.h>

int main() {
int counter = 0;
int threshold = 5;
int flag = 0;

for (int i = 0; i < 10; i++) {
counter += i;

if (counter > threshold) {
flag = 1;
}

printf("i=%d, counter=%d, flag=%d\n", i, counter, flag);
}

return 0;
}

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 REPL-button button in the up right corner of Debug view to open REPL input box.

In this example below, typing i+counter in the REPL window and then pressing Enter to send it, the Debug Console output the return value of i+counter.

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.

  1. Make sure the debug session is on;
  2. Open the disassembly view from view's pull-down menu.

Configure toolchains

When you start working with ZStudio, a default built-in toolchain ZCC is readily available. We recommend using builtin toolchain for the best support.

Switch the builtin toolchain version

ZStudio comes with the latest ZCC toolchain built in by default. However, you can download historical versions of the ZCC toolchain in Pack Manager and switch the toolchain version in your project settings.

Go to Tools > Toolchain Manage > Download Toolchain. In the Package Manager panel, expand the “Toolchains” and "Toolchian Libraries” categories. Here you can download all historical toolchain versions in the list, along with the corresponding library versions. Libraries are installed directly into the matching toolchain version, so you only need to switch the toolchain in the project.

  • Installinstall-button: Download and install historical versions of toolchains and libraries.
  • Uninstalluninstall-button: Remove installed toolchains and libraries; you can reinstall them when needed.
  • Unavailableban-button: Built‑in toolchain versions; operations are not allowed.

After installation, you can switch toolchains within the project. Right‑click the project node, select Project Settings, and choose the downloaded version from the Toolchain dropdown to switch the toolchain version.

Create a custom toolchain

You can switch to the custom compiler on your machine as needed. ZStudio supports multiple toolchains within a single project, allowing you to seamlessly switch between them when required.

Go to Tools > Toolchain Manage> Add Toolchain. In the Add Toolchain dialog box, configure the toolchain settings. When the configuration is completed, click "Save" to create it.

Custom toolchain Configuration

Add toolchain 1

Add toolchain 2

  • Toolchain Path: Specify the path of the toolchain on your machine.

  • Toolchain Name: Specify the name of the toolchain. It can't be edited after creation.

  • Toolchain Type: Specify the type of the toolchain. ZStudio supports gcc-based and llvm-based toolchains.

  • Target: Specify the targets your custom toolchain supports.

    • Platform: Select the platform of the toolchain from pull-down box, such as "RISC-V", "x86" or "ARM". At least one platform needs to be specified. It depends on the toolchain you used.

    • Target Arguments: Specify target arguments, such as "--target=x86_64-linux-gnu", which can be switched in Project Configuration.

  • Simulator Type: Use our built-in simulator or specify the path of your local simulator.

Add toolchain 3

Add toolchain 4

  • Tools: You need to specify the path of each tools (Debugger, C Compiler, C++ Compiler, Assembler, Linker, AR, Objdump, Objcopy, Readelf, Size and NM) to combine into your custom toolchain.

Edit or remove toolchains

To edit toolchain configuration, go to Tools > Toolchain Manage> Edit Toolchain Configuration.

Select the toolchain you want to edit and from the pull-down box, and adjust the configuration. The toolchain name can't be changed after creation.

To remove toolchain configuration, go to Tools > Toolchain Manage> Remove Toolchain Configuration.

Specify custom toolchain for a project

After you have set up your custom toolchain, you can configure your project to use it by right-clicking the right-click the project node in Solution Explorer and select Project Configuration. In the Toolchain pull-down box, select your custom toolchain.

You can now build and debug the project using your custom toolchain. If you specify multiple target arguments for your custom toolchain, you can switch between them in Build Configuration. Right-click the project node in Solution Explorer and select Build Configuration. In the Target pull-down box, select the target argument which will be passed to the compiler.