Skip to content

Commit 34dac0f

Browse files
authored
Implement C library for UART communication with CRC16 support and stream mode
* Implement C library for UART communication with CRC16 support and streaming mode * Fix comments
1 parent 34a52ba commit 34dac0f

11 files changed

Lines changed: 289 additions & 101 deletions

File tree

c/l4/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
2+
3+
add_library(module_l4_c STATIC)
4+
5+
target_sources(module_l4_c
6+
PRIVATE
7+
src/Channel_c.c
8+
)
9+
10+
target_include_directories(module_l4_c PUBLIC
11+
$<INSTALL_INTERFACE:include>
12+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
13+
)

c/l4/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Channel_c.h
2+
3+
UART communication channel configuration and CRC calculation definitions. You can redefine them.
4+
5+
## `BufferSize_t`
6+
Type definition for buffer size. Defaults to `uint8_t` if not previously defined.
7+
Used to specify the maximum buffer size for UART data transmission.
8+
9+
## `V2STYXLIB_CRC16_POLY`
10+
CRC16 polynomial value used for checksum calculation.
11+
Default: `0x1021` (CCITT polynomial).
12+
Used in the CRC16-CCITT algorithm for error detection.
13+
14+
## `V2STYXLIB_CRC16_INITIAL_VALUE`
15+
Initial value for CRC16 calculation.
16+
Default: `0xFFFF`.
17+
Used as the starting point for CRC16 calculation.
18+
19+
## `V2STYXLIB_STREAMING_MODE`
20+
Flag bit indicating streaming mode is enabled.
21+
Default: `0x01`.
22+
When set, UART operates in streaming mode:
23+
- SOF (Start of Frame) markers are sent before each data frame.
24+
- The sender does not wait for responses between transmissions.
25+
26+
## `V2STYXLIB_SOF_MARKER_1`
27+
First byte of the Start of Frame (SOF) marker sequence.
28+
Default: `0x55`.
29+
Used in streaming mode to indicate the beginning of a new data frame.
30+
31+
## `V2STYXLIB_SOF_MARKER_2`
32+
Second byte of the Start of Frame (SOF) marker sequence.
33+
Default: `0xAA`.
34+
Used with `V2STYXLIB_SOF_MARKER_1` to form the two-byte SOF marker sequence: `0x55 0xAA`.
35+
36+
## `V2STYXLIB_SEND_CRC16`
37+
Flag bit indicating CRC16 is appended to each transmitted frame.
38+
Default: `0x02`.
39+
When set, a 2-byte CRC16 checksum (using `V2STYXLIB_CRC16_POLY` and
40+
`V2STYXLIB_CRC16_INITIAL_VALUE`) is added at the beggining of every frame,
41+
before the payload.
42+
This extends the frame layout by two bytes and enables end-to-end error detection.

c/l4/include/ChannelUartStm8.h

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,7 @@
33
#include <stdint.h>
44
#include "stm8s.h"
55

6-
typedef uint8_t BufferSize_t;
7-
8-
#ifndef V2STYXLIB_CRC16_POLY
9-
#define V2STYXLIB_CRC16_POLY 0x1021
10-
#endif
11-
#ifndef V2STYXLIB_CRC16_INITIAL_VALUE
12-
#define V2STYXLIB_CRC16_INITIAL_VALUE 0xFFFF
13-
#endif
14-
15-
#define V2STYXLIB_STREAMING_MODE 0x01
16-
17-
#ifndef V2STYXLIB_SOF_MARKER_1
18-
#define V2STYXLIB_SOF_MARKER_1 0x55
19-
#define V2STYXLIB_SOF_MARKER_2 0xAA
20-
#endif
21-
22-
typedef struct {
23-
uint8_t config;
24-
} V2styxlibUartConfig;
25-
26-
/**
27-
* useStreamingMode - is a boolean flag that indicates whether to use streaming mode for UART communication.
28-
* In streaming mode client will not wait for the response after sending a message, but will continue to send messages without blocking.
29-
* We will send SOF marker 0x55 0xAA (check V2STYXLIB_SOF_MARKER_xx) before each frame.
30-
*/
31-
void v2styxlib_uart_configure_proto(
32-
V2styxlibUartConfig *config,
33-
bool useStreamingMode
34-
);
6+
#include "Channel_c.h"
357

368
/**
379
* baudRateDivider - is a value that determines the data transmission speed over UART.

c/l4/include/Channel_c.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
#include <stdbool.h>
5+
6+
#ifndef BufferSize_t
7+
#define BufferSize_t uint8_t
8+
#endif
9+
10+
#ifndef V2STYXLIB_CRC16_POLY
11+
#define V2STYXLIB_CRC16_POLY 0x1021
12+
#endif
13+
#ifndef V2STYXLIB_CRC16_INITIAL_VALUE
14+
#define V2STYXLIB_CRC16_INITIAL_VALUE 0xFFFF
15+
#endif
16+
17+
#ifndef V2STYXLIB_STREAMING_MODE
18+
#define V2STYXLIB_STREAMING_MODE 0x01
19+
#endif
20+
#ifndef V2STYXLIB_SEND_CRC16
21+
#define V2STYXLIB_SEND_CRC16 0x02
22+
#endif
23+
24+
#ifndef V2STYXLIB_SOF_MARKER_1
25+
#define V2STYXLIB_SOF_MARKER_1 0x55
26+
#define V2STYXLIB_SOF_MARKER_2 0xAA
27+
#endif
28+
29+
#ifdef __cplusplus
30+
extern "C" {
31+
#endif
32+
33+
typedef struct {
34+
uint8_t config;
35+
} V2styxlibUartConfig;
36+
37+
/**
38+
* useStreamingMode - is a boolean flag that indicates whether to
39+
* use streaming mode for UART communication.
40+
* In streaming mode client will not wait for the response after
41+
* sending a message, but will continue to send messages without blocking.
42+
* We will send SOF marker 0x55 0xAA (check V2STYXLIB_SOF_MARKER_xx) before each frame.
43+
*
44+
* sendCrc16 - is a boolean flag that indicates whether to calculate and send
45+
* CRC16 checksum with each message.
46+
*/
47+
void v2styxlib_uart_configure_proto(
48+
V2styxlibUartConfig *config,
49+
bool useStreamingMode,
50+
bool sendCrc16
51+
);
52+
53+
/**
54+
* Calculate the CRC16 checksum for the given data.
55+
*
56+
* data - pointer to the data buffer
57+
* length - length of the data buffer
58+
*
59+
* Returns the calculated CRC16 checksum.
60+
*/
61+
uint16_t v2styxlib_crc16_calculate(const uint8_t *data, BufferSize_t length);
62+
63+
#ifdef __cplusplus
64+
}
65+
#endif

c/l4/src/ChannelUartStm8.c

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,6 @@
22

33
#define WAIT_FOR_TXE() while (!(UART1->SR & UART1_SR_TXE))
44

5-
static inline uint16_t v2styxlib_uart_crc16_update(uint16_t crc, uint8_t data) {
6-
crc ^= (uint16_t)data << 8;
7-
for (uint8_t i = 0; i < 8; i++) {
8-
if (crc & 0x8000) {
9-
crc = (crc << 1) ^ V2STYXLIB_CRC16_POLY;
10-
} else {
11-
crc <<= 1;
12-
}
13-
}
14-
return crc;
15-
}
16-
17-
static uint16_t v2styxlib_uart_crc16_calculate(const uint8_t *data, BufferSize_t length) {
18-
uint16_t crc = V2STYXLIB_CRC16_INITIAL_VALUE;
19-
for (BufferSize_t i = 0; i < length; i++) {
20-
crc = v2styxlib_uart_crc16_update(crc, data[i]);
21-
}
22-
return crc;
23-
}
24-
25-
void v2styxlib_uart_configure_proto(
26-
V2styxlibUartConfig *config,
27-
bool useStreamingMode
28-
) {
29-
if (useStreamingMode) {
30-
config->config |= V2STYXLIB_STREAMING_MODE;
31-
} else {
32-
config->config &= ~V2STYXLIB_STREAMING_MODE;
33-
}
34-
}
35-
365
void v2styxlib_uart_setup(uint16_t baudRateDivider)
376
{
387
UART1->BRR2 = ((baudRateDivider >> 8) & 0xF0) | (baudRateDivider & 0x0F);
@@ -54,16 +23,20 @@ void v2styxlib_uart_send(
5423
UART1->DR = V2STYXLIB_SOF_MARKER_2;
5524
}
5625

57-
// send packet size
58-
WAIT_FOR_TXE();
59-
UART1->DR = length + 2; // +2 for CRC16
60-
61-
// then CRC16
62-
uint16_t crc = v2styxlib_uart_crc16_calculate(buffer, length);
63-
WAIT_FOR_TXE();
64-
UART1->DR = (crc >> 8) & 0xFF; // send high byte of CRC
6526
WAIT_FOR_TXE();
66-
UART1->DR = crc & 0xFF; // send low byte of CRC
27+
if (config->config & V2STYXLIB_SEND_CRC16) {
28+
// send packet size + 2 bytes for CRC16
29+
UART1->DR = length + 2;
30+
// then CRC16
31+
uint16_t crc = v2styxlib_crc16_calculate(buffer, length);
32+
WAIT_FOR_TXE();
33+
UART1->DR = (crc >> 8) & 0xFF; // send high byte of CRC
34+
WAIT_FOR_TXE();
35+
UART1->DR = crc & 0xFF; // send low byte of CRC
36+
} else {
37+
// send packet size
38+
UART1->DR = length;
39+
}
6740

6841
// then send the actual data
6942
for (BufferSize_t i = 0; i < length; i++) {

c/l4/src/Channel_c.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "Channel_c.h"
2+
3+
static inline uint16_t v2styxlib_crc16_update(uint16_t crc, uint8_t data) {
4+
crc ^= (uint16_t)data << 8;
5+
for (uint8_t i = 0; i < 8; i++) {
6+
if (crc & 0x8000) {
7+
crc = (crc << 1) ^ V2STYXLIB_CRC16_POLY;
8+
} else {
9+
crc <<= 1;
10+
}
11+
}
12+
return crc;
13+
}
14+
15+
uint16_t v2styxlib_crc16_calculate(const uint8_t *data, BufferSize_t length) {
16+
uint16_t crc = V2STYXLIB_CRC16_INITIAL_VALUE;
17+
for (BufferSize_t i = 0; i < length; i++) {
18+
crc = v2styxlib_crc16_update(crc, data[i]);
19+
}
20+
return crc;
21+
}
22+
23+
void v2styxlib_uart_configure_proto(
24+
V2styxlibUartConfig *config,
25+
bool useStreamingMode,
26+
bool sendCrc16
27+
) {
28+
if (useStreamingMode) {
29+
config->config |= V2STYXLIB_STREAMING_MODE;
30+
} else {
31+
config->config &= ~V2STYXLIB_STREAMING_MODE;
32+
}
33+
if (sendCrc16) {
34+
config->config |= V2STYXLIB_SEND_CRC16;
35+
} else {
36+
config->config &= ~V2STYXLIB_SEND_CRC16;
37+
}
38+
}

cpp/CMakeLists.txt

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ set(CMAKE_C_STANDARD 99)
1818
set(CMAKE_C_STANDARD_REQUIRED True)
1919

2020
option(USE_STD_MEMORY "Use std lib <memory>" ON)
21-
22-
# find_package(Catch2 3 REQUIRED)
23-
24-
include(FetchContent)
25-
FetchContent_Declare(
26-
Catch2
27-
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
28-
GIT_TAG v3.5.3
29-
)
30-
FetchContent_MakeAvailable(Catch2)
31-
include(Catch)
21+
option(ENABLE_CATCH2 "Enable Catch2" ON)
22+
23+
if (ENABLE_CATCH2)
24+
include(FetchContent)
25+
FetchContent_Declare(
26+
Catch2
27+
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
28+
GIT_TAG v3.5.3
29+
)
30+
FetchContent_MakeAvailable(Catch2)
31+
include(Catch)
32+
endif()
3233

3334
# For GCC and Clang compilers
3435
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
@@ -39,6 +40,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
3940
add_compile_options(/we4716)
4041
endif()
4142

43+
add_compile_definition(BufferSize_t=uint16_t)
44+
45+
add_subdirectory(../c/l4 module/l4_c)
4246
add_subdirectory(modules/l4)
4347
add_subdirectory(modules/l5)
4448

cpp/modules/l4/CMakeLists.txt

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,43 @@
11
CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
22

33
add_library(module_l4 STATIC)
4-
add_executable(module_l4_tests
5-
test/test_dummy.cpp)
64

75
target_sources(module_l4
86
PRIVATE
97
src/ChannelRx.cpp
108
src/ChannelTx.cpp
11-
src/impl/ClientsRepoImpl.cpp
12-
src/impl/ChannelUnixFile.cpp
139
)
1410

1511
target_include_directories(module_l4 PUBLIC
1612
$<INSTALL_INTERFACE:include>
1713
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
1814
)
1915

16+
target_link_libraries(
17+
module_l4
18+
module_l4_c
19+
)
2020

2121
if (USE_STD_MEMORY)
2222
target_compile_definitions(module_l4 PRIVATE USE_STD_MEMORY)
23-
target_compile_definitions(module_l4_tests PRIVATE USE_STD_MEMORY)
23+
endif()
24+
25+
if (SUPPORT_UNIX)
26+
target_sources(module_l4
27+
PRIVATE
28+
src/impl/ClientsRepoImpl.cpp
29+
src/impl/ChannelUnixFile.cpp
30+
)
31+
endif()
32+
33+
if (SUPPORT_RP2040)
34+
target_sources(module_l4
35+
PRIVATE
36+
src/styxpico/ChannelUsbUart.cpp
37+
)
38+
target_link_libraries(module_l4
39+
pico_stdlib
40+
)
2441
endif()
2542

2643
if(CMAKE_CXX_STANDARD GREATER_EQUAL 23)
@@ -53,9 +70,23 @@ else()
5370

5471
endif()
5572

56-
target_include_directories(module_l4_tests PRIVATE ./include/)
57-
target_link_libraries(module_l4_tests PUBLIC Catch2::Catch2WithMain module_l4)
58-
59-
catch_discover_tests(module_l4_tests
60-
PROPERTIES
61-
TIMEOUT 10)
73+
if (ENABLE_CATCH2)
74+
add_executable(module_l4_tests
75+
test/test_dummy.cpp)
76+
if (USE_STD_MEMORY)
77+
target_compile_definitions(module_l4_tests PRIVATE USE_STD_MEMORY)
78+
endif()
79+
if(CMAKE_CXX_STANDARD GREATER_EQUAL 23)
80+
message("Build tests for C++23")
81+
target_sources(module_l4_tests PRIVATE
82+
test/test_ChannelUnixTcp.cpp
83+
test/test_ChannelUnixPipeImpl.cpp
84+
)
85+
endif()
86+
target_include_directories(module_l4_tests PRIVATE ./include/)
87+
target_link_libraries(module_l4_tests PUBLIC Catch2::Catch2WithMain module_l4)
88+
89+
catch_discover_tests(module_l4_tests
90+
PROPERTIES
91+
TIMEOUT 10)
92+
endif()

0 commit comments

Comments
 (0)