diff --git a/.config b/.config
index 315a37d..f681dac 100644
--- a/.config
+++ b/.config
@@ -659,6 +659,8 @@ CONFIG_RT_USING_CPP_EXCEPTIONS=y
# tools packages
#
# CONFIG_PKG_USING_VECTOR is not set
+# CONFIG_PKG_USING_SORCH is not set
+# CONFIG_PKG_USING_DICT is not set
# CONFIG_PKG_USING_CMBACKTRACE is not set
# CONFIG_PKG_USING_MCOREDUMP is not set
# CONFIG_PKG_USING_EASYFLASH is not set
@@ -840,6 +842,8 @@ CONFIG_PKG_LITTLEFS_VER="latest"
# CONFIG_PKG_USING_HEARTBEAT is not set
# CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set
# CONFIG_PKG_USING_CHERRYECAT is not set
+# CONFIG_PKG_USING_EVENT_LOOP is not set
+# CONFIG_PKG_USING_THREAD_MANAGER is not set
# end of system packages
#
diff --git a/.idea/editor.xml b/.idea/editor.xml
index fef3201..53a15f5 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -139,6 +139,7 @@
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index dbb6095..2fd7a0e 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,6 +2,7 @@
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c4f0e4..3d389d7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -112,11 +112,14 @@ ADD_DEFINITIONS(
# Library source files
SET(RT_APP_ERPC_SOURCES
+ applications/erpc/proto/generated/file_service_interface.cpp
+ applications/erpc/proto/generated/servo_service_server.cpp
+ applications/erpc/service/src/file_service_impl.cpp
+ applications/erpc/service/src/erpc_server_main.cpp
+ applications/erpc/proto/generated/file_service_server.cpp
+ applications/erpc/service/src/servo_service_impl.cpp
applications/erpc/proto/generated/servo_service_interface.cpp
applications/erpc/common/src/erpc_error_handler.cpp
- applications/erpc/service/src/servo_service_impl.cpp
- applications/erpc/proto/generated/servo_service_server.cpp
- applications/erpc/service/src/erpc_server_main.cpp
)
SET(RT_APPLICATIONS_SOURCES
@@ -124,13 +127,13 @@ SET(RT_APPLICATIONS_SOURCES
)
SET(RT_CHERRYUSB_SOURCES
+ rt-thread/components/drivers/usb/cherryusb/core/usbd_core.c
rt-thread/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c
+ rt-thread/components/drivers/usb/cherryusb/class/msc/usbd_msc.c
+ rt-thread/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c
rt-thread/components/drivers/usb/cherryusb/platform/rtthread/usb_msh.c
rt-thread/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_acm.c
- rt-thread/components/drivers/usb/cherryusb/core/usbd_core.c
rt-thread/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c
- rt-thread/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c
- rt-thread/components/drivers/usb/cherryusb/class/msc/usbd_msc.c
rt-thread/components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c
)
@@ -199,30 +202,30 @@ SET(RT_DRIVERS_SOURCES
)
SET(RT_ERPC_SOURCES
- packages/erpc-1.14.0/erpc_c/transports/erpc_inter_thread_buffer_transport.cpp
+ packages/erpc-1.14.0/erpc_c/setup/erpc_setup_usb_cdc.cpp
+ packages/erpc-1.14.0/erpc_c/port/erpc_threading_pthreads.cpp
+ packages/erpc-1.14.0/erpc_c/infra/erpc_server.cpp
+ packages/erpc-1.14.0/erpc_c/infra/erpc_simple_server.cpp
packages/erpc-1.14.0/erpc_c/port/erpc_port_rtt.cpp
- packages/erpc-1.14.0/erpc_c/transports/erpc_usb_cdc_transport.cpp
packages/erpc-1.14.0/erpc_c/infra/erpc_transport_arbitrator.cpp
packages/erpc-1.14.0/erpc_c/setup/erpc_setup_mbf_dynamic.cpp
- packages/erpc-1.14.0/erpc_c/setup/erpc_setup_usb_cdc.cpp
- packages/erpc-1.14.0/erpc_c/infra/erpc_basic_codec.cpp
packages/erpc-1.14.0/erpc_c/setup/erpc_server_setup.cpp
- packages/erpc-1.14.0/erpc_c/infra/erpc_message_buffer.cpp
- packages/erpc-1.14.0/erpc_c/infra/erpc_framed_transport.cpp
- packages/erpc-1.14.0/erpc_c/infra/erpc_pre_post_action.cpp
- packages/erpc-1.14.0/erpc_c/infra/erpc_simple_server.cpp
- packages/erpc-1.14.0/erpc_c/setup/erpc_setup_mbf_static.cpp
- packages/erpc-1.14.0/erpc_c/infra/erpc_server.cpp
- packages/erpc-1.14.0/erpc_c/infra/erpc_crc16.cpp
packages/erpc-1.14.0/erpc_c/infra/erpc_message_loggers.cpp
- packages/erpc-1.14.0/erpc_c/port/erpc_threading_pthreads.cpp
+ packages/erpc-1.14.0/erpc_c/transports/erpc_inter_thread_buffer_transport.cpp
+ packages/erpc-1.14.0/erpc_c/setup/erpc_setup_mbf_static.cpp
+ packages/erpc-1.14.0/erpc_c/transports/erpc_usb_cdc_transport.cpp
+ packages/erpc-1.14.0/erpc_c/infra/erpc_pre_post_action.cpp
+ packages/erpc-1.14.0/erpc_c/infra/erpc_message_buffer.cpp
+ packages/erpc-1.14.0/erpc_c/infra/erpc_basic_codec.cpp
+ packages/erpc-1.14.0/erpc_c/infra/erpc_framed_transport.cpp
+ packages/erpc-1.14.0/erpc_c/infra/erpc_crc16.cpp
)
SET(RT_FAL_SOURCES
- rt-thread/components/fal/src/fal_partition.c
rt-thread/components/fal/src/fal.c
- rt-thread/components/fal/src/fal_rtt.c
rt-thread/components/fal/src/fal_flash.c
+ rt-thread/components/fal/src/fal_partition.c
+ rt-thread/components/fal/src/fal_rtt.c
)
SET(RT_FILESYSTEM_SOURCES
@@ -234,11 +237,11 @@ SET(RT_FILESYSTEM_SOURCES
)
SET(RT_FINSH_SOURCES
- rt-thread/components/finsh/msh_file.c
- rt-thread/components/finsh/shell.c
- rt-thread/components/finsh/msh_parse.c
- rt-thread/components/finsh/cmd.c
rt-thread/components/finsh/msh.c
+ rt-thread/components/finsh/msh_parse.c
+ rt-thread/components/finsh/shell.c
+ rt-thread/components/finsh/cmd.c
+ rt-thread/components/finsh/msh_file.c
)
SET(RT_KERNEL_SOURCES
@@ -261,15 +264,15 @@ SET(RT_KERNEL_SOURCES
SET(RT_KLIBC_SOURCES
rt-thread/src/klibc/kstdio.c
- rt-thread/src/klibc/kstring.c
rt-thread/src/klibc/rt_vsscanf.c
+ rt-thread/src/klibc/kstring.c
rt-thread/src/klibc/kerrno.c
)
SET(RT_KTIME_SOURCES
- rt-thread/components/drivers/ktime/src/cputimer.c
- rt-thread/components/drivers/ktime/src/boottime.c
rt-thread/components/drivers/ktime/src/hrtimer.c
+ rt-thread/components/drivers/ktime/src/boottime.c
+ rt-thread/components/drivers/ktime/src/cputimer.c
)
SET(RT_LIBCPU_SOURCES
@@ -282,45 +285,45 @@ SET(RT_LIBCPU_SOURCES
)
SET(RT_LIBRARIES_SOURCES
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_adc.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_lptim.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cryp.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_usart.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_crc_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nor.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_adc_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_comp.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_crc.c
libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c
- libraries/STM32H7xx_HAL/CMSIS/Device/ST/STM32H7xx/Source/Templates/system_stm32h7xx.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_crc.c
libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cryp_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_qspi.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cec.c
libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sram.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart_ex.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c
- libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c
+ libraries/STM32H7xx_HAL/CMSIS/Device/ST/STM32H7xx/Source/Templates/system_stm32h7xx.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nor.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_crc_ex.c
libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_usart.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_adc.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart_ex.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_lptim.c
libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_comp.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cec.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cryp.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_adc_ex.c
+ libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_qspi.c
)
SET(RT_LITTLEFS_SOURCES
- packages/littlefs-latest/lfs.c
- packages/littlefs-latest/dfs_lfs.c
- packages/littlefs-latest/lfs_crc.c
packages/littlefs-latest/lfs_util.c
+ packages/littlefs-latest/lfs_crc.c
+ packages/littlefs-latest/dfs_lfs.c
+ packages/littlefs-latest/lfs.c
)
SET(RT_POSIX_SOURCES
@@ -338,9 +341,9 @@ SET(RT_POSIX_SOURCES
)
SET(RT_SERVO_CONTROL_SOURCES
- applications/servo_manager/src/servo_driver.cpp
applications/servo_manager/src/servo_manager.cpp
applications/servo_manager/src/servo_control.cpp
+ applications/servo_manager/src/servo_driver.cpp
)
SET(RT_UTC_UTEST_SOURCES
diff --git a/applications/erpc/SConscript b/applications/erpc/SConscript
index a96b5b8..2c5e117 100644
--- a/applications/erpc/SConscript
+++ b/applications/erpc/SConscript
@@ -23,12 +23,18 @@ gen_dir = p('proto', 'generated')
# interface 建议始终编译(两端都可能需要)
src += [p('proto', 'generated', 'servo_service_interface.cpp')]
+if os.path.exists(p('proto', 'generated', 'file_service_interface.cpp')):
+ src += [p('proto', 'generated', 'file_service_interface.cpp')]
src += [p('common', 'src', 'erpc_error_handler.cpp')]
if GetDepend(['ERPC_MODE_SERVER']):
src += [p('proto', 'generated', 'servo_service_server.cpp')]
+ if os.path.exists(p('proto', 'generated', 'file_service_server.cpp')):
+ src += [p('proto', 'generated', 'file_service_server.cpp')]
if GetDepend(['ERPC_MODE_CLIENT']):
src += [p('proto', 'generated', 'servo_service_client.cpp')]
+ if os.path.exists(p('proto', 'generated', 'file_service_client.cpp')):
+ src += [p('proto', 'generated', 'file_service_client.cpp')]
CPPPATH = [
cwd,
diff --git a/applications/erpc/proto/file_service.erpc b/applications/erpc/proto/file_service.erpc
new file mode 100644
index 0000000..abb8b6e
--- /dev/null
+++ b/applications/erpc/proto/file_service.erpc
@@ -0,0 +1,39 @@
+// file_service.erpc
+program file_service
+
+@id(2)
+interface file_service
+{
+ /**
+ * @brief 开始一次文件上传会话。
+ * @param path 目标文件路径;服务端会先写入 ".part" 临时文件。
+ * @param total_size 本次上传的文件总字节数,用于服务端校验最终大小。
+ * @return RT_EOK 表示成功;负数表示 RT-Thread/POSIX 错误码。
+ */
+ fileWriteBegin(string path, uint32 total_size) -> int32
+
+ /**
+ * @brief 写入一个文件分块。
+ * @param data 当前分块的二进制内容;dataLength 是分块字节数,data 是分块数据指针。
+ * @return RT_EOK 表示成功;负数表示 RT-Thread/POSIX 错误码。
+ *
+ * @note 单个分块会被封装进一次 eRPC 消息,最大可用长度受 ERPC_DEFAULT_BUFFER_SIZE 限制。
+ */
+ fileWriteChunk(binary data) -> int32
+
+ /**
+ * @brief 完成上传会话。
+ * @return RT_EOK 表示成功;负数表示 RT-Thread/POSIX 错误码。
+ *
+ * @note 服务端会先校验已接收字节数是否等于 total_size,然后把临时文件重命名为目标文件。
+ */
+ fileWriteEnd() -> int32
+
+ /**
+ * @brief 取消当前上传会话。
+ * @return RT_EOK 表示成功;负数表示 RT-Thread/POSIX 错误码。
+ *
+ * @note 服务端会关闭当前文件并删除残留的 ".part" 临时文件。
+ */
+ fileWriteAbort() -> int32
+}
diff --git a/applications/erpc/proto/generated/c_file_service_client.cpp b/applications/erpc/proto/generated/c_file_service_client.cpp
new file mode 100644
index 0000000..90f0b7b
--- /dev/null
+++ b/applications/erpc/proto/generated/c_file_service_client.cpp
@@ -0,0 +1,77 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#include "c_file_service_client.h"
+#include "file_service_client.hpp"
+#include "erpc_manually_constructed.hpp"
+
+using namespace erpc;
+using namespace std;
+using namespace erpcShim;
+
+
+#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
+file_service_client *s_file_service_client = nullptr;
+#else
+ERPC_MANUALLY_CONSTRUCTED_STATIC(file_service_client, s_file_service_client);
+#endif
+
+int32_t fileWriteBegin(const char * path, uint32_t total_size)
+{
+ int32_t result;
+ result = s_file_service_client->fileWriteBegin(path, total_size);
+
+ return result;
+}
+
+int32_t fileWriteChunk(const binary_t * data)
+{
+ int32_t result;
+ result = s_file_service_client->fileWriteChunk(data);
+
+ return result;
+}
+
+int32_t fileWriteEnd(void)
+{
+ int32_t result;
+ result = s_file_service_client->fileWriteEnd();
+
+ return result;
+}
+
+int32_t fileWriteAbort(void)
+{
+ int32_t result;
+ result = s_file_service_client->fileWriteAbort();
+
+ return result;
+}
+
+void initfile_service_client(erpc_client_t client)
+{
+#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
+ erpc_assert(s_file_service_client == nullptr);
+ s_file_service_client = new file_service_client(reinterpret_cast(client));
+#else
+ erpc_assert(!s_file_service_client.isUsed());
+ s_file_service_client.construct(reinterpret_cast(client));
+#endif
+}
+
+void deinitfile_service_client(void)
+{
+#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
+ if (s_file_service_client != nullptr)
+ {
+ delete s_file_service_client;
+ s_file_service_client = nullptr;
+ }
+#else
+ s_file_service_client.destroy();
+#endif
+}
diff --git a/applications/erpc/proto/generated/c_file_service_client.h b/applications/erpc/proto/generated/c_file_service_client.h
new file mode 100644
index 0000000..aee5a27
--- /dev/null
+++ b/applications/erpc/proto/generated/c_file_service_client.h
@@ -0,0 +1,54 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if !defined(_c_file_service_client_h_)
+#define _c_file_service_client_h_
+
+#include "file_service_common.h"
+#include "erpc_client_manager.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+#if !defined(ERPC_FUNCTIONS_DEFINITIONS)
+#define ERPC_FUNCTIONS_DEFINITIONS
+
+
+/*! @brief file_service identifiers */
+enum _file_service_ids
+{
+ kfile_service_service_id = 2,
+ kfile_service_fileWriteBegin_id = 1,
+ kfile_service_fileWriteChunk_id = 2,
+ kfile_service_fileWriteEnd_id = 3,
+ kfile_service_fileWriteAbort_id = 4,
+};
+
+//! @name file_service
+//@{
+int32_t fileWriteBegin(const char * path, uint32_t total_size);
+
+int32_t fileWriteChunk(const binary_t * data);
+
+int32_t fileWriteEnd(void);
+
+int32_t fileWriteAbort(void);
+//@}
+
+#endif // ERPC_FUNCTIONS_DEFINITIONS
+
+void initfile_service_client(erpc_client_t client);
+
+void deinitfile_service_client(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // _c_file_service_client_h_
diff --git a/applications/erpc/proto/generated/c_file_service_server.cpp b/applications/erpc/proto/generated/c_file_service_server.cpp
new file mode 100644
index 0000000..9e0b275
--- /dev/null
+++ b/applications/erpc/proto/generated/c_file_service_server.cpp
@@ -0,0 +1,97 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#include
+#include "c_file_service_server.h"
+#include "file_service_server.hpp"
+#include "erpc_manually_constructed.hpp"
+
+using namespace erpc;
+using namespace std;
+using namespace erpcShim;
+
+
+class file_service_server: public file_service_interface
+{
+ public:
+ virtual ~file_service_server() {};
+
+
+ int32_t fileWriteBegin(const char * path, uint32_t total_size)
+ {
+ int32_t result;
+ result = ::fileWriteBegin(path, total_size);
+
+ return result;
+ }
+
+ int32_t fileWriteChunk(const binary_t * data)
+ {
+ int32_t result;
+ result = ::fileWriteChunk(data);
+
+ return result;
+ }
+
+ int32_t fileWriteEnd(void)
+ {
+ int32_t result;
+ result = ::fileWriteEnd();
+
+ return result;
+ }
+
+ int32_t fileWriteAbort(void)
+ {
+ int32_t result;
+ result = ::fileWriteAbort();
+
+ return result;
+ }
+};
+
+ERPC_MANUALLY_CONSTRUCTED_STATIC(file_service_service, s_file_service_service);
+ERPC_MANUALLY_CONSTRUCTED_STATIC(file_service_server, s_file_service_server);
+
+erpc_service_t create_file_service_service(void)
+{
+ erpc_service_t service;
+
+#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
+ service = new (nothrow) file_service_service(new (nothrow)file_service_server());
+#else
+ if (s_file_service_service.isUsed())
+ {
+ service = NULL;
+ }
+ else
+ {
+ s_file_service_server.construct();
+ s_file_service_service.construct(s_file_service_server.get());
+ service = s_file_service_service.get();
+ }
+#endif
+
+ return service;
+}
+
+void destroy_file_service_service(erpc_service_t service)
+{
+#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
+ if (service)
+ {
+ delete (file_service_server *)(((file_service_service *)service)->getHandler());
+ delete (file_service_service *)service;
+ }
+#else
+ (void)service;
+ erpc_assert(service == s_file_service_service.get());
+ s_file_service_service.destroy();
+ s_file_service_server.destroy();
+#endif
+}
+
diff --git a/applications/erpc/proto/generated/c_file_service_server.h b/applications/erpc/proto/generated/c_file_service_server.h
new file mode 100644
index 0000000..4c2d899
--- /dev/null
+++ b/applications/erpc/proto/generated/c_file_service_server.h
@@ -0,0 +1,59 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if !defined(_c_file_service_server_h_)
+#define _c_file_service_server_h_
+
+#include "file_service_common.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+typedef void * erpc_service_t;
+
+#if !defined(ERPC_FUNCTIONS_DEFINITIONS)
+#define ERPC_FUNCTIONS_DEFINITIONS
+
+
+/*! @brief file_service identifiers */
+enum _file_service_ids
+{
+ kfile_service_service_id = 2,
+ kfile_service_fileWriteBegin_id = 1,
+ kfile_service_fileWriteChunk_id = 2,
+ kfile_service_fileWriteEnd_id = 3,
+ kfile_service_fileWriteAbort_id = 4,
+};
+
+//! @name file_service
+//@{
+int32_t fileWriteBegin(const char * path, uint32_t total_size);
+
+int32_t fileWriteChunk(const binary_t * data);
+
+int32_t fileWriteEnd(void);
+
+int32_t fileWriteAbort(void);
+//@}
+
+
+#endif // ERPC_FUNCTIONS_DEFINITIONS
+
+/*! @brief Return file_service_service service object. */
+erpc_service_t create_file_service_service(void);
+
+/*! @brief Destroy file_service_service service object. */
+void destroy_file_service_service(erpc_service_t service);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // _c_file_service_server_h_
diff --git a/applications/erpc/proto/generated/c_servo_service_client.cpp b/applications/erpc/proto/generated/c_servo_service_client.cpp
index 9fa05ed..4d2e659 100644
--- a/applications/erpc/proto/generated/c_servo_service_client.cpp
+++ b/applications/erpc/proto/generated/c_servo_service_client.cpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/c_servo_service_client.h b/applications/erpc/proto/generated/c_servo_service_client.h
index 371a54d..32f8dc3 100644
--- a/applications/erpc/proto/generated/c_servo_service_client.h
+++ b/applications/erpc/proto/generated/c_servo_service_client.h
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/c_servo_service_server.cpp b/applications/erpc/proto/generated/c_servo_service_server.cpp
index 1ac9159..fc939b1 100644
--- a/applications/erpc/proto/generated/c_servo_service_server.cpp
+++ b/applications/erpc/proto/generated/c_servo_service_server.cpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/c_servo_service_server.h b/applications/erpc/proto/generated/c_servo_service_server.h
index 4efd69b..58dc6e9 100644
--- a/applications/erpc/proto/generated/c_servo_service_server.h
+++ b/applications/erpc/proto/generated/c_servo_service_server.h
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/file_service_client.cpp b/applications/erpc/proto/generated/file_service_client.cpp
new file mode 100644
index 0000000..996b6e9
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_client.cpp
@@ -0,0 +1,302 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
+#include "erpc_port.h"
+#endif
+#include "erpc_codec.hpp"
+#include "file_service_client.hpp"
+#include "erpc_manually_constructed.hpp"
+
+#if 11400 != ERPC_VERSION_NUMBER
+#error "The generated shim code version is different to the rest of eRPC code."
+#endif
+
+using namespace erpc;
+using namespace std;
+using namespace erpcShim;
+
+//! @brief Function to write struct binary_t
+static void write_binary_t_struct(erpc::Codec * codec, const binary_t * data);
+
+
+// Write struct binary_t function implementation
+static void write_binary_t_struct(erpc::Codec * codec, const binary_t * data)
+{
+ if(NULL == data)
+ {
+ return;
+ }
+
+ codec->writeBinary(data->dataLength, data->data);
+}
+
+
+
+
+file_service_client::file_service_client(ClientManager *manager)
+:m_clientManager(manager)
+{
+}
+
+file_service_client::~file_service_client()
+{
+}
+
+// file_service interface fileWriteBegin function client shim.
+int32_t file_service_client::fileWriteBegin(const char * path, uint32_t total_size)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ int32_t result;
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb preCB = m_clientManager->getPreCB();
+ if (preCB)
+ {
+ preCB();
+ }
+#endif
+
+ // Get a new request.
+ RequestContext request = m_clientManager->createRequest(false);
+
+ // Encode the request.
+ Codec * codec = request.getCodec();
+
+ if (codec == NULL)
+ {
+ err = kErpcStatus_MemoryError;
+ }
+ else
+ {
+ codec->startWriteMessage(message_type_t::kInvocationMessage, m_serviceId, m_fileWriteBeginId, request.getSequence());
+
+ {
+ uint32_t path_len = strlen((const char*)path);
+
+ codec->writeString(path_len, (const char*)path);
+ }
+
+ codec->write(total_size);
+
+ // Send message to server
+ // Codec status is checked inside this function.
+ m_clientManager->performRequest(request);
+
+ codec->read(result);
+
+ err = codec->getStatus();
+ }
+
+ // Dispose of the request.
+ m_clientManager->releaseRequest(request);
+
+ // Invoke error handler callback function
+ m_clientManager->callErrorHandler(err, m_fileWriteBeginId);
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb postCB = m_clientManager->getPostCB();
+ if (postCB)
+ {
+ postCB();
+ }
+#endif
+
+
+ if (err != kErpcStatus_Success)
+ {
+ result = -1;
+ }
+
+ return result;
+}
+
+// file_service interface fileWriteChunk function client shim.
+int32_t file_service_client::fileWriteChunk(const binary_t * data)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ int32_t result;
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb preCB = m_clientManager->getPreCB();
+ if (preCB)
+ {
+ preCB();
+ }
+#endif
+
+ // Get a new request.
+ RequestContext request = m_clientManager->createRequest(false);
+
+ // Encode the request.
+ Codec * codec = request.getCodec();
+
+ if (codec == NULL)
+ {
+ err = kErpcStatus_MemoryError;
+ }
+ else
+ {
+ codec->startWriteMessage(message_type_t::kInvocationMessage, m_serviceId, m_fileWriteChunkId, request.getSequence());
+
+ write_binary_t_struct(codec, data);
+
+ // Send message to server
+ // Codec status is checked inside this function.
+ m_clientManager->performRequest(request);
+
+ codec->read(result);
+
+ err = codec->getStatus();
+ }
+
+ // Dispose of the request.
+ m_clientManager->releaseRequest(request);
+
+ // Invoke error handler callback function
+ m_clientManager->callErrorHandler(err, m_fileWriteChunkId);
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb postCB = m_clientManager->getPostCB();
+ if (postCB)
+ {
+ postCB();
+ }
+#endif
+
+
+ if (err != kErpcStatus_Success)
+ {
+ result = -1;
+ }
+
+ return result;
+}
+
+// file_service interface fileWriteEnd function client shim.
+int32_t file_service_client::fileWriteEnd(void)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ int32_t result;
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb preCB = m_clientManager->getPreCB();
+ if (preCB)
+ {
+ preCB();
+ }
+#endif
+
+ // Get a new request.
+ RequestContext request = m_clientManager->createRequest(false);
+
+ // Encode the request.
+ Codec * codec = request.getCodec();
+
+ if (codec == NULL)
+ {
+ err = kErpcStatus_MemoryError;
+ }
+ else
+ {
+ codec->startWriteMessage(message_type_t::kInvocationMessage, m_serviceId, m_fileWriteEndId, request.getSequence());
+
+ // Send message to server
+ // Codec status is checked inside this function.
+ m_clientManager->performRequest(request);
+
+ codec->read(result);
+
+ err = codec->getStatus();
+ }
+
+ // Dispose of the request.
+ m_clientManager->releaseRequest(request);
+
+ // Invoke error handler callback function
+ m_clientManager->callErrorHandler(err, m_fileWriteEndId);
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb postCB = m_clientManager->getPostCB();
+ if (postCB)
+ {
+ postCB();
+ }
+#endif
+
+
+ if (err != kErpcStatus_Success)
+ {
+ result = -1;
+ }
+
+ return result;
+}
+
+// file_service interface fileWriteAbort function client shim.
+int32_t file_service_client::fileWriteAbort(void)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ int32_t result;
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb preCB = m_clientManager->getPreCB();
+ if (preCB)
+ {
+ preCB();
+ }
+#endif
+
+ // Get a new request.
+ RequestContext request = m_clientManager->createRequest(false);
+
+ // Encode the request.
+ Codec * codec = request.getCodec();
+
+ if (codec == NULL)
+ {
+ err = kErpcStatus_MemoryError;
+ }
+ else
+ {
+ codec->startWriteMessage(message_type_t::kInvocationMessage, m_serviceId, m_fileWriteAbortId, request.getSequence());
+
+ // Send message to server
+ // Codec status is checked inside this function.
+ m_clientManager->performRequest(request);
+
+ codec->read(result);
+
+ err = codec->getStatus();
+ }
+
+ // Dispose of the request.
+ m_clientManager->releaseRequest(request);
+
+ // Invoke error handler callback function
+ m_clientManager->callErrorHandler(err, m_fileWriteAbortId);
+
+#if ERPC_PRE_POST_ACTION
+ pre_post_action_cb postCB = m_clientManager->getPostCB();
+ if (postCB)
+ {
+ postCB();
+ }
+#endif
+
+
+ if (err != kErpcStatus_Success)
+ {
+ result = -1;
+ }
+
+ return result;
+}
diff --git a/applications/erpc/proto/generated/file_service_client.hpp b/applications/erpc/proto/generated/file_service_client.hpp
new file mode 100644
index 0000000..4ed6674
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_client.hpp
@@ -0,0 +1,40 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if !defined(_file_service_client_hpp_)
+#define _file_service_client_hpp_
+
+#include "file_service_interface.hpp"
+
+#include "erpc_client_manager.h"
+
+namespace erpcShim
+{
+
+class file_service_client: public file_service_interface
+{
+ public:
+ file_service_client(erpc::ClientManager *manager);
+
+ virtual ~file_service_client();
+
+ virtual int32_t fileWriteBegin(const char * path, uint32_t total_size);
+
+ virtual int32_t fileWriteChunk(const binary_t * data);
+
+ virtual int32_t fileWriteEnd(void);
+
+ virtual int32_t fileWriteAbort(void);
+
+ protected:
+ erpc::ClientManager *m_clientManager;
+};
+
+} // erpcShim
+
+
+#endif // _file_service_client_hpp_
diff --git a/applications/erpc/proto/generated/file_service_common.h b/applications/erpc/proto/generated/file_service_common.h
new file mode 100644
index 0000000..d3c3c33
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_common.h
@@ -0,0 +1,47 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if !defined(_file_service_common_h_)
+#define _file_service_common_h_
+
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+#include
+#include
+#include
+
+#include "erpc_version.h"
+
+#if 11400 != ERPC_VERSION_NUMBER
+#error "The generated shim code version is different to the rest of eRPC code."
+#endif
+
+
+#if !defined(ERPC_TYPE_DEFINITIONS_FILE_SERVICE)
+#define ERPC_TYPE_DEFINITIONS_FILE_SERVICE
+
+// Aliases data types declarations
+typedef struct binary_t binary_t;
+
+// Structures/unions data types declarations
+struct binary_t
+{
+ uint8_t * data;
+ uint32_t dataLength;
+};
+
+
+#endif // ERPC_TYPE_DEFINITIONS_FILE_SERVICE
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // _file_service_common_h_
diff --git a/applications/erpc/proto/generated/file_service_common.hpp b/applications/erpc/proto/generated/file_service_common.hpp
new file mode 100644
index 0000000..2101699
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_common.hpp
@@ -0,0 +1,39 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if !defined(_file_service_common_hpp_)
+#define _file_service_common_hpp_
+
+
+#include
+#include
+
+#include "erpc_version.h"
+
+#if 11400 != ERPC_VERSION_NUMBER
+#error "The generated shim code version is different to the rest of eRPC code."
+#endif
+
+
+#if !defined(ERPC_TYPE_DEFINITIONS_FILE_SERVICE)
+#define ERPC_TYPE_DEFINITIONS_FILE_SERVICE
+
+// Aliases data types declarations
+typedef struct binary_t binary_t;
+
+// Structures/unions data types declarations
+struct binary_t
+{
+ uint8_t * data;
+ uint32_t dataLength;
+};
+
+
+#endif // ERPC_TYPE_DEFINITIONS_FILE_SERVICE
+
+
+#endif // _file_service_common_hpp_
diff --git a/applications/erpc/proto/generated/file_service_interface.cpp b/applications/erpc/proto/generated/file_service_interface.cpp
new file mode 100644
index 0000000..721b410
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_interface.cpp
@@ -0,0 +1,20 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#include "file_service_interface.hpp"
+
+#if 11400 != ERPC_VERSION_NUMBER
+#error "The generated shim code version is different to the rest of eRPC code."
+#endif
+
+
+using namespace std;
+using namespace erpcShim;
+
+file_service_interface::~file_service_interface(void)
+{
+}
diff --git a/applications/erpc/proto/generated/file_service_interface.hpp b/applications/erpc/proto/generated/file_service_interface.hpp
new file mode 100644
index 0000000..0cb5284
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_interface.hpp
@@ -0,0 +1,41 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if !defined(_file_service_interface_hpp_)
+#define _file_service_interface_hpp_
+
+#include "file_service_common.hpp"
+
+namespace erpcShim
+{
+
+
+// Abstract base class for file_service
+class file_service_interface
+{
+ public:
+ static const uint8_t m_serviceId = 2;
+ static const uint8_t m_fileWriteBeginId = 1;
+ static const uint8_t m_fileWriteChunkId = 2;
+ static const uint8_t m_fileWriteEndId = 3;
+ static const uint8_t m_fileWriteAbortId = 4;
+
+ virtual ~file_service_interface(void);
+
+ virtual int32_t fileWriteBegin(const char * path, uint32_t total_size) = 0;
+
+ virtual int32_t fileWriteChunk(const binary_t * data) = 0;
+
+ virtual int32_t fileWriteEnd(void) = 0;
+
+ virtual int32_t fileWriteAbort(void) = 0;
+private:
+};
+} // erpcShim
+
+
+#endif // _file_service_interface_hpp_
diff --git a/applications/erpc/proto/generated/file_service_server.cpp b/applications/erpc/proto/generated/file_service_server.cpp
new file mode 100644
index 0000000..b9ca419
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_server.cpp
@@ -0,0 +1,327 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#include "file_service_server.hpp"
+#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
+#include
+#include "erpc_port.h"
+#endif
+#include "erpc_manually_constructed.hpp"
+
+#if 11400 != ERPC_VERSION_NUMBER
+#error "The generated shim code version is different to the rest of eRPC code."
+#endif
+
+using namespace erpc;
+using namespace std;
+using namespace erpcShim;
+
+#if ERPC_NESTED_CALLS_DETECTION
+extern bool nestingDetection;
+#endif
+
+
+//! @brief Function to read struct binary_t
+static void read_binary_t_struct(erpc::Codec * codec, binary_t * data);
+
+
+// Read struct binary_t function implementation
+static void read_binary_t_struct(erpc::Codec * codec, binary_t * data)
+{
+ if(NULL == data)
+ {
+ return;
+ }
+
+ uint8_t * data_local;
+ codec->readBinary(data->dataLength, &data_local);
+ if (data->dataLength > 0)
+ {
+ data->data = (uint8_t *) erpc_malloc(data->dataLength * sizeof(uint8_t));
+ if (data->data == NULL)
+ {
+ codec->updateStatus(kErpcStatus_MemoryError);
+ }
+ else
+ {
+ memcpy(data->data, data_local, data->dataLength);
+ }
+ }
+ else
+ {
+ data->data = NULL;
+ }
+}
+
+
+//! @brief Function to free space allocated inside struct binary_t
+static void free_binary_t_struct(binary_t * data);
+
+
+// Free space allocated inside struct binary_t function implementation
+static void free_binary_t_struct(binary_t * data)
+{
+ erpc_free(data->data);
+}
+
+
+
+file_service_service::file_service_service(file_service_interface *_file_service_interface)
+ : erpc::Service(file_service_interface::m_serviceId)
+ , m_handler(_file_service_interface)
+{
+}
+
+file_service_service::~file_service_service()
+{
+}
+
+// return service interface handler.
+file_service_interface* file_service_service::getHandler(void)
+{
+ return m_handler;
+}
+
+// Call the correct server shim based on method unique ID.
+erpc_status_t file_service_service::handleInvocation(uint32_t methodId, uint32_t sequence, Codec * codec, MessageBufferFactory *messageFactory, Transport * transport)
+{
+ erpc_status_t erpcStatus;
+ switch (methodId)
+ {
+ case file_service_interface::m_fileWriteBeginId:
+ {
+ erpcStatus = fileWriteBegin_shim(codec, messageFactory, transport, sequence);
+ break;
+ }
+
+ case file_service_interface::m_fileWriteChunkId:
+ {
+ erpcStatus = fileWriteChunk_shim(codec, messageFactory, transport, sequence);
+ break;
+ }
+
+ case file_service_interface::m_fileWriteEndId:
+ {
+ erpcStatus = fileWriteEnd_shim(codec, messageFactory, transport, sequence);
+ break;
+ }
+
+ case file_service_interface::m_fileWriteAbortId:
+ {
+ erpcStatus = fileWriteAbort_shim(codec, messageFactory, transport, sequence);
+ break;
+ }
+
+ default:
+ {
+ erpcStatus = kErpcStatus_InvalidArgument;
+ break;
+ }
+ }
+
+ return erpcStatus;
+}
+
+// Server shim for fileWriteBegin of file_service interface.
+erpc_status_t file_service_service::fileWriteBegin_shim(Codec * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ char * path = NULL;
+ uint32_t total_size;
+ int32_t result;
+
+ // startReadMessage() was already called before this shim was invoked.
+
+ {
+ uint32_t path_len;
+ char * path_local;
+ codec->readString(path_len, &path_local);
+ path = (char*) erpc_malloc((path_len + 1) * sizeof(char));
+ if ((path == NULL) || (path_local == NULL))
+ {
+ codec->updateStatus(kErpcStatus_MemoryError);
+ }
+ else
+ {
+ memcpy(path, path_local, path_len);
+ (path)[path_len] = 0;
+ }
+ }
+
+ codec->read(total_size);
+
+ err = codec->getStatus();
+ if (err == kErpcStatus_Success)
+ {
+ // Invoke the actual served function.
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = true;
+#endif
+ result = m_handler->fileWriteBegin(path, total_size);
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = false;
+#endif
+
+ // preparing MessageBuffer for serializing data
+ err = messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize());
+ }
+
+ if (err == kErpcStatus_Success)
+ {
+ // preparing codec for serializing data
+ codec->reset(transport->reserveHeaderSize());
+
+ // Build response message.
+ codec->startWriteMessage(message_type_t::kReplyMessage, file_service_interface::m_serviceId, file_service_interface::m_fileWriteBeginId, sequence);
+
+ codec->write(result);
+
+ err = codec->getStatus();
+ }
+
+ erpc_free(path);
+
+ return err;
+}
+
+// Server shim for fileWriteChunk of file_service interface.
+erpc_status_t file_service_service::fileWriteChunk_shim(Codec * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ binary_t *data = NULL;
+ data = (binary_t *) erpc_malloc(sizeof(binary_t));
+ if (data == NULL)
+ {
+ codec->updateStatus(kErpcStatus_MemoryError);
+ }
+ int32_t result;
+
+ // startReadMessage() was already called before this shim was invoked.
+
+ read_binary_t_struct(codec, data);
+
+ err = codec->getStatus();
+ if (err == kErpcStatus_Success)
+ {
+ // Invoke the actual served function.
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = true;
+#endif
+ result = m_handler->fileWriteChunk(data);
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = false;
+#endif
+
+ // preparing MessageBuffer for serializing data
+ err = messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize());
+ }
+
+ if (err == kErpcStatus_Success)
+ {
+ // preparing codec for serializing data
+ codec->reset(transport->reserveHeaderSize());
+
+ // Build response message.
+ codec->startWriteMessage(message_type_t::kReplyMessage, file_service_interface::m_serviceId, file_service_interface::m_fileWriteChunkId, sequence);
+
+ codec->write(result);
+
+ err = codec->getStatus();
+ }
+
+ if (data)
+ {
+ free_binary_t_struct(data);
+ }
+ erpc_free(data);
+
+ return err;
+}
+
+// Server shim for fileWriteEnd of file_service interface.
+erpc_status_t file_service_service::fileWriteEnd_shim(Codec * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ int32_t result;
+
+ // startReadMessage() was already called before this shim was invoked.
+
+ err = codec->getStatus();
+ if (err == kErpcStatus_Success)
+ {
+ // Invoke the actual served function.
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = true;
+#endif
+ result = m_handler->fileWriteEnd();
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = false;
+#endif
+
+ // preparing MessageBuffer for serializing data
+ err = messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize());
+ }
+
+ if (err == kErpcStatus_Success)
+ {
+ // preparing codec for serializing data
+ codec->reset(transport->reserveHeaderSize());
+
+ // Build response message.
+ codec->startWriteMessage(message_type_t::kReplyMessage, file_service_interface::m_serviceId, file_service_interface::m_fileWriteEndId, sequence);
+
+ codec->write(result);
+
+ err = codec->getStatus();
+ }
+
+ return err;
+}
+
+// Server shim for fileWriteAbort of file_service interface.
+erpc_status_t file_service_service::fileWriteAbort_shim(Codec * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence)
+{
+ erpc_status_t err = kErpcStatus_Success;
+
+ int32_t result;
+
+ // startReadMessage() was already called before this shim was invoked.
+
+ err = codec->getStatus();
+ if (err == kErpcStatus_Success)
+ {
+ // Invoke the actual served function.
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = true;
+#endif
+ result = m_handler->fileWriteAbort();
+#if ERPC_NESTED_CALLS_DETECTION
+ nestingDetection = false;
+#endif
+
+ // preparing MessageBuffer for serializing data
+ err = messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize());
+ }
+
+ if (err == kErpcStatus_Success)
+ {
+ // preparing codec for serializing data
+ codec->reset(transport->reserveHeaderSize());
+
+ // Build response message.
+ codec->startWriteMessage(message_type_t::kReplyMessage, file_service_interface::m_serviceId, file_service_interface::m_fileWriteAbortId, sequence);
+
+ codec->write(result);
+
+ err = codec->getStatus();
+ }
+
+ return err;
+}
diff --git a/applications/erpc/proto/generated/file_service_server.hpp b/applications/erpc/proto/generated/file_service_server.hpp
new file mode 100644
index 0000000..b08231c
--- /dev/null
+++ b/applications/erpc/proto/generated/file_service_server.hpp
@@ -0,0 +1,58 @@
+/*
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 12:01:23 2026.
+ *
+ * AUTOGENERATED - DO NOT EDIT
+ */
+
+
+#if !defined(_file_service_server_hpp_)
+#define _file_service_server_hpp_
+
+#include "file_service_interface.hpp"
+
+#include "erpc_server.hpp"
+#include "erpc_codec.hpp"
+
+#if 11400 != ERPC_VERSION_NUMBER
+#error "The generated shim code version is different to the rest of eRPC code."
+#endif
+
+
+namespace erpcShim
+{
+
+/*!
+ * @brief Service subclass for file_service.
+ */
+class file_service_service : public erpc::Service
+{
+public:
+ file_service_service(file_service_interface *_file_service_interface);
+
+ virtual ~file_service_service();
+
+ /*! @brief return service interface handler. */
+ file_service_interface* getHandler(void);
+
+ /*! @brief Call the correct server shim based on method unique ID. */
+ virtual erpc_status_t handleInvocation(uint32_t methodId, uint32_t sequence, erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport);
+
+private:
+ file_service_interface *m_handler;
+ /*! @brief Server shim for fileWriteBegin of file_service interface. */
+ erpc_status_t fileWriteBegin_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence);
+
+ /*! @brief Server shim for fileWriteChunk of file_service interface. */
+ erpc_status_t fileWriteChunk_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence);
+
+ /*! @brief Server shim for fileWriteEnd of file_service interface. */
+ erpc_status_t fileWriteEnd_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence);
+
+ /*! @brief Server shim for fileWriteAbort of file_service interface. */
+ erpc_status_t fileWriteAbort_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence);
+};
+
+} // erpcShim
+
+
+#endif // _file_service_server_hpp_
diff --git a/applications/erpc/proto/generated/servo_service_client.cpp b/applications/erpc/proto/generated/servo_service_client.cpp
index b19738c..1f81a05 100644
--- a/applications/erpc/proto/generated/servo_service_client.cpp
+++ b/applications/erpc/proto/generated/servo_service_client.cpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/servo_service_client.hpp b/applications/erpc/proto/generated/servo_service_client.hpp
index ed52458..1fc338a 100644
--- a/applications/erpc/proto/generated/servo_service_client.hpp
+++ b/applications/erpc/proto/generated/servo_service_client.hpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/servo_service_common.h b/applications/erpc/proto/generated/servo_service_common.h
index e318de9..896b497 100644
--- a/applications/erpc/proto/generated/servo_service_common.h
+++ b/applications/erpc/proto/generated/servo_service_common.h
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/servo_service_common.hpp b/applications/erpc/proto/generated/servo_service_common.hpp
index b0b69b9..1c1a8fb 100644
--- a/applications/erpc/proto/generated/servo_service_common.hpp
+++ b/applications/erpc/proto/generated/servo_service_common.hpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/servo_service_interface.cpp b/applications/erpc/proto/generated/servo_service_interface.cpp
index c9f35e3..ae5979e 100644
--- a/applications/erpc/proto/generated/servo_service_interface.cpp
+++ b/applications/erpc/proto/generated/servo_service_interface.cpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/servo_service_interface.hpp b/applications/erpc/proto/generated/servo_service_interface.hpp
index fece815..d232db9 100644
--- a/applications/erpc/proto/generated/servo_service_interface.hpp
+++ b/applications/erpc/proto/generated/servo_service_interface.hpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/servo_service_server.cpp b/applications/erpc/proto/generated/servo_service_server.cpp
index d9d836a..4ccd0dc 100644
--- a/applications/erpc/proto/generated/servo_service_server.cpp
+++ b/applications/erpc/proto/generated/servo_service_server.cpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/proto/generated/servo_service_server.hpp b/applications/erpc/proto/generated/servo_service_server.hpp
index 633603e..f2d012d 100644
--- a/applications/erpc/proto/generated/servo_service_server.hpp
+++ b/applications/erpc/proto/generated/servo_service_server.hpp
@@ -1,5 +1,5 @@
/*
- * Generated by erpcgen 1.14.0 on Thu Apr 23 10:54:10 2026.
+ * Generated by erpcgen 1.14.0 on Tue Apr 28 13:10:25 2026.
*
* AUTOGENERATED - DO NOT EDIT
*/
diff --git a/applications/erpc/service/include/file_service_impl.h b/applications/erpc/service/include/file_service_impl.h
new file mode 100644
index 0000000..767a2ff
--- /dev/null
+++ b/applications/erpc/service/include/file_service_impl.h
@@ -0,0 +1,43 @@
+//
+// Created by Administrator on 2026/4/27.
+//
+
+#ifndef RTTHREAD_HEAD_FILE_SERVICE_IMPL_H
+#define RTTHREAD_HEAD_FILE_SERVICE_IMPL_H
+
+
+#include
+
+#include "erpc/proto/generated/file_service_server.hpp"
+#include
+
+
+class FileServiceImpl : public erpcShim::file_service_interface
+{
+public:
+ FileServiceImpl();
+ ~FileServiceImpl() override;
+
+ int32_t fileWriteBegin(const char* path, uint32_t total_size) override;
+ int32_t fileWriteChunk(const binary_t* data) override;
+ int32_t fileWriteEnd(void) override;
+ int32_t fileWriteAbort(void) override;
+
+private:
+ // 当前实现一次只允许一个上传会话;下面的上传状态由 upload_mutex_ 保护。
+ rt_mutex_t upload_mutex_;
+ int upload_fd_;
+ uint32_t upload_expected_size_;
+ uint32_t upload_received_size_;
+ std::string upload_target_path_;
+ std::string upload_temp_path_;
+
+ // 规范化上传路径,并拒绝设备路径和父目录跳转。
+ static bool normalizeUploadPath(const char* path, std::string* normalized);
+ static int32_t posixErrorToRtError(void);
+ void resetUploadStateLocked(void);
+ // 调用方必须已经持有 upload_mutex_。
+ int32_t abortUploadLocked(void);
+};
+
+#endif
diff --git a/applications/erpc/service/include/servo_service_impl.h b/applications/erpc/service/include/servo_service_impl.h
index 38ab14b..57e6b3c 100644
--- a/applications/erpc/service/include/servo_service_impl.h
+++ b/applications/erpc/service/include/servo_service_impl.h
@@ -11,9 +11,9 @@
#include "erpc/proto/generated/servo_service_server.hpp"
#include "servo_manager/include/servo_manager.h"
-extern "C" {
+
#include
-}
+
class ServoServiceImpl : public erpcShim::servo_service_interface
{
diff --git a/applications/erpc/service/src/erpc_server_main.cpp b/applications/erpc/service/src/erpc_server_main.cpp
index 8a50702..c91c0b9 100644
--- a/applications/erpc/service/src/erpc_server_main.cpp
+++ b/applications/erpc/service/src/erpc_server_main.cpp
@@ -19,6 +19,12 @@
#include "erpc/common/include/erpc_error_handler.h"
+#include "erpc/proto/generated/file_service_server.hpp"
+#include "erpc/proto/generated/file_service_interface.hpp"
+#include "erpc/service/include/file_service_impl.h"
+
+
+
#ifndef ERPC_THREAD_STACK
#define ERPC_THREAD_STACK (4096)
#endif
@@ -72,6 +78,11 @@ static void erpc_server_entry(void *parameter)
erpc_add_service_to_server(server, &service);
+ static FileServiceImpl file_impl;
+ static erpcShim::file_service_service file_service(&file_impl);
+ erpc_add_service_to_server(server, &file_service);
+
+
rt_kprintf("[erpc] server run\r\n");
erpc_server_run(server);
while (true){
diff --git a/applications/erpc/service/src/file_service_impl.cpp b/applications/erpc/service/src/file_service_impl.cpp
new file mode 100644
index 0000000..bd41258
--- /dev/null
+++ b/applications/erpc/service/src/file_service_impl.cpp
@@ -0,0 +1,278 @@
+//
+// Created by Administrator on 2026/4/27.
+//
+
+#include "erpc/service/include/file_service_impl.h"
+#include
+#include
+
+FileServiceImpl::FileServiceImpl()
+ : upload_mutex_(RT_NULL),
+ upload_fd_(-1),
+ upload_expected_size_(0),
+ upload_received_size_(0)
+{
+ upload_mutex_ = rt_mutex_create("sv_file", RT_IPC_FLAG_PRIO);
+}
+
+FileServiceImpl::~FileServiceImpl()
+{
+ if (upload_mutex_) {
+ rt_mutex_take(upload_mutex_, RT_WAITING_FOREVER);
+ (void)abortUploadLocked();
+ rt_mutex_release(upload_mutex_);
+ rt_mutex_delete(upload_mutex_);
+ upload_mutex_ = RT_NULL;
+ }
+}
+
+bool FileServiceImpl::normalizeUploadPath(const char* path, std::string* normalized)
+{
+ std::string local_path;
+
+ if (!path || !normalized) {
+ return false;
+ }
+
+ local_path.assign(path);
+ if (local_path.empty()) {
+ return false;
+ }
+
+ if (local_path[0] != '/') {
+ local_path.insert(local_path.begin(), '/');
+ }
+
+ // 避免覆盖设备节点,也避免通过 ".." 跳出预期目录。
+ if (local_path == "/" ||
+ local_path.rfind("/dev", 0) == 0 ||
+ local_path.find("/../") != std::string::npos ||
+ (local_path.size() >= 3 && local_path.compare(local_path.size() - 3, 3, "/..") == 0)) {
+ return false;
+ }
+
+ *normalized = local_path;
+ return true;
+}
+
+int32_t FileServiceImpl::posixErrorToRtError(void)
+{
+ const int err = rt_get_errno();
+
+ if (err > 0) {
+ return -err;
+ }
+ if (err < 0) {
+ return err;
+ }
+
+ return -RT_ERROR;
+}
+
+void FileServiceImpl::resetUploadStateLocked(void)
+{
+ upload_fd_ = -1;
+ upload_expected_size_ = 0;
+ upload_received_size_ = 0;
+ upload_target_path_.clear();
+ upload_temp_path_.clear();
+}
+
+int32_t FileServiceImpl::abortUploadLocked(void)
+{
+ // 取消上传时尽量关闭文件、删除残留的 .part 文件,并清空内存状态。
+ if (upload_fd_ >= 0) {
+ if (::close(upload_fd_) != 0) {
+ const int32_t err = posixErrorToRtError();
+ upload_fd_ = -1;
+ if (!upload_temp_path_.empty()) {
+ (void)::unlink(upload_temp_path_.c_str());
+ }
+ resetUploadStateLocked();
+ return err;
+ }
+ }
+
+ if (!upload_temp_path_.empty()) {
+ (void)::unlink(upload_temp_path_.c_str());
+ }
+
+ resetUploadStateLocked();
+ return RT_EOK;
+}
+
+int32_t FileServiceImpl::fileWriteBegin(const char* path, uint32_t total_size)
+{
+ std::string normalized_path;
+ std::string temp_path;
+ int fd;
+
+ if (!upload_mutex_) {
+ rt_kprintf("[FileService][E] fileWriteBegin: upload mutex is null\n");
+ return -RT_ENOMEM;
+ }
+
+ if (!normalizeUploadPath(path, &normalized_path)) {
+ rt_kprintf("[FileService][E] fileWriteBegin: invalid path=%s\n",
+ path ? path : "(null)");
+ return -RT_EINVAL;
+ }
+
+ temp_path = normalized_path + ".part";
+
+ rt_mutex_take(upload_mutex_, RT_WAITING_FOREVER);
+ // 单会话上传可以避免多个客户端同时写同一组上传状态。
+ if (upload_fd_ >= 0) {
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteBegin: upload already active, path=%s\n",
+ upload_target_path_.c_str());
+ return -RT_EBUSY;
+ }
+
+ // 先写临时文件,只有 fileWriteEnd() 校验完整大小后才发布到目标路径。
+ (void)::unlink(temp_path.c_str());
+ fd = ::open(temp_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
+ if (fd < 0) {
+ const int32_t err = posixErrorToRtError();
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteBegin: open failed, path=%s err=%d\n",
+ temp_path.c_str(),
+ (int)err);
+ return err;
+ }
+
+ upload_fd_ = fd;
+ upload_expected_size_ = total_size;
+ upload_received_size_ = 0;
+ upload_target_path_ = normalized_path;
+ upload_temp_path_ = temp_path;
+ rt_mutex_release(upload_mutex_);
+
+ rt_kprintf("[FileService] fileWriteBegin: path=%s size=%u\n",
+ upload_target_path_.c_str(),
+ (unsigned)upload_expected_size_);
+ return RT_EOK;
+}
+
+int32_t FileServiceImpl::fileWriteChunk(const binary_t* data)
+{
+ uint32_t remaining;
+ const uint8_t* cursor;
+
+ if (!upload_mutex_) {
+ return -RT_ENOMEM;
+ }
+
+ if (!data || (!data->data && data->dataLength > 0)) {
+ rt_kprintf("[FileService][E] fileWriteChunk: invalid chunk\n");
+ return -RT_EINVAL;
+ }
+
+ rt_mutex_take(upload_mutex_, RT_WAITING_FOREVER);
+ if (upload_fd_ < 0) {
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteChunk: upload not started\n");
+ return -RT_ERROR;
+ }
+
+ // 防止客户端重传、偏移错误或长度错误导致写入超过声明的 total_size。
+ if (data->dataLength > (upload_expected_size_ - upload_received_size_)) {
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteChunk: chunk overflow, recv=%u chunk=%u total=%u\n",
+ (unsigned)upload_received_size_,
+ (unsigned)data->dataLength,
+ (unsigned)upload_expected_size_);
+ return -RT_EINVAL;
+ }
+
+ remaining = data->dataLength;
+ cursor = data->data;
+ // write() 可能只写入部分数据,因此循环直到当前 eRPC binary 块全部落盘。
+ while (remaining > 0) {
+ const ssize_t written = ::write(upload_fd_, cursor, remaining);
+ if (written <= 0) {
+ const int32_t err = posixErrorToRtError();
+ (void)abortUploadLocked();
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteChunk: write failed, err=%d\n", (int)err);
+ return err;
+ }
+
+ remaining -= (uint32_t)written;
+ cursor += written;
+ upload_received_size_ += (uint32_t)written;
+ }
+
+ rt_mutex_release(upload_mutex_);
+ return RT_EOK;
+}
+
+int32_t FileServiceImpl::fileWriteEnd(void)
+{
+ if (!upload_mutex_) {
+ return -RT_ENOMEM;
+ }
+
+ rt_mutex_take(upload_mutex_, RT_WAITING_FOREVER);
+ if (upload_fd_ < 0) {
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteEnd: upload not started\n");
+ return -RT_ERROR;
+ }
+
+ // 最终大小必须完全一致,避免缺块时发布不完整文件。
+ if (upload_received_size_ != upload_expected_size_) {
+ const uint32_t received = upload_received_size_;
+ const uint32_t expected = upload_expected_size_;
+ (void)abortUploadLocked();
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteEnd: size mismatch, recv=%u expected=%u\n",
+ (unsigned)received,
+ (unsigned)expected);
+ return -RT_EINVAL;
+ }
+
+ if (::close(upload_fd_) != 0) {
+ const int32_t err = posixErrorToRtError();
+ upload_fd_ = -1;
+ (void)::unlink(upload_temp_path_.c_str());
+ resetUploadStateLocked();
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteEnd: close failed, err=%d\n", (int)err);
+ return err;
+ }
+ upload_fd_ = -1;
+
+ if (::rename(upload_temp_path_.c_str(), upload_target_path_.c_str()) != 0) {
+ (void)::unlink(upload_target_path_.c_str());
+ if (::rename(upload_temp_path_.c_str(), upload_target_path_.c_str()) != 0) {
+ const int32_t err = posixErrorToRtError();
+ (void)::unlink(upload_temp_path_.c_str());
+ resetUploadStateLocked();
+ rt_mutex_release(upload_mutex_);
+ rt_kprintf("[FileService][E] fileWriteEnd: rename failed, err=%d\n", (int)err);
+ return err;
+ }
+ }
+
+ rt_kprintf("[FileService] fileWriteEnd: path=%s size=%u\n",
+ upload_target_path_.c_str(),
+ (unsigned)upload_received_size_);
+ resetUploadStateLocked();
+ rt_mutex_release(upload_mutex_);
+ return RT_EOK;
+}
+
+int32_t FileServiceImpl::fileWriteAbort(void)
+{
+ int32_t err;
+
+ if (!upload_mutex_) {
+ return -RT_ENOMEM;
+ }
+
+ rt_mutex_take(upload_mutex_, RT_WAITING_FOREVER);
+ err = abortUploadLocked();
+ rt_mutex_release(upload_mutex_);
+ return err;
+}
diff --git a/packages/erpc-1.14.0/erpc_c/config/erpc_config.h b/packages/erpc-1.14.0/erpc_c/config/erpc_config.h
index a5ec3c3..0dcc16d 100644
--- a/packages/erpc-1.14.0/erpc_c/config/erpc_config.h
+++ b/packages/erpc-1.14.0/erpc_c/config/erpc_config.h
@@ -114,7 +114,9 @@
//! Uncomment to change the size of buffers allocated by one of MessageBufferFactory.
//! (@ref client_setup and @ref server_setup). The default size is set to 256.
//! For RPMsg transport layer, ERPC_DEFAULT_BUFFER_SIZE must be 2^n - 16.
-#define ERPC_DEFAULT_BUFFER_SIZE (512U)
+// fileWriteChunk(binary) with a 4096 byte payload needs at least:
+// 6 bytes framed header + 8 bytes eRPC message header + 4 bytes binary length + 4096 bytes data.
+#define ERPC_DEFAULT_BUFFER_SIZE (8192U)
//! @def ERPC_DEFAULT_BUFFERS_COUNT
//!