Reusable, hardware-agnostic library for safe memory access with a structured message encoder/decoder for a simulated embedded communication link.
| # | Name | ID |
|---|---|---|
| 1 | Alaa Abd El-Nasser Mohamed | 9230233 |
| 2 | Alaa Ahmed Mobarek | 9230229 |
project1/
├── STD_TYPES.h # Portable fixed-width type aliases
├── BIT_MATH.h # MISRA-C compliant bit manipulation macros
├── MemScanner.h # Memory inspection module header
├── MemScanner.c # Memory inspection module implementation
├── message.h # Message struct, payload types, prototypes
├── message.c # Encoder, decoder, handler registration
└── main.c # Demonstration (C1 + C2)
Defines all portable type aliases used across the project:
uint8,uint16,uint32— unsigned fixed-width integerssint8,sint16,sint32— signed fixed-width integersboolean,TRUE,FALSESTD_ReturnTypewithSTD_OK/STD_FAILUREVoidPtrfor generic raw memory access- No raw C types (
int,char,long) appear outside this file
MISRA-C compliant macro library for bit manipulation:
SET_BIT(reg, bit)— set a single bitCLR_BIT(reg, bit)— clear a single bitTOG_BIT(reg, bit)— toggle a single bitGET_BIT(reg, bit)— read a single bitSET_MASK/CLR_MASK— multi-bit mask operationsWRITE_FIELD/READ_FIELD— bit-field region access
All macros use unsigned literals, full parenthesization, and avoid signed-shift operations.
Hardware-inspired memory inspection module (modeled after OpenOCD / pyOCD):
| Function | Description |
|---|---|
MemScanner_ReadByte |
Read 1 byte at a given offset |
MemScanner_ReadHalfWord |
Read 16-bit value (Little-Endian) |
MemScanner_ReadWord |
Read 32-bit value (Little-Endian) |
MemScanner_WriteByte |
Write 1 byte at a given offset |
MemScanner_HexDump |
Print memory region as formatted hex |
MemScanner_MemFill |
Fill memory region with a byte value |
MemScanner_MemCompare |
Compare two memory regions byte-by-byte |
MemScanner_FindByte |
Search for first occurrence of a byte |
Byte 0 Byte 1 Bytes 2–5
───────── ───────── ─────────────────────
HEADER LENGTH PAYLOAD (4 bytes)
Bits 2:0 → MSG_TYPE (0–7)
Bit 3 → PRIORITY (0 = normal, 1 = high)
Bits 7:4 → SEQ_NUM (0–15, auto-increments)
| MSG_TYPE | Name | Payload |
|---|---|---|
| 0 | SENSOR_READING |
lower 16 bits = temperature (×0.1 °C), upper 16 bits = humidity (×0.1 %RH) |
| 1 | DEVICE_COMMAND |
byte 0 = command ID, byte 1 = parameter, bytes 2–3 = unused (0x00) |
message_t is a __attribute__((packed)) struct of exactly 6 bytes, verified at compile time with _Static_assert.
- Accepts
msgType,priority, andMessagePayload_t - Builds the header byte using bit-fields
- Writes payload bytes into a 6-byte buffer
- Auto-increments
seqNum(hidden static state, wraps 0–15) - Returns pointer to internal buffer — must be copied immediately
- Accepts a raw
void*6-byte buffer - Parses header, length, and payload into a
message_tstruct - For
SENSOR_READING: payload accessible as 32-bit, two 16-bit halves, or 4 individual bytes (via union) - Automatically calls the registered handler for the decoded message type
- Returns
STD_OKorSTD_FAILURE
- Stores up to 8 handler function pointers (one per message type)
- All state is encapsulated inside
message.c(not visible externally) - If no handler is registered for a type, decode still succeeds silently
Register handlers (sensor_handler, command_handler)
│
▼
Encode SENSOR_READING
temp = 255 (25.5 °C × 10)
humid = 600 (60.0 %RH × 10)
│
▼
Encode DEVICE_COMMAND
cmd_id = 0x01, param = 0xFF
│
▼
messageDecode(sensorBuffer) → sensor_handler() called automatically
messageDecode(commandBuffer) → command_handler() called automatically
sensor_handler prints:
- Raw 32-bit value
- Two 16-bit halves (temp + humidity)
- Four individual bytes
command_handler prints:
- Command ID
- Parameter
| Step | Function | What it does |
|---|---|---|
| 6 | HexDump |
Prints raw bytes of both message buffers |
| 7 | ReadByte |
Reads HEADER (offset 0) and LENGTH (offset 1) |
| 8 | ReadHalfWord |
Reads temperature (lower 16 bits) at offset 2 |
| 9 | ReadWord |
Reads full 32-bit payload at offset 2 |
| 10 | WriteByte |
Copies sensor buffer, flips PRIORITY bit, dumps both |
| 11 | MemFill |
Fills empty 6-byte buffer with 0xAA, dumps to verify |
| 12 | MemCompare |
Compares two identical buffers (→ 0), then modified (→ offset) |
| 13 | FindByte |
Finds known byte (→ offset), searches missing byte (→ -1) |
- Union-based payload —
SensorPayload_tuses a union so the same 4 bytes are simultaneously accessible asuint32, twouint16halves, oruint8 bytes[]with zero overhead. - Static sequence number —
seqNumlives as astaticvariable insidemessage.c, invisible to the caller, auto-wrapping at 15. - Static encoder buffer —
messageEncodereturns a pointer to a static internal buffer. Always copy it before the next encode call. - Compile-time size check —
_Static_assert(sizeof(message_t) == 6)catches accidental padding at build time. - Hardware-agnostic types — All types go through
STD_TYPES.h; no raw C types appear outside it.
gcc -Wall -Wextra -o project1 main.c message.c MemScanner.c
./project1Team name format: sbe27_embedded_spring26_team##