Link Search Menu Expand Document

Memory Alignment

ARM Cortex M MCU can perform unaligned access for certain instructions.

Although GCC has option -mnounaligned-access to do everything byte-wise, the resulting code will be slower. We code carefully to avoid invalid unaligned access.

Defining Compact C Struct

We need to define C struct in compact form, i.e., with only 1 byte alignment, which is the minimum.

Also we need the same code compilable on both GCC and Microsoft VC++. It’s a bit tricky. We finally settled with a BYTE_ALIGNED macro.

#include "align.h"

Below is a definition of a Hornet/Zigbee NPDU (Network Protocol Data Unit) header.

BYTE_ALIGNED(
typedef struct {
    npdu_fcf_t  fcf;
    uint16_t    dest_addr;
    uint16_t    src_addr;
    uint8_t     radius;
    uint8_t     sequence;
}) npdu_header_fixed_t;

C bit field declaration shall also be defined in this way.

BYTE_ALIGNED(
typedef struct {
    union {
        struct {
            uint8_t     frame_type : 2;
            uint8_t     protocol_version : 4;
            uint8_t     discover_route : 2;
            uint8_t     multicast : 1;
            uint8_t     security : 1;
            uint8_t     source_route : 1;
            uint8_t     dest_ieee_addr : 1;
            uint8_t     src_ieee_addr : 1;
            uint8_t     busy : 1;
            uint8_t     reserved : 2;
        };
        uint16_t		raw;
    };
} ) npdu_fcf_t;

64 Bit Access

For 64 bit types, such as int64_t or uint64_t, unaligned access is not allowed on ARM.

Hornet defined appropriate helper functions. Note the input arguments are all pointers to 64 bit numbers.

// Returns true if the 64 bit number is NOT zero.
static inline uint8_t int64_is_nonzero(const void *dest);
// Set 64 bit number ito zero.
static inline void int64_zero(void *dest);
// Copy 64 bit number.
static inline void int64_copy(void *dest, const void *src);
// Test if two 64 bit numbers are equal.
static inline uint8_t int64_equal(const void *dest, const void *src);