Endianness-independent code

This commit is contained in:
Valerio De Benedetto 2023-03-13 12:30:32 +01:00
parent 2feb8b639e
commit f70fbd5260
4 changed files with 10 additions and 43 deletions

View File

@ -1,6 +1,7 @@
# nanoMODBUS - A compact MODBUS RTU/TCP C library for embedded/microcontrollers # nanoMODBUS - A compact MODBUS RTU/TCP C library for embedded/microcontrollers
nanoMODBUS is a small C library that implements the Modbus protocol. It is especially useful in embedded and resource-constrained nanoMODBUS is a small C library that implements the Modbus protocol. It is especially useful in embedded and
resource-constrained
systems like microcontrollers. systems like microcontrollers.
Its main features are: Its main features are:
@ -124,12 +125,6 @@ is useful, for example, to pass the connection a function should operate on.
Its initial value can be set inside the `nmbs_platform_conf` struct when creating the `nmbs_t` instance, and changed at Its initial value can be set inside the `nmbs_platform_conf` struct when creating the `nmbs_t` instance, and changed at
any time via the `nmbs_set_platform_arg` API method. any time via the `nmbs_set_platform_arg` API method.
## Platform endianness
nanoMODBUS will attempt to detect the endianness of the platform at build time. If the automatic detection fails, you
can manually set the endianness of the platform by defining either `NMBS_BIG_ENDIAN` or `NMBS_LITTLE_ENDIAN` in your
build flags.
## Tests and examples ## Tests and examples
Tests and examples can be built and run on Linux with CMake: Tests and examples can be built and run on Linux with CMake:

View File

@ -8,8 +8,6 @@
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#define NMBS_LITTLE_ENDIAN 1
#include "..\..\nanomodbus.h" #include "..\..\nanomodbus.h"
#include "comm.h" #include "comm.h"

View File

@ -82,7 +82,7 @@
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NMBS_BIG_ENDIAN=1WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
</ClCompile> </ClCompile>
<Link> <Link>
@ -110,7 +110,7 @@
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NMBS_LITTLE_ENDIAN=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<UndefineAllPreprocessorDefinitions>false</UndefineAllPreprocessorDefinitions> <UndefineAllPreprocessorDefinitions>false</UndefineAllPreprocessorDefinitions>
</ClCompile> </ClCompile>

View File

@ -26,7 +26,6 @@
#include "nanomodbus.h" #include "nanomodbus.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
@ -37,18 +36,6 @@
#define DEBUG(...) (void) (0) #define DEBUG(...) (void) (0)
#endif #endif
#if !defined(NMBS_BIG_ENDIAN) && !defined(NMBS_LITTLE_ENDIAN)
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || defined(__BIG_ENDIAN__) || defined(__ARMEB__) || \
defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
#define NMBS_BIG_ENDIAN
#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \
defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) || \
defined(__MIPSEL__) || defined(__AVR_ARCH__)
#define NMBS_LITTLE_ENDIAN
#else
#error "Failed to automatically detect platform endianness. Please define either NMBS_BIG_ENDIAN or NMBS_LITTLE_ENDIAN."
#endif
#endif
static uint8_t get_1(nmbs_t* nmbs) { static uint8_t get_1(nmbs_t* nmbs) {
uint8_t result = nmbs->msg.buf[nmbs->msg.buf_idx]; uint8_t result = nmbs->msg.buf[nmbs->msg.buf_idx];
@ -56,45 +43,32 @@ static uint8_t get_1(nmbs_t* nmbs) {
return result; return result;
} }
static void put_1(nmbs_t* nmbs, uint8_t data) { static void put_1(nmbs_t* nmbs, uint8_t data) {
nmbs->msg.buf[nmbs->msg.buf_idx] = data; nmbs->msg.buf[nmbs->msg.buf_idx] = data;
nmbs->msg.buf_idx++; nmbs->msg.buf_idx++;
} }
static void discard_1(nmbs_t* nmbs) { static void discard_1(nmbs_t* nmbs) {
nmbs->msg.buf_idx++; nmbs->msg.buf_idx++;
} }
#ifdef NMBS_BIG_ENDIAN
static uint16_t get_2(nmbs_t* m) {
uint16_t result = (*(uint16_t*) (m->msg.buf + m->msg.buf_idx));
m->msg.buf_idx += 2;
return result;
}
static void put_2(nmbs_t* m, uint16_t w) {
(*(uint16_t*) (m->msg.buf + m->msg.buf_idx)) = w;
m->msg.buf_idx += 2;
}
#else
static uint16_t get_2(nmbs_t* nmbs) { static uint16_t get_2(nmbs_t* nmbs) {
uint16_t result = uint16_t result =
((uint16_t) (nmbs->msg.buf[nmbs->msg.buf_idx + 1])) | (((uint16_t) nmbs->msg.buf[nmbs->msg.buf_idx] << 8)); ((uint16_t) nmbs->msg.buf[nmbs->msg.buf_idx]) << 8 | (uint16_t) nmbs->msg.buf[nmbs->msg.buf_idx + 1];
nmbs->msg.buf_idx += 2; nmbs->msg.buf_idx += 2;
return result; return result;
} }
static void put_2(nmbs_t* nmbs, uint16_t data) { static void put_2(nmbs_t* nmbs, uint16_t data) {
nmbs->msg.buf[nmbs->msg.buf_idx] = ((uint8_t) ((((uint16_t) (data)) & 0xFF00) >> 8)); nmbs->msg.buf[nmbs->msg.buf_idx] = (uint8_t) ((data >> 8) & 0xFFU);
nmbs->msg.buf[nmbs->msg.buf_idx + 1] = ((uint8_t) (((uint16_t) (data)) & 0x00FF)); nmbs->msg.buf[nmbs->msg.buf_idx + 1] = (uint8_t) data;
nmbs->msg.buf_idx += 2; nmbs->msg.buf_idx += 2;
} }
#endif
static void msg_buf_reset(nmbs_t* nmbs) { static void msg_buf_reset(nmbs_t* nmbs) {
nmbs->msg.buf_idx = 0; nmbs->msg.buf_idx = 0;