Add uart module.

This commit is contained in:
fancy 2023-11-12 07:33:51 -08:00
parent 2af2c45e7a
commit 1bf1a4ddca
9 changed files with 461 additions and 34 deletions

View File

@ -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();
}

View File

@ -4,3 +4,4 @@ add_subdirectory(Config)
add_subdirectory(StatusCode)
add_subdirectory(Log)
add_subdirectory(SharedData)
add_subdirectory(UartDevice)

View File

@ -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开源库:依赖
```
&emsp;&emsp;用于跨进程进行数据共享的中间件。

View File

@ -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

View File

@ -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})

View File

@ -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 <cstddef>
#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

View File

@ -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); }

View File

@ -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 <cstring>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
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<UartDeviceImpl>(uartInfo);
return (UartDevice *)(((char *)impl) + sizeof(UartDeviceHeader));
}

View File

@ -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 <cstddef>
#include <memory>
#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<UartDeviceImpl> mUartImpl;
} UartDeviceImpl_S;
UartDevice *NewUartDeviceImpl(const UartInfo &uartInfo);
static inline UartDeviceImpl_S *UartDeviceImplConvert(UartDevice *object)
{
return ((UartDeviceImpl_S *)(((char *)object) - sizeof(UartDeviceHeader)));
}
#endif