How to develop C++ application on RTOS-core?

I need to make an application on RTOS-core using C++ instead of C. How to do this? I’ve just tried to replace an extension on freertos/cvitek/task/main/src/main.c file to .cpp but that led to errors during the build process:

duo-buildroot-sdk/freertos/cvitek/arch/riscv64/src/start.S:135: undefined reference to "main"

What do you need c++ for?

I think available compilers were limited to C.

1 Like

A linker issue. Do you need to define main in the C++ or add an extern "C"?

I’ve got a lot ready-to-use code written in C++ so I don’t want waste my time and money to convert it back into C.

If you mean something like that

#ifdef __cplusplus
extern "C" {
#endif

int main(void)
{
	pre_system_init();
	printf("CVIRTOS Build Date:%s  (Time :%s) \n", __DATE__, __TIME__);
#ifndef __riscv
	mmu_enable();
	printf("enable I/D cache & MMU done\n");
#endif
	/* Configure the hardware ready to run the demo. */
	prvSetupHardware();
#if ( configUSE_TRACE_FACILITY == 1 )
	vTraceEnable(TRC_START);
#endif
	post_system_init();

#ifdef CVIRTOS
	{
		main_cvirtos();
	}
#else
#error "Not correct running definition"
#endif

	/* Don't expect to reach here. */
	return 0;
}


#ifdef __cplusplus
}
#endif

it doesn’t work.

I did. Shame it did not work.

Instead you could convert the project into C++ in its entirety, i.e.

diff --git a/freertos/cvitek/task/CMakeLists.txt b/freertos/cvitek/task/CMakeLists.txt
index d23d7f4e7..a885560c4 100644
--- a/freertos/cvitek/task/CMakeLists.txt
+++ b/freertos/cvitek/task/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.16.5)
 
-project(arch C ASM)
+project(arch CXX ASM)
 
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)

and then include the C++ source files.

diff --git a/freertos/cvitek/task/comm/CMakeLists.txt b/freertos/cvitek/task/comm/CMakeLists.txt
index 1082dc10b..56197f49b 100644
--- a/freertos/cvitek/task/comm/CMakeLists.txt
+++ b/freertos/cvitek/task/comm/CMakeLists.txt
@@ -1,4 +1,4 @@
-file(GLOB _SOURCES "src/${RUN_ARCH}/*.c")
+file(GLOB _SOURCES "src/${RUN_ARCH}/*.cpp" "src/${RUN_ARCH}/*.c")
 
 include_directories(include)
 include_directories(${CMAKE_INSTALL_INC_PREFIX}/arch)

You will then need to clean the build files and fix anything affected by the change of compiler.

rm -Rf u-boot-2021.10/build/cv1800b_milkv_duo_sd freertos/cvitek/build freertos/cvitek/install
./build.sh milkv-duo-lite

Maybe a subset of the above changes may be enough.

Thanks for suggestion, but I’m stuck in trouble during compilation FreeRTOS under c++: I’ve got an error:

FAILED: comm/CMakeFiles/comm.dir/src/riscv64/comm_main.cpp.obj 
/home/user/milkv/duo-buildroot-sdk/host-tools/gcc/riscv64-elf-x86_64/bin/riscv64-unknown-elf-g++  -I/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/task/comm/include -I/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/arch -I/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/common -I/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/kernel -I/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/driver/spinlock -I/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/driver/rtos_cmdqu -I/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/hal/config -Wno-missing-field-initializers -Wno-parentheses -Wall -Wextra -fno-strict-aliasing -static --specs=nosys.specs -std=gnu++11 -MD -MT comm/CMakeFiles/comm.dir/src/riscv64/comm_main.cpp.obj -MF comm/CMakeFiles/comm.dir/src/riscv64/comm_main.cpp.obj.d -o comm/CMakeFiles/comm.dir/src/riscv64/comm_main.cpp.obj -c /home/user/milkv/duo-buildroot-sdk/freertos/cvitek/task/comm/src/riscv64/comm_main.cpp
In file included from /home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/kernel/portable.h:53,
                 from /home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/kernel/FreeRTOS.h:68,
                 from /home/user/milkv/duo-buildroot-sdk/freertos/cvitek/task/comm/src/riscv64/comm_main.cpp:5:
/home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/kernel/portmacro.h:181:3: error: #error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https:

but /home/user/milkv/duo-buildroot-sdk/freertos/cvitek/install/include/kernel/FreeRTOSConfig.h file has already defined values of configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS:


#ifdef RISCV_QEMU
#define configMTIME_BASE_ADDRESS		( CLINT_ADDR + CLINT_MTIME )
#else
#undef configMTIME_BASE_ADDRESS  // get MTIME from rdtime
#endif
#define configMTIMECMP_BASE_ADDRESS		( CLINT_ADDR + CLINT_MTIMECMP )

Can anyone help?

I’ve finally fixed all 100500 issues and build RTOS application on C++. Here are diff files if anyone want to reproduce that.

--- /home/owner/Public/freertos/cvitek/scripts/toolchain-riscv64-elf.cmake
+++ /home/owner/Public/duo-buildroot-sdk-Duo-V1.0.9/freertos/cvitek/scripts/toolchain-riscv64-elf.cmake
@@ -57,3 +57,21 @@
 
 set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers" )
 set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-parentheses" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=rv64imafdc" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mabi=lp64d" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=medany" )
+
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFREERTOS_BSP" )
+if ($ENV{DDR_64MB_SIZE} STREQUAL "y")
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLINUX_BSP_64MB" )
+else()
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLINUX_BSP_128MB" )
+endif()
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__riscv_xlen=64" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTHEAD_C906" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCONFIG_64BIT" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRISCV_FPU" )
--- /home/owner/Public/freertos/cvitek/task/comm/CMakeLists.txt
+++ /home/owner/Public/duo-buildroot-sdk-Duo-V1.0.9/freertos/cvitek/task/comm/CMakeLists.txt
@@ -1,4 +1,5 @@
-file(GLOB _SOURCES "src/${RUN_ARCH}/*.c")
+#file(GLOB _SOURCES "src/${RUN_ARCH}/*.c")
+file(GLOB _SOURCES "src/${RUN_ARCH}/*.c" "src/${RUN_ARCH}/*.cpp")
 
 include_directories(include)
 include_directories(${CMAKE_INSTALL_INC_PREFIX}/arch)
 
--- /home/owner/Public/freertos/cvitek/task/main/CMakeLists.txt
+++ /home/owner/Public/duo-buildroot-sdk-Duo-V1.0.9/freertos/cvitek/task/main/CMakeLists.txt
@@ -1,4 +1,5 @@
-file(GLOB _SOURCES "src/*.c" "*.S")
+#file(GLOB _SOURCES "src/*.c" "*.S")
+file(GLOB _SOURCES "src/*.c" "src/*.cpp" "*.S")

# try to find out the include folder recursively under CMAKE_INSTALL_PREFIX folder
MACRO(HEADER_DIRECTORIES return_list)

--- /home/owner/Public/freertos/cvitek/task/CMakeLists.txt
+++ /home/owner/Public/duo-buildroot-sdk-Duo-V1.0.9/freertos/cvitek/task/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.16.5)
 
-project(arch C ASM)
+project(arch C CXX ASM)
 
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -12,7 +12,7 @@
 set(SAFETY_FLAGS "-Wall -Wextra -fno-strict-aliasing -static --specs=nosys.specs")
 #set(SAFETY_FLAGS "-Werror -Wall -Wextra -fno-strict-aliasing")
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAFETY_FLAGS} -D${RUN_TYPE}")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAFETY_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAFETY_FLAGS} -D${RUN_TYPE}")
 
 include(${TOP_DIR}/scripts/ParseConfiguration.cmake)
 ParseConfiguration("${BUILD_ENV_PATH}/.config")
 
--- /home/owner/Public/freertos/cvitek/task/main/src/main.c
+++ /home/owner/Public/duo-buildroot-sdk-Duo-V1.0.9/freertos/cvitek/task/main/src/main.cpp
@@ -100,10 +100,16 @@
 
 /* Prototypes for the standard FreeRTOS callback/hook functions implemented
 within this file. */
+extern "C"
+{
 void vApplicationMallocFailedHook(void);
 void vApplicationIdleHook(void);
 void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName);
 void vApplicationTickHook(void);
+void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
+				    StackType_t **ppxTimerTaskStackBuffer,
+				    uint32_t *pulTimerTaskStackSize);
+}
 
 /* configAPPLICATION_ALLOCATED_HEAP is set to 1 in FreeRTOSConfig.h so the
 application can define the array used as the FreeRTOS heap.  This is done so the
@@ -113,6 +119,12 @@
 uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ( ( section( ".heap" ) ) );
 #endif
 /*-----------------------------------------------------------*/
+
+extern "C"
+{
+extern void pre_system_init();
+extern void post_system_init();
+}
 
 int main(void)
 {
 
--- /home/owner/Public/freertos/cvitek/task/comm/src/riscv64/comm_main.c
+++ /home/owner/Public/duo-buildroot-sdk-Duo-V1.0.9/freertos/cvitek/task/comm/src/riscv64/comm_main.cpp
@@ -9,6 +9,8 @@
 #include "delay.h"
 
 /* cvitek includes. */
+extern "C"
+{
 #include "printf.h"
 #include "rtos_cmdqu.h"
 #include "cvi_mailbox.h"
@@ -16,10 +18,12 @@
 #include "top_reg.h"
 #include "memmap.h"
 #include "comm.h"
+
 #include "cvi_spinlock.h"
 
 /* Milk-V Duo */
 #include "milkv_duo_io.h"
+}
 
 // #define __DEBUG__
 #ifdef __DEBUG__
@@ -40,14 +44,14 @@
 /****************************************************************************
  * Function prototypes
  ****************************************************************************/
-void prvQueueISR(void);
+int prvQueueISR(int, void*);
 void prvCmdQuRunTask(void *pvParameters);
-
 
 /****************************************************************************
  * Global parameters
  ****************************************************************************/
-TASK_CTX_S gTaskCtx[1] = {
+
+/*TASK_CTX_S gTaskCtx[1] = {
 	{
 		.name = "CMDQU",
 		.stack_size = configMINIMAL_STACK_SIZE,
@@ -56,7 +60,19 @@
 		.queLength = 30,
 		.queHandle = NULL,
 	},
+};*/
+
+TASK_CTX_S gTaskCtx[1] = {
+	{
+		"CMDQU",
+		configMINIMAL_STACK_SIZE,
+		tskIDLE_PRIORITY + 5,
+		prvCmdQuRunTask,
+		30,
+		NULL,
+	},
 };
+
 
 /* mailbox parameters */
 volatile struct mailbox_set_register *mbox_reg;
@@ -85,6 +101,7 @@
 		TASK_INIT(i);
 	}
 }
+
 
 void main_cvirtos(void)
 {
@@ -221,14 +238,14 @@
 				drv_spin_unlock_irqrestore(&mailbox_lock, flags);
 				if (valid >= MAILBOX_MAX_NUM) {
 				    printf("No valid mailbox is available\n");
-				    return -1;
+				    return ;
 				}
 				break;
 		}
 	}
 }
 
-void prvQueueISR(void)
+int  prvQueueISR(int, void*)
 {
 	printf("prvQueueISR\n");
 	unsigned char set_val;
@@ -278,4 +295,6 @@
 			}
 		}
 	}
-}
+	
+	return 0;
+}
 
1 Like