From 1bf1a4ddcad661231cf6eee846a9047e31f072af Mon Sep 17 00:00:00 2001 From: fancy <258828110.@qq.com> Date: Sun, 12 Nov 2023 07:33:51 -0800 Subject: [PATCH] Add uart module. --- test/utils/SharedData/src/SharedDataTest.cpp | 42 +-- utils/CMakeLists.txt | 1 + utils/SharedData/README.md | 13 +- utils/SharedData/include/SharedData.h | 2 +- utils/UartDevice/CMakeLists.txt | 53 ++++ utils/UartDevice/include/UartDevice.h | 56 ++++ utils/UartDevice/src/UartDevice.cpp | 17 ++ utils/UartDevice/src/UartDeviceImpl.cpp | 255 +++++++++++++++++++ utils/UartDevice/src/UartDeviceImpl.h | 56 ++++ 9 files changed, 461 insertions(+), 34 deletions(-) create mode 100644 utils/UartDevice/CMakeLists.txt create mode 100644 utils/UartDevice/include/UartDevice.h create mode 100644 utils/UartDevice/src/UartDevice.cpp create mode 100644 utils/UartDevice/src/UartDeviceImpl.cpp create mode 100644 utils/UartDevice/src/UartDeviceImpl.h diff --git a/test/utils/SharedData/src/SharedDataTest.cpp b/test/utils/SharedData/src/SharedDataTest.cpp index 472ab3f..6ce7efd 100644 --- a/test/utils/SharedData/src/SharedDataTest.cpp +++ b/test/utils/SharedData/src/SharedDataTest.cpp @@ -63,10 +63,10 @@ TEST(SharedDataTest, Demo2) PrintStringCode(code); LogInfo("readableData = %d\n", readableData); EXPECT_EQ(readableData, WRITABLE_DATA); - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } if (nullptr != sharedDataMinor) { - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } ILogUnInit(); } @@ -93,10 +93,10 @@ TEST(SharedDataTest, Demo3) LogInfo("readableData = %d\n", readableData); EXPECT_NE(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, DEFAULT_DATA); - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } if (nullptr != sharedDataMinor) { - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } ILogUnInit(); } @@ -122,10 +122,10 @@ TEST(SharedDataTest, Demo4) LogInfo("readableData = %d\n", readableData); EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, WRITABLE_DATA); - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } if (nullptr != sharedDataMinor) { - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } ILogUnInit(); } @@ -145,7 +145,7 @@ TEST(SharedDataTest, Demo5) LogInfo("readableData = %d\n", readableData); EXPECT_NE(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, DEFAULT_DATA); - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } ILogUnInit(); } @@ -166,10 +166,10 @@ TEST(SharedDataTest, Demo6) LogInfo("readableData = %d\n", readableData); EXPECT_NE(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, DEFAULT_DATA); - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } if (nullptr != sharedDataMinor) { - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } ILogUnInit(); } @@ -195,10 +195,10 @@ TEST(SharedDataTest, Demo7) LogInfo("readableData = %d\n", readableData); EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, WRITABLE_DATA); - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } if (nullptr != sharedDataPrimary) { - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } ILogUnInit(); } @@ -224,10 +224,10 @@ TEST(SharedDataTest, UNIT_SharedData_DEME_Demo7) LogInfo("readableData = %d\n", readableData); EXPECT_NE(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, DEFAULT_DATA); - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } if (nullptr != sharedDataPrimary) { - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } ILogUnInit(); } @@ -253,10 +253,10 @@ TEST(SharedDataTest, UNIT_SharedData_DEME_Demo8) LogInfo("readableData = %d\n", readableData); EXPECT_NE(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, DEFAULT_DATA); - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } if (nullptr != sharedDataPrimary) { - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } ILogUnInit(); } @@ -282,10 +282,10 @@ TEST(SharedDataTest, UNIT_SharedData_DEME_Demo9) LogInfo("readableData = %d\n", readableData); EXPECT_NE(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, DEFAULT_DATA); - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } if (nullptr != sharedDataPrimary) { - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } ILogUnInit(); } @@ -309,10 +309,10 @@ TEST(SharedDataTest, UNIT_SharedData_DEME_Demo10) PrintStringCode(code); LogInfo("readableData = %d\n", readableData); EXPECT_NE(code.mStatusCode, STATUS_CODE_OK); - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } if (nullptr != sharedDataPrimary) { - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } ILogUnInit(); } @@ -337,10 +337,10 @@ TEST(SharedDataTest, UNIT_SharedData_DEME_Demo11) LogInfo("readableData = %d\n", readableData); EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); EXPECT_EQ(readableData, 189); - IFree(sharedDataMinor); + IShareDataFree(sharedDataMinor); } if (nullptr != sharedDataPrimary) { - IFree(sharedDataPrimary); + IShareDataFree(sharedDataPrimary); } ILogUnInit(); } diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index a8dd921..83af998 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -4,3 +4,4 @@ add_subdirectory(Config) add_subdirectory(StatusCode) add_subdirectory(Log) add_subdirectory(SharedData) +add_subdirectory(UartDevice) diff --git a/utils/SharedData/README.md b/utils/SharedData/README.md index 63e9fe0..4a1e21c 100644 --- a/utils/SharedData/README.md +++ b/utils/SharedData/README.md @@ -2,15 +2,4 @@ ## 1.1. 概述 -  用于跨进程进行数据共享的中间件。 - -## 1.2. UML类图 - -```mermaid -classDiagram - i_ipc_config <.. ipc_config:实现 - ipc_config --> i_config_manager:依赖 - ipc_config --> IHal:依赖 - i_config_manager <.. config_manager:实现 - config_manager --> libconfig开源库:依赖 -``` \ No newline at end of file +  用于跨进程进行数据共享的中间件。 \ No newline at end of file diff --git a/utils/SharedData/include/SharedData.h b/utils/SharedData/include/SharedData.h index 21988e0..13c804d 100644 --- a/utils/SharedData/include/SharedData.h +++ b/utils/SharedData/include/SharedData.h @@ -54,7 +54,7 @@ static inline void ISetWritableData(SharedData *object, void *buf, const unsigne { object->mSetWritableData(object, buf, bufLength); } -static inline void IFree(SharedData *object) { object->mFree(object); } +static inline void IShareDataFree(SharedData *object) { object->mFree(object); } #ifdef __cplusplus } #endif diff --git a/utils/UartDevice/CMakeLists.txt b/utils/UartDevice/CMakeLists.txt new file mode 100644 index 0000000..aeccb34 --- /dev/null +++ b/utils/UartDevice/CMakeLists.txt @@ -0,0 +1,53 @@ +include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${UTILS_SOURCE_PATH}/StatusCode/include + ${UTILS_SOURCE_PATH}/Log/include +) +# link_directories( +# ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME UartDevice) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} StatusCode Log) + +if ("${CLANG_TIDY_SUPPORT}" MATCHES "true") +add_custom_target( + UartDevice_code_check + COMMAND ${CLANG_TIDY_EXE} + -checks='${CLANG_TIDY_CHECKS}' + --header-filter=.* + --system-headers=false + ${SRC_FILES} + ${CLANG_TIDY_CONFIG} + -p ${CMAKE_SOURCE_DIR_IPCSDK}/cmake-shell + WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/UartDevice +) +file(GLOB_RECURSE HEADER_FILES *.h) +add_custom_target( + UartDevice_code_format + COMMAND ${CLANG_FORMAT_EXE} + -style=file + -i ${SRC_FILES} ${HEADER_FILES} + WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/UartDevice +) +add_custom_command( + TARGET ${TARGET_NAME} + PRE_BUILD + COMMAND make UartDevice_code_check + COMMAND make UartDevice_code_format + WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/cmake-shell/ +) +endif() + +define_file_name(${TARGET_NAME}) \ No newline at end of file diff --git a/utils/UartDevice/include/UartDevice.h b/utils/UartDevice/include/UartDevice.h new file mode 100644 index 0000000..cc761dc --- /dev/null +++ b/utils/UartDevice/include/UartDevice.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef UARTD_EVICE_H +#define UARTD_EVICE_H +#include "StatusCode.h" +#include +#ifdef __cplusplus +extern "C" { +#endif +typedef struct uart_info +{ + const char *mDevice; + const int mSpeed; + const int mFlowCtrl; + const int mDataBits; + const int mStopBits; + const int mParity; +} UartInfo; +typedef struct uart_device UartDevice; +typedef struct uart_device +{ + const StatusCode (*mOpen)(UartDevice *); + const size_t (*mSend)(UartDevice *, const char *, const size_t); + const size_t (*mRecv)(UartDevice *, char *, const size_t, const unsigned int); + void (*mTcflush)(UartDevice *); + void (*mFree)(void *); +} UartDevice; +UartDevice *CreateUartDevice(const UartInfo info); +static inline const StatusCode IUartOpen(UartDevice *object) { return object->mOpen(object); } +static inline const size_t IUartSend(UartDevice *object, const char *buff, const size_t buffLength) +{ + return object->mSend(object, buff, buffLength); +} +static inline const size_t IUartRecv(UartDevice *object, char *buff, const size_t buffLength, + const unsigned int timeoutMs) +{ + return object->mRecv(object, buff, buffLength, timeoutMs); +} +static inline void IUartTcflush(UartDevice *object) { return object->mTcflush(object); } +static inline void IUartDeviceFree(UartDevice *object) { object->mFree(object); } +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/utils/UartDevice/src/UartDevice.cpp b/utils/UartDevice/src/UartDevice.cpp new file mode 100644 index 0000000..6c31106 --- /dev/null +++ b/utils/UartDevice/src/UartDevice.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "UartDevice.h" +#include "UartDeviceImpl.h" +UartDevice *CreateUartDevice(const UartInfo info) { return NewUartDeviceImpl(info); } \ No newline at end of file diff --git a/utils/UartDevice/src/UartDeviceImpl.cpp b/utils/UartDevice/src/UartDeviceImpl.cpp new file mode 100644 index 0000000..d1e150d --- /dev/null +++ b/utils/UartDevice/src/UartDeviceImpl.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "UartDeviceImpl.h" +#include "ILog.h" +#include +#include +#include +#include +#include +#include +#include +constexpr int INVALID_FD = -1; +static const char *UART_DEVICE_NAME = "uart_device"; +UartDeviceImpl::UartDeviceImpl(const UartInfo &uatrInfo) : mUatrInfo(uatrInfo) { mFd = -1; } +const StatusCode UartDeviceImpl::UartOpen(void) +{ + mFd = open(mUatrInfo.mDevice, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (INVALID_FD == mFd) { + perror("Can't Open Serial Port"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + return SetConfig(); +} + +const size_t UartDeviceImpl::UartSend(const char *buff, const size_t &buffLength) +{ + constexpr int SEND_FAILED = -1; + size_t len = 0; + if (mFd <= 0) { + LogError("open uart failed.\n"); + return SEND_FAILED; + } + // TODO: what if write return less then buffLength? + len = write(mFd, buff, buffLength); + if (len == buffLength) { + return len; + } + tcflush(mFd, TCOFLUSH); + return len; +} +const size_t UartDeviceImpl::UartRecv(char *buff, const size_t &buffLength, const unsigned int &timeOutMs, + const unsigned int delayRead) +{ + constexpr int RECV_FAILED = -1; + int len, fs_sel; + fd_set fs_read; + struct timeval time; + + if (mFd <= 0) { + return RECV_FAILED; + } + + FD_ZERO(&fs_read); + FD_SET(mFd, &fs_read); + time.tv_sec = timeOutMs / 1000; + time.tv_usec = (timeOutMs % 1000) * 1000; + fs_sel = select(mFd + 1, &fs_read, NULL, NULL, &time); + if (fs_sel) { + usleep(1000 * delayRead); + len = read(mFd, buff, buffLength); + return len; + } + return RECV_FAILED; +} +void UartDeviceImpl::UartTcflush(void) +{ + if (mFd > 0) { + tcflush(mFd, TCIFLUSH); + } +} +const StatusCode UartDeviceImpl::SetConfig(void) +{ + int i; + int speed_arr[] = {B1152000, + B1000000, + B921600, + B576000, + B500000, + B460800, + B230400, + B115200, + B19200, + B9600, + B4800, + B2400, + B1200, + B300}; + int name_arr[] = { + 1152000, 1000000, 921600, 576000, 500000, 460800, 230400, 115200, 19200, 9600, 4800, 2400, 1200, 300}; + struct termios options; + + if (tcgetattr(mFd, &options) != 0) { + perror("SetupSerial 1"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + + // set buater rate + for (i = 0; i < (int)(sizeof(speed_arr) / sizeof(int)); i++) { + if (mUatrInfo.mSpeed == name_arr[i]) { + cfsetispeed(&options, speed_arr[i]); + cfsetospeed(&options, speed_arr[i]); + } + } + + // set control model + options.c_cflag |= CLOCAL; + options.c_cflag |= CREAD; + + // set flow control + switch (mUatrInfo.mFlowCtrl) { + case 0: // none + options.c_cflag &= ~CRTSCTS; + break; + case 1: // use hard ware + options.c_cflag |= CRTSCTS; + break; + case 2: // use sofware + options.c_cflag |= IXON | IXOFF | IXANY; + break; + } + + // select data bit + options.c_cflag &= ~CSIZE; + switch (mUatrInfo.mDataBits) { + case 5: + options.c_cflag |= CS5; + break; + case 6: + options.c_cflag |= CS6; + break; + case 7: + options.c_cflag |= CS7; + break; + case 8: + options.c_cflag |= CS8; + break; + default: + fprintf(stderr, "Unsupported data size\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + + // select parity bit + switch (mUatrInfo.mParity) { + case 'n': + case 'N': + options.c_cflag &= ~PARENB; + options.c_iflag &= ~INPCK; + break; + case 'o': + case 'O': + options.c_cflag |= (PARODD | PARENB); + options.c_iflag |= INPCK; + break; + case 'e': + case 'E': + options.c_cflag |= PARENB; + options.c_cflag &= ~PARODD; + options.c_iflag |= INPCK; + break; + case 's': + case 'S': + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + break; + default: + fprintf(stderr, "Unsupported parity\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + // set stopbit + switch (mUatrInfo.mStopBits) { + case 1: + options.c_cflag &= ~CSTOPB; + break; + case 2: + options.c_cflag |= CSTOPB; + break; + default: + fprintf(stderr, "Unsupported stop bits\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + + // set raw data output + options.c_oflag &= ~OPOST; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + // options.c_lflag &= ~(ISIG | ICANON); + // set wait time + options.c_cc[VTIME] = 1; + options.c_cc[VMIN] = 1; + tcflush(mFd, TCIFLUSH); + // set the attribute to HiSerial device + if (tcsetattr(mFd, TCSANOW, &options) != 0) { + perror("com set error!\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + return CreateStatusCode(STATUS_CODE_OK); +} +const StatusCode (*mOpen)(UartDevice *); +static const StatusCode UartOpen(UartDevice *object) +{ + UartDeviceImpl_S *impl = UartDeviceImplConvert(object); + return impl->mUartImpl->UartOpen(); +} +static const size_t UartSend(UartDevice *object, const char *buff, const size_t buffLength) +{ + UartDeviceImpl_S *impl = UartDeviceImplConvert(object); + return impl->mUartImpl->UartSend(buff, buffLength); +} +static const size_t UartRecv(UartDevice *object, char *buff, const size_t buffLength, const unsigned int timeoutMs) +{ + UartDeviceImpl_S *impl = UartDeviceImplConvert(object); + constexpr int READ_NOT_DELAY = 0; + return impl->mUartImpl->UartRecv(buff, buffLength, timeoutMs, READ_NOT_DELAY); +} +static void UartTcflush(UartDevice *object) +{ + UartDeviceImpl_S *impl = UartDeviceImplConvert(object); + return impl->mUartImpl->UartTcflush(); +} +static void UartImpllFree(void *ptr) +{ + UartDeviceImpl_S *object = ((UartDeviceImpl_S *)(((char *)ptr) - sizeof(UartDeviceHeader))); + if (UART_DEVICE_NAME == object->mHeader.mCheckName) { + object->mUartImpl = nullptr; + free(((char *)ptr) - sizeof(UartDeviceHeader)); + } + else { + LogError("Unknow ptr.\n"); + } +} +UartDevice *NewUartDeviceImpl(const UartInfo &uartInfo) +{ + UartDeviceImpl_S *impl = (UartDeviceImpl_S *)malloc(sizeof(UartDeviceImpl_S)); + UartDeviceImpl_S tmp; + memcpy((void *)impl, (void *)&tmp, sizeof(UartDeviceImpl_S)); + impl->mHeader.mCheckName = UART_DEVICE_NAME; + impl->mBase.mOpen = UartOpen; + impl->mBase.mSend = UartSend; + impl->mBase.mRecv = UartRecv; + impl->mBase.mTcflush = UartTcflush; + impl->mBase.mFree = UartImpllFree; + impl->mUartImpl = std::make_shared(uartInfo); + return (UartDevice *)(((char *)impl) + sizeof(UartDeviceHeader)); +} \ No newline at end of file diff --git a/utils/UartDevice/src/UartDeviceImpl.h b/utils/UartDevice/src/UartDeviceImpl.h new file mode 100644 index 0000000..b240b92 --- /dev/null +++ b/utils/UartDevice/src/UartDeviceImpl.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef UARTDE_VICEIMPL_H +#define UARTDE_VICEIMPL_H +#include "StatusCode.h" +#include "UartDevice.h" +#include +#include +#define UART_DEVICE_INIT_NAME "UART" +typedef struct uart_device_header +{ + const char *mCheckName; +} UartDeviceHeader; +class UartDeviceImpl +{ +public: + UartDeviceImpl(const UartInfo &uatrInfo); + virtual ~UartDeviceImpl() = default; + const StatusCode UartOpen(void); + const size_t UartSend(const char *buff, const size_t &buffLength); + const size_t UartRecv(char *buff, const size_t &buffLength, const unsigned int &timeOutMs = 0, + const unsigned int delayRead = 0); + void UartTcflush(void); + +private: + const StatusCode SetConfig(void); + +private: + const UartInfo mUatrInfo; + int mFd; +}; +typedef struct uart_device_impl UartDeviceImpl_S; +typedef struct uart_device_impl +{ + UartDeviceHeader mHeader; + UartDevice mBase; + std::shared_ptr mUartImpl; +} UartDeviceImpl_S; +UartDevice *NewUartDeviceImpl(const UartInfo &uartInfo); +static inline UartDeviceImpl_S *UartDeviceImplConvert(UartDevice *object) +{ + return ((UartDeviceImpl_S *)(((char *)object) - sizeof(UartDeviceHeader))); +} +#endif \ No newline at end of file