Wi-SUN NCP Application#

Overview#

The Wi-SUN NCP (Network Co-Processor) application provides a production-ready implementation for handling Wi-SUN stack communication through a message-based interface. The NCP acts as a bridge between a host processor and the Wi-SUN stack.

Message Flow#

Requests#

Host Application → Transport/driver → NCP Task → Wi-SUN Stack

Confirmations/Indications#

Wi-SUN Stack → NCP Task → Transport/driver → Host application

The NCP receives complete messages from the transport layer, validates them, forwards to the Wi-SUN stack, and returns confirmations and asynchronous indications.

Buffer Format Requirements#

Message Structure#

All messages sent to the NCP transport layer must follow this format:

┌─────────────────┬─────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────┐
│   Header (8B)   │ Message Body (varies according to the request/confirmation) │ Variable Data (varies according to trailing data size)   │
└─────────────────┴─────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────

Header Format#

typedef struct {
  uint16_t length;
  uint8_t id;
  uint8_t info;
} sl_wisun_msg_header_t;

Critical Requirements:

  • header.length must equal the total message size

  • header.id must be a valid Wi-SUN message ID

  • Message must be complete

Buffer Size Configuration#

Configure SL_WSNCP_BUFFER_SIZE in your .slcp file:

- name: "SL_WSNCP_BUFFER_SIZE" 
  value: "1500"

Usage Examples#

1. Basic Request#

// Example: Get IP address
sl_wisun_msg_get_ip_address_req_t req = {0};

// Initialize request
req.header.id = SL_WISUN_MSG_GET_IP_ADDRESS_REQ_ID;
req.header.length = sizeof(req);  // Must match actual size
req.body.address_type = SL_WISUN_IP_ADDRESS_TYPE_GLOBAL;

// Send to the ncp host

2. Socket Operations#

// Example: Open UDP socket
sl_wisun_msg_open_socket_req_t open_req = {0};

open_req.header.id = SL_WISUN_MSG_OPEN_SOCKET_REQ_ID;
open_req.header.length = sizeof(open_req);
open_req.body.domain = AF_INET6;
open_req.body.type = SOCK_DGRAM;
open_req.body.protocol = IPPROTO_UDP;

// send to the ncp host

3. Variable Data Messages#

// Example: Send data to socket
uint16_t data_length = 100;  // Example payload size
uint8_t *sendto_buffer = malloc(sizeof(sl_wisun_msg_sendto_on_socket_req_t) + data_length);
sl_wisun_msg_sendto_on_socket_req_t *sendto_req = (sl_wisun_msg_sendto_on_socket_req_t *)sendto_buffer;

// Initialize request
sendto_req->header.id = SL_WISUN_MSG_SENDTO_ON_SOCKET_REQ_ID;
sendto_req->header.length = sizeof(sl_wisun_msg_sendto_on_socket_req_t) + data_length;
sendto_req->body.socket_id = socket_id;
sendto_req->body.remote_address = remote_ipv6_address;
sendto_req->body.remote_port = remote_port;
sendto_req->body.data_length = data_length;

// Copy data after the fixed structure
memcpy(sendto_req->body.data, payload_data, data_length);

// send to the ncp host

Confirmation Handling#

What You Need to Do:#

  • Configure SL_WSNCP_BUFFER_SIZE in your .slcp to sufficiently hold all you intended confirmations plus any trailing data.

Minimum confirmation buffer size: sizeof(sl_wisun_msg_header_t) + sizeof(uint32_t) (12 bytes) for status field.

Confirmation Reception#

// Handle confirmation from transport layer
void handle_confirmation(uint16_t len, const uint8_t *data) {
    if (len < sizeof(sl_wisun_msg_header_t) + sizeof(uint32_t)) {
        printf("Confirmation too small\n");
        return;
    }
    
    const sl_wisun_msg_header_t *header = (const sl_wisun_msg_header_t *)data;
    const uint32_t *status = (const uint32_t *)(data + sizeo(sl_wisun_msg_header_t));
    
    if (*status == SL_STATUS_OK) {
        // Process successful confirmation
        printf("Request ID:0x%02X successful\n", header->id);
        // Access confirmation data based on message type
    } else {
        // Handle error
        printf("Request ID:0x%02X failed with status: 0x%08X\n", *status);
    }
}

Validation and Error Handling#

Buffer Validation#

The NCP performs these checks:

  1. Size Check:

    • Message must fit in configured buffer size

    • For request messages, message length should be the size of the request (hdr + body + trailing data if any)

    • For confirmation messages, length should be sufficient to hold the confirmation (hdr + body + trailing data if any)

  2. Header Validation: Valid message ID and length consistency

  3. Completeness Check: Message must be complete (no fragmentation)

Error Responses#

// Handle common errors
if (status == SL_STATUS_WOULD_OVERFLOW) {
    // Message too large - increase buffer size
    printf("Message too large for buffer\n");
}

if (status == SL_STATUS_INVALID_PARAMETER) {
    // Invalid message format - check header.length
    printf("Invalid message format\n");
}

Best Practices#

  1. Always set header.length correctly - must match total message size

  2. Use appropriate buffer sizes for your message types

  3. Send complete messages - no fragmentation

  4. Allocate sufficient confirmation buffers - account for variable data

Common Issues#

  1. Buffer Overflow: Increase SL_WSNCP_BUFFER_SIZE

  2. Header Length Mismatch: Ensure header.length equals actual message size

  3. Invalid Message ID: Use correct Wi-SUN message IDs

  4. Incomplete Messages: Send complete messages in single transmission

  5. Confirmation Buffer Too Small: Allocate sufficient space for confirmation + variable data