C
Develop the Application Backend (RH850)
This topic guides you through the steps to create and build the application's backend using GHS MULTI IDE. The backend enables the application's UI to communicate with the platform and get the required information from the hardware. In this case, the device interface gets the status of the on-board user button. The following diagram describes the interaction between the two components:
Export application and platform sources
This section provides you step-by-step instructions to create a GHS MULTI IDE project from a QmlProject, complete with application and platform sources exported by the Qt for MCUs tools.
- Create a batch script with the following commands, which calls the
qmlprojectexporter
to generate a GHS Multi IDE projectset QUL_ROOT=C:\path\to\QtMCUs\2.10.0 set QMLPROJECT_FILE=C:\path\to\YourProject.qmlproject set BOARDDEFAULTS=%QUL_ROOT%\platform\boards\renesas\rh850-d1m1a-baremetal\cmake\BoardDefaults_32bpp.qmlprojectconfig set RGL_DIR=C:\path\to\rgl_ghs_D1Mx_obj_V2.1.0a set PROJECT_DIR=C:\path\to\PROJECT_DIR %QUL_ROOT%\bin\qmlprojectexporter.exe %QMLPROJECT_FILE% --platform=rh850-d1m1a-baremetal --toolchain=GHS --boarddefaults=%BOARDDEFAULTS% --outdir=%PROJECT_DIR% --project-type=ghs --include-ide-generated-hw-code --board-sdk=%RGL_DIR%
Before running the script, make sure that the following variables are set:
RGL_DIR
to the Renesas Graphics Library (RGL) 2.1.0a install path,QUL_ROOT
andQMLPROJECT_FILE
.PROJECT_DIR
to the output directory where you want to place the GHS project files.
Now, run the script from the command prompt to generate the following:
- C++ sources generated from QML in
%PROJECT_DIR%/QtMCUs/generated
- The exported platform sources in
%PROJECT_DIR%/QtMCUs/platform
- A top-level project file with subproject files in
%PROJECT_DIR%/GHS
.
The generated GHS project includes the following:
%PROJECT_DIR%/GHS/project.gpj
: The top-level project file.%PROJECT_DIR%/GHS/prj/program.gpj
: The program compile definitions, include directories, compiler and linker options.%PROJECT_DIR%/GHS/prj/drivers.gpj
: List of the RGL sources.%PROJECT_DIR%/GHS/prj/QtMCUs/qul_platform.gpj
: List of the RH850-D1M1A platform sources.%PROJECT_DIR%/GHS/prj/QtMCUs/qul_app.gpj
: List of the generated sources from the qmlproject export.%PROJECT_DIR%/GHS/prj/QtMCUs/qul_module_<ModuleName>.gpj
: One subproject for each module, including the sources generated for the corresponding QmlProject module.%PROJECT_DIR%/GHS/prj\application.gpj
: A convenience empty subproject for the application, which you will edit in the next section.%PROJECT_DIR%/GHS/mcu_<YourProject>_qul_workspace.gmb
: A workspace with some added commands for convenience. See GHS Multi IDE QUL Workspace for more details.%PROJECT_DIR%/GHS/qul_probe_E1.con
: Contains metadata for making a connection to the E1 probe.%PROJECT_DIR%/GHS/qul_probe_E2.con
: Contains metadata for making a connection to the E2 probe.
For more information, refer to Exporting a Qt for MCUs project with platform sources.
Build application in GHS MULTI IDE
The following instructions guide you through the GHS project adaptation steps needed to build the application:
- Launch the GHS MULTI Launcher (
mstart.exe
) - Select File > Load Workspace from File... and navigate to %PROJECT_DIR%/GHS as exported in the previous section. Select the workspace file
mcu_<YourProject>_qul_workspace.gmb
. - Double click the Project Manager entry in the workspace to open the project in the Project Manager.
- Create a new file named
main.cpp
in any directory. The directory will be referred to as BACKEND_DIR:#include "YourProject.h" #include <qul/application.h> #include <qul/qul.h> int main() { Qul::initHardware(); Qul::initPlatform(); Qul::Application app; static YourProject item; app.setRootItem(&item); app.exec(); return 0; }
This contains the default entrypoint for the application. You will extend this entrypoint later with extra configuration steps to use the LED and user button. Refer to the running Qt Quick Ultralite in applications for more information. Make sure to use the same project name (YourProject) that you chose in the earlier chapter.
- Right-click
application.gpj
and select Edit. Replace its contents with the following.#!gbuild macro APPLICATION_EXPORT_DIR=C:/path/to/PROJECT_DIR/QtMCUs/generated macro BACKEND_DIR=C:/path/to/BACKEND_DIR [Subproject] -DQUL_STD_STRING_SUPPORT -I${APPLICATION_EXPORT_DIR} # ----- backend ----- ${BACKEND_DIR}/main.cpp
Make sure to set the
APPLICATION_EXPORT_DIR
macro to the directory that has the exported UI sources, and the BACKEND_DIR macro to the directory containingmain.cpp
and the backend sources you created earlier.Note: Indentation is important in
.gpj
project files. Make sure there is no whitespace in the beginning of the line including the source file. Refer to the MULTI IDE documentation for more information - The application binary name is
application.elf
by default. To use a different name, change-o application.elf
to-o YourProject.elf
in theprogram.gpj
project file. - At this point, to verify that the steps so far have been followed correctly, you can build and flash your partially implemented application to the RH850 board to run it on the target hardware.
Before flashing, make sure that the board is connected to the target board and the computer. For more information, see connecting Renesas RH850 to the probe.
Once the connection is established, you can use GHS MULTI IDE to flash the application onto the board and debug using the capabilities in the IDE.
In the next section, you will add the low-level logic to enable interaction between UI and hardware with the user button.
Develop the C++ backend
The following instructions guide you through the process of developing the C++ backend for your application:
- Create new C++ source and header files and name them
deviceinterface.cpp
anddeviceinterface.h
respectively. Save these files in the BACKEND_DIR directory that you just created. - Replace the contents of
deviceinterface.h
with the following:#ifndef DEVICEINTERFACE_H #define DEVICEINTERFACE_H #include <qul/signal.h> #include <qul/singleton.h> #include <qul/eventqueue.h> typedef int HWButtonEvent; class DeviceInterface : public Qul::Singleton<DeviceInterface>, public Qul::EventQueue<HWButtonEvent> { public: Qul::Signal<void(int button)> buttonEvent; void onEvent(const HWButtonEvent &inputEvent); void toggleLED(); }; #endif //DEVICEINTERFACE_H
The header declares the
DeviceInterface
class, which inherits from Qul::Singleton and Qul::EventQueue. It also declares thebuttonEvent
Signal and theHWButtonEvent
event type. This allows the Singleton object instance to be globally available. It provides an interface between C++ and QML, to emit the changed signal on receiving theHWButtonEvent
input event. For more information, refer to Defining Singletons in QML and Transferring data from Interrupt Handlers to QML. - Similarly, replace the contents of
deviceinterface.cpp
with the following:#include "deviceinterface.h" #include "boardutils.h" void DeviceInterface::onEvent(const HWButtonEvent &inputEvent) { buttonEvent(inputEvent); } void DeviceInterface::toggleLED() { BoardUtils::toggleLED(); }
- Create a new C++ source and header files pair and name them
boardutils.cpp
andboardutils.h
respectively. Save these files in the BACKEND_DIR directory. - Replace the code in
boardutils.h
with the following:#ifndef BOARDUTILS_H #define BOARDUTILS_H namespace BoardUtils { void configure(); void toggleLED(); } // namespace BoardUtils #endif //BOARDUTILS_H
- Add the RH850-D1M1A-specific implementation of
BoardUtils::configure()
andBoardUtils::toggleLED()
toboardutils.cpp
:#include "boardutils.h" #include "deviceinterface.h" #include "r_typedefs.h" #include "r_bsp_hmi_api.h" #define LED_NR 0 #define LED_BRIGHTNESS_ON 100u #define LED_BRIGHTNESS_OFF 0u void button_handler() { DeviceInterface::instance().postEventFromInterrupt(0); } namespace BoardUtils { void configure() { R_BSP_HMI_Init(); R_BSP_SetButtonCallback(BSP_BTN_CENTER_PRESS, button_handler); R_BSP_HMI_SetLed(LED_NR, LED_BRIGHTNESS_OFF); } void toggleLED() { static bool isOff = true; R_BSP_HMI_SetLed(LED_NR, isOff ? LED_BRIGHTNESS_ON : LED_BRIGHTNESS_OFF); isOff = !isOff; } } // namespace BoardUtils
The configuration function calls BSP-specific initialization functions from the RGL library for the user LED and button. It then registers
button_handler()
as the interrupt request handler for the user button events. The interrupt request handler propagates the low-level interrupt events to the QML context using the DeviceInterface Singleton object. - To properly configure the RH850 LED and button, change
main.cpp
to include theboardutils.h
header and to callBoardUtils::configure()
after the normal platform initialization:#include "boardutils.h" ... int main() { Qul::initHardware(); Qul::initPlatform(); BoardUtils::configure(); ... }
- Add the new source files to
application.gpj
:#!gbuild ... # ----- backend ----- ${BACKEND_DIR}/main.cpp ${BACKEND_DIR}/boardutils.cpp ${BACKEND_DIR}/deviceinterface.cpp
- Finally, add the RGL library sources needed for LED and user button interaction to
application.gpj
:${QUL_BOARD_SDK_DIR}/vlib/bsp/board/d1mx_mango/src/hmi/r_bsp_hmi_knob.c
${QUL_BOARD_SDK_DIR}/vlib/bsp/board/d1mx_mango/src/hmi/r_bsp_sys_hmi.c
${QUL_BOARD_SDK_DIR}/vlib/bsp/hmi/src/r_bsp_hmi_main.c
Integrate UI and backend in Design Studio
Use the DeviceInterface Singleton object from Qt Design Studio, to access the low-level backend functions that you implemented in the earlier section.
- Open your project in Qt Design Studio and select the Connections view.
- Select the button in the Connections tab to add a new connection.
- Select the new connection and use the Connection panel to jump to the Code view.
- In Code view, add the first connection with
statusRect
as thetarget
, andDeviceInterface.toggleLED()
as the action for theonPressedChanged
signal. - In Code view, add the second connection with
DeviceInterface
as thetarget
, andstatusRect.pressed = !statusRect.pressed
as the action for theonButtonEvent
signal.Now when you press the button, the event propagates to the QML context, which changes the
statusRect.pressed
property. This results in changing the color of the UI item. In response to thestatusRect.pressed
property change, theDeviceInterface.toggleLED()
method toggles the LED. - Use a text editor to change
yourproject.qmlproject
to generate the necessary C++/QML interfaces needed for the singleton object:InterfaceFiles { files: ["C:/path/to/BACKEND_DIR/deviceinterface.h"] }
Change the BACKEND_DIR path to the directory containing the
deviceinterface.h
file.For more information, refer to QmlProject InterfaceFiles.
Update the GHS project after making changes to the UI
Since you have made changes to the UI parts of your application, export the UI sources again using qmlprojectexporter
.
Use the --update-project command-line argument to apply new changes in UI code to an existing GHS project. Use one of the methods listed below:
- Use the predefined command under
Sync Qmlproject files
in the workspace in the GHS MULTI Launcher. Double click it in the UI to update the project files. - Manually invoke
qmlprojectexporter
using the following batch script:set QUL_ROOT=C:\path\to\QtMCUs\2.10.0 set QMLPROJECT_FILE=C:\path\to\YourProject.qmlproject set PROJECT_DIR=C:\path\to\PROJECT_DIR set QMLPROJECT_DIR=%PROJECT_DIR%\QtMCUs\generated %QUL_ROOT%\bin\qmlprojectexporter.exe %QMLPROJECT_FILE% --update-project=%PROJECT_DIR%/GHS/project.gpj
Your application is now ready. Build your GHS MULTI project and flash it to the RH850 board to test that everything works as intended. Next, you can try to experiment and add support for another LED.
Available under certain Qt licenses.
Find out more.