Serial Communications (SC) Family Guide
Overview
The SC family is NAI’s line of programmable serial-communications smart function modules. Each module provides multiple independent, full-duplex serial channels, and every channel is software-configurable for RS-232 (single-ended), RS-422/485 (differential), and RS-423 (pending) — in asynchronous or synchronous modes, at programmable baud rate, parity, data bits, and stop bits, with on-chip transmit/receive FIFOs.
This page is the starting point for any SC module. Use it to understand the family, pick the member that fits your channel count and isolation needs, wire a serial link, and confirm you can talk to the module with a loopback. It’s aimed at engineers integrating serial devices — GPS/INS units, radios, sensors, displays, telemetry, and legacy avionics serial buses — into an NAI board or system.
In a real system, an SC module is how your processor talks to the serial devices around it. On a rugged platform that usually means a GPS receiver or inertial navigation unit streaming position data, a radio or datalink terminal, engine/environmental sensors, cockpit displays, or older avionics boxes that only speak a serial protocol. The interface you choose follows the link: RS-232 for short, point-to-point connections to a single nearby device; RS-422/485 for longer, noisier cable runs and multi-drop buses where several devices share one line. NAI also builds these same modules into larger serial subsystems — the FACE-certified Serial IOSS and the Remote Data Concentrators (RDC) — that switch and concentrate many serial lines in aerospace and defense systems.
(NAI’s other communication / data-bus families: the AR family for ARINC 429/575, the CB family for CANbus, and the FT family for MIL-STD-1553 & 1760.)
For a short visual introduction to the serial communications family, watch this overview:
SC modules at a glance
| Module | Channels | Isolation | What makes it different | Manual |
|---|---|---|---|---|
| SC1 | 4 | Non-isolated | Baseline programmable serial (RS-232/422/485) | SC1-2-7 Manual |
| SC2 | 4 | Isolated | SC1 with isolated outputs | SC1-2-7 Manual |
| SC7 | 4 | Non-isolated | SC1 with the CTS flow-control pins reallocated as 4 GPIO | SC1-2-7 Manual |
| SC3 | 8 | Iso or non-iso | Highest channel count; 8 async or 4 sync channels | SC3 Manual |
| SC5 | 4 | Isolated | Individually isolated; async/sync; SYNC clock or GPO | SC5 Manual |
| SC6 | 4 | Non-isolated | SC5’s non-isolated twin; async/sync; SYNC clock or GPO | SC6 Manual |
Choosing a member:
- Most channels in one slot — SC3 (8 channels; run as 8 async or 4 sync).
- Galvanic isolation — SC2 or SC5 (SC5 is individually isolated per channel).
- Non-isolated, standard serial — SC1 or SC6.
- Extra GPIO alongside serial — SC7 (its CTS flow-control pins become 4 GPIO).
- Synchronous (clocked) operation, or a SYNC clock / GPO — SC3, SC5, or SC6.
Combination modules that include serial:
| Module | Combines | Manual |
|---|---|---|
| CM4 | Serial + Discrete I/O | CM4 Manual |
| CMH | Serial (async) + Differential I/O | CMH Manual |
Physical setup
Serial wiring depends on the protocol you program and on the per-module pinout, so the exact TX/RX pins always come from that module’s manual. The setup pattern is the same for every SC module:
- Identify the module’s slot number on your NAI motherboard or system.
- Bring the channel signals out through the breakout board, where the slot’s pins appear as generic IO# numbers.
- Map IO# pins to the channel’s serial signals — by the pinout in the module’s manual or the module’s overlay card.
- Wire your serial device to the mapped TX/RX pins.
Two ideas cover every SC wiring job:
- Choose the electrical interface in software, then wire to match it. RS-232 is single-ended — each signal is a single wire measured against a shared ground. RS-422/485 are differential — each signal is a balanced pair of wires (a
+and a−), which rejects noise and reaches much farther. Set the interface withnaibrd_SER_SetInterface; the wiring you run has to match that choice. - Always cross transmit and receive. The module’s TX (what it sends) goes to the device’s RX (what it listens on), and the module’s RX comes from the device’s TX.
Two worked examples — your module’s manual or overlay card gives the actual pin numbers:
RS-232 to a nearby device (e.g. a GPS receiver) — 3 wires:
| Module pin | → | Device pin |
|---|---|---|
| TX | → | RX |
| RX | ← | TX |
| GND | ↔ | GND |
Then set baud, parity, data bits, and stop bits to match the device (e.g. 9600 8N1).
RS-422 over a longer or noisier run — 2 pairs (4 signal wires):
| Module pins | → | Device pins |
|---|---|---|
| TX+ / TX− (one pair) | → | RX+ / RX− |
| RX+ / RX− (one pair) | ← | TX+ / TX− |
Each direction is its own balanced pair, so it tolerates long cables and electrical noise far better than RS-232.
Two module-specific notes: isolated variants (SC2, SC5) keep channels galvanically separated, so reference signals to the isolated ground, not system/chassis ground. And in synchronous mode a clock rides on the companion channel; in async mode those pins are free to act as a GPO (SC5/SC6) or GPIO (SC7).
Software
There’s nothing SC-specific about which software you run. The NAI SSK (naibrd library) is identical across every OS and architecture — PetaLinux, VxWorks, DEOS, Windows. What OS you’re on is determined by your motherboard/SBC, not by the SC module. The only family-specific part is which API functions you call — and note the prefix is naibrd_SER_* (serial), not naibrd_SC_*.
Where to find what you need:
- Which functions/registers to call — the specific module’s manual (e.g. SC3 Manual) documents the SER registers (protocol, interface level, baud, parity, FIFOs).
- Building and deploying on your platform — Connecting to Boards covers the toolchain, deployment, and terminal access for PetaLinux/ARM Linux, VxWorks, DEOS, and Windows.
- Launching the app on the board itself — Running Applications from the Target walks through loading and launching your executable on the target.
Example — a 68ARM2 SBC with an SC3 module: pull the naibrd_SER_* calls from the SC3 Manual, set up the ARM Linux toolchain per Connecting to Boards, then load and launch a serial sample on the target per Running Applications from the Target.
Confirm communication
Before wiring anything to a real device, prove the whole chain — board connection, SSK, and the module — works.
Internal loopback (no wiring). Every SC channel can wrap its own transmitter back to its receiver internally. The loopback sample does exactly this: it configures a channel for async, writes data to the TX FIFO, loops it back through the module’s internal path, and verifies the bytes read back match — with no external cabling. Run SER Async Loopback (SSK 2.x) (or SER ASync LOOPBACK (SSK 1.x)); if it passes, you’re talking to the module.
External TX→RX (also proves your wiring). As a step up, jumper one channel’s transmit to another channel’s receive (matching the interface level you program — e.g. an RS-422 pair to an RS-422 pair), transmit on the first channel, and read the bytes on the second. This validates the physical pins and your cabling on top of the module itself. The transmit/receive sample pair SER Async Xmit and SER Async Recv demonstrates the two-channel flow.
Features
Each SC operation works per channel through the naibrd_SER_* API (note the prefix is SER, not SC). The blocks below group the calls by what you’re doing, with the SSK 1.x and 2.x signatures side by side. (The 1.x → 2.x rename is extensive here: SetProtocol→SetCommProtocol, SetInterfaceLevel→SetInterface, SetParity→SetParityType, SetDataBits/SetStopBits→SetNumDataBits/SetNumStopBits (now enum-typed), TransmitBuffer→LoadBufferWithTimeOut32, ReceiveBuffer32→ReceiveBufferWithTimeOut32, GetChannelStatus→GetChanMappedStatus, and nai_ser_* enum types → naibrd_ser_*.)
Configure a channel
What it does: set the channel’s protocol (async/sync), electrical interface (RS-232/422/485), baud rate, and framing (data bits, stop bits, parity).
Applies to: all SC modules (sync mode on SC3/SC5/SC6).
Relevant APIs:
/* SSK 1.x */
nai_status_t naibrd_SER_SetProtocol(int32_t cardIndex, int32_t module, int32_t channel, nai_ser_protocol_t protocol);
nai_status_t naibrd_SER_SetInterfaceLevel(int32_t cardIndex, int32_t module, int32_t channel, nai_ser_interface_t level);
nai_status_t naibrd_SER_SetBaudrate(int32_t cardIndex, int32_t module, int32_t channel, uint32_t baudRate);
nai_status_t naibrd_SER_SetParity(int32_t cardIndex, int32_t module, int32_t channel, nai_ser_parity_t parity);
nai_status_t naibrd_SER_SetDataBits(int32_t cardIndex, int32_t module, int32_t channel, uint8_t dataBits);
nai_status_t naibrd_SER_SetStopBits(int32_t cardIndex, int32_t module, int32_t channel, uint8_t stopBits);/* SSK 2.x */
nai_status_t naibrd_SER_SetCommProtocol(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ser_protocol_t protocol);
nai_status_t naibrd_SER_SetInterface(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ser_interface_t level);
nai_status_t naibrd_SER_SetBaudrate(int32_t cardIndex, int32_t module, int32_t channel, uint32_t baudRate);
nai_status_t naibrd_SER_SetParityType(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ser_parity_t parity);
nai_status_t naibrd_SER_SetNumDataBits(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ser_data_bits_t dataBits);
nai_status_t naibrd_SER_SetNumStopBits(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ser_stop_bits_t stopBits);Exercise it: Async Transmit · Async Receive · ESP2 “SC” tab.
Transmit
What it does: write bytes into the channel’s transmit FIFO; check how many words are queued.
Applies to: all SC modules.
Relevant APIs:
/* SSK 1.x */
nai_status_t naibrd_SER_TransmitBuffer(int32_t cardIndex, int32_t module, int32_t channel, int32_t width, const void* buffer, uint32_t count, uint32_t* outwritten);
nai_status_t naibrd_SER_GetTxBufferCnt(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* outcount);/* SSK 2.x */
nai_status_t naibrd_SER_LoadBufferWithTimeOut32(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_buffer, int32_t txCount, int32_t bufferLength, int32_t timeout_msec, int32_t* p_outwritten);
nai_status_t naibrd_SER_GetTxBufferCnt(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_outcount);Exercise it: Async Transmit · ESP2 “SC” tab.
Receive
What it does: enable the receiver, poll the receive FIFO count, and read the received bytes.
Applies to: all SC modules.
Relevant APIs:
/* SSK 1.x */
nai_status_t naibrd_SER_SetReceiverEnable(int32_t cardIndex, int32_t module, int32_t channel, bool_t enable);
nai_status_t naibrd_SER_GetRxBufferCnt(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* outcount);
nai_status_t naibrd_SER_ReceiveBuffer32(int32_t cardIndex, int32_t module, int32_t channel, uint32_t outbuffer[], uint32_t length, uint32_t* outreceived);/* SSK 2.x */
nai_status_t naibrd_SER_SetReceiverEnable(int32_t cardIndex, int32_t module, int32_t channel, bool_t enable);
nai_status_t naibrd_SER_GetRxBufferCnt(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_outcount);
nai_status_t naibrd_SER_ReceiveBufferWithTimeOut32(int32_t cardIndex, int32_t module, int32_t channel, uint32_t outbuffer[], int32_t bufferLength, int32_t expectedCount, int32_t timeout_msec, int32_t* p_outreceived);Exercise it: Async Receive · ESP2 “SC” tab.
Status, BIT & flow control
What it does: read per-channel status, run Built-In Test, and drive/read the RS-232 hardware flow-control lines (RTS/CTS — repurposed as GPIO on SC7).
Applies to: all SC modules.
Relevant APIs:
/* SSK 1.x */
nai_status_t naibrd_SER_GetChannelStatus(int32_t cardIndex, int32_t module, nai_ser_status_type_t type, nai_ser_status_t* outchannelStatus);
nai_status_t naibrd_SER_InitiateBIT(int32_t cardIndex, int32_t module, int32_t channel, bool_t waitForResult);
nai_status_t naibrd_SER_CheckBITComplete(int32_t cardIndex, int32_t module, int32_t channel, bool_t* outBitComplete);
nai_status_t naibrd_SER_SetRTS(int32_t cardIndex, int32_t module, int32_t channel, bool_t active);
nai_status_t naibrd_SER_GetCTS(int32_t cardIndex, int32_t module, int32_t channel, bool_t* outactive);/* SSK 2.x */
nai_status_t naibrd_SER_GetChanMappedStatus(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ser_chan_mapped_status_type_t statusType, nai_status_bit_t* p_outstatusBit);
nai_status_t naibrd_SER_InitiateBIT(int32_t cardIndex, int32_t module, int32_t channel, bool_t waitForResult);
nai_status_t naibrd_SER_CheckBITComplete(int32_t cardIndex, int32_t module, int32_t channel, bool_t* p_outbitComplete);
nai_status_t naibrd_SER_SetRTS(int32_t cardIndex, int32_t module, int32_t channel, bool_t active);
nai_status_t naibrd_SER_GetCTS(int32_t cardIndex, int32_t module, int32_t channel, bool_t* p_outactive);Exercise it: Built-In Test · Async + GPIO · ESP2 “SC” tab.
Try it
Serial channels are configured the same way regardless of which sample you run. Every NAI sample starts with the standard connection flow — naiapp_RunBoardMenu() opens or loads a board connection, then naiapp_query_CardIndex() and naiapp_query_ModuleNumber() pick the board and module slot (opened under the hood by naibrd_OpenDevice()), giving you the cardIndex / module / channel coordinates every naibrd_SER_* call takes. When you write your own program, you do the same — see Opening a Software Handle to Your Board.
Configuring a channel for 9600 8N1 async on an RS-422 interface looks like this (straight from the SER sample apps):
/* SSK 1.x */
naibrd_SER_ChannelReset(cardIndex, module, channel);
naibrd_SER_ClearRxFifo(cardIndex, module, channel);
naibrd_SER_ClearTxFifo(cardIndex, module, channel);
naibrd_SER_SetProtocol(cardIndex, module, channel, NAI_SER_PROTOCOL_ASYNC);
naibrd_SER_SetInterfaceLevel(cardIndex, module, channel, NAI_SER_INTF_RS422);
naibrd_SER_SetParity(cardIndex, module, channel, NAI_SER_PARITY_NONE);
naibrd_SER_SetDataBits(cardIndex, module, channel, 8);
naibrd_SER_SetStopBits(cardIndex, module, channel, 1);
naibrd_SER_SetBaudrate(cardIndex, module, channel, 9600);
/* On a receive channel, also enable the receiver: */
naibrd_SER_SetReceiverEnable(cardIndex, module, channel, TRUE);/* SSK 2.x */
naibrd_SER_ChannelReset(cardIndex, module, channel);
naibrd_SER_ClearRxFifo(cardIndex, module, channel);
naibrd_SER_ClearTxFifo(cardIndex, module, channel);
naibrd_SER_SetCommProtocol(cardIndex, module, channel, NAIBRD_SER_PROTOCOL_ASYNC);
naibrd_SER_SetInterface(cardIndex, module, channel, NAIBRD_SER_INTF_RS422);
naibrd_SER_SetParityType(cardIndex, module, channel, NAIBRD_SER_PARITY_NONE);
naibrd_SER_SetNumDataBits(cardIndex, module, channel, NAIBRD_SER_DATA_BITS_8);
naibrd_SER_SetNumStopBits(cardIndex, module, channel, NAIBRD_SER_STOP_BITS_1);
naibrd_SER_SetBaudrate(cardIndex, module, channel, 9600);
/* On a receive channel, also enable the receiver: */
naibrd_SER_SetReceiverEnable(cardIndex, module, channel, TRUE);From there you send bytes (naibrd_SER_TransmitBuffer in 1.x / naibrd_SER_LoadBufferWithTimeOut32 in 2.x) and read them back (naibrd_SER_GetRxBufferCnt + naibrd_SER_ReceiveBuffer32 in 1.x / naibrd_SER_ReceiveBufferWithTimeOut32 in 2.x) — see the Transmit and Receive blocks above.
Browse the serial samples: Async Transmit · Async Receive · Async Loopback · Async + GPIO · Built-In Test (SSK 2.x); SSK 1.x equivalents include SER_ASync_Tx, SER_ASync_Rx, and SER_ASync_LOOPBACK.
Hardware capabilities and status monitoring
This section covers what the hardware provides and what you can monitor — for how to configure and drive each channel, see Features and Try it above.
What the hardware provides:
- Multi-protocol serial channels — every channel runs asynchronous (UART-style) serial; synchronous protocols are available on SC3/SC5/SC6.
- Software-selectable electrical interface — set each channel to RS-232, RS-422, or RS-485 in software (
naibrd_SER_SetInterface), with no jumpers or rewiring. - Fully programmable framing — baud rate, data bits, stop bits, parity, and encoding, per channel.
- Independent transmit and receive FIFOs — buffer bytes in each direction, with programmable almost-full / almost-empty and high/low watermark thresholds for flow pacing.
- Hardware flow control — RS-232 RTS/CTS lines (
naibrd_SER_SetRTS/naibrd_SER_GetCTS); on SC7 these lines are repurposed as general-purpose I/O. - Galvanic isolation — channels on SC2/SC5 are isolated from system ground.
- Built-In Test — per-channel BIT you can run on demand (
naibrd_SER_InitiateBIT→naibrd_SER_CheckBITComplete).
Statuses you can monitor programmatically
Per channel, in real-time and latched form via naibrd_SER_GetChanMappedStatus:
| Status | What it tells you |
|---|---|
| BIT | A built-in-test fault on the channel |
| RX data available | The receive FIFO has bytes ready to read |
Per-byte receive conditions (returned with the data, and available as event-mapped statuses you can raise interrupts on):
| Condition | What it tells you |
|---|---|
| Parity error | A byte arrived with a parity mismatch |
| Framing error | A byte’s stop bit was malformed — usually a baud-rate or format mismatch |
| Overrun | The receive FIFO overflowed before it was read |
| CRC error | (Synchronous modes) a frame failed its CRC check |
| Break / abort | A line break or aborted frame was detected |
| FIFO watermarks / TX–RX complete | Buffer-level events for pacing transmit and receive |
ESP2’s status panel shows SC channel state and status interactively if you’d rather watch it in a GUI first.
Common pitfalls
- Interface level doesn’t match the wiring. Programming a channel as RS-232 while it’s wired differentially (or vice versa) yields garbage or silence. Set
naibrd_SER_SetInterfaceto match how the channel is physically wired. - Both ends must agree on baud, parity, data bits, and stop bits. A mismatch (e.g. 9600 8N1 vs 115200 8E1) produces framing errors or gibberish — configure both sides identically.
- No data received? The receiver may not be enabled. Transmit-only channels don’t need it, but a receive channel requires
naibrd_SER_SetReceiverEnable(..., TRUE). - TX and RX not crossed. The module’s TX must reach the device’s RX and vice versa; wiring TX→TX is a common mistake.
- Sync vs async confusion. Synchronous mode expects a clock on the companion channel; for plain UART-style serial use async (
NAIBRD_SER_PROTOCOL_ASYNC). - Isolated-module grounding. On SC2/SC5, channels are galvanically isolated — reference signals to the isolated ground, not chassis/system ground.
Related resources
- AR Family Guide — ARINC 429/575 avionics data bus
- CB Family Guide — CANbus (CAN 2.0 A/B, J1939, MilCAN)
- FT Family Guide — MIL-STD-1553 & 1760
- Download the SSK — get the library and sample apps
- Connecting to Boards — power, network, terminal, and file transfer to your board
- Opening a Software Handle to Your Board — establish the connection your
naibrd_SER_*calls run against - Running Applications from the Target — load and launch a built sample on the board
- ESP2 Quick Start — exercise serial channels with no code via the Embedded Soft Panel
